synvert-core 0.59.0 → 0.61.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '093f0af943a24314d55691d222fb181ab0526c4e1e8c557a38824609773a17a4'
4
- data.tar.gz: 96b272edcb8ed63b346bfc30c76210aee11e7cab618045b0fed27107edbe5bfd
3
+ metadata.gz: 7f5de89db1e920d9a0f1f55543f5e68121daaadec9c28558438561a303e1ef52
4
+ data.tar.gz: b7b491df1978ab9a628b4230753332044b1fe6d4fd53426b80d4047c3da9fbf7
5
5
  SHA512:
6
- metadata.gz: 6cd336f74ddcbd5342811670824cf0f821c693a3b331f82dfb1f756f7deed41ae2f6d32cbba208a138f96a240476182c674adb2a5ab4940acda70e7737024f09
7
- data.tar.gz: 6e9f09306f30fbde3dc552df33d09e2bc1e0651dcda418640cbcdc648704e427e670b4d910ffdd7039f48262c7d4cd62197e18dd111f512d1591c31643746580
6
+ metadata.gz: 0b5957ba9a2812b7efeb224d0aa8776cdde9c664f35a35b1247e2445fe294c2c803c83eb4d6b4c7be4bde98ea0a196982ac7ae8974fc3c90874bf396b15d7d1c
7
+ data.tar.gz: e8d838167caff111711f4fc61cb431b52eb53817a268f65c920f915e31c6a0fb785f1bbaa43f43210657b2c93db7d33656f4c9338e887d5f0afdc1a004eb7167
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.61.2 (2021-12-21)
4
+
5
+ * Restrict activesupport version to ~> 6
6
+
7
+ ## 0.61.1 (2021-12-12)
8
+
9
+ * Fix prepend action for def and defs nodes
10
+ * Fix append action for def and defs nodes
11
+
12
+ ## 0.61.0 (2021-12-10)
13
+
14
+ * Add `Node#child_node_by_name`
15
+ * Fix `Node#child_node_range` for array
16
+
17
+ ## 0.60.0 (2021-12-02)
18
+
19
+ * Add `to_string` to `sym` node
20
+
3
21
  ## 0.59.0 (2021-11-17)
4
22
 
5
23
  * Use option `stop_when_match` instead of `recursive`
@@ -343,6 +343,43 @@ module Parser::AST
343
343
  loc.expression.line
344
344
  end
345
345
 
346
+ # Get child node by child name.
347
+ #
348
+ # @param [String] name of child node.
349
+ # @return [Parser::AST::Node] the child node.
350
+ def child_node_by_name(child_name)
351
+ direct_child_name, nested_child_name = child_name.to_s.split('.', 2)
352
+ if respond_to?(direct_child_name)
353
+ child_node = send(direct_child_name)
354
+
355
+ if nested_child_name
356
+ if child_node.is_a?(Array)
357
+ child_direct_child_name, child_nested_child_name = nested_child_name.split('.', 2)
358
+ child_direct_child_node = child_direct_child_name =~ /\A\d+\z/ ? child_node[child_direct_child_name.to_i - 1] : child_node.send(child_direct_child_name)
359
+ return child_direct_child_node.child_node_by_name(child_nested_child_name) if child_nested_child_name
360
+ return child_direct_child_node if child_direct_child_node
361
+
362
+ raise Synvert::Core::MethodNotSupported,
363
+ "child_node_by_name is not handled for #{debug_info}, child_name: #{child_name}"
364
+ end
365
+
366
+ return child_node.child_node_by_name(nested_child_name)
367
+ end
368
+
369
+ return nil if child_node.nil?
370
+
371
+ return child_node if child_node.is_a?(Parser::AST::Node)
372
+
373
+ # arguments
374
+ return nil if child_node.empty?
375
+
376
+ return child_node
377
+ end
378
+
379
+ raise Synvert::Core::MethodNotSupported,
380
+ "child_node_by_name is not handled for #{debug_info}, child_name: #{child_name}"
381
+ end
382
+
346
383
  # Get the source range of child node.
347
384
  #
348
385
  # @param [String] name of child node.
@@ -382,10 +419,10 @@ module Parser::AST
382
419
 
383
420
  if nested_child_name
384
421
  if child_node.is_a?(Array)
385
- child_direct_child_name, *child_nested_child_name = nested_child_name
386
- child_direct_child_node = child_direct_child_name =~ /\A\d+\z/ ? child_node[child_direct_child_name] : child_node.send(child_direct_child_name)
387
- if child_nested_child_name.length > 0
388
- return child_direct_child_node.child_node_range(child_nested_child_name.join('.'))
422
+ child_direct_child_name, child_nested_child_name = nested_child_name.split('.', 2)
423
+ child_direct_child_node = child_direct_child_name =~ /\A\d+\z/ ? child_node[child_direct_child_name.to_i - 1] : child_node.send(child_direct_child_name)
424
+ if child_nested_child_name
425
+ return child_direct_child_node.child_node_range(child_nested_child_name)
389
426
  elsif child_direct_child_node
390
427
  return (
391
428
  Parser::Source::Range.new(
@@ -486,8 +523,8 @@ module Parser::AST
486
523
  def rewritten_source(code)
487
524
  code.gsub(/{{(.*?)}}/m) do
488
525
  old_code = Regexp.last_match(1)
489
- if respond_to? old_code.split(/\.|\[/).first
490
- evaluated = instance_eval old_code
526
+ if respond_to?(old_code.split('.').first)
527
+ evaluated = child_node_by_name(old_code)
491
528
  case evaluated
492
529
  when Parser::AST::Node
493
530
  if evaluated.type == :args
@@ -552,6 +589,13 @@ module Parser::AST
552
589
  ":#{to_value}"
553
590
  end
554
591
 
592
+ # convert symbol to string
593
+ def to_string
594
+ return to_source unless type == :sym
595
+
596
+ "#{to_value}"
597
+ end
598
+
555
599
  # convert lambda {} to -> {}
556
600
  def to_lambda_literal
557
601
  if type == :block && caller.type == :send && caller.receiver.nil? && caller.message == :lambda
@@ -17,7 +17,7 @@ module Synvert::Core
17
17
  # @param node [Parser::AST::Node]
18
18
  # @return [String] n times whitesphace
19
19
  def indent(node)
20
- if %i[block class].include? node.type
20
+ if %i[block class def defs].include? node.type
21
21
  ' ' * (node.column + DEFAULT_INDENT)
22
22
  else
23
23
  ' ' * node.column
@@ -16,6 +16,10 @@ module Synvert::Core
16
16
  end
17
17
  when :class
18
18
  @node.children[1] ? @node.children[1].loc.expression.end_pos : @node.children[0].loc.expression.end_pos
19
+ when :def
20
+ @node.children[1].empty? ? @node.loc.name.end_pos : @node.children[1].loc.expression.end_pos
21
+ when :defs
22
+ @node.children[2].empty? ? @node.loc.name.end_pos : @node.children[2].loc.expression.end_pos
19
23
  else
20
24
  @node.children.last.loc.expression.end_pos
21
25
  end
@@ -29,7 +33,7 @@ module Synvert::Core
29
33
  # @param node [Parser::AST::Node]
30
34
  # @return [String] n times whitesphace
31
35
  def indent(node)
32
- if %i[block class].include? node.type
36
+ if %i[block class def defs].include?(node.type)
33
37
  ' ' * (node.column + DEFAULT_INDENT)
34
38
  else
35
39
  ' ' * node.column
@@ -81,11 +81,10 @@ module Synvert::Core
81
81
  def fetch(group, name)
82
82
  group = group.to_s
83
83
  name = name.to_s
84
- if rewriters[group] && rewriters[group][name]
85
- rewriters[group][name]
86
- else
87
- raise RewriterNotFound, "Rewriter #{group} #{name} not found"
88
- end
84
+ rewriter = rewriters.dig(group, name)
85
+ raise RewriterNotFound, "Rewriter #{group} #{name} not found" unless rewriter
86
+
87
+ rewriter
89
88
  end
90
89
 
91
90
  # Get a registered rewriter by group and name, then process that rewriter.
@@ -166,9 +165,8 @@ module Synvert::Core
166
165
  def process
167
166
  @affected_files = Set.new
168
167
  instance_eval(&@block)
169
- if !@affected_files.empty? && @redo_until_no_change
170
- process
171
- end
168
+
169
+ process if !@affected_files.empty? && @redo_until_no_change # redo
172
170
  end
173
171
 
174
172
  # Process rewriter with sandbox mode.
@@ -236,9 +234,10 @@ module Synvert::Core
236
234
  def within_files(file_patterns, &block)
237
235
  return if @sandbox
238
236
 
239
- if (!@ruby_version || @ruby_version.match?) && (!@gem_spec || @gem_spec.match?)
240
- Rewriter::Instance.new(self, Array(file_patterns), &block).process
241
- end
237
+ return if @ruby_version && !@ruby_version.match?
238
+ return if @gem_spec && !@gem_spec.match?
239
+
240
+ Rewriter::Instance.new(self, Array(file_patterns), &block).process
242
241
  end
243
242
 
244
243
  # Parse within_file dsl, it finds a specifiled file.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '0.59.0'
5
+ VERSION = '0.61.2'
6
6
  end
7
7
  end
@@ -554,6 +554,54 @@ describe Parser::AST::Node do
554
554
  end
555
555
  end
556
556
 
557
+ describe '#child_node_by_name' do
558
+ context 'block node' do
559
+ it 'checks caller' do
560
+ node = parse('Factory.define :user do |user|; end')
561
+ child_node = node.child_node_by_name(:caller)
562
+ expect(child_node).to eq node.caller
563
+ end
564
+
565
+ it 'checks arguments' do
566
+ node = parse('Factory.define :user do |user|; end')
567
+ child_node = node.child_node_by_name(:arguments)
568
+ expect(child_node).to eq node.arguments
569
+ end
570
+
571
+ it 'checks caller.receiver' do
572
+ node = parse('Factory.define :user do |user|; end')
573
+ child_node = node.child_node_by_name('caller.receiver')
574
+ expect(child_node).to eq node.caller.receiver
575
+ end
576
+
577
+ it 'checks caller.message' do
578
+ node = parse('Factory.define :user do |user|; end')
579
+ child_node = node.child_node_by_name('caller.message')
580
+ expect(child_node).to eq node.caller.message
581
+ end
582
+ end
583
+
584
+ context 'array' do
585
+ it 'checks array by index' do
586
+ node = parse('factory :admin, class: User do; end')
587
+ child_node = node.child_node_by_name('caller.arguments.2')
588
+ expect(child_node).to eq node.caller.arguments[1]
589
+ end
590
+
591
+ it 'checks array by method' do
592
+ node = parse('factory :admin, class: User do; end')
593
+ child_node = node.child_node_by_name('caller.arguments.second')
594
+ expect(child_node).to eq node.caller.arguments[1]
595
+ end
596
+
597
+ it "checks array' value" do
598
+ node = parse('factory :admin, class: User do; end')
599
+ child_node = node.child_node_by_name('caller.arguments.second.class_value')
600
+ expect(child_node).to eq node.caller.arguments[1].class_value
601
+ end
602
+ end
603
+ end
604
+
557
605
  describe '#child_node_range' do
558
606
  context 'block node' do
559
607
  it 'checks caller' do
@@ -720,6 +768,26 @@ describe Parser::AST::Node do
720
768
  expect(range).to be_nil
721
769
  end
722
770
  end
771
+
772
+ context 'array' do
773
+ it 'checks array by index' do
774
+ node = parse('factory :admin, class: User do; end')
775
+ range = node.child_node_range('caller.arguments.2')
776
+ expect(range.to_range).to eq(16...27)
777
+ end
778
+
779
+ it 'checks array by method' do
780
+ node = parse('factory :admin, class: User do; end')
781
+ range = node.child_node_range('caller.arguments.second')
782
+ expect(range.to_range).to eq(16...27)
783
+ end
784
+
785
+ it "checks array' value" do
786
+ node = parse('factory :admin, class: User do; end')
787
+ range = node.child_node_range('caller.arguments.second.class_value')
788
+ expect(range.to_range).to eq(23...27)
789
+ end
790
+ end
723
791
  end
724
792
 
725
793
  describe '#rewritten_source' do
@@ -827,6 +895,22 @@ describe Parser::AST::Node do
827
895
  end
828
896
  end
829
897
 
898
+ describe '#to_string' do
899
+ context 'sym node' do
900
+ it 'converts symbol to string' do
901
+ node = parse(':foobar')
902
+ expect(node.to_string).to eq 'foobar'
903
+ end
904
+ end
905
+
906
+ context 'other node' do
907
+ it 'does nothing' do
908
+ node = parse("'foobar'")
909
+ expect(node.to_string).to eq "'foobar'"
910
+ end
911
+ end
912
+ end
913
+
830
914
  describe '#to_lambda_literal' do
831
915
  context 'lambda node' do
832
916
  it 'converts to lambda literal without arguments' do
@@ -45,5 +45,26 @@ module Synvert::Core
45
45
  expect(subject.rewritten_code).to eq "\ngem 'twitter'"
46
46
  end
47
47
  end
48
+
49
+ describe 'def node' do
50
+ subject do
51
+ source = "def teardown\n do_something\nend"
52
+ class_node = Parser::CurrentRuby.parse(source)
53
+ instance = double(current_node: class_node)
54
+ Rewriter::AppendAction.new(instance, 'super').process
55
+ end
56
+
57
+ it 'gets begin_pos' do
58
+ expect(subject.begin_pos).to eq "def teardown\n do_something".length
59
+ end
60
+
61
+ it 'gets end_pos' do
62
+ expect(subject.end_pos).to eq "def teardown\n do_something".length
63
+ end
64
+
65
+ it 'gets rewritten_code' do
66
+ expect(subject.rewritten_code).to eq "\n super"
67
+ end
68
+ end
48
69
  end
49
70
  end
@@ -87,5 +87,89 @@ module Synvert::Core
87
87
  expect(subject.rewritten_code).to eq "\n include Deletable"
88
88
  end
89
89
  end
90
+
91
+ describe 'def node without args' do
92
+ subject do
93
+ source = "def setup\n do_something\nend"
94
+ def_node = Parser::CurrentRuby.parse(source)
95
+ instance = double(current_node: def_node)
96
+ Rewriter::PrependAction.new(instance, 'super').process
97
+ end
98
+
99
+ it 'gets begin_pos' do
100
+ expect(subject.begin_pos).to eq 'def setup'.length
101
+ end
102
+
103
+ it 'gets end_pos' do
104
+ expect(subject.end_pos).to eq 'def setup'.length
105
+ end
106
+
107
+ it 'gets rewritten_code' do
108
+ expect(subject.rewritten_code).to eq "\n super"
109
+ end
110
+ end
111
+
112
+ describe 'def node with args' do
113
+ subject do
114
+ source = "def setup(foobar)\n do_something\nend"
115
+ def_node = Parser::CurrentRuby.parse(source)
116
+ instance = double(current_node: def_node)
117
+ Rewriter::PrependAction.new(instance, 'super').process
118
+ end
119
+
120
+ it 'gets begin_pos' do
121
+ expect(subject.begin_pos).to eq 'def setup(foobar)'.length
122
+ end
123
+
124
+ it 'gets end_pos' do
125
+ expect(subject.end_pos).to eq 'def setup(foobar)'.length
126
+ end
127
+
128
+ it 'gets rewritten_code' do
129
+ expect(subject.rewritten_code).to eq "\n super"
130
+ end
131
+ end
132
+
133
+ describe 'defs node without args' do
134
+ subject do
135
+ source = "def self.foo\n do_something\nend"
136
+ def_node = Parser::CurrentRuby.parse(source)
137
+ instance = double(current_node: def_node)
138
+ Rewriter::PrependAction.new(instance, 'do_something_first').process
139
+ end
140
+
141
+ it 'gets begin_pos' do
142
+ expect(subject.begin_pos).to eq 'def self.foo'.length
143
+ end
144
+
145
+ it 'gets end_pos' do
146
+ expect(subject.end_pos).to eq 'def self.foo'.length
147
+ end
148
+
149
+ it 'gets rewritten_code' do
150
+ expect(subject.rewritten_code).to eq "\n do_something_first"
151
+ end
152
+ end
153
+
154
+ describe 'defs node with args' do
155
+ subject do
156
+ source = "def self.foo(bar)\n do_something\nend"
157
+ def_node = Parser::CurrentRuby.parse(source)
158
+ instance = double(current_node: def_node)
159
+ Rewriter::PrependAction.new(instance, 'do_something_first').process
160
+ end
161
+
162
+ it 'gets begin_pos' do
163
+ expect(subject.begin_pos).to eq 'def self.foo(bar)'.length
164
+ end
165
+
166
+ it 'gets end_pos' do
167
+ expect(subject.end_pos).to eq 'def self.foo(bar)'.length
168
+ end
169
+
170
+ it 'gets rewritten_code' do
171
+ expect(subject.rewritten_code).to eq "\n do_something_first"
172
+ end
173
+ end
90
174
  end
91
175
  end
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_runtime_dependency "activesupport"
22
+ spec.add_runtime_dependency "activesupport", "~> 6"
23
23
  spec.add_runtime_dependency "erubis"
24
24
  spec.add_runtime_dependency "parser"
25
25
 
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synvert-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.59.0
4
+ version: 0.61.2
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-11-17 00:00:00.000000000 Z
11
+ date: 2021-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '6'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ">="
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '6'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: erubis
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -218,7 +218,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
218
  - !ruby/object:Gem::Version
219
219
  version: '0'
220
220
  requirements: []
221
- rubygems_version: 3.2.22
221
+ rubygems_version: 3.2.32
222
222
  signing_key:
223
223
  specification_version: 4
224
224
  summary: convert ruby code to better syntax.