synvert-core 0.52.0 → 0.54.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 346c7567c1fec413a81afbe2ec5348f9cd66ac03ed08e8a6cf0fbf47ba049d08
4
- data.tar.gz: c4a274d516c1301eb0be17777bd26a16561943077260508925cc3c5eae43e799
3
+ metadata.gz: dce993d0b27272e83abe3bd3a1ff2a9917a2c9953bb30e57671216aed001292c
4
+ data.tar.gz: 0b65093ca670d59065707e122a9964f163fbca2e4201fd75005295b7841e4db1
5
5
  SHA512:
6
- metadata.gz: ee568051d2872db9f81c7d9a3609379eba74db82862ad55976b962e0c4b835dca9f7af74c67014554f6ee919edde2dab050a77fc248bc71ed2c4969009cede1d
7
- data.tar.gz: 80dd4085d700581a02dd9507e88e0cbf28e978cbbd61d0e0906c73d2f713abbdd9393caec13d6854b3727d1b1fdd87a673d67323b4b315990a00f06fa23a1f44
6
+ metadata.gz: 4bb49555a37b7778e37216f267b0e2ab938030ac5428f7bbef60d8462fb83597693bad9a5cd12c43c52a80330de48662151abbcc8edebb7572538f1520539bac
7
+ data.tar.gz: eaf5690913c21c3b043f5119f2b8b4afe08c16c5a9db8d9d209a42f0a64a72d4f19376da6dee6ed43b04b79d8077f4463a47acb5d18742a6dcb1499b3191db7a
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.54.1 (2021-09-08)
4
+
5
+ * Rewrite `remove` action
6
+
7
+ ## 0.54.0 (2021-08-28)
8
+
9
+ * Change `goto_scope` param from array to string
10
+
11
+ ## 0.53.0 (2021-08-22)
12
+
13
+ * Fix nested child in Node#child_node_range
14
+ * Rename synvert-core to synvert-core-ruby
15
+
3
16
  ## 0.52.0 (2021-08-21)
4
17
 
5
18
  * ``Node#child_node_range`` supports nested child
data/README.md CHANGED
@@ -1,12 +1,11 @@
1
- # Synvert::Core
1
+ # synvert-core-ruby
2
2
 
3
- <img src="https://xinminlabs.github.io/synvert/img/logo_96.png" alt="logo" width="32" height="32" />
3
+ <img src="https://synvert.xinminlabs.com/img/logo_96.png" alt="logo" width="32" height="32" />
4
4
 
5
- ![Main workflow](https://github.com/xinminlabs/synvert-core/actions/workflows/main.yml/badge.svg)
6
- [![Coverage Status](https://coveralls.io/repos/xinminlabs/synvert-core/badge.png?branch=master)](https://coveralls.io/r/xinminlabs/synvert-core)
5
+ ![Main workflow](https://github.com/xinminlabs/synvert-core-ruby/actions/workflows/main.yml/badge.svg)
7
6
  [![Gem Version](https://badge.fury.io/rb/synvert-core.png)](http://badge.fury.io/rb/synvert-core)
8
7
 
9
- synvert-core provides a dsl to convert ruby source code.
8
+ synvert-core-ruby provides a dsl to convert ruby source code.
10
9
 
11
10
  ## Installation
12
11
 
@@ -31,11 +30,11 @@ Or install it yourself as:
31
30
 
32
31
  ## Contributing
33
32
 
34
- 1. Fork it ( https://github.com/[my-github-username]/synvert-core/fork )
33
+ 1. Fork it ( https://github.com/[my-github-username]/synvert-core-ruby/fork )
35
34
  2. Create your feature branch (`git checkout -b my-new-feature`)
36
35
  3. Commit your changes (`git commit -am 'Add some feature'`)
37
36
  4. Push to the branch (`git push origin my-new-feature`)
38
37
  5. Create a new Pull Request
39
38
 
40
- [1]: https://xinminlabs.github.io/synvert/
41
- [2]: https://rubydoc.info/github/xinminlabs/synvert-core/master/frames
39
+ [1]: https://synvert.xinminlabs.com
40
+ [2]: https://rubydoc.info/github/xinminlabs/synvert-core-ruby/master/frames
@@ -341,7 +341,7 @@ module Parser::AST
341
341
  # @param [String] name of child node.
342
342
  # @return [Parser::Source::Range] source range of child node.
343
343
  def child_node_range(child_name)
344
- case [type, child_name]
344
+ case [type, child_name.to_sym]
345
345
  when %i[block pipes], %i[def parentheses], %i[defs parentheses]
346
346
  Parser::Source::Range.new('(string)', arguments.loc.expression.begin_pos, arguments.loc.expression.end_pos)
347
347
  when %i[block arguments], %i[def arguments], %i[defs arguments]
@@ -369,35 +369,38 @@ module Parser::AST
369
369
  Parser::Source::Range.new('(string)', loc.begin.begin_pos, loc.end.end_pos)
370
370
  end
371
371
  else
372
- child_node = self
373
- child_name.to_s.split('.').each do |key|
374
- if child_node.respond_to?(key)
375
- child_node = child_node.send(key)
376
- return nil if child_node.nil?
377
- else
378
- raise Synvert::Core::MethodNotSupported,
379
- "child_node_range is not handled for #{child_node.debug_info}, child_name: #{child_name}"
372
+ direct_child_name, nested_child_name = child_name.to_s.split('.', 2)
373
+ if respond_to?(direct_child_name)
374
+ child_node = send(direct_child_name)
375
+
376
+ return child_node.child_node_range(nested_child_name) if nested_child_name
377
+
378
+ return nil if child_node.nil?
379
+
380
+ if child_node.is_a?(Parser::AST::Node)
381
+ return(
382
+ Parser::Source::Range.new(
383
+ '(string)',
384
+ child_node.loc.expression.begin_pos,
385
+ child_node.loc.expression.end_pos
386
+ )
387
+ )
380
388
  end
381
- end
382
389
 
383
- if child_node.is_a?(Parser::AST::Node)
390
+ # arguments
391
+ return nil if child_node.empty?
392
+
384
393
  return(
385
394
  Parser::Source::Range.new(
386
395
  '(string)',
387
- child_node.loc.expression.begin_pos,
388
- child_node.loc.expression.end_pos
396
+ child_node.first.loc.expression.begin_pos,
397
+ child_node.last.loc.expression.end_pos
389
398
  )
390
399
  )
391
400
  end
392
401
 
393
- # arguments
394
- return nil if child_node.empty?
395
-
396
- Parser::Source::Range.new(
397
- '(string)',
398
- child_node.first.loc.expression.begin_pos,
399
- child_node.last.loc.expression.end_pos
400
- )
402
+ raise Synvert::Core::MethodNotSupported,
403
+ "child_node_range is not handled for #{debug_info}, child_name: #{child_name}"
401
404
  end
402
405
  end
403
406
 
@@ -1,21 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
- # RemoveAction to delete code.
4
+ # DeleteAction to delete child nodes.
5
5
  class Rewriter::DeleteAction < Rewriter::Action
6
6
  def initialize(instance, *selectors)
7
7
  super(instance, nil)
8
8
  @selectors = selectors
9
9
  end
10
10
 
11
- # Begin position of code to replace.
11
+ # Begin position of code to delete.
12
12
  #
13
13
  # @return [Integer] begin position.
14
14
  def begin_pos
15
15
  @selectors.map { |selector| @node.child_node_range(selector) }.compact.map(&:begin_pos).min
16
16
  end
17
17
 
18
- # End position of code to replace.
18
+ # End position of code to delete.
19
19
  #
20
20
  # @return [Integer] end position.
21
21
  def end_pos
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
- # AddAction to add code to the node.
4
+ # InsertAction to add code to the node.
5
5
  class Rewriter::InsertAction < Rewriter::Action
6
6
  def initialize(instance, code, at:)
7
7
  super(instance, code)
@@ -1,29 +1,55 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
- # RemoveAction to remove code.
4
+ # RemoveAction to remove current node.
5
5
  class Rewriter::RemoveAction < Rewriter::Action
6
- def initialize(instance, code = nil)
7
- super
6
+ def initialize(instance)
7
+ super(instance, nil)
8
8
  end
9
9
 
10
10
  # Begin position of code to replace.
11
11
  #
12
12
  # @return [Integer] begin position.
13
13
  def begin_pos
14
- @node.loc.expression.begin_pos
14
+ if take_whole_line?
15
+ start_index
16
+ else
17
+ @node.loc.expression.begin_pos
18
+ end
15
19
  end
16
20
 
17
21
  # End position of code to replace.
18
22
  #
19
23
  # @return [Integer] end position.
20
24
  def end_pos
21
- @node.loc.expression.end_pos
25
+ if take_whole_line?
26
+ end_index
27
+ else
28
+ @node.loc.expression.end_pos
29
+ end
22
30
  end
23
31
 
24
32
  # The rewritten code, always empty string.
25
33
  def rewritten_code
26
34
  ''
27
35
  end
36
+
37
+ private
38
+
39
+ def take_whole_line?
40
+ @node.to_source == file_source[start_index...end_index].strip
41
+ end
42
+
43
+ def start_index
44
+ file_source[0..@node.loc.expression.begin_pos].rindex("\n") + "\n".length
45
+ end
46
+
47
+ def end_index
48
+ file_source[@node.loc.expression.end_pos..-1].index("\n") + @node.loc.expression.end_pos + "\n".length
49
+ end
50
+
51
+ def file_source
52
+ @file_source ||= @instance.file_source
53
+ end
28
54
  end
29
55
  end
@@ -64,6 +64,11 @@ module Synvert::Core
64
64
  # @return current filename
65
65
  attr_accessor :current_node, :current_file
66
66
 
67
+ # Current file source
68
+ def file_source
69
+ self.class.file_source(current_file)
70
+ end
71
+
67
72
  # Initialize an instance.
68
73
  #
69
74
  # @param rewriter [Synvert::Core::Rewriter]
@@ -107,7 +112,6 @@ module Synvert::Core
107
112
  conflict_actions = get_conflict_actions
108
113
  @actions.reverse_each do |action|
109
114
  source[action.begin_pos...action.end_pos] = action.rewritten_code
110
- source = remove_code_or_whole_line(source, action.line)
111
115
  end
112
116
  @actions = []
113
117
 
@@ -139,7 +143,7 @@ module Synvert::Core
139
143
 
140
144
  # Set current_node properly, process and set current_node back to original current_node.
141
145
  #
142
- # @param node [Parser::AST::Node] node set to current_node
146
+ # @param node [Parser::AST::Node] node set to other_node
143
147
  # @yield process
144
148
  def process_with_other_node(node)
145
149
  original_node = current_node
@@ -177,10 +181,10 @@ module Synvert::Core
177
181
  # Parse goto_node dsl, it creates a [Synvert::Core::Rewriter::GotoScope] to go to a child node,
178
182
  # then continue operating on the child node.
179
183
  #
180
- # @param *child_node_names [Array] the name of the child nodes.
184
+ # @param child_node_name [Symbol|String] the name of the child nodes.
181
185
  # @param block [Block] block code to continue operating on the matching nodes.
182
- def goto_node(*child_node_names, &block)
183
- Rewriter::GotoScope.new(self, *child_node_names, &block).process
186
+ def goto_node(child_node_name, &block)
187
+ Rewriter::GotoScope.new(self, child_node_name, &block).process
184
188
  end
185
189
 
186
190
  # Parse if_exist_node dsl, it creates a [Synvert::Core::Rewriter::IfExistCondition] to check
@@ -323,25 +327,6 @@ module Synvert::Core
323
327
  conflict_actions
324
328
  end
325
329
 
326
- # It checks if code is removed and that line is empty.
327
- #
328
- # @param source [String] source code of file
329
- # @param line [String] the line number
330
- def remove_code_or_whole_line(source, line)
331
- newline_at_end_of_line = source[-1] == "\n"
332
- source_arr = source.split("\n")
333
- if source_arr[line - 1] && source_arr[line - 1].strip.empty?
334
- source_arr.delete_at(line - 1)
335
- if source_arr[line - 2] && source_arr[line - 2].strip.empty? && source_arr[line - 1] &&
336
- source_arr[line - 1].strip.empty?
337
- source_arr.delete_at(line - 1)
338
- end
339
- source_arr.join("\n") + (newline_at_end_of_line ? "\n" : '')
340
- else
341
- source
342
- end
343
- end
344
-
345
330
  # It updates a file with new source code.
346
331
  #
347
332
  # @param file_path [String] the file path
@@ -6,11 +6,11 @@ module Synvert::Core
6
6
  # Initialize a scope
7
7
  #
8
8
  # @param instance [Synvert::Core::Rewriter::Instance]
9
- # @param *child_node_names [Array]
9
+ # @param child_node_name [Symbol|string]
10
10
  # @param block [Block]
11
- def initialize(instance, *child_node_names, &block)
11
+ def initialize(instance, child_node_name, &block)
12
12
  @instance = instance
13
- @child_node_names = child_node_names
13
+ @child_node_name = child_node_name
14
14
  @block = block
15
15
  end
16
16
 
@@ -20,7 +20,7 @@ module Synvert::Core
20
20
  return unless current_node
21
21
 
22
22
  child_node = current_node
23
- @child_node_names.each do |child_node_name|
23
+ @child_node_name.to_s.split('.').each do |child_node_name|
24
24
  child_node = child_node_name.is_a?(Parser::AST::Node) ? child_node_name : child_node.send(child_node_name)
25
25
  end
26
26
  @instance.process_with_other_node child_node do
@@ -81,7 +81,7 @@ module Synvert::Core
81
81
  def fetch(group, name)
82
82
  group = group.to_s
83
83
  name = name.to_s
84
- if exist? group, name
84
+ if rewriters[group] && rewriters[group][name]
85
85
  rewriters[group][name]
86
86
  else
87
87
  raise RewriterNotFound, "Rewriter #{group} #{name} not found"
@@ -96,34 +96,13 @@ module Synvert::Core
96
96
  # @return [Synvert::Core::Rewriter] the registered rewriter.
97
97
  # @raise [Synvert::Core::RewriterNotFound] if the registered rewriter is not found.
98
98
  def call(group, name, sandbox = false)
99
- group = group.to_s
100
- name = name.to_s
101
- if exist? group, name
102
- rewriter = rewriters[group][name]
103
- if sandbox
104
- rewriter.process_with_sandbox
105
- else
106
- rewriter.process
107
- end
108
- rewriter
109
- else
110
- raise RewriterNotFound, "Rewriter #{group}/#{name} not found"
111
- end
112
- end
113
-
114
- # Check if one rewriter exist.
115
- #
116
- # @param group [String] the rewriter group.
117
- # @param name [String] the rewriter name.
118
- # @return [Boolean] true if the rewriter exist.
119
- def exist?(group, name)
120
- group = group.to_s
121
- name = name.to_s
122
- if rewriters[group] && rewriters[group][name]
123
- true
99
+ rewriter = fetch(group, name)
100
+ if sandbox
101
+ rewriter.process_with_sandbox
124
102
  else
125
- false
103
+ rewriter.process
126
104
  end
105
+ rewriter
127
106
  end
128
107
 
129
108
  # Get all available rewriters
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '0.52.0'
5
+ VERSION = '0.54.1'
6
6
  end
7
7
  end
@@ -526,6 +526,12 @@ describe Parser::AST::Node do
526
526
  range = node.child_node_range('caller.receiver')
527
527
  expect(range.to_range).to eq(0...7)
528
528
  end
529
+
530
+ it 'checks caller.message' do
531
+ node = parse('Factory.define :user do |user|; end')
532
+ range = node.child_node_range('caller.message')
533
+ expect(range.to_range).to eq(8...14)
534
+ end
529
535
  end
530
536
 
531
537
  context 'class node' do
@@ -7,7 +7,7 @@ module Synvert::Core
7
7
  subject {
8
8
  source = "user = User.new params[:user]\nuser.save\nrender\n"
9
9
  send_node = Parser::CurrentRuby.parse(source).children[1]
10
- instance = double(current_node: send_node)
10
+ instance = double(current_node: send_node, file_source: source)
11
11
  Rewriter::RemoveAction.new(instance)
12
12
  }
13
13
 
@@ -16,7 +16,7 @@ module Synvert::Core
16
16
  end
17
17
 
18
18
  it 'gets end_pos' do
19
- expect(subject.end_pos).to eq "user = User.new params[:user]\nuser.save".length
19
+ expect(subject.end_pos).to eq "user = User.new params[:user]\nuser.save\n".length
20
20
  end
21
21
 
22
22
  it 'gets rewritten_code' do
@@ -54,9 +54,9 @@ module Synvert::Core
54
54
  it 'parses goto_node' do
55
55
  scope = double
56
56
  block = proc {}
57
- expect(Rewriter::GotoScope).to receive(:new).with(instance, :caller, :receiver, &block).and_return(scope)
57
+ expect(Rewriter::GotoScope).to receive(:new).with(instance, 'caller.receiver', &block).and_return(scope)
58
58
  expect(scope).to receive(:process)
59
- instance.goto_node(:caller, :receiver, &block)
59
+ instance.goto_node('caller.receiver', &block)
60
60
  end
61
61
 
62
62
  it 'parses if_exist_node' do
@@ -24,7 +24,7 @@ module Synvert::Core
24
24
  run = false
25
25
  type_in_scope = nil
26
26
  scope =
27
- Rewriter::GotoScope.new instance, :caller, :receiver do
27
+ Rewriter::GotoScope.new instance, 'caller.receiver' do
28
28
  run = true
29
29
  type_in_scope = node.type
30
30
  end
@@ -249,17 +249,6 @@ module Synvert::Core
249
249
  expect { Rewriter.call 'group', 'rewriter' }.to raise_error(RewriterNotFound)
250
250
  end
251
251
 
252
- context 'exist?' do
253
- it 'returns true if rewriter exists' do
254
- Rewriter.new 'group', 'rewriter'
255
- expect(Rewriter.exist?('group', 'rewriter')).to be_truthy
256
- end
257
-
258
- it 'returns false if rewriter does not exist' do
259
- expect(Rewriter.exist?('group', 'rewriter')).to be_falsey
260
- end
261
- end
262
-
263
252
  context 'available' do
264
253
  it 'lists empty rewriters' do
265
254
  expect(Rewriter.availables).to eq({})
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
11
11
  spec.email = ["flyerhzm@gmail.com"]
12
12
  spec.summary = 'convert ruby code to better syntax.'
13
13
  spec.description = 'convert ruby code to better syntax automatically.'
14
- spec.homepage = "https://github.com/xinminlabs/synvert-core"
14
+ spec.homepage = "https://github.com/xinminlabs/synvert-core-ruby"
15
15
  spec.license = "MIT"
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synvert-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.52.0
4
+ version: 0.54.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-21 00:00:00.000000000 Z
11
+ date: 2021-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -198,8 +198,8 @@ files:
198
198
  - spec/synvert/core/rewriter/scope_spec.rb
199
199
  - spec/synvert/core/rewriter/warning_spec.rb
200
200
  - spec/synvert/core/rewriter_spec.rb
201
- - synvert-core.gemspec
202
- homepage: https://github.com/xinminlabs/synvert-core
201
+ - synvert-core-ruby.gemspec
202
+ homepage: https://github.com/xinminlabs/synvert-core-ruby
203
203
  licenses:
204
204
  - MIT
205
205
  metadata: {}