synvert-core 1.4.0 → 1.5.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 +4 -4
- data/.gitignore +0 -4
- data/CHANGELOG.md +6 -0
- data/Gemfile +0 -3
- data/Guardfile +0 -9
- data/README.md +30 -12
- data/Rakefile +1 -15
- data/lib/synvert/core/engine/erb.rb +1 -1
- data/lib/synvert/core/engine.rb +1 -1
- data/lib/synvert/core/node_ext.rb +0 -466
- data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +20 -17
- data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +1 -1
- data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +1 -1
- data/lib/synvert/core/rewriter/instance.rb +83 -133
- data/lib/synvert/core/rewriter/scope/query_scope.rb +2 -2
- data/lib/synvert/core/rewriter/scope/within_scope.rb +4 -4
- data/lib/synvert/core/rewriter.rb +0 -10
- data/lib/synvert/core/version.rb +1 -1
- data/lib/synvert/core.rb +4 -6
- data/spec/synvert/core/engine/erb_spec.rb +3 -3
- data/spec/synvert/core/node_ext_spec.rb +0 -795
- data/spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb +21 -1
- data/spec/synvert/core/rewriter/instance_spec.rb +47 -115
- data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +1 -4
- data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +1 -4
- data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +1 -4
- data/synvert-core-ruby.gemspec +4 -2
- metadata +44 -61
- data/lib/synvert/core/array_ext.rb +0 -48
- data/lib/synvert/core/node_query/compiler/array.rb +0 -34
- data/lib/synvert/core/node_query/compiler/attribute.rb +0 -39
- data/lib/synvert/core/node_query/compiler/attribute_list.rb +0 -24
- data/lib/synvert/core/node_query/compiler/basic_selector.rb +0 -28
- data/lib/synvert/core/node_query/compiler/boolean.rb +0 -23
- data/lib/synvert/core/node_query/compiler/comparable.rb +0 -86
- data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +0 -51
- data/lib/synvert/core/node_query/compiler/expression.rb +0 -41
- data/lib/synvert/core/node_query/compiler/float.rb +0 -23
- data/lib/synvert/core/node_query/compiler/identifier.rb +0 -41
- data/lib/synvert/core/node_query/compiler/integer.rb +0 -23
- data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +0 -7
- data/lib/synvert/core/node_query/compiler/nil.rb +0 -23
- data/lib/synvert/core/node_query/compiler/parse_error.rb +0 -7
- data/lib/synvert/core/node_query/compiler/regexp.rb +0 -37
- data/lib/synvert/core/node_query/compiler/selector.rb +0 -113
- data/lib/synvert/core/node_query/compiler/string.rb +0 -23
- data/lib/synvert/core/node_query/compiler/symbol.rb +0 -23
- data/lib/synvert/core/node_query/compiler.rb +0 -25
- data/lib/synvert/core/node_query/lexer.rex +0 -99
- data/lib/synvert/core/node_query/lexer.rex.rb +0 -299
- data/lib/synvert/core/node_query/parser.racc.rb +0 -306
- data/lib/synvert/core/node_query/parser.y +0 -60
- data/lib/synvert/core/node_query.rb +0 -36
- data/lib/synvert/core/rewriter/action/append_action.rb +0 -28
- data/lib/synvert/core/rewriter/action/delete_action.rb +0 -34
- data/lib/synvert/core/rewriter/action/insert_action.rb +0 -34
- data/lib/synvert/core/rewriter/action/insert_after_action.rb +0 -22
- data/lib/synvert/core/rewriter/action/prepend_action.rb +0 -44
- data/lib/synvert/core/rewriter/action/remove_action.rb +0 -56
- data/lib/synvert/core/rewriter/action/replace_action.rb +0 -33
- data/lib/synvert/core/rewriter/action/replace_with_action.rb +0 -36
- data/lib/synvert/core/rewriter/action/wrap_action.rb +0 -37
- data/lib/synvert/core/rewriter/action.rb +0 -102
- data/spec/synvert/core/node_query/lexer_spec.rb +0 -580
- data/spec/synvert/core/node_query/parser_spec.rb +0 -337
- data/spec/synvert/core/rewriter/action/append_action_spec.rb +0 -70
- data/spec/synvert/core/rewriter/action/delete_action_spec.rb +0 -26
- data/spec/synvert/core/rewriter/action/insert_action_spec.rb +0 -70
- data/spec/synvert/core/rewriter/action/insert_after_action_spec.rb +0 -26
- data/spec/synvert/core/rewriter/action/prepend_action_spec.rb +0 -175
- data/spec/synvert/core/rewriter/action/remove_action_spec.rb +0 -26
- data/spec/synvert/core/rewriter/action/replace_action_spec.rb +0 -28
- data/spec/synvert/core/rewriter/action/replace_with_action_spec.rb +0 -59
- data/spec/synvert/core/rewriter/action/wrap_action_spec.rb +0 -31
- data/spec/synvert/core/rewriter/action_spec.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71ae91a324677995dbfd9b1251ebf2a0a01e7c25289dcebcf86abb07599b1db8
|
4
|
+
data.tar.gz: 4370235d14aee70f57b6b02313637e9d24b13ca2aee61b71e4fa4022f78bc3f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bcd68a69575a6cd5c5c0bc7a91f82d09d2f438ab06988c01ad14c7d97c863bc2556f5c3ad7d054e35cfcb830cb778ec10a9797952a56a9391062b4bf3ce2a3f
|
7
|
+
data.tar.gz: be7b4c9fda8428c0d2a8c29350f6d2c60c40577c0f990ed5d8f4d2742fc2545fc8ddbd139298aaf39a9e69e9e9bf83fe29385745ac7ef10459da836572df9327
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/Guardfile
CHANGED
@@ -3,14 +3,5 @@
|
|
3
3
|
guard :rspec, cmd: 'bundle exec rspec' do
|
4
4
|
watch(%r{^spec/.+_spec\.rb$})
|
5
5
|
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
6
|
-
watch('lib/synvert/core/node_query/lexer.rex.rb') { 'spec/synvert/core/node_query/lexer_spec.rb' }
|
7
|
-
watch('lib/synvert/core/node_query/compiler.rb') { 'spec/synvert/core/node_query/parser_spec.rb' }
|
8
|
-
watch(%r{^lib/synvert/core/node_query/compiler/.*\.rb$}) { 'spec/synvert/core/node_query/parser_spec.rb' }
|
9
|
-
watch('lib/synvert/core/node_query/parser.racc.rb') { 'spec/synvert/core/node_query/parser_spec.rb' }
|
10
6
|
watch('spec/spec_helper.rb') { "spec" }
|
11
7
|
end
|
12
|
-
|
13
|
-
guard :rake, task: 'generate' do
|
14
|
-
watch('lib/synvert/core/node_query/lexer.rex')
|
15
|
-
watch('lib/synvert/core/node_query/parser.y')
|
16
|
-
end
|
data/README.md
CHANGED
@@ -8,29 +8,46 @@
|
|
8
8
|
Synvert core provides a set of DSLs to rewrite ruby code. e.g.
|
9
9
|
|
10
10
|
```ruby
|
11
|
-
Synvert::Rewriter.new '
|
11
|
+
Synvert::Rewriter.new 'factory_bot', 'convert_factory_girl_to_factory_bot' do
|
12
12
|
description <<~EOS
|
13
|
-
It converts
|
13
|
+
It converts FactoryGirl to FactoryBot
|
14
14
|
|
15
15
|
```ruby
|
16
|
-
|
17
|
-
|
18
|
-
end.flatten
|
16
|
+
require 'factory_girl'
|
17
|
+
require 'factory_girl_rails'
|
19
18
|
```
|
20
19
|
|
21
20
|
=>
|
22
21
|
|
23
22
|
```ruby
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
require 'factory_bot'
|
24
|
+
require 'factory_bot_rails'
|
25
|
+
```
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
FactoryGirl.create(:user)
|
29
|
+
FactoryGirl.build(:user)
|
30
|
+
```
|
31
|
+
|
32
|
+
=>
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
FactoryBot.create(:user)
|
36
|
+
FactoryBot.build(:user)
|
27
37
|
```
|
28
38
|
EOS
|
29
39
|
|
30
|
-
within_files Synvert::
|
31
|
-
|
32
|
-
|
33
|
-
|
40
|
+
within_files Synvert::RAILS_TEST_FILES do
|
41
|
+
find_node '.const[name=FactoryGirl]' do
|
42
|
+
replace_with 'FactoryBot'
|
43
|
+
end
|
44
|
+
|
45
|
+
find_node ".send[receiver=nil][message=require][arguments.size=1][arguments.first='factory_girl']" do
|
46
|
+
replace :arguments, with: "'factory_bot'"
|
47
|
+
end
|
48
|
+
|
49
|
+
with_node type: 'send', receiver: nil, message: 'require', arguments: { size: 1, first: "'factory_girl_rails'" } do
|
50
|
+
replace :arguments, with: "'factory_bot_rails'"
|
34
51
|
end
|
35
52
|
end
|
36
53
|
end
|
@@ -56,6 +73,7 @@ DSLs are as follows
|
|
56
73
|
|
57
74
|
Scopes:
|
58
75
|
|
76
|
+
* [find_node](./Synvert/Core/Rewriter/Instance.html#find_node-instance_method) - recursively find matching ast nodes by node query language
|
59
77
|
* [within_node](./Synvert/Core/Rewriter/Instance.html#within_node-instance_method) - recursively find matching ast nodes
|
60
78
|
* [with_node](./Synvert/Core/Rewriter/Instance.html#with_node-instance_method) - alias to within_node
|
61
79
|
* [goto_node](./Synvert/Core/Rewriter/Instance.html#goto_node-instance_method) - go to a child node
|
data/Rakefile
CHANGED
@@ -2,21 +2,7 @@
|
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require 'rspec/core/rake_task'
|
5
|
-
RSpec::Core::RakeTask.new(:spec)
|
6
|
-
require 'oedipus_lex'
|
7
|
-
Rake.application.rake_require "oedipus_lex"
|
8
|
-
|
9
|
-
file "lib/synvert/core/node_query/lexer.rex.rb" => "lib/synvert/core/node_query/lexer.rex"
|
10
|
-
file "lib/synvert/core/node_query/parser.racc.rb" => "lib/synvert/core/node_query/parser.y"
|
11
5
|
|
12
|
-
|
13
|
-
task :parser => "lib/synvert/core/node_query/parser.racc.rb"
|
14
|
-
task :generate => [:lexer, :parser]
|
15
|
-
|
16
|
-
rule '.racc.rb' => '.y' do |t|
|
17
|
-
cmd = "bundle exec racc -l -v -o #{t.name} #{t.source}"
|
18
|
-
sh cmd
|
19
|
-
end
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
20
7
|
|
21
8
|
task :default => :spec
|
22
|
-
task :spec => :generate
|
data/lib/synvert/core/engine.rb
CHANGED
@@ -29,311 +29,6 @@ module Parser::AST
|
|
29
29
|
# Source Code to Ast Node
|
30
30
|
# {https://synvert-playground.xinminlabs.com/ruby}
|
31
31
|
class Node
|
32
|
-
TYPE_CHILDREN = {
|
33
|
-
and: %i[left_value right_value],
|
34
|
-
arg: %i[name],
|
35
|
-
begin: %i[body],
|
36
|
-
block: %i[caller arguments body],
|
37
|
-
blockarg: %i[name],
|
38
|
-
const: %i[parent_const name],
|
39
|
-
class: %i[name parent_class body],
|
40
|
-
csend: %i[receiver message arguments],
|
41
|
-
cvasgn: %i[left_value right_value],
|
42
|
-
cvar: %i[name],
|
43
|
-
def: %i[name arguments body],
|
44
|
-
definded?: %i[arguments],
|
45
|
-
defs: %i[self name arguments body],
|
46
|
-
hash: %i[pairs],
|
47
|
-
ivasgn: %i[left_value right_value],
|
48
|
-
ivar: %i[name],
|
49
|
-
lvar: %i[name],
|
50
|
-
lvasgn: %i[left_value right_value],
|
51
|
-
masgn: %i[left_value right_value],
|
52
|
-
module: %i[name body],
|
53
|
-
or: %i[left_value right_value],
|
54
|
-
or_asgn: %i[left_value right_value],
|
55
|
-
pair: %i[key value],
|
56
|
-
restarg: %i[name],
|
57
|
-
send: %i[receiver message arguments],
|
58
|
-
super: %i[arguments],
|
59
|
-
zsuper: %i[]
|
60
|
-
}
|
61
|
-
|
62
|
-
# Initialize a Node.
|
63
|
-
#
|
64
|
-
# It extends {Parser::AST::Node} and set parent for its child nodes.
|
65
|
-
def initialize(type, children = [], properties = {})
|
66
|
-
@mutable_attributes = {}
|
67
|
-
super
|
68
|
-
# children could be nil for s(:array)
|
69
|
-
Array(children).each do |child_node|
|
70
|
-
if child_node.is_a?(Parser::AST::Node)
|
71
|
-
child_node.parent = self
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# Get the parent node.
|
77
|
-
# @return [Parser::AST::Node] parent node.
|
78
|
-
def parent
|
79
|
-
@mutable_attributes[:parent]
|
80
|
-
end
|
81
|
-
|
82
|
-
# Set the parent node.
|
83
|
-
# @param node [Parser::AST::Node] parent node.
|
84
|
-
def parent=(node)
|
85
|
-
@mutable_attributes[:parent] = node
|
86
|
-
end
|
87
|
-
|
88
|
-
# Get the sibling nodes.
|
89
|
-
# @return [Array<Parser::AST::Node>] sibling nodes.
|
90
|
-
def siblings
|
91
|
-
index = parent.children.index(self)
|
92
|
-
parent.children[index + 1..]
|
93
|
-
end
|
94
|
-
|
95
|
-
# Dyamically defined method
|
96
|
-
# caller, key, left_value, message, name, pairs, parent_class, parent_const, receivr, rgith_value and value.
|
97
|
-
# based on const TYPE_CHILDREN.
|
98
|
-
%i[
|
99
|
-
caller
|
100
|
-
key
|
101
|
-
left_value
|
102
|
-
message
|
103
|
-
name
|
104
|
-
pairs
|
105
|
-
parent_class
|
106
|
-
parent_const
|
107
|
-
receiver
|
108
|
-
right_value
|
109
|
-
value
|
110
|
-
].each do |method_name|
|
111
|
-
define_method(method_name) do
|
112
|
-
index = TYPE_CHILDREN[type]&.index(method_name)
|
113
|
-
return children[index] if index
|
114
|
-
|
115
|
-
raise Synvert::Core::MethodNotSupported, "#{method_name} is not handled for #{debug_info}"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# Return the left value of node.
|
120
|
-
# It supports :and, :cvagn, :lvasgn, :masgn, :or and :or_asgn nodes.
|
121
|
-
# @example
|
122
|
-
# node # s(:or_asgn, s(:lvasgn, :a), s(:int, 1))
|
123
|
-
# node.left_value # :a
|
124
|
-
# @return [Parser::AST::Node] left value of node.
|
125
|
-
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
126
|
-
def left_value
|
127
|
-
return children[0].children[0] if type == :or_asgn
|
128
|
-
|
129
|
-
index = TYPE_CHILDREN[type]&.index(:left_value)
|
130
|
-
return children[index] if index
|
131
|
-
|
132
|
-
raise Synvert::Core::MethodNotSupported, "#{left_value} is not handled for #{debug_info}"
|
133
|
-
end
|
134
|
-
|
135
|
-
# Get arguments of node.
|
136
|
-
# It supports :block, :csend, :def, :defined?, :defs and :send nodes.
|
137
|
-
# @example
|
138
|
-
# node # s(:send, s(:const, nil, :FactoryGirl), :create, s(:sym, :post), s(:hash, s(:pair, s(:sym, :title), s(:str, "post"))))
|
139
|
-
# node.arguments # [s(:sym, :post), s(:hash, s(:pair, s(:sym, :title), s(:str, "post")))]
|
140
|
-
# @return [Array<Parser::AST::Node>] arguments of node.
|
141
|
-
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
142
|
-
def arguments
|
143
|
-
case type
|
144
|
-
when :def, :block
|
145
|
-
children[1].children
|
146
|
-
when :defs
|
147
|
-
children[2].children
|
148
|
-
when :send, :csend
|
149
|
-
children[2..-1]
|
150
|
-
when :defined?
|
151
|
-
children
|
152
|
-
else
|
153
|
-
raise Synvert::Core::MethodNotSupported, "arguments is not handled for #{debug_info}"
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
# Get body of node.
|
158
|
-
# It supports :begin, :block, :class, :def, :defs and :module node.
|
159
|
-
# @example
|
160
|
-
# node # s(:block, s(:send, s(:const, nil, :RSpec), :configure), s(:args, s(:arg, :config)), s(:send, nil, :include, s(:const, s(:const, nil, :EmailSpec), :Helpers)))
|
161
|
-
# node.body # [s(:send, nil, :include, s(:const, s(:const, nil, :EmailSpec), :Helpers))]
|
162
|
-
# @return [Array<Parser::AST::Node>] body of node.
|
163
|
-
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
164
|
-
def body
|
165
|
-
case type
|
166
|
-
when :begin
|
167
|
-
children
|
168
|
-
when :def, :block, :class, :module
|
169
|
-
return [] if children[2].nil?
|
170
|
-
|
171
|
-
:begin == children[2].type ? children[2].body : children[2..-1]
|
172
|
-
when :defs
|
173
|
-
return [] if children[3].nil?
|
174
|
-
|
175
|
-
:begin == children[3].type ? children[3].body : children[3..-1]
|
176
|
-
else
|
177
|
-
raise Synvert::Core::MethodNotSupported, "body is not handled for #{debug_info}"
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
# Get condition of node.
|
182
|
-
# It supports :if node.
|
183
|
-
# @example
|
184
|
-
# node # s(:if, s(:defined?, s(:const, nil, :Bundler)), nil, nil)
|
185
|
-
# node.condition # s(:defined?, s(:const, nil, :Bundler))
|
186
|
-
# @return [Parser::AST::Node] condition of node.
|
187
|
-
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
188
|
-
def condition
|
189
|
-
if :if == type
|
190
|
-
children[0]
|
191
|
-
else
|
192
|
-
raise Synvert::Core::MethodNotSupported, "condition is not handled for #{debug_info}"
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
# Get keys of :hash node.
|
197
|
-
# @example
|
198
|
-
# node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)), s(:pair, s(:str, "foo"), s(:str, "bar")))
|
199
|
-
# node.keys # [s(:sym, :foo), s(:str, "foo")]
|
200
|
-
# @return [Array<Parser::AST::Node>] keys of node.
|
201
|
-
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
202
|
-
def keys
|
203
|
-
if :hash == type
|
204
|
-
children.map { |child| child.children[0] }
|
205
|
-
else
|
206
|
-
raise Synvert::Core::MethodNotSupported, "keys is not handled for #{debug_info}"
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
# Get values of :hash node.
|
211
|
-
# @example
|
212
|
-
# node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)), s(:pair, s(:str, "foo"), s(:str, "bar")))
|
213
|
-
# node.values # [s(:sym, :bar), s(:str, "bar")]
|
214
|
-
# @return [Array<Parser::AST::Node>] values of node.
|
215
|
-
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
216
|
-
def values
|
217
|
-
if :hash == type
|
218
|
-
children.map { |child| child.children[1] }
|
219
|
-
else
|
220
|
-
raise Synvert::Core::MethodNotSupported, "keys is not handled for #{debug_info}"
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
# Check if :hash node contains specified key.
|
225
|
-
# @example
|
226
|
-
# node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
|
227
|
-
# node.key?(:foo) # true
|
228
|
-
# @param [Symbol, String] key value.
|
229
|
-
# @return [Boolean] true if specified key exists.
|
230
|
-
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
231
|
-
def key?(key)
|
232
|
-
if :hash == type
|
233
|
-
children.any? { |pair_node| pair_node.key.to_value == key }
|
234
|
-
else
|
235
|
-
raise Synvert::Core::MethodNotSupported, "key? is not handled for #{debug_info}"
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
# Get :hash value node according to specified key.
|
240
|
-
# @example
|
241
|
-
# node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
|
242
|
-
# node.hash_value(:foo) # s(:sym, :bar)
|
243
|
-
# @param [Symbol, String] key value.
|
244
|
-
# @return [Parser::AST::Node] hash value of node.
|
245
|
-
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
246
|
-
def hash_value(key)
|
247
|
-
if :hash == type
|
248
|
-
value_node = children.find { |pair_node| pair_node.key.to_value == key }
|
249
|
-
value_node&.value
|
250
|
-
else
|
251
|
-
raise Synvert::Core::MethodNotSupported, "hash_value is not handled for #{debug_info}"
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
# Return the exact value of node.
|
256
|
-
# It supports :array, :begin, :erange, :false, :float, :irange, :int, :str, :sym and :true nodes.
|
257
|
-
# @example
|
258
|
-
# node # s(:array, s(:str, "str"), s(:sym, :str))
|
259
|
-
# node.to_value # ['str', :str]
|
260
|
-
# @return [Object] exact value.
|
261
|
-
# @raise [Synvert::Core::MethodNotSupported] if calls on other node.
|
262
|
-
def to_value
|
263
|
-
case type
|
264
|
-
when :int, :float, :str, :sym
|
265
|
-
children.last
|
266
|
-
when :true
|
267
|
-
true
|
268
|
-
when :false
|
269
|
-
false
|
270
|
-
when :nil
|
271
|
-
nil
|
272
|
-
when :array
|
273
|
-
children.map(&:to_value)
|
274
|
-
when :irange
|
275
|
-
(children.first.to_value..children.last.to_value)
|
276
|
-
when :erange
|
277
|
-
(children.first.to_value...children.last.to_value)
|
278
|
-
when :begin
|
279
|
-
children.first.to_value
|
280
|
-
else
|
281
|
-
self
|
282
|
-
end
|
283
|
-
end
|
284
|
-
|
285
|
-
# Respond key value and source for hash node, e.g.
|
286
|
-
# @example
|
287
|
-
# node # s(:hash, s(:pair, s(:sym, :foo), s(:sym, :bar)))
|
288
|
-
# node.foo_value # :bar
|
289
|
-
# node.foo_source # ":bar"
|
290
|
-
def method_missing(method_name, *args, &block)
|
291
|
-
if :args == type && children.respond_to?(method_name)
|
292
|
-
return children.send(method_name, *args, &block)
|
293
|
-
elsif :hash == type && method_name.to_s.include?('_value')
|
294
|
-
key = method_name.to_s.sub('_value', '')
|
295
|
-
return hash_value(key.to_sym)&.to_value if key?(key.to_sym)
|
296
|
-
return hash_value(key.to_s)&.to_value if key?(key.to_s)
|
297
|
-
|
298
|
-
return nil
|
299
|
-
elsif :hash == type && method_name.to_s.include?('_source')
|
300
|
-
key = method_name.to_s.sub('_source', '')
|
301
|
-
return hash_value(key.to_sym)&.to_source if key?(key.to_sym)
|
302
|
-
return hash_value(key.to_s)&.to_source if key?(key.to_s)
|
303
|
-
|
304
|
-
return nil
|
305
|
-
end
|
306
|
-
|
307
|
-
super
|
308
|
-
end
|
309
|
-
|
310
|
-
def respond_to_missing?(method_name, *args)
|
311
|
-
if :args == type && children.respond_to?(method_name)
|
312
|
-
return true
|
313
|
-
elsif :hash == type && method_name.to_s.include?('_value')
|
314
|
-
key = method_name.to_s.sub('_value', '')
|
315
|
-
return true if key?(key.to_sym) || key?(key.to_s)
|
316
|
-
elsif :hash == type && method_name.to_s.include?('_source')
|
317
|
-
key = method_name.to_s.sub('_source', '')
|
318
|
-
return true if key?(key.to_sym) || key?(key.to_s)
|
319
|
-
end
|
320
|
-
|
321
|
-
super
|
322
|
-
end
|
323
|
-
|
324
|
-
# Return the debug info.
|
325
|
-
#
|
326
|
-
# @return [String] file, line, source and node.
|
327
|
-
def debug_info
|
328
|
-
"\n" +
|
329
|
-
[
|
330
|
-
"file: #{loc.expression.source_buffer.name}",
|
331
|
-
"line: #{loc.expression.line}",
|
332
|
-
"source: #{to_source}",
|
333
|
-
"node: #{inspect}"
|
334
|
-
].join("\n")
|
335
|
-
end
|
336
|
-
|
337
32
|
# Get the file name of node.
|
338
33
|
#
|
339
34
|
# @return [String] file name.
|
@@ -341,13 +36,6 @@ module Parser::AST
|
|
341
36
|
loc.expression&.source_buffer.name
|
342
37
|
end
|
343
38
|
|
344
|
-
# Get the source code of node.
|
345
|
-
#
|
346
|
-
# @return [String] source code.
|
347
|
-
def to_source
|
348
|
-
loc.expression&.source
|
349
|
-
end
|
350
|
-
|
351
39
|
# Get the column of node.
|
352
40
|
#
|
353
41
|
# @return [Integer] column.
|
@@ -362,113 +50,6 @@ module Parser::AST
|
|
362
50
|
loc.expression.line
|
363
51
|
end
|
364
52
|
|
365
|
-
# Get child node by the name.
|
366
|
-
#
|
367
|
-
# @param child_name [String] name of child node.
|
368
|
-
# @return [Parser::AST::Node] the child node.
|
369
|
-
def child_node_by_name(child_name)
|
370
|
-
direct_child_name, nested_child_name = child_name.to_s.split('.', 2)
|
371
|
-
if respond_to?(direct_child_name)
|
372
|
-
child_node = send(direct_child_name)
|
373
|
-
|
374
|
-
return child_node.child_node_by_name(nested_child_name) if nested_child_name
|
375
|
-
|
376
|
-
return nil if child_node.nil?
|
377
|
-
|
378
|
-
return child_node if child_node.is_a?(Parser::AST::Node)
|
379
|
-
|
380
|
-
return child_node
|
381
|
-
end
|
382
|
-
|
383
|
-
raise Synvert::Core::MethodNotSupported,
|
384
|
-
"child_node_by_name is not handled for #{debug_info}, child_name: #{child_name}"
|
385
|
-
end
|
386
|
-
|
387
|
-
# Get the source range of child node.
|
388
|
-
#
|
389
|
-
# @param child_name [String] name of child node.
|
390
|
-
# @return [Parser::Source::Range] source range of child node.
|
391
|
-
def child_node_range(child_name)
|
392
|
-
case [type, child_name.to_sym]
|
393
|
-
when %i[block pipes], %i[def parentheses], %i[defs parentheses]
|
394
|
-
Parser::Source::Range.new(
|
395
|
-
'(string)',
|
396
|
-
arguments.first.loc.expression.begin_pos - 1,
|
397
|
-
arguments.last.loc.expression.end_pos + 1
|
398
|
-
)
|
399
|
-
when %i[block arguments], %i[def arguments], %i[defs arguments]
|
400
|
-
Parser::Source::Range.new(
|
401
|
-
'(string)',
|
402
|
-
arguments.first.loc.expression.begin_pos,
|
403
|
-
arguments.last.loc.expression.end_pos
|
404
|
-
)
|
405
|
-
when %i[class name], %i[def name], %i[defs name]
|
406
|
-
loc.name
|
407
|
-
when %i[defs dot]
|
408
|
-
loc.operator
|
409
|
-
when %i[defs self]
|
410
|
-
Parser::Source::Range.new('(string)', loc.operator.begin_pos - 'self'.length, loc.operator.begin_pos)
|
411
|
-
when %i[send dot], %i[csend dot]
|
412
|
-
loc.dot
|
413
|
-
when %i[send message], %i[csend message]
|
414
|
-
if loc.operator
|
415
|
-
Parser::Source::Range.new('(string)', loc.selector.begin_pos, loc.operator.end_pos)
|
416
|
-
else
|
417
|
-
loc.selector
|
418
|
-
end
|
419
|
-
when %i[send parentheses], %i[csend parentheses]
|
420
|
-
if loc.begin && loc.end
|
421
|
-
Parser::Source::Range.new('(string)', loc.begin.begin_pos, loc.end.end_pos)
|
422
|
-
end
|
423
|
-
else
|
424
|
-
direct_child_name, nested_child_name = child_name.to_s.split('.', 2)
|
425
|
-
if respond_to?(direct_child_name)
|
426
|
-
child_node = send(direct_child_name)
|
427
|
-
|
428
|
-
return child_node.child_node_range(nested_child_name) if nested_child_name
|
429
|
-
|
430
|
-
return nil if child_node.nil?
|
431
|
-
|
432
|
-
if child_node.is_a?(Parser::AST::Node)
|
433
|
-
return(
|
434
|
-
Parser::Source::Range.new(
|
435
|
-
'(string)',
|
436
|
-
child_node.loc.expression.begin_pos,
|
437
|
-
child_node.loc.expression.end_pos
|
438
|
-
)
|
439
|
-
)
|
440
|
-
end
|
441
|
-
|
442
|
-
# arguments
|
443
|
-
return nil if child_node.empty?
|
444
|
-
|
445
|
-
return(
|
446
|
-
Parser::Source::Range.new(
|
447
|
-
'(string)',
|
448
|
-
child_node.first.loc.expression.begin_pos,
|
449
|
-
child_node.last.loc.expression.end_pos
|
450
|
-
)
|
451
|
-
)
|
452
|
-
end
|
453
|
-
|
454
|
-
raise Synvert::Core::MethodNotSupported,
|
455
|
-
"child_node_range is not handled for #{debug_info}, child_name: #{child_name}"
|
456
|
-
end
|
457
|
-
end
|
458
|
-
|
459
|
-
# Recursively iterate all child nodes of node.
|
460
|
-
#
|
461
|
-
# @yield [child] Gives a child node.
|
462
|
-
# @yieldparam child [Parser::AST::Node] child node
|
463
|
-
def recursive_children(&block)
|
464
|
-
children.each do |child|
|
465
|
-
if child.is_a?(Parser::AST::Node)
|
466
|
-
stop = yield child
|
467
|
-
child.recursive_children(&block) unless stop == :stop
|
468
|
-
end
|
469
|
-
end
|
470
|
-
end
|
471
|
-
|
472
53
|
# Match node with rules.
|
473
54
|
# It provides some additional keywords to match rules, +any+, +contain+, +not+, +in+, +not_in+, +gt+, +gte+, +lt+, +lte+.
|
474
55
|
# @example
|
@@ -506,53 +87,6 @@ module Parser::AST
|
|
506
87
|
end
|
507
88
|
end
|
508
89
|
|
509
|
-
# Get rewritten source code.
|
510
|
-
# @example
|
511
|
-
# node.rewritten_source("create({{arguments}})") # "create(:post)"
|
512
|
-
# @param code [String] raw code.
|
513
|
-
# @return [String] rewritten code, replace string in block !{{ }} in raw code.
|
514
|
-
# @raise [Synvert::Core::MethodNotSupported] if string in block !{{ }} does not support.
|
515
|
-
def rewritten_source(code)
|
516
|
-
code.gsub(/{{(.*?)}}/m) do
|
517
|
-
old_code = Regexp.last_match(1)
|
518
|
-
if respond_to?(old_code.split('.').first)
|
519
|
-
evaluated = child_node_by_name(old_code)
|
520
|
-
case evaluated
|
521
|
-
when Parser::AST::Node
|
522
|
-
if evaluated.type == :args
|
523
|
-
evaluated.loc.expression.source[1...-1]
|
524
|
-
else
|
525
|
-
evaluated.loc.expression.source
|
526
|
-
end
|
527
|
-
when Array
|
528
|
-
if evaluated.size > 0
|
529
|
-
file_source = evaluated.first.loc.expression.source_buffer.source
|
530
|
-
source = file_source[evaluated.first.loc.expression.begin_pos...evaluated.last.loc.expression.end_pos]
|
531
|
-
lines = source.split "\n"
|
532
|
-
lines_count = lines.length
|
533
|
-
if lines_count > 1 && lines_count == evaluated.size
|
534
|
-
new_code = []
|
535
|
-
lines.each_with_index { |line, index|
|
536
|
-
new_code << (index == 0 ? line : line[evaluated.first.indent - 2..-1])
|
537
|
-
}
|
538
|
-
new_code.join("\n")
|
539
|
-
else
|
540
|
-
source
|
541
|
-
end
|
542
|
-
end
|
543
|
-
when String, Symbol, Integer, Float
|
544
|
-
evaluated
|
545
|
-
when NilClass
|
546
|
-
'nil'
|
547
|
-
else
|
548
|
-
raise Synvert::Core::MethodNotSupported, "rewritten_source is not handled for #{evaluated.inspect}"
|
549
|
-
end
|
550
|
-
else
|
551
|
-
"{{#{old_code}}}"
|
552
|
-
end
|
553
|
-
end
|
554
|
-
end
|
555
|
-
|
556
90
|
# Strip curly braces for hash.
|
557
91
|
# @example
|
558
92
|
# node # s(:hash, s(:pair, s(:sym, :foo), s(:str, "bar")))
|