synvert-core 0.57.0 → 0.58.3

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: '01935a8e5222f3058d6bcca0057cbe684ce0a43dabeaeac97dac0aa17c230b79'
4
- data.tar.gz: 427851e9745c4c960b1f437c397e9332ebf6a8df4126c58652927c9810db7d05
3
+ metadata.gz: 1c6266f727e24e5cd93cc1db656d84dc177dc0fceb0ab435a14164216d6dec80
4
+ data.tar.gz: 53e06769f132ac67ee113af6fecdb327184adc034b00aa58c0af8eab376ef45f
5
5
  SHA512:
6
- metadata.gz: 50a73df1cb5034afeb269776f5e4bf76873b236e490fa54e6bffd91dabfb2726260b99bca95230022314be890454645b8c032c4006c22271a7a460c50b77e3dc
7
- data.tar.gz: c7ca6e209b229a3951b6846173268d254034e3ff9480e47add2e7649326ab004d806f09ec784fdf86154c8414c7e9e947e6ea72e6fbc5c2d65018f1909928e18
6
+ metadata.gz: fb0db8ed1e6636145f25ec8ca3cc3653ce415e7381c8e5d2126e7da7174782c57a2a4d60a3693794ae93ac02bd178b40f55971ffbf721e0d86b7c73fd17b930a
7
+ data.tar.gz: ee6222b098f64dcc809d0d54ed9c1bad84f54816e05602b601c7ae8b0211f26fb41c05e46fe9728dc362536971021cc2a6e232a5e9f8ac34eff3f6ef55e94cb3
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.58.3 (2021-11-16)
4
+
5
+ * Return block value by `next`
6
+ * Add `Node#filename` method
7
+
8
+ ## 0.58.2 (2021-10-23)
9
+
10
+ * Do not break the whole `recursive_children`
11
+
12
+ ## 0.58.0 (2021-10-23)
13
+
14
+ * Support `left_value` and `right_value` for `and` and `or` node
15
+ * Rewrite `within_node` and `within_direct_node`, `WithinScope` accepts `recursive` and `direct` options
16
+
3
17
  ## 0.57.0 (2021-10-02)
4
18
 
5
19
  * Compare ruby version in `.ruby-version` or `.rvmrc`
@@ -215,7 +215,7 @@ module Parser::AST
215
215
  # @return [Parser::AST::Node] variable nodes.
216
216
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
217
217
  def left_value
218
- if %i[masgn lvasgn ivasgn cvasgn].include? type
218
+ if %i[masgn lvasgn ivasgn cvasgn and or].include? type
219
219
  children[0]
220
220
  elsif :or_asgn == type
221
221
  children[0].children[0]
@@ -229,7 +229,7 @@ module Parser::AST
229
229
  # @return [Array<Parser::AST::Node>] variable nodes.
230
230
  # @raise [Synvert::Core::MethodNotSupported] if calls on other node.
231
231
  def right_value
232
- if %i[masgn lvasgn ivasgn cvasgn or_asgn].include? type
232
+ if %i[masgn lvasgn ivasgn cvasgn or_asgn and or].include? type
233
233
  children[1]
234
234
  else
235
235
  raise Synvert::Core::MethodNotSupported, "right_value is not handled for #{debug_info}"
@@ -315,6 +315,13 @@ module Parser::AST
315
315
  ].join("\n")
316
316
  end
317
317
 
318
+ # Get the file name of the current node.
319
+ #
320
+ # @return [String] file name.
321
+ def filename
322
+ loc.expression&.source_buffer.name
323
+ end
324
+
318
325
  # Get the source code of current node.
319
326
  #
320
327
  # @return [String] source code.
@@ -432,8 +439,8 @@ module Parser::AST
432
439
  def recursive_children(&block)
433
440
  children.each do |child|
434
441
  if child.is_a?(Parser::AST::Node)
435
- yield child
436
- child.recursive_children(&block)
442
+ stop = yield child
443
+ child.recursive_children(&block) unless stop == :stop
437
444
  end
438
445
  end
439
446
  end
@@ -55,7 +55,7 @@ module Synvert::Core
55
55
 
56
56
  def squeeze_spaces
57
57
  if file_source[@begin_pos - 1] == ' ' && file_source[@end_pos] == ' '
58
- @begin_pos = @begin_pos - 1
58
+ @begin_pos -= 1
59
59
  end
60
60
  end
61
61
 
@@ -67,19 +67,19 @@ module Synvert::Core
67
67
  after_line_is_blank = lines[end_line] == ''
68
68
 
69
69
  if lines.length > 1 && before_line_is_blank && after_line_is_blank
70
- @end_pos = @end_pos + "\n".length
70
+ @end_pos += "\n".length
71
71
  end
72
72
  end
73
73
 
74
74
  def remove_comma
75
75
  if ',' == file_source[@begin_pos - 1]
76
- @begin_pos = @begin_pos - 1
76
+ @begin_pos -= 1
77
77
  elsif ', ' == file_source[@begin_pos - 2, 2]
78
- @begin_pos = @begin_pos - 2
78
+ @begin_pos -= 2
79
79
  elsif ', ' == file_source[@end_pos, 2]
80
- @end_pos = @end_pos + 2
80
+ @end_pos += 2
81
81
  elsif ',' == file_source[@end_pos]
82
- @end_pos = @end_pos + 1
82
+ @end_pos += 1
83
83
  end
84
84
  end
85
85
 
@@ -161,9 +161,11 @@ module Synvert::Core
161
161
  # then continue operating on each matching ast node.
162
162
  #
163
163
  # @param rules [Hash] rules to find mathing ast nodes.
164
+ # @param options [Hash] optional, set if recursive or not.
164
165
  # @param block [Block] block code to continue operating on the matching nodes.
165
- def within_node(rules, &block)
166
- Rewriter::WithinScope.new(self, rules, { recursive: true }, &block).process
166
+ def within_node(rules, options = nil, &block)
167
+ options ||= { recursive: true }
168
+ Rewriter::WithinScope.new(self, rules, options, &block).process
167
169
  end
168
170
 
169
171
  alias with_node within_node
@@ -174,7 +176,7 @@ module Synvert::Core
174
176
  # @param rules [Hash] rules to find mathing ast nodes.
175
177
  # @param block [Block] block code to continue operating on the matching nodes.
176
178
  def within_direct_node(rules, &block)
177
- Rewriter::WithinScope.new(self, rules, { recursive: false }, &block).process
179
+ Rewriter::WithinScope.new(self, rules, { direct: true }, &block).process
178
180
  end
179
181
 
180
182
  alias with_direct_node within_direct_node
@@ -21,7 +21,7 @@ module Synvert::Core
21
21
  elsif File.exist?(File.join(Configuration.path, '.rvmrc'))
22
22
  versionFile = '.rvmrc'
23
23
  end
24
- return true if !versionFile
24
+ return true unless versionFile
25
25
 
26
26
  version = File.read(File.join(Configuration.path, versionFile))
27
27
  Gem::Version.new(version) >= Gem::Version.new(@version)
@@ -9,7 +9,7 @@ module Synvert::Core
9
9
  # @param rules [Hash]
10
10
  # @param options [Hash]
11
11
  # @param block [Block]
12
- def initialize(instance, rules, options = { recursive: true }, &block)
12
+ def initialize(instance, rules, options = {}, &block)
13
13
  @instance = instance
14
14
  @rules = rules
15
15
  @options = options
@@ -23,7 +23,14 @@ module Synvert::Core
23
23
  current_node = @instance.current_node
24
24
  return unless current_node
25
25
 
26
- matching_nodes = find_matching_nodes(current_node)
26
+ matching_nodes =
27
+ if @options[:direct]
28
+ find_direct_matching_nodes(current_node)
29
+ elsif @options[:recursive]
30
+ find_recursive_matching_nodes(current_node)
31
+ else
32
+ find_matching_nodes(current_node)
33
+ end
27
34
  @instance.process_with_node current_node do
28
35
  matching_nodes.each do |matching_node|
29
36
  @instance.process_with_node matching_node do
@@ -35,36 +42,73 @@ module Synvert::Core
35
42
 
36
43
  private
37
44
 
38
- def find_matching_nodes(current_node)
45
+ # Find the matching nodes only in current or direct children.
46
+ def find_direct_matching_nodes(current_node)
39
47
  matching_nodes = []
40
- if @options[:recursive]
41
- if current_node.is_a?(Parser::AST::Node)
42
- matching_nodes << current_node if current_node.match? @rules
43
- current_node.recursive_children do |child_node|
44
- matching_nodes << child_node if child_node.match? @rules
45
- end
46
- else
47
- current_node.each do |node|
48
- matching_nodes << node if node.match? @rules
49
- node.recursive_children do |child_node|
50
- matching_nodes << child_node if child_node.match? @rules
51
- end
52
- end
53
- end
54
- elsif current_node.is_a?(Parser::AST::Node)
48
+ if current_node.is_a?(Parser::AST::Node)
55
49
  if current_node.type == :begin
56
50
  current_node.children.each do |child_node|
57
- matching_nodes << child_node if child_node.match? @rules
51
+ matching_nodes << child_node if child_node.match?(@rules)
58
52
  end
59
- elsif current_node.match? @rules
53
+ elsif current_node.match?(@rules)
60
54
  matching_nodes << current_node
61
55
  end
62
56
  else
63
57
  current_node.each do |child_node|
64
- matching_nodes << child_node if child_node.match? @rules
58
+ matching_nodes << child_node if child_node.match?(@rules)
59
+ end
60
+ end
61
+ matching_nodes
62
+ end
63
+
64
+ # Find matching nodes in all recursive children.
65
+ def find_recursive_matching_nodes(current_node)
66
+ matching_nodes = []
67
+ if current_node.is_a?(Parser::AST::Node)
68
+ matching_nodes << current_node if current_node.match?(@rules)
69
+ current_node.recursive_children do |child_node|
70
+ matching_nodes << child_node if child_node.match?(@rules)
71
+ end
72
+ else
73
+ current_node.each do |node|
74
+ matching_nodes << node if node.match?(@rules)
75
+ node.recursive_children do |child_node|
76
+ matching_nodes << child_node if child_node.match?(@rules)
77
+ end
78
+ end
79
+ end
80
+ matching_nodes
81
+ end
82
+
83
+ # Find matching nodes in recursive children but do not continue on matching nodes.
84
+ def find_matching_nodes(current_node)
85
+ matching_nodes = []
86
+ if current_node.is_a?(Parser::AST::Node)
87
+ if current_node.match?(@rules)
88
+ matching_nodes << current_node
89
+ return matching_nodes
90
+ end
91
+ current_node.recursive_children do |child_node|
92
+ if child_node.match?(@rules)
93
+ matching_nodes << child_node
94
+ next :stop
95
+ end
96
+ end
97
+ else
98
+ current_node.each do |node|
99
+ if node.match?(@rules)
100
+ matching_nodes << node
101
+ next
102
+ end
103
+ node.recursive_children do |child_node|
104
+ if child_node.match?(@rules)
105
+ matching_nodes << child_node
106
+ next :stop
107
+ end
108
+ end
65
109
  end
66
110
  end
67
111
  matching_nodes
68
112
  end
69
113
  end
70
- end
114
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '0.57.0'
5
+ VERSION = '0.58.3'
6
6
  end
7
7
  end
@@ -291,6 +291,16 @@ describe Parser::AST::Node do
291
291
  node = parse('a ||= 1')
292
292
  expect(node.left_value).to eq :a
293
293
  end
294
+
295
+ it 'gets for and' do
296
+ node = parse('foo && bar')
297
+ expect(node.left_value).to eq parse('foo')
298
+ end
299
+
300
+ it 'gets for or' do
301
+ node = parse('foo || bar')
302
+ expect(node.left_value).to eq parse('foo')
303
+ end
294
304
  end
295
305
 
296
306
  describe '#right_value' do
@@ -323,6 +333,16 @@ describe Parser::AST::Node do
323
333
  node = parse('a ||= 1')
324
334
  expect(node.right_value).to eq parse('1')
325
335
  end
336
+
337
+ it 'gets for and' do
338
+ node = parse('foo && bar')
339
+ expect(node.right_value).to eq parse('bar')
340
+ end
341
+
342
+ it 'gets for or' do
343
+ node = parse('foo || bar')
344
+ expect(node.right_value).to eq parse('bar')
345
+ end
326
346
  end
327
347
 
328
348
  describe '#to_value' do
@@ -376,6 +396,14 @@ describe Parser::AST::Node do
376
396
  end
377
397
  end
378
398
 
399
+ describe '#filename' do
400
+ it 'gets file name' do
401
+ source = 'foobar'
402
+ node = parse(source)
403
+ expect(node.filename).to eq '(string)'
404
+ end
405
+ end
406
+
379
407
  describe '#to_source' do
380
408
  it 'gets for node' do
381
409
  source = 'params[:user][:email]'
@@ -31,13 +31,23 @@ module Synvert::Core
31
31
  instance.with_node(type: 'send', message: 'create', &block)
32
32
  end
33
33
 
34
- it 'parses within_direct_node' do
34
+ it 'parses within_node with recursive false' do
35
35
  scope = double
36
36
  block = proc {}
37
37
  expect(Rewriter::WithinScope).to receive(:new)
38
38
  .with(instance, { type: 'send', message: 'create' }, { recursive: false }, &block)
39
39
  .and_return(scope)
40
40
  expect(scope).to receive(:process)
41
+ instance.within_node({ type: 'send', message: 'create' }, { recursive: false }, &block)
42
+ end
43
+
44
+ it 'parses within_direct_node' do
45
+ scope = double
46
+ block = proc {}
47
+ expect(Rewriter::WithinScope).to receive(:new)
48
+ .with(instance, { type: 'send', message: 'create' }, { direct: true }, &block)
49
+ .and_return(scope)
50
+ expect(scope).to receive(:process)
41
51
  instance.within_direct_node(type: 'send', message: 'create', &block)
42
52
  end
43
53
 
@@ -45,7 +55,7 @@ module Synvert::Core
45
55
  scope = double
46
56
  block = proc {}
47
57
  expect(Rewriter::WithinScope).to receive(:new)
48
- .with(instance, { type: 'send', message: 'create' }, { recursive: false }, &block)
58
+ .with(instance, { type: 'send', message: 'create' }, { direct: true }, &block)
49
59
  .and_return(scope)
50
60
  expect(scope).to receive(:process)
51
61
  instance.with_direct_node(type: 'send', message: 'create', &block)
@@ -51,6 +51,33 @@ module Synvert::Core
51
51
  expect(type_in_scope).to eq :send
52
52
  expect(instance.current_node.type).to eq :block
53
53
  end
54
+
55
+ it 'matches multiple block nodes' do
56
+ block_nodes = []
57
+ scope = Rewriter::WithinScope.new(instance, { type: 'block' }, { recursive: true }) do
58
+ block_nodes << node
59
+ end
60
+ scope.process
61
+ expect(block_nodes.size).to eq 2
62
+ end
63
+
64
+ it 'matches only one block node if no recursive' do
65
+ block_nodes = []
66
+ scope = Rewriter::WithinScope.new(instance, { type: 'block' } , { recursive: false }) do
67
+ block_nodes << node
68
+ end
69
+ scope.process
70
+ expect(block_nodes.size).to eq 1
71
+ end
72
+
73
+ it 'matches only one direct node' do
74
+ block_nodes = []
75
+ scope = Rewriter::WithinScope.new(instance, { type: 'block' } , { direct: true }) do
76
+ block_nodes << node
77
+ end
78
+ scope.process
79
+ expect(block_nodes.size).to eq 1
80
+ end
54
81
  end
55
82
  end
56
83
  end
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.57.0
4
+ version: 0.58.3
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-10-02 00:00:00.000000000 Z
11
+ date: 2021-11-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport