synvert-core 0.34.0 → 0.39.0

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: 34cd9673c3a822eb4c9b41930aa069b8c8494d6e81091c37b0184864f302f94d
4
- data.tar.gz: 852ff317acabb0d20528a168d6639b10b9ac576f1c70f64af2e17923762addaa
3
+ metadata.gz: bd079f46cc8d4a8097a794b11c02e98294c217d801538e4c9dafa4305fd3b6d8
4
+ data.tar.gz: 81018b9a711fca607aa4b2dc3170e9172531140392172b5cd27d4118383a6c31
5
5
  SHA512:
6
- metadata.gz: 9a23ba7d43b7eef7a6508925a6d9aa2c925e12cd392999f0d2e263be5a5df7c934a735cb00e584f4cddbdccd8779d6eed1dddd338d9d1f9838d9d983c21f74dc
7
- data.tar.gz: 92008bfc0d05c3d71d9948e0db6a3c8c09ca05b4aff4d2a1cafb6fd93fb0308554a738f2447d962d4751b82827f22aeee9f81d2c7727fb63190018984a7a8a6e
6
+ metadata.gz: 78fd6e0b7b28661b5d352a6835f35b713ca829a2a9ae4260e605541b00e9eb151b66b45018a954e1b98682b45bbbddaac359a582281904dd784b2004ded00c9b
7
+ data.tar.gz: 6a4a33419eafeac609f92d68593ee12b5e5608c24865289cd53f6bb631ef047dc83f1cb7648984d70fded95c9141b6c4a58056280675b55f321836e2b3005dbd
data/CHANGELOG.md CHANGED
@@ -1,9 +1,25 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 0.39.0 (2021-06-23)
4
+
5
+ * Add `prepend` dsl instead of `insert`
6
+
7
+ ## 0.38.0 (2021-06-21)
8
+
9
+ * Add `xxx_source` for `hash` node
10
+
11
+ ## 0.36.0 (2021-06-21)
12
+
13
+ * Require `active_support/core_ext/array`
14
+
15
+ ## 0.35.0 (2021-05-17)
16
+
17
+ * Add `contain` rule
18
+
3
19
  ## 0.34.0 (2021-05-16)
4
20
 
5
21
  * `child_node_name` supports [:def, :parentheses] and [:defs, :parentheses]
6
- * rename `pipe` to `pipes`
22
+ * Rename `pipe` to `pipes`
7
23
 
8
24
  ## 0.33.0 (2021-05-10)
9
25
 
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]
@@ -399,7 +412,7 @@ module Parser::AST
399
412
  def match?(rules)
400
413
  flat_hash(rules).keys.all? do |multi_keys|
401
414
  case multi_keys.last
402
- when :any
415
+ when :any, :contain
403
416
  actual_values = actual_value(self, multi_keys[0...-1])
404
417
  expected = expected_value(rules, multi_keys)
405
418
  actual_values.any? { |actual| match_value?(actual, expected) }
@@ -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'
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Synvert::Core
4
+ # AddAction to add code to the node.
5
+ class Rewriter::AddAction < Rewriter::Action
6
+ # Begin position to insert code.
7
+ #
8
+ # @return [Integer] begin position.
9
+ def begin_pos
10
+ @node.loc.expression.end_pos
11
+ end
12
+
13
+ # End position, always same to begin position.
14
+ #
15
+ # @return [Integer] end position.
16
+ def end_pos
17
+ begin_pos
18
+ end
19
+
20
+ private
21
+
22
+ # The rewritten source code.
23
+ #
24
+ # @return [String] rewritten code.
25
+ def rewritten_code
26
+ rewritten_source
27
+ end
28
+ end
29
+ 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.34.0'
5
+ VERSION = '0.39.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')
@@ -414,6 +426,12 @@ describe Parser::AST::Node do
414
426
  expect(node).to be_match(type: 'send', arguments: { any: 'Lifo::Cache' })
415
427
  end
416
428
 
429
+ it 'matches arguments contain' do
430
+ source = 'def slow(foo, bar, &block); end'
431
+ node = parse(source)
432
+ expect(node).to be_match(type: 'def', arguments: { contain: '&block' })
433
+ end
434
+
417
435
  it 'matches not' do
418
436
  source = 'class Synvert; end'
419
437
  node = parse(source)
@@ -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,6 +94,15 @@ 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,
@@ -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.34.0
4
+ version: 0.39.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-16 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
@@ -146,10 +146,12 @@ files:
146
146
  - lib/synvert/core/node_ext.rb
147
147
  - lib/synvert/core/rewriter.rb
148
148
  - lib/synvert/core/rewriter/action.rb
149
+ - lib/synvert/core/rewriter/action/add_action.rb
149
150
  - lib/synvert/core/rewriter/action/append_action.rb
150
151
  - lib/synvert/core/rewriter/action/delete_action.rb
151
152
  - lib/synvert/core/rewriter/action/insert_action.rb
152
153
  - lib/synvert/core/rewriter/action/insert_after_action.rb
154
+ - lib/synvert/core/rewriter/action/prepend_action.rb
153
155
  - lib/synvert/core/rewriter/action/remove_action.rb
154
156
  - lib/synvert/core/rewriter/action/replace_action.rb
155
157
  - lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb
@@ -176,6 +178,7 @@ files:
176
178
  - spec/synvert/core/rewriter/action/delete_action_spec.rb
177
179
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
178
180
  - spec/synvert/core/rewriter/action/insert_after_action_spec.rb
181
+ - spec/synvert/core/rewriter/action/prepend_action_spec.rb
179
182
  - spec/synvert/core/rewriter/action/remove_action_spec.rb
180
183
  - spec/synvert/core/rewriter/action/replace_action_spec.rb
181
184
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb
@@ -227,6 +230,7 @@ test_files:
227
230
  - spec/synvert/core/rewriter/action/delete_action_spec.rb
228
231
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
229
232
  - spec/synvert/core/rewriter/action/insert_after_action_spec.rb
233
+ - spec/synvert/core/rewriter/action/prepend_action_spec.rb
230
234
  - spec/synvert/core/rewriter/action/remove_action_spec.rb
231
235
  - spec/synvert/core/rewriter/action/replace_action_spec.rb
232
236
  - spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb