synvert-core 1.4.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +0 -1
- data/.gitignore +0 -5
- data/CHANGELOG.md +12 -0
- data/Gemfile +0 -3
- data/Gemfile.lock +101 -0
- data/Guardfile +0 -9
- data/README.md +31 -13
- 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 -639
- 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 -5
- data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +1 -1
- data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +1 -5
- data/lib/synvert/core/rewriter/condition.rb +5 -1
- data/lib/synvert/core/rewriter/instance.rb +91 -140
- data/lib/synvert/core/rewriter/scope/query_scope.rb +8 -6
- data/lib/synvert/core/rewriter/scope/within_scope.rb +4 -87
- 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 -965
- data/spec/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action_spec.rb +21 -1
- data/spec/synvert/core/rewriter/instance_spec.rb +64 -131
- data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +1 -4
- data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +1 -16
- data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +22 -13
- data/synvert-core-ruby.gemspec +5 -3
- metadata +46 -62
- 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
@@ -4,37 +4,40 @@ module Synvert::Core
|
|
4
4
|
# ReplaceErbStmtWithExprAction to replace erb stmt code to expr,
|
5
5
|
# @example
|
6
6
|
# e.g. <% form_for ... %> => <%= form_for ... %>.
|
7
|
-
class Rewriter::ReplaceErbStmtWithExprAction <
|
7
|
+
class Rewriter::ReplaceErbStmtWithExprAction < NodeMutation::Action
|
8
8
|
# Initialize a ReplaceErbStmtWithExprAction.
|
9
9
|
#
|
10
|
-
# @param
|
11
|
-
def initialize(
|
12
|
-
super(
|
10
|
+
# @param node [Synvert::Core::Rewriter::Node]
|
11
|
+
def initialize(node)
|
12
|
+
super(node, nil)
|
13
13
|
end
|
14
14
|
|
15
|
-
# The
|
15
|
+
# The new erb expr code.
|
16
16
|
#
|
17
|
-
# @return [String]
|
18
|
-
def
|
19
|
-
@node
|
20
|
-
|
21
|
-
|
17
|
+
# @return [String] new code.
|
18
|
+
def new_code
|
19
|
+
NodeMutation.adapter.file_content(@node)[@start...@end]
|
20
|
+
.sub(Engine::ERUBY_STMT_SPLITTER, '@output_buffer.append= ')
|
21
|
+
.sub(Engine::ERUBY_STMT_SPLITTER, Engine::ERUBY_EXPR_SPLITTER)
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
26
|
# Calculate the begin the end positions.
|
27
27
|
def calculate_position
|
28
|
-
|
29
|
-
|
28
|
+
node_start = NodeMutation.adapter.get_start(@node)
|
29
|
+
node_source = NodeMutation.adapter.get_source(@node)
|
30
|
+
file_content = NodeMutation.adapter.file_content(@node)
|
31
|
+
|
32
|
+
whitespace_index = node_start
|
33
|
+
while file_content[whitespace_index -= 1] == ' '
|
30
34
|
end
|
31
|
-
@
|
35
|
+
@start = whitespace_index - Engine::ERUBY_STMT_SPLITTER.length + 1
|
32
36
|
|
33
|
-
|
34
|
-
|
35
|
-
while @node.loc.expression.source_buffer.source[node_begin_pos += 1] != '@'
|
37
|
+
at_index = node_start + node_source.index('do')
|
38
|
+
while file_content[at_index += 1] != '@'
|
36
39
|
end
|
37
|
-
@
|
40
|
+
@end = at_index
|
38
41
|
end
|
39
42
|
end
|
40
43
|
end
|
@@ -9,11 +9,7 @@ module Synvert::Core
|
|
9
9
|
#
|
10
10
|
# @return [Boolean]
|
11
11
|
def match?
|
12
|
-
|
13
|
-
@instance.current_node.recursive_children do |child_node|
|
14
|
-
match ||= child_node&.match?(@rules)
|
15
|
-
end
|
16
|
-
match
|
12
|
+
@node_query.query_nodes(target_node, including_self: false, stop_at_first_match: true).size > 0
|
17
13
|
end
|
18
14
|
end
|
19
15
|
end
|
@@ -9,11 +9,7 @@ module Synvert::Core
|
|
9
9
|
#
|
10
10
|
# return [Boolean]
|
11
11
|
def match?
|
12
|
-
|
13
|
-
@instance.current_node.recursive_children do |child_node|
|
14
|
-
match ||= child_node&.match?(@rules)
|
15
|
-
end
|
16
|
-
!match
|
12
|
+
@node_query.query_nodes(target_node, including_self: false, stop_at_first_match: true).size == 0
|
17
13
|
end
|
18
14
|
end
|
19
15
|
end
|
@@ -10,7 +10,7 @@ module Synvert::Core
|
|
10
10
|
# @yield run when condition matches
|
11
11
|
def initialize(instance, rules, &block)
|
12
12
|
@instance = instance
|
13
|
-
@
|
13
|
+
@node_query = NodeQuery.new(rules)
|
14
14
|
@block = block
|
15
15
|
end
|
16
16
|
|
@@ -27,5 +27,9 @@ module Synvert::Core
|
|
27
27
|
def match?
|
28
28
|
raise NotImplementedError, 'must be implemented by subclasses'
|
29
29
|
end
|
30
|
+
|
31
|
+
def target_node
|
32
|
+
@instance.current_node
|
33
|
+
end
|
30
34
|
end
|
31
35
|
end
|
@@ -20,66 +20,13 @@ module Synvert::Core
|
|
20
20
|
rewriter.helpers.each { |helper| singleton_class.send(:define_method, helper[:name], &helper[:block]) }
|
21
21
|
end
|
22
22
|
|
23
|
-
class << self
|
24
|
-
# Get file source.
|
25
|
-
#
|
26
|
-
# @param file_path [String] file path
|
27
|
-
# @return [String] file source
|
28
|
-
def file_source(file_path)
|
29
|
-
@file_source ||= {}
|
30
|
-
@file_source[file_path] ||=
|
31
|
-
begin
|
32
|
-
source = File.read(file_path, encoding: 'UTF-8')
|
33
|
-
source = Engine::ERB.encode(source) if /\.erb$/.match?(file_path)
|
34
|
-
source
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Get file ast.
|
39
|
-
#
|
40
|
-
# @param file_path [String] file path
|
41
|
-
# @return [String] ast node for file
|
42
|
-
def file_ast(file_path)
|
43
|
-
@file_ast ||= {}
|
44
|
-
@file_ast[file_path] ||=
|
45
|
-
begin
|
46
|
-
buffer = Parser::Source::Buffer.new file_path
|
47
|
-
buffer.source = file_source(file_path)
|
48
|
-
|
49
|
-
parser = Parser::CurrentRuby.new
|
50
|
-
parser.reset
|
51
|
-
parser.parse buffer
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
# Write source to file and remove cached file source and ast.
|
56
|
-
#
|
57
|
-
# @param file_path [String] file path
|
58
|
-
# @param source [String] file source
|
59
|
-
def write_file(file_path, source)
|
60
|
-
source = Engine::ERB.decode(source) if /\.erb/.match?(file_path)
|
61
|
-
File.write(file_path, source.gsub(/ +\n/, "\n"))
|
62
|
-
@file_source[file_path] = nil
|
63
|
-
@file_ast[file_path] = nil
|
64
|
-
end
|
65
|
-
|
66
|
-
# Reset file source and ast.
|
67
|
-
def reset
|
68
|
-
@file_source = {}
|
69
|
-
@file_ast = {}
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
23
|
# @!attribute [rw] current_node
|
74
24
|
# @return current parsing node
|
75
25
|
# @!attribute [rw] current_file
|
76
26
|
# @return current filename
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
def file_source
|
81
|
-
self.class.file_source(current_file)
|
82
|
-
end
|
27
|
+
# @!attribute [rw] current_mutation
|
28
|
+
# @return current mutation
|
29
|
+
attr_accessor :current_node, :current_file, :current_mutation
|
83
30
|
|
84
31
|
# Process the instance.
|
85
32
|
# It finds specified files, for each file, it executes the block code, rewrites the original code,
|
@@ -132,11 +79,13 @@ module Synvert::Core
|
|
132
79
|
# # matches FactoryBot.create(:user)
|
133
80
|
# find_node '.send[receiver=FactoryBot][message=create][arguments.size=1]' do
|
134
81
|
# end
|
135
|
-
# @param
|
82
|
+
# @param nql [String] node query language to find matching ast nodes.
|
136
83
|
# @yield run on the matching nodes.
|
137
84
|
# @raise [Synvert::Core::NodeQuery::Compiler::ParseError] if query string is invalid.
|
138
|
-
def find_node(
|
139
|
-
Rewriter::QueryScope.new(self,
|
85
|
+
def find_node(nql, options = {}, &block)
|
86
|
+
Rewriter::QueryScope.new(self, nql, options, &block).process
|
87
|
+
rescue NodeQueryLexer::ScanError, Racc::ParseError => e
|
88
|
+
raise NodeQuery::Compiler::ParseError, "Invalid query string: #{nql}"
|
140
89
|
end
|
141
90
|
|
142
91
|
# Parse +within_node+ dsl, it creates a {Synvert::Core::Rewriter::WithinScope} to recursively find matching ast nodes,
|
@@ -147,12 +96,11 @@ module Synvert::Core
|
|
147
96
|
# end
|
148
97
|
# @param rules [Hash] rules to find mathing ast nodes.
|
149
98
|
# @param options [Hash] optional
|
150
|
-
# @option
|
151
|
-
# @option
|
99
|
+
# @option including_self [Boolean] set if query the current node, default is true
|
100
|
+
# @option stop_at_first_match [Boolean] set if stop at first match, default is false
|
101
|
+
# @option recursive [Boolean] set if recursively query child nodes, default is true
|
152
102
|
# @yield run on the matching nodes.
|
153
103
|
def within_node(rules, options = {}, &block)
|
154
|
-
options[:stop_when_match] ||= false
|
155
|
-
options[:direct] ||= false
|
156
104
|
Rewriter::WithinScope.new(self, rules, options, &block).process
|
157
105
|
end
|
158
106
|
|
@@ -231,7 +179,7 @@ module Synvert::Core
|
|
231
179
|
# end
|
232
180
|
# @param code [String] code need to be appended.
|
233
181
|
def append(code)
|
234
|
-
@
|
182
|
+
@current_mutation.append(@current_node, code)
|
235
183
|
end
|
236
184
|
|
237
185
|
# Parse +prepend+ dsl, it creates a {Synvert::Core::Rewriter::PrependAction} to
|
@@ -250,7 +198,7 @@ module Synvert::Core
|
|
250
198
|
# end
|
251
199
|
# @param code [String] code need to be prepended.
|
252
200
|
def prepend(code)
|
253
|
-
@
|
201
|
+
@current_mutation.prepend(@current_node, code)
|
254
202
|
end
|
255
203
|
|
256
204
|
# Parse +insert+ dsl, it creates a {Synvert::Core::Rewriter::InsertAction} to insert code.
|
@@ -265,7 +213,7 @@ module Synvert::Core
|
|
265
213
|
# @param at [String] insert position, beginning or end
|
266
214
|
# @param to [String] where to insert, if it is nil, will insert to current node.
|
267
215
|
def insert(code, at: 'end', to: nil)
|
268
|
-
@
|
216
|
+
@current_mutation.insert(@current_node, code, at: at, to: to)
|
269
217
|
end
|
270
218
|
|
271
219
|
# Parse +insert_after+ dsl, it creates a {Synvert::Core::Rewriter::InsertAfterAction} to
|
@@ -280,7 +228,22 @@ module Synvert::Core
|
|
280
228
|
# end
|
281
229
|
# @param code [String] code need to be inserted.
|
282
230
|
def insert_after(code)
|
283
|
-
@
|
231
|
+
@current_mutation.insert_after(@current_node, code)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Parse +replace_erb_stmt_with_expr+ dsl, it creates a {Synvert::Core::Rewriter::ReplaceErbStmtWithExprAction} to
|
235
|
+
# replace erb stmt code to expr code.
|
236
|
+
# @example
|
237
|
+
# # <% form_for post do |f| %>
|
238
|
+
# # <% end %>
|
239
|
+
# # =>
|
240
|
+
# # <%= form_for post do |f| %>
|
241
|
+
# # <% end %>
|
242
|
+
# with_node type: 'block', caller: { type: 'send', receiver: nil, message: 'form_for' } do
|
243
|
+
# replace_erb_stmt_with_expr
|
244
|
+
# end
|
245
|
+
def replace_erb_stmt_with_expr
|
246
|
+
@current_mutation.actions << Rewriter::ReplaceErbStmtWithExprAction.new(@current_node).process
|
284
247
|
end
|
285
248
|
|
286
249
|
# Parse +replace_with+ dsl, it creates a {Synvert::Core::Rewriter::ReplaceWithAction} to
|
@@ -294,7 +257,7 @@ module Synvert::Core
|
|
294
257
|
# end
|
295
258
|
# @param code [String] code need to be replaced with.
|
296
259
|
def replace_with(code)
|
297
|
-
@
|
260
|
+
@current_mutation.replace_with(@current_node, code)
|
298
261
|
end
|
299
262
|
|
300
263
|
# Parse +replace+ dsl, it creates a {Synvert::Core::Rewriter::ReplaceAction} to
|
@@ -310,22 +273,7 @@ module Synvert::Core
|
|
310
273
|
# @param selectors [Array<Symbol>] selector names of child node.
|
311
274
|
# @param with [String] code need to be replaced with.
|
312
275
|
def replace(*selectors, with:)
|
313
|
-
@
|
314
|
-
end
|
315
|
-
|
316
|
-
# Parse +replace_erb_stmt_with_expr+ dsl, it creates a {Synvert::Core::Rewriter::ReplaceErbStmtWithExprAction} to
|
317
|
-
# replace erb stmt code to expr code.
|
318
|
-
# @example
|
319
|
-
# # <% form_for post do |f| %>
|
320
|
-
# # <% end %>
|
321
|
-
# # =>
|
322
|
-
# # <%= form_for post do |f| %>
|
323
|
-
# # <% end %>
|
324
|
-
# with_node type: 'block', caller: { type: 'send', receiver: nil, message: 'form_for' } do
|
325
|
-
# replace_erb_stmt_with_expr
|
326
|
-
# end
|
327
|
-
def replace_erb_stmt_with_expr
|
328
|
-
@actions << Rewriter::ReplaceErbStmtWithExprAction.new(self).process
|
276
|
+
@current_mutation.replace(@current_node, *selectors, with: with)
|
329
277
|
end
|
330
278
|
|
331
279
|
# Parse +remove+ dsl, it creates a {Synvert::Core::Rewriter::RemoveAction} to remove current node.
|
@@ -336,7 +284,7 @@ module Synvert::Core
|
|
336
284
|
# @param options [Hash] options.
|
337
285
|
# @option and_comma [Boolean] delete extra comma.
|
338
286
|
def remove(**options)
|
339
|
-
@
|
287
|
+
@current_mutation.remove(@current_node, **options)
|
340
288
|
end
|
341
289
|
|
342
290
|
# Parse +delete+ dsl, it creates a {Synvert::Core::Rewriter::DeleteAction} to delete child nodes.
|
@@ -351,7 +299,7 @@ module Synvert::Core
|
|
351
299
|
# @param options [Hash]
|
352
300
|
# @option and_comma [Boolean] delete extra comma.
|
353
301
|
def delete(*selectors, **options)
|
354
|
-
@
|
302
|
+
@current_mutation.delete(@current_node, *selectors, **options)
|
355
303
|
end
|
356
304
|
|
357
305
|
# Parse +wrap+ dsl, it creates a {Synvert::Core::Rewriter::WrapAction} to
|
@@ -368,9 +316,8 @@ module Synvert::Core
|
|
368
316
|
# wrap with: 'module Synvert'
|
369
317
|
# end
|
370
318
|
# @param with [String] code need to be wrapped with.
|
371
|
-
|
372
|
-
|
373
|
-
@actions << Rewriter::WrapAction.new(self, with: with, indent: indent).process
|
319
|
+
def wrap(with:)
|
320
|
+
@current_mutation.wrap(@current_node, with: with)
|
374
321
|
end
|
375
322
|
|
376
323
|
# Parse +warn+ dsl, it creates a {Synvert::Core::Rewriter::Warning} to save warning message.
|
@@ -397,65 +344,69 @@ module Synvert::Core
|
|
397
344
|
#
|
398
345
|
# @param file_path [String]
|
399
346
|
def process_file(file_path)
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
source[action.begin_pos...action.end_pos] = action.rewritten_code
|
347
|
+
puts file_path if Configuration.show_run_process
|
348
|
+
|
349
|
+
@current_file = file_path
|
350
|
+
while true
|
351
|
+
source = read_source(file_path)
|
352
|
+
@current_mutation = NodeMutation.new(source)
|
353
|
+
begin
|
354
|
+
node = parse_code(file_path, source)
|
355
|
+
|
356
|
+
process_with_node(node) do
|
357
|
+
instance_eval(&@block)
|
358
|
+
rescue NoMethodError => e
|
359
|
+
puts [
|
360
|
+
"error: #{e.message}",
|
361
|
+
"file: #{file_path}",
|
362
|
+
"source: #{source}",
|
363
|
+
"line: #{current_node.line}"
|
364
|
+
].join("\n")
|
365
|
+
raise
|
420
366
|
end
|
421
|
-
@actions = []
|
422
367
|
|
423
|
-
|
368
|
+
result = @current_mutation.process
|
369
|
+
if result.affected?
|
370
|
+
@rewriter.add_affected_file(file_path)
|
371
|
+
write_source(file_path, result.new_source)
|
372
|
+
end
|
373
|
+
break unless result.conflicted?
|
374
|
+
rescue Parser::SyntaxError
|
375
|
+
puts "[Warn] file #{file_path} was not parsed correctly."
|
376
|
+
# do nothing, iterate next file
|
424
377
|
end
|
425
|
-
|
426
|
-
puts "[Warn] file #{file_path} was not parsed correctly."
|
427
|
-
# do nothing, iterate next file
|
428
|
-
end while !conflict_actions.empty?
|
378
|
+
end
|
429
379
|
end
|
430
380
|
|
431
|
-
#
|
432
|
-
#
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
end
|
447
|
-
j -= 1
|
448
|
-
end
|
449
|
-
conflict_actions
|
381
|
+
# Read file source.
|
382
|
+
# @param file_path [String] file path
|
383
|
+
# @return [String] file source
|
384
|
+
def read_source(file_path)
|
385
|
+
source = File.read(file_path, encoding: 'UTF-8')
|
386
|
+
source = Engine::Erb.encode(source) if /\.erb$/.match?(file_path)
|
387
|
+
source
|
388
|
+
end
|
389
|
+
|
390
|
+
# Write file source to file.
|
391
|
+
# @param file_path [String] file path
|
392
|
+
# @param source [String] file source
|
393
|
+
def write_source(file_path, source)
|
394
|
+
source = Engine::Erb.decode(source) if /\.erb/.match?(file_path)
|
395
|
+
File.write(file_path, source.gsub(/ +\n/, "\n"))
|
450
396
|
end
|
451
397
|
|
452
|
-
#
|
398
|
+
# Parse code ast node.
|
453
399
|
#
|
454
|
-
# @param file_path [String]
|
455
|
-
# @param
|
456
|
-
|
457
|
-
|
458
|
-
|
400
|
+
# @param file_path [String] file path
|
401
|
+
# @param file_path [String] file path
|
402
|
+
# @return [Node] ast node for file
|
403
|
+
def parse_code(file_path, source)
|
404
|
+
buffer = Parser::Source::Buffer.new file_path
|
405
|
+
buffer.source = source
|
406
|
+
|
407
|
+
parser = Parser::CurrentRuby.new
|
408
|
+
parser.reset
|
409
|
+
parser.parse buffer
|
459
410
|
end
|
460
411
|
end
|
461
412
|
end
|
@@ -6,11 +6,14 @@ module Synvert::Core
|
|
6
6
|
# Initialize a QueryScope.
|
7
7
|
#
|
8
8
|
# @param instance [Synvert::Core::Rewriter::Instance]
|
9
|
-
# @param
|
9
|
+
# @param nql [String]
|
10
|
+
# @param options [Hash]
|
10
11
|
# @yield run on all matching nodes
|
11
|
-
def initialize(instance,
|
12
|
+
def initialize(instance, nql, options = {}, &block)
|
12
13
|
super(instance, &block)
|
13
|
-
|
14
|
+
|
15
|
+
@options = { including_self: true, stop_at_first_match: false, recursive: true }.merge(options)
|
16
|
+
@node_query = NodeQuery.new(nql)
|
14
17
|
end
|
15
18
|
|
16
19
|
# Find out the matching nodes.
|
@@ -22,15 +25,14 @@ module Synvert::Core
|
|
22
25
|
current_node = @instance.current_node
|
23
26
|
return unless current_node
|
24
27
|
|
28
|
+
matching_nodes = @node_query.query_nodes(current_node, @options)
|
25
29
|
@instance.process_with_node(current_node) do
|
26
|
-
|
30
|
+
matching_nodes.each do |node|
|
27
31
|
@instance.process_with_node(node) do
|
28
32
|
@instance.instance_eval(&@block)
|
29
33
|
end
|
30
34
|
end
|
31
35
|
end
|
32
|
-
rescue NodeQuery::Lexer::ScanError, Racc::ParseError => e
|
33
|
-
raise NodeQuery::Compiler::ParseError, "Invalid query string: #{@query_string}"
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
@@ -11,8 +11,9 @@ module Synvert::Core
|
|
11
11
|
# @yield run on all matching nodes
|
12
12
|
def initialize(instance, rules, options = {}, &block)
|
13
13
|
super(instance, &block)
|
14
|
-
|
15
|
-
@options = options
|
14
|
+
|
15
|
+
@options = { including_self: true, stop_at_first_match: false, recursive: true }.merge(options)
|
16
|
+
@node_query = NodeQuery.new(rules)
|
16
17
|
end
|
17
18
|
|
18
19
|
# Find out the matching nodes.
|
@@ -22,14 +23,7 @@ module Synvert::Core
|
|
22
23
|
current_node = @instance.current_node
|
23
24
|
return unless current_node
|
24
25
|
|
25
|
-
matching_nodes =
|
26
|
-
if @options[:direct]
|
27
|
-
find_direct_matching_nodes(current_node)
|
28
|
-
elsif @options[:stop_when_match]
|
29
|
-
find_matching_nodes(current_node)
|
30
|
-
else
|
31
|
-
find_recursive_matching_nodes(current_node)
|
32
|
-
end
|
26
|
+
matching_nodes = @node_query.query_nodes(current_node, @options)
|
33
27
|
@instance.process_with_node current_node do
|
34
28
|
matching_nodes.each do |matching_node|
|
35
29
|
@instance.process_with_node matching_node do
|
@@ -38,82 +32,5 @@ module Synvert::Core
|
|
38
32
|
end
|
39
33
|
end
|
40
34
|
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
# Find the matching nodes only in current or direct children.
|
45
|
-
#
|
46
|
-
# @param current_node [Parser::AST::Node]
|
47
|
-
def find_direct_matching_nodes(current_node)
|
48
|
-
matching_nodes = []
|
49
|
-
if current_node.is_a?(Parser::AST::Node)
|
50
|
-
if current_node.type == :begin
|
51
|
-
current_node.children.each do |child_node|
|
52
|
-
matching_nodes << child_node if child_node.match?(@rules)
|
53
|
-
end
|
54
|
-
elsif current_node.match?(@rules)
|
55
|
-
matching_nodes << current_node
|
56
|
-
end
|
57
|
-
else
|
58
|
-
current_node.each do |child_node|
|
59
|
-
matching_nodes << child_node if child_node.match?(@rules)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
matching_nodes
|
63
|
-
end
|
64
|
-
|
65
|
-
# Find matching nodes in all recursive children.
|
66
|
-
#
|
67
|
-
# @param current_node [Parser::AST::Node]
|
68
|
-
def find_recursive_matching_nodes(current_node)
|
69
|
-
matching_nodes = []
|
70
|
-
if current_node.is_a?(Parser::AST::Node)
|
71
|
-
matching_nodes << current_node if current_node.match?(@rules)
|
72
|
-
current_node.recursive_children do |child_node|
|
73
|
-
matching_nodes << child_node if child_node.match?(@rules)
|
74
|
-
end
|
75
|
-
else
|
76
|
-
current_node.each do |node|
|
77
|
-
matching_nodes << node if node.match?(@rules)
|
78
|
-
node.recursive_children do |child_node|
|
79
|
-
matching_nodes << child_node if child_node.match?(@rules)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
matching_nodes
|
84
|
-
end
|
85
|
-
|
86
|
-
# Find matching nodes in recursive children but do not continue on matching nodes.
|
87
|
-
#
|
88
|
-
# @param current_node [Parser::AST::Node]
|
89
|
-
def find_matching_nodes(current_node)
|
90
|
-
matching_nodes = []
|
91
|
-
if current_node.is_a?(Parser::AST::Node)
|
92
|
-
if current_node.match?(@rules)
|
93
|
-
matching_nodes << current_node
|
94
|
-
return matching_nodes
|
95
|
-
end
|
96
|
-
current_node.recursive_children do |child_node|
|
97
|
-
if child_node.match?(@rules)
|
98
|
-
matching_nodes << child_node
|
99
|
-
next :stop
|
100
|
-
end
|
101
|
-
end
|
102
|
-
else
|
103
|
-
current_node.each do |node|
|
104
|
-
if node.match?(@rules)
|
105
|
-
matching_nodes << node
|
106
|
-
next
|
107
|
-
end
|
108
|
-
node.recursive_children do |child_node|
|
109
|
-
if child_node.match?(@rules)
|
110
|
-
matching_nodes << child_node
|
111
|
-
next :stop
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
matching_nodes
|
117
|
-
end
|
118
35
|
end
|
119
36
|
end
|
@@ -8,17 +8,7 @@ module Synvert::Core
|
|
8
8
|
# One Rewriter checks if the depndency version matches, and it can contain one or many {Synvert::Core::Rewriter::Instance},
|
9
9
|
# which define the behavior what files and what codes to detect and rewrite to what code.
|
10
10
|
class Rewriter
|
11
|
-
autoload :Action, 'synvert/core/rewriter/action'
|
12
|
-
autoload :AppendAction, 'synvert/core/rewriter/action/append_action'
|
13
|
-
autoload :DeleteAction, 'synvert/core/rewriter/action/delete_action'
|
14
|
-
autoload :InsertAction, 'synvert/core/rewriter/action/insert_action'
|
15
|
-
autoload :InsertAfterAction, 'synvert/core/rewriter/action/insert_after_action'
|
16
|
-
autoload :RemoveAction, 'synvert/core/rewriter/action/remove_action'
|
17
|
-
autoload :PrependAction, 'synvert/core/rewriter/action/prepend_action'
|
18
|
-
autoload :ReplaceAction, 'synvert/core/rewriter/action/replace_action'
|
19
11
|
autoload :ReplaceErbStmtWithExprAction, 'synvert/core/rewriter/action/replace_erb_stmt_with_expr_action'
|
20
|
-
autoload :ReplaceWithAction, 'synvert/core/rewriter/action/replace_with_action'
|
21
|
-
autoload :WrapAction, 'synvert/core/rewriter/action/wrap_action'
|
22
12
|
|
23
13
|
autoload :Warning, 'synvert/core/rewriter/warning'
|
24
14
|
|
data/lib/synvert/core/version.rb
CHANGED
data/lib/synvert/core.rb
CHANGED
@@ -4,14 +4,13 @@ require 'synvert/core/version'
|
|
4
4
|
require 'bundler'
|
5
5
|
require 'parser'
|
6
6
|
require 'parser/current'
|
7
|
-
require '
|
7
|
+
require 'parser_node_ext'
|
8
|
+
require_relative './core/node_ext'
|
8
9
|
require 'active_support'
|
9
|
-
require 'active_support/core_ext/object'
|
10
|
-
require 'active_support/core_ext/array'
|
11
10
|
require 'erubis'
|
12
11
|
require 'set'
|
13
|
-
require '
|
14
|
-
require '
|
12
|
+
require 'node_query'
|
13
|
+
require 'node_mutation'
|
15
14
|
|
16
15
|
module Synvert
|
17
16
|
module Core
|
@@ -20,7 +19,6 @@ module Synvert
|
|
20
19
|
autoload :Engine, 'synvert/core/engine'
|
21
20
|
autoload :RewriterNotFound, 'synvert/core/exceptions'
|
22
21
|
autoload :MethodNotSupported, 'synvert/core/exceptions'
|
23
|
-
autoload :NodeQuery, 'synvert/core/node_query'
|
24
22
|
end
|
25
23
|
end
|
26
24
|
|