synvert-core 0.35.0 → 0.40.0

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: 9c718983fb8e6e6216ac660fba2aa1b9beeacf96db451d65b4df3df827a396c0
4
- data.tar.gz: a6fd2918b8de9d92bfe4a50f1c135154d5b94eacd21b3e88c740e1869e4c4686
3
+ metadata.gz: 5c729d2f456550a622a39f2e43d6d6c7f701f8b1330af038c436a03ec162d828
4
+ data.tar.gz: 8f5e7642d9073bfa38798dbd237a416037047991d530f4ff862623007ffa81f7
5
5
  SHA512:
6
- metadata.gz: 8a828ec38b3d152a6620dd8fb5101a4fa0594da95eaede5612dd805f8b719bc52ebcaa1c00de48bb17fb306ebcf0cd6a7beb109dc91602afd5e305aafe521e47
7
- data.tar.gz: 496d20ef84817d2e8073573b67635f8cb520fc430a647eba909ff9a49dce8fa4f9f5c99245123aa390d7b7d0356c955ca1f78c8073ee17984e1dfa14a8914e51
6
+ metadata.gz: 1187929417e2611b85d95dad5cc2f985d86cc4a1638d0ebecc4baeacc8dfa124ed5ec6595845a941fe7fe13c1666255333aa9f4249f297899c84ab8518a1b809
7
+ data.tar.gz: 729ff991e4a120d655faaa5517915d6d2614396668f08268a93b70c86f00ce038ec12ff09cf7d5cc060e34b7af8604689f3e4948b32a26bf4fc85ae520da1d21
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.40.0 (2021-06-23)
4
+
5
+ * Rewrite `insert` action
6
+
7
+ ## 0.39.0 (2021-06-23)
8
+
9
+ * Add `prepend` action instead of `insert`
10
+
11
+ ## 0.38.0 (2021-06-21)
12
+
13
+ * Add `xxx_source` for `hash` node
14
+
15
+ ## 0.36.0 (2021-06-21)
16
+
17
+ * Require `active_support/core_ext/array`
18
+
3
19
  ## 0.35.0 (2021-05-17)
4
20
 
5
21
  * Add `contain` rule
data/lib/synvert/core.rb CHANGED
@@ -6,6 +6,7 @@ require 'parser'
6
6
  require 'parser/current'
7
7
  require 'ast'
8
8
  require 'active_support/core_ext/object'
9
+ require 'active_support/core_ext/array'
9
10
  require 'erubis'
10
11
  require 'set'
11
12
  require 'synvert/core/node_ext'
@@ -269,6 +269,12 @@ module Parser::AST
269
269
  return hash_value(key.to_sym)&.to_value if key?(key.to_sym)
270
270
  return hash_value(key.to_s)&.to_value if key?(key.to_s)
271
271
 
272
+ return nil
273
+ elsif :hash == type && method_name.to_s.include?('_source')
274
+ key = method_name.to_s.sub('_source', '')
275
+ return hash_value(key.to_sym)&.to_source if key?(key.to_sym)
276
+ return hash_value(key.to_s)&.to_source if key?(key.to_s)
277
+
272
278
  return nil
273
279
  end
274
280
 
@@ -281,6 +287,9 @@ module Parser::AST
281
287
  elsif :hash == type && method_name.to_s.include?('_value')
282
288
  key = method_name.to_s.sub('_value', '')
283
289
  return true if key?(key.to_sym) || key?(key.to_s)
290
+ elsif :hash == type && method_name.to_s.include?('_source')
291
+ key = method_name.to_s.sub('_source', '')
292
+ return true if key?(key.to_sym) || key?(key.to_s)
284
293
  end
285
294
 
286
295
  super
@@ -332,7 +341,11 @@ module Parser::AST
332
341
  when %i[block pipes], %i[def parentheses], %i[defs parentheses]
333
342
  Parser::Source::Range.new('(string)', arguments.loc.expression.begin_pos, arguments.loc.expression.end_pos)
334
343
  when %i[block arguments], %i[def arguments], %i[defs arguments]
335
- Parser::Source::Range.new('(string)', arguments.first.loc.expression.begin_pos, arguments.last.loc.expression.end_pos)
344
+ Parser::Source::Range.new(
345
+ '(string)',
346
+ arguments.first.loc.expression.begin_pos,
347
+ arguments.last.loc.expression.end_pos
348
+ )
336
349
  when %i[class name], %i[def name], %i[defs name]
337
350
  loc.name
338
351
  when %i[defs dot]
@@ -18,6 +18,7 @@ module Synvert::Core
18
18
  class Rewriter
19
19
  autoload :Action, 'synvert/core/rewriter/action'
20
20
  autoload :AppendAction, 'synvert/core/rewriter/action/append_action'
21
+ autoload :PrependAction, 'synvert/core/rewriter/action/prepend_action'
21
22
  autoload :InsertAction, 'synvert/core/rewriter/action/insert_action'
22
23
  autoload :InsertAfterAction, 'synvert/core/rewriter/action/insert_after_action'
23
24
  autoload :ReplaceWithAction, 'synvert/core/rewriter/action/replace_with_action'
@@ -1,26 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Synvert::Core
4
- # InsertAction to insert code to the top of node body.
4
+ # AddAction to add code to the node.
5
5
  class Rewriter::InsertAction < Rewriter::Action
6
- DO_LENGTH = ' do'.length
7
-
8
6
  # Begin position to insert code.
9
7
  #
10
8
  # @return [Integer] begin position.
11
9
  def begin_pos
12
- case @node.type
13
- when :block
14
- if @node.children[1].children.empty?
15
- @node.children[0].loc.expression.end_pos + DO_LENGTH
16
- else
17
- @node.children[1].loc.expression.end_pos
18
- end
19
- when :class
20
- @node.children[1] ? @node.children[1].loc.expression.end_pos : @node.children[0].loc.expression.end_pos
21
- else
22
- @node.children.last.loc.expression.end_pos
23
- end
10
+ @node.loc.expression.end_pos
24
11
  end
25
12
 
26
13
  # End position, always same to begin position.
@@ -30,18 +17,11 @@ module Synvert::Core
30
17
  begin_pos
31
18
  end
32
19
 
33
- private
34
-
35
- # Indent of the node.
20
+ # The rewritten source code.
36
21
  #
37
- # @param node [Parser::AST::Node]
38
- # @return [String] n times whitesphace
39
- def indent(node)
40
- if %i[block class].include? node.type
41
- ' ' * (node.indent + DEFAULT_INDENT)
42
- else
43
- ' ' * node.indent
44
- end
22
+ # @return [String] rewritten code.
23
+ def rewritten_code
24
+ rewritten_source
45
25
  end
46
26
  end
47
27
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synvert::Core
4
+ # PrependAction to prepend code to the top of node body.
5
+ class Rewriter::PrependAction < Rewriter::Action
6
+ DO_LENGTH = ' do'.length
7
+
8
+ # Begin position to prepend code.
9
+ #
10
+ # @return [Integer] begin position.
11
+ def begin_pos
12
+ case @node.type
13
+ when :block
14
+ if @node.children[1].children.empty?
15
+ @node.children[0].loc.expression.end_pos + DO_LENGTH
16
+ else
17
+ @node.children[1].loc.expression.end_pos
18
+ end
19
+ when :class
20
+ @node.children[1] ? @node.children[1].loc.expression.end_pos : @node.children[0].loc.expression.end_pos
21
+ else
22
+ @node.children.last.loc.expression.end_pos
23
+ end
24
+ end
25
+
26
+ # End position, always same to begin position.
27
+ #
28
+ # @return [Integer] end position.
29
+ def end_pos
30
+ begin_pos
31
+ end
32
+
33
+ private
34
+
35
+ # Indent of the node.
36
+ #
37
+ # @param node [Parser::AST::Node]
38
+ # @return [String] n times whitesphace
39
+ def indent(node)
40
+ if %i[block class].include? node.type
41
+ ' ' * (node.indent + DEFAULT_INDENT)
42
+ else
43
+ ' ' * node.indent
44
+ end
45
+ end
46
+ end
47
+ end
@@ -224,6 +224,15 @@ module Synvert::Core
224
224
  @actions << Rewriter::AppendAction.new(self, code, options)
225
225
  end
226
226
 
227
+ # Parse prepend dsl, it creates a [Synvert::Core::Rewriter::PrependAction] to
228
+ # prepend the code to the top of current node body.
229
+ #
230
+ # @param code [String] code need to be prepended.
231
+ # @param options [Hash] action options.
232
+ def prepend(code, options = {})
233
+ @actions << Rewriter::PrependAction.new(self, code, options)
234
+ end
235
+
227
236
  # Parse insert dsl, it creates a [Synvert::Core::Rewriter::InsertAction] to
228
237
  # insert the code to the top of current node body.
229
238
  #
@@ -37,9 +37,18 @@ module Synvert::Core
37
37
  def find_matching_nodes(current_node)
38
38
  matching_nodes = []
39
39
  if @options[:recursive]
40
- matching_nodes << current_node if current_node.match? @rules
41
- current_node.recursive_children do |child_node|
42
- matching_nodes << child_node if child_node.match? @rules
40
+ if current_node.is_a?(Parser::AST::Node)
41
+ matching_nodes << current_node if current_node.match? @rules
42
+ current_node.recursive_children do |child_node|
43
+ matching_nodes << child_node if child_node.match? @rules
44
+ end
45
+ else
46
+ current_node.each do |node|
47
+ matching_nodes << node if node.match? @rules
48
+ node.recursive_children do |child_node|
49
+ matching_nodes << child_node if child_node.match? @rules
50
+ end
51
+ end
43
52
  end
44
53
  elsif current_node.is_a?(Parser::AST::Node)
45
54
  if current_node.type == :begin
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Synvert
4
4
  module Core
5
- VERSION = '0.35.0'
5
+ VERSION = '0.40.0'
6
6
  end
7
7
  end
@@ -360,6 +360,18 @@ describe Parser::AST::Node do
360
360
  end
361
361
  end
362
362
 
363
+ describe 'key value source by method_missing' do
364
+ it 'gets for key value source' do
365
+ node = parse('{:foo => :bar}')
366
+ expect(node.foo_source).to eq ':bar'
367
+
368
+ node = parse("{'foo' => 'bar'}")
369
+ expect(node.foo_source).to eq "'bar'"
370
+
371
+ expect(node.bar_source).to be_nil
372
+ end
373
+ end
374
+
363
375
  describe '#recursive_children' do
364
376
  it 'iterates all children recursively' do
365
377
  node = parse('class Synvert; def current_node; @node; end; end')
@@ -4,88 +4,23 @@ require 'spec_helper'
4
4
 
5
5
  module Synvert::Core
6
6
  describe Rewriter::InsertAction do
7
- describe 'block node without args' do
8
- subject {
9
- source = "Synvert::Application.configure do\nend"
10
- block_node = Parser::CurrentRuby.parse(source)
11
- instance = double(current_node: block_node)
12
- Rewriter::InsertAction.new(instance, 'config.eager_load = true')
13
- }
14
-
15
- it 'gets begin_pos' do
16
- expect(subject.begin_pos).to eq 'Synvert::Application.configure do'.length
17
- end
18
-
19
- it 'gets end_pos' do
20
- expect(subject.end_pos).to eq 'Synvert::Application.configure do'.length
21
- end
22
-
23
- it 'gets rewritten_code' do
24
- expect(subject.rewritten_code).to eq "\n config.eager_load = true"
25
- end
26
- end
27
-
28
- describe 'block node with args' do
29
- subject {
30
- source = "RSpec.configure do |config|\nend"
31
- block_node = Parser::CurrentRuby.parse(source)
32
- instance = double(current_node: block_node)
33
- Rewriter::InsertAction.new(instance, '{{arguments.first}}.include FactoryGirl::Syntax::Methods')
34
- }
35
-
36
- it 'gets begin_pos' do
37
- expect(subject.begin_pos).to eq 'RSpec.configure do |config|'.length
38
- end
39
-
40
- it 'gets end_pos' do
41
- expect(subject.end_pos).to eq 'RSpec.configure do |config|'.length
42
- end
43
-
44
- it 'gets rewritten_code' do
45
- expect(subject.rewritten_code).to eq "\n config.include FactoryGirl::Syntax::Methods"
46
- end
7
+ subject {
8
+ source = "User.where(username: 'Richard')"
9
+ node = Parser::CurrentRuby.parse(source)
10
+ instance = double(current_node: node)
11
+ Rewriter::InsertAction.new(instance, '.first')
12
+ }
13
+
14
+ it 'gets begin_pos' do
15
+ expect(subject.begin_pos).to eq "User.where(username: 'Richard')".length
47
16
  end
48
17
 
49
- describe 'class node without superclass' do
50
- subject {
51
- source = "class User\n has_many :posts\nend"
52
- class_node = Parser::CurrentRuby.parse(source)
53
- instance = double(current_node: class_node)
54
- Rewriter::InsertAction.new(instance, 'include Deletable')
55
- }
56
-
57
- it 'gets begin_pos' do
58
- expect(subject.begin_pos).to eq 'class User'.length
59
- end
60
-
61
- it 'gets end_pos' do
62
- expect(subject.end_pos).to eq 'class User'.length
63
- end
64
-
65
- it 'gets rewritten_code' do
66
- expect(subject.rewritten_code).to eq "\n include Deletable"
67
- end
18
+ it 'gets end_pos' do
19
+ expect(subject.end_pos).to eq "User.where(username: 'Richard')".length
68
20
  end
69
21
 
70
- describe 'class node with superclass' do
71
- subject {
72
- source = "class User < ActiveRecord::Base\n has_many :posts\nend"
73
- class_node = Parser::CurrentRuby.parse(source)
74
- instance = double(current_node: class_node)
75
- Rewriter::InsertAction.new(instance, 'include Deletable')
76
- }
77
-
78
- it 'gets begin_pos' do
79
- expect(subject.begin_pos).to eq 'class User < ActionRecord::Base'.length
80
- end
81
-
82
- it 'gets end_pos' do
83
- expect(subject.end_pos).to eq 'class User < ActionRecord::Base'.length
84
- end
85
-
86
- it 'gets rewritten_code' do
87
- expect(subject.rewritten_code).to eq "\n include Deletable"
88
- end
22
+ it 'gets rewritten_code' do
23
+ expect(subject.rewritten_code).to eq ".first"
89
24
  end
90
25
  end
91
26
  end
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ module Synvert::Core
6
+ describe Rewriter::PrependAction do
7
+ describe 'block node without args' do
8
+ subject {
9
+ source = "Synvert::Application.configure do\nend"
10
+ block_node = Parser::CurrentRuby.parse(source)
11
+ instance = double(current_node: block_node)
12
+ Rewriter::PrependAction.new(instance, 'config.eager_load = true')
13
+ }
14
+
15
+ it 'gets begin_pos' do
16
+ expect(subject.begin_pos).to eq 'Synvert::Application.configure do'.length
17
+ end
18
+
19
+ it 'gets end_pos' do
20
+ expect(subject.end_pos).to eq 'Synvert::Application.configure do'.length
21
+ end
22
+
23
+ it 'gets rewritten_code' do
24
+ expect(subject.rewritten_code).to eq "\n config.eager_load = true"
25
+ end
26
+ end
27
+
28
+ describe 'block node with args' do
29
+ subject {
30
+ source = "RSpec.configure do |config|\nend"
31
+ block_node = Parser::CurrentRuby.parse(source)
32
+ instance = double(current_node: block_node)
33
+ Rewriter::PrependAction.new(instance, '{{arguments.first}}.include FactoryGirl::Syntax::Methods')
34
+ }
35
+
36
+ it 'gets begin_pos' do
37
+ expect(subject.begin_pos).to eq 'RSpec.configure do |config|'.length
38
+ end
39
+
40
+ it 'gets end_pos' do
41
+ expect(subject.end_pos).to eq 'RSpec.configure do |config|'.length
42
+ end
43
+
44
+ it 'gets rewritten_code' do
45
+ expect(subject.rewritten_code).to eq "\n config.include FactoryGirl::Syntax::Methods"
46
+ end
47
+ end
48
+
49
+ describe 'class node without superclass' do
50
+ subject {
51
+ source = "class User\n has_many :posts\nend"
52
+ class_node = Parser::CurrentRuby.parse(source)
53
+ instance = double(current_node: class_node)
54
+ Rewriter::PrependAction.new(instance, 'include Deletable')
55
+ }
56
+
57
+ it 'gets begin_pos' do
58
+ expect(subject.begin_pos).to eq 'class User'.length
59
+ end
60
+
61
+ it 'gets end_pos' do
62
+ expect(subject.end_pos).to eq 'class User'.length
63
+ end
64
+
65
+ it 'gets rewritten_code' do
66
+ expect(subject.rewritten_code).to eq "\n include Deletable"
67
+ end
68
+ end
69
+
70
+ describe 'class node with superclass' do
71
+ subject {
72
+ source = "class User < ActiveRecord::Base\n has_many :posts\nend"
73
+ class_node = Parser::CurrentRuby.parse(source)
74
+ instance = double(current_node: class_node)
75
+ Rewriter::PrependAction.new(instance, 'include Deletable')
76
+ }
77
+
78
+ it 'gets begin_pos' do
79
+ expect(subject.begin_pos).to eq 'class User < ActionRecord::Base'.length
80
+ end
81
+
82
+ it 'gets end_pos' do
83
+ expect(subject.end_pos).to eq 'class User < ActionRecord::Base'.length
84
+ end
85
+
86
+ it 'gets rewritten_code' do
87
+ expect(subject.rewritten_code).to eq "\n include Deletable"
88
+ end
89
+ end
90
+ end
91
+ end
@@ -94,13 +94,22 @@ module Synvert::Core
94
94
  instance.append 'include FactoryGirl::Syntax::Methods'
95
95
  end
96
96
 
97
+ it 'parses prepend' do
98
+ expect(Rewriter::PrependAction).to receive(:new).with(
99
+ instance,
100
+ '{{arguments.first}}.include FactoryGirl::Syntax::Methods',
101
+ {}
102
+ )
103
+ instance.prepend '{{arguments.first}}.include FactoryGirl::Syntax::Methods'
104
+ end
105
+
97
106
  it 'parses insert' do
98
107
  expect(Rewriter::InsertAction).to receive(:new).with(
99
108
  instance,
100
- '{{arguments.first}}.include FactoryGirl::Syntax::Methods',
109
+ '.first',
101
110
  {}
102
111
  )
103
- instance.insert '{{arguments.first}}.include FactoryGirl::Syntax::Methods'
112
+ instance.insert '.first'
104
113
  end
105
114
 
106
115
  it 'parses insert_after' do
@@ -8,16 +8,16 @@ module Synvert::Core
8
8
  rewriter = Rewriter.new('foo', 'bar')
9
9
  Rewriter::Instance.new(rewriter, 'file pattern')
10
10
  }
11
- let(:source) {
12
- "
13
- describe Post do
14
- it 'gets post' do
15
- FactoryGirl.create :post
16
- end
17
- end
18
- "
19
- }
11
+ let(:source) { <<~EOS }
12
+ describe Post do
13
+ it 'gets post' do
14
+ FactoryGirl.create :post
15
+ end
16
+ end
17
+ EOS
18
+
20
19
  let(:node) { Parser::CurrentRuby.parse(source) }
20
+
21
21
  before do
22
22
  Rewriter::Instance.reset
23
23
  instance.current_node = node
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.35.0
4
+ version: 0.40.0
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-05-17 00:00:00.000000000 Z
11
+ date: 2021-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -150,6 +150,7 @@ files:
150
150
  - lib/synvert/core/rewriter/action/delete_action.rb
151
151
  - lib/synvert/core/rewriter/action/insert_action.rb
152
152
  - lib/synvert/core/rewriter/action/insert_after_action.rb
153
+ - lib/synvert/core/rewriter/action/prepend_action.rb
153
154
  - lib/synvert/core/rewriter/action/remove_action.rb
154
155
  - lib/synvert/core/rewriter/action/replace_action.rb
155
156
  - lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb
@@ -176,6 +177,7 @@ files:
176
177
  - spec/synvert/core/rewriter/action/delete_action_spec.rb
177
178
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
178
179
  - spec/synvert/core/rewriter/action/insert_after_action_spec.rb
180
+ - spec/synvert/core/rewriter/action/prepend_action_spec.rb
179
181
  - spec/synvert/core/rewriter/action/remove_action_spec.rb
180
182
  - spec/synvert/core/rewriter/action/replace_action_spec.rb
181
183
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb
@@ -227,6 +229,7 @@ test_files:
227
229
  - spec/synvert/core/rewriter/action/delete_action_spec.rb
228
230
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
229
231
  - spec/synvert/core/rewriter/action/insert_after_action_spec.rb
232
+ - spec/synvert/core/rewriter/action/prepend_action_spec.rb
230
233
  - spec/synvert/core/rewriter/action/remove_action_spec.rb
231
234
  - spec/synvert/core/rewriter/action/replace_action_spec.rb
232
235
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb