synvert-core 0.50.0 → 0.52.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: 88e62c155c2171dfeda2631d99c88992f6ffbc9e0f50341d9db79262ef636ad2
4
- data.tar.gz: 4dfec29835aa657065eb5aa35f16a804971674d81215f1b3c860dbe9b3db06fc
3
+ metadata.gz: b0ab6b6fbee0d7b58203ccde9af31179caa3f6cd0b52bdceb8262683daa31e1e
4
+ data.tar.gz: 0670bf038c8e7074893e68eafc4a60e4a27c94d4287dda21a7ab6a03322ce044
5
5
  SHA512:
6
- metadata.gz: a95b38e7f84022599442040b6717e4551b7333cb28cf4337f1d0ab47610ea6ea7cec761490871579a57e25928758e8fd8f3973b56291f3198b5074f5633b0af5
7
- data.tar.gz: e841587f4b654b76e0790f1272f1ff8fa2bdb2c747d1aae9126d51c4c22978ab12b393725e03118b104f6d573bfb7f63bdd2fa9eab36032a56db75958f4b7ac1
6
+ metadata.gz: ceae8c9049ae4488f4831594ba2527c970ba88a8479d0eb1477e832597de59f7ca2e9e45389eab4bfa609f8eb2de9498d54340163323cc1329278ad90de1db70
7
+ data.tar.gz: 5a74ad849852d919bc274726201a03f00aec7741ddd8a8a3abd4a38e3f1584a358a7ca65c2238d885686274d1cfe9157dd4b5b74ac971bb05efd0af411366ae0
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.52.1 (2021-08-21)
4
+
5
+ * Fix nested child in Node#child_node_range
6
+
7
+ ## 0.52.0 (2021-08-21)
8
+
9
+ * ``Node#child_node_range`` supports nested child
10
+ * Require `fileutils`
11
+ * Rename `Node#indent` to `Node#column`
12
+
13
+ ## 0.51.0 (2021-08-12)
14
+
15
+ * Add `wrap` action
16
+ * Add new dsl `redo_until_no_change`
17
+
3
18
  ## 0.50.0 (2021-08-11)
4
19
 
5
20
  * Support `:module` in `body`
@@ -322,10 +322,10 @@ module Parser::AST
322
322
  loc.expression&.source
323
323
  end
324
324
 
325
- # Get the indent of current node.
325
+ # Get the column of current node.
326
326
  #
327
- # @return [Integer] indent.
328
- def indent
327
+ # @return [Integer] column.
328
+ def column
329
329
  loc.expression.column
330
330
  end
331
331
 
@@ -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,8 +369,12 @@ 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
- if respond_to?(child_name)
373
- child_node = send(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
+
374
378
  return nil if child_node.nil?
375
379
 
376
380
  if child_node.is_a?(Parser::AST::Node)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'fileutils'
4
+
3
5
  module Synvert::Core
4
6
  # Rewriter is the top level namespace in a snippet.
5
7
  #
@@ -18,14 +20,15 @@ module Synvert::Core
18
20
  class Rewriter
19
21
  autoload :Action, 'synvert/core/rewriter/action'
20
22
  autoload :AppendAction, 'synvert/core/rewriter/action/append_action'
21
- autoload :PrependAction, 'synvert/core/rewriter/action/prepend_action'
23
+ autoload :DeleteAction, 'synvert/core/rewriter/action/delete_action'
22
24
  autoload :InsertAction, 'synvert/core/rewriter/action/insert_action'
23
25
  autoload :InsertAfterAction, 'synvert/core/rewriter/action/insert_after_action'
24
- autoload :ReplaceWithAction, 'synvert/core/rewriter/action/replace_with_action'
26
+ autoload :RemoveAction, 'synvert/core/rewriter/action/remove_action'
27
+ autoload :PrependAction, 'synvert/core/rewriter/action/prepend_action'
25
28
  autoload :ReplaceAction, 'synvert/core/rewriter/action/replace_action'
26
29
  autoload :ReplaceErbStmtWithExprAction, 'synvert/core/rewriter/action/replace_erb_stmt_with_expr_action'
27
- autoload :RemoveAction, 'synvert/core/rewriter/action/remove_action'
28
- autoload :DeleteAction, 'synvert/core/rewriter/action/delete_action'
30
+ autoload :ReplaceWithAction, 'synvert/core/rewriter/action/replace_with_action'
31
+ autoload :WrapAction, 'synvert/core/rewriter/action/wrap_action'
29
32
 
30
33
  autoload :Warning, 'synvert/core/rewriter/warning'
31
34
 
@@ -175,13 +178,18 @@ module Synvert::Core
175
178
  @sub_snippets = []
176
179
  @warnings = []
177
180
  @affected_files = Set.new
181
+ @redo_until_no_change = false
178
182
  self.class.register(@group, @name, self)
179
183
  end
180
184
 
181
185
  # Process the rewriter.
182
186
  # It will call the block.
183
187
  def process
188
+ @affected_files = Set.new
184
189
  instance_eval(&@block)
190
+ if !@affected_files.empty? && @redo_until_no_change
191
+ process
192
+ end
185
193
  end
186
194
 
187
195
  # Process rewriter with sandbox mode.
@@ -314,5 +322,10 @@ module Synvert::Core
314
322
  @todo
315
323
  end
316
324
  end
325
+
326
+ # Rerun the snippet until no change.
327
+ def redo_until_no_change
328
+ @redo_until_no_change = true
329
+ end
317
330
  end
318
331
  end
@@ -12,7 +12,7 @@ module Synvert::Core
12
12
  if :begin == @node.type
13
13
  @node.loc.expression.end_pos
14
14
  else
15
- @node.loc.expression.end_pos - @node.indent - END_LENGTH
15
+ @node.loc.expression.end_pos - @node.column - END_LENGTH
16
16
  end
17
17
  end
18
18
 
@@ -31,9 +31,9 @@ module Synvert::Core
31
31
  # @return [String] n times whitesphace
32
32
  def indent(node)
33
33
  if %i[block class].include? node.type
34
- ' ' * (node.indent + DEFAULT_INDENT)
34
+ ' ' * (node.column + DEFAULT_INDENT)
35
35
  else
36
- ' ' * node.indent
36
+ ' ' * node.column
37
37
  end
38
38
  end
39
39
  end
@@ -4,10 +4,8 @@ module Synvert::Core
4
4
  # AddAction to add code to the node.
5
5
  class Rewriter::InsertAction < Rewriter::Action
6
6
  def initialize(instance, code, at:)
7
- @instance = instance
8
- @code = code
7
+ super(instance, code)
9
8
  @at = at
10
- @node = @instance.current_node
11
9
  end
12
10
 
13
11
  # Begin position to insert code.
@@ -24,7 +24,7 @@ module Synvert::Core
24
24
  # @param node [Parser::AST::Node]
25
25
  # @return [String] n times whitesphace
26
26
  def indent(node)
27
- ' ' * node.indent
27
+ ' ' * node.column
28
28
  end
29
29
  end
30
30
  end
@@ -38,9 +38,9 @@ module Synvert::Core
38
38
  # @return [String] n times whitesphace
39
39
  def indent(node)
40
40
  if %i[block class].include? node.type
41
- ' ' * (node.indent + DEFAULT_INDENT)
41
+ ' ' * (node.column + DEFAULT_INDENT)
42
42
  else
43
- ' ' * node.indent
43
+ ' ' * node.column
44
44
  end
45
45
  end
46
46
  end
@@ -4,10 +4,8 @@ module Synvert::Core
4
4
  # ReplaceAction to replace child node with code.
5
5
  class Rewriter::ReplaceAction < Rewriter::Action
6
6
  def initialize(instance, *selectors, with:)
7
- @instance = instance
7
+ super(instance, with)
8
8
  @selectors = selectors
9
- @code = with
10
- @node = @instance.current_node
11
9
  end
12
10
 
13
11
  # Begin position of code to replace.
@@ -24,7 +24,7 @@ module Synvert::Core
24
24
  if rewritten_source.include?("\n")
25
25
  new_code = []
26
26
  rewritten_source.split("\n").each_with_index do |line, index|
27
- new_code << (index == 0 ? line : indent(@node) + line)
27
+ new_code << (index == 0 ? line : indent + line)
28
28
  end
29
29
  new_code.join("\n")
30
30
  else
@@ -36,10 +36,9 @@ module Synvert::Core
36
36
 
37
37
  # Indent of the node
38
38
  #
39
- # @param node [Parser::AST::Node]
40
39
  # @return [String] n times whitesphace
41
- def indent(node)
42
- ' ' * node.indent
40
+ def indent
41
+ ' ' * @node.column
43
42
  end
44
43
  end
45
44
  end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synvert::Core
4
+ # WrapAction to warp node within a block, class or module.
5
+ #
6
+ # Note: if WrapAction is conflicted with another action (begin_pos and end_pos are overlapped),
7
+ # we have to put those 2 actions into 2 within_file scopes.
8
+ class Rewriter::WrapAction < Rewriter::Action
9
+ def initialize(instance, with:, indent: nil)
10
+ super(instance, with)
11
+ @indent = indent || @node.column
12
+ end
13
+
14
+ # Begin position of code to wrap.
15
+ #
16
+ # @return [Integer] begin position.
17
+ def begin_pos
18
+ @node.loc.expression.begin_pos
19
+ end
20
+
21
+ # End position of code to wrap.
22
+ #
23
+ # @return [Integer] end position.
24
+ def end_pos
25
+ @node.loc.expression.end_pos
26
+ end
27
+
28
+ # The rewritten source code.
29
+ #
30
+ # @return [String] rewritten code.
31
+ def rewritten_code
32
+ "#{@code}\n#{' ' * @indent}" +
33
+ @node.to_source.split("\n").map { |line| " #{line}" }.join("\n") +
34
+ "\n#{' ' * @indent}end"
35
+ end
36
+ end
37
+ end
@@ -279,6 +279,15 @@ module Synvert::Core
279
279
  @actions << Rewriter::DeleteAction.new(self, *selectors)
280
280
  end
281
281
 
282
+ # Parse wrap with dsl, it creates a [Synvert::Core::Rewriter::WrapAction] to
283
+ # wrap current node with code.
284
+ #
285
+ # @param with [String] code need to be wrapped with.
286
+ # @param indent [Integer] number of whitespaces.
287
+ def wrap(with:, indent: nil)
288
+ @actions << Rewriter::WrapAction.new(self, with: with, indent: indent)
289
+ end
290
+
282
291
  # Parse warn dsl, it creates a [Synvert::Core::Rewriter::Warning] to save warning message.
283
292
  #
284
293
  # @param message [String] warning message.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
- # WithinScope finds out nodes which match rules, then change its scope to matching node.
4
+ # WithinScope finds out nodes which match rules, then changes its scope to matching node.
5
5
  class Rewriter::WithinScope < Rewriter::Scope
6
6
  # Initialize a scope
7
7
  #
@@ -16,8 +16,9 @@ module Synvert::Core
16
16
  @block = block
17
17
  end
18
18
 
19
- # Find out the matching nodes. It checks the current node and iterates all child nodes,
20
- # then run the block code with each matching node.
19
+ # Find out the matching nodes.
20
+ # It checks the current node and iterates all child nodes,
21
+ # then run the block code on each matching node.
21
22
  def process
22
23
  current_node = @instance.current_node
23
24
  return unless current_node
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '0.50.0'
5
+ VERSION = '0.52.1'
6
6
  end
7
7
  end
@@ -359,10 +359,10 @@ describe Parser::AST::Node do
359
359
  end
360
360
  end
361
361
 
362
- describe '#indent' do
362
+ describe '#column' do
363
363
  it 'gets column number' do
364
364
  node = parse(' FactoryGirl.create :post')
365
- expect(node.indent).to eq 2
365
+ expect(node.column).to eq 2
366
366
  end
367
367
  end
368
368
 
@@ -520,6 +520,18 @@ describe Parser::AST::Node do
520
520
  range = node.child_node_range(:pipes)
521
521
  expect(range.to_range).to eq(24...30)
522
522
  end
523
+
524
+ it 'checks caller.receiver' do
525
+ node = parse('Factory.define :user do |user|; end')
526
+ range = node.child_node_range('caller.receiver')
527
+ expect(range.to_range).to eq(0...7)
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
523
535
  end
524
536
 
525
537
  context 'class node' do
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module Synvert::Core
6
+ describe Rewriter::WrapAction do
7
+ subject {
8
+ source = "class Bar\nend"
9
+ node = Parser::CurrentRuby.parse(source)
10
+ instance = double(current_node: node)
11
+ Rewriter::WrapAction.new(instance, with: 'module Foo')
12
+ }
13
+
14
+ it 'gets begin_pos' do
15
+ expect(subject.begin_pos).to eq 0
16
+ end
17
+
18
+ it 'gets end_pos' do
19
+ expect(subject.end_pos).to eq "class Bar\nend".length
20
+ end
21
+
22
+ it 'gets rewritten_code' do
23
+ expect(subject.rewritten_code).to eq <<~EOS.strip
24
+ module Foo
25
+ class Bar
26
+ end
27
+ end
28
+ EOS
29
+ end
30
+ end
31
+ end
@@ -140,6 +140,11 @@ module Synvert::Core
140
140
  instance.delete :dot, :message
141
141
  end
142
142
 
143
+ it 'parses wrap with' do
144
+ expect(Rewriter::WrapAction).to receive(:new).with(instance, with: 'module Foo', indent: nil)
145
+ instance.wrap with: 'module Foo'
146
+ end
147
+
143
148
  it 'parses warn' do
144
149
  expect(Rewriter::Warning).to receive(:new).with(instance, 'foobar')
145
150
  instance.warn 'foobar'
@@ -214,6 +214,15 @@ module Synvert::Core
214
214
  expect(rewriter.todo).to eq "this rewriter doesn't do blah blah blah"
215
215
  end
216
216
 
217
+ it 'parses redo_until_no_change' do
218
+ rewriter =
219
+ Rewriter.new 'group', 'name' do
220
+ redo_until_no_change
221
+ end
222
+ rewriter.process
223
+ expect(rewriter.instance_variable_get('@redo_until_no_change')).to be_truthy
224
+ end
225
+
217
226
  describe 'class methods' do
218
227
  before :each do
219
228
  Rewriter.clear
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.50.0
4
+ version: 0.52.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-11 00:00:00.000000000 Z
11
+ date: 2021-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -155,6 +155,7 @@ files:
155
155
  - lib/synvert/core/rewriter/action/replace_action.rb
156
156
  - lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb
157
157
  - lib/synvert/core/rewriter/action/replace_with_action.rb
158
+ - lib/synvert/core/rewriter/action/wrap_action.rb
158
159
  - lib/synvert/core/rewriter/any_value.rb
159
160
  - lib/synvert/core/rewriter/condition.rb
160
161
  - lib/synvert/core/rewriter/condition/if_exist_condition.rb
@@ -182,6 +183,7 @@ files:
182
183
  - spec/synvert/core/rewriter/action/replace_action_spec.rb
183
184
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb
184
185
  - spec/synvert/core/rewriter/action/replace_with_action_spec.rb
186
+ - spec/synvert/core/rewriter/action/wrap_action_spec.rb
185
187
  - spec/synvert/core/rewriter/action_spec.rb
186
188
  - spec/synvert/core/rewriter/condition/if_exist_condition_spec.rb
187
189
  - spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb
@@ -192,7 +194,7 @@ files:
192
194
  - spec/synvert/core/rewriter/instance_spec.rb
193
195
  - spec/synvert/core/rewriter/ruby_version_spec.rb
194
196
  - spec/synvert/core/rewriter/scope/goto_scope_spec.rb
195
- - spec/synvert/core/rewriter/scope/within_scope.rb
197
+ - spec/synvert/core/rewriter/scope/within_scope_spec.rb
196
198
  - spec/synvert/core/rewriter/scope_spec.rb
197
199
  - spec/synvert/core/rewriter/warning_spec.rb
198
200
  - spec/synvert/core/rewriter_spec.rb
@@ -216,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
216
218
  - !ruby/object:Gem::Version
217
219
  version: '0'
218
220
  requirements: []
219
- rubygems_version: 3.1.6
221
+ rubygems_version: 3.2.22
220
222
  signing_key:
221
223
  specification_version: 4
222
224
  summary: convert ruby code to better syntax.
@@ -234,6 +236,7 @@ test_files:
234
236
  - spec/synvert/core/rewriter/action/replace_action_spec.rb
235
237
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb
236
238
  - spec/synvert/core/rewriter/action/replace_with_action_spec.rb
239
+ - spec/synvert/core/rewriter/action/wrap_action_spec.rb
237
240
  - spec/synvert/core/rewriter/action_spec.rb
238
241
  - spec/synvert/core/rewriter/condition/if_exist_condition_spec.rb
239
242
  - spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb
@@ -244,7 +247,7 @@ test_files:
244
247
  - spec/synvert/core/rewriter/instance_spec.rb
245
248
  - spec/synvert/core/rewriter/ruby_version_spec.rb
246
249
  - spec/synvert/core/rewriter/scope/goto_scope_spec.rb
247
- - spec/synvert/core/rewriter/scope/within_scope.rb
250
+ - spec/synvert/core/rewriter/scope/within_scope_spec.rb
248
251
  - spec/synvert/core/rewriter/scope_spec.rb
249
252
  - spec/synvert/core/rewriter/warning_spec.rb
250
253
  - spec/synvert/core/rewriter_spec.rb