synvert-core 0.52.0 → 0.54.1
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/CHANGELOG.md +13 -0
- data/README.md +7 -8
- data/lib/synvert/core/node_ext.rb +24 -21
- data/lib/synvert/core/rewriter/action/delete_action.rb +3 -3
- data/lib/synvert/core/rewriter/action/insert_action.rb +1 -1
- data/lib/synvert/core/rewriter/action/remove_action.rb +31 -5
- data/lib/synvert/core/rewriter/instance.rb +9 -24
- data/lib/synvert/core/rewriter/scope/goto_scope.rb +4 -4
- data/lib/synvert/core/rewriter.rb +6 -27
- data/lib/synvert/core/version.rb +1 -1
- data/spec/synvert/core/node_ext_spec.rb +6 -0
- data/spec/synvert/core/rewriter/action/remove_action_spec.rb +2 -2
- data/spec/synvert/core/rewriter/instance_spec.rb +2 -2
- data/spec/synvert/core/rewriter/scope/goto_scope_spec.rb +1 -1
- data/spec/synvert/core/rewriter_spec.rb +0 -11
- data/{synvert-core.gemspec → synvert-core-ruby.gemspec} +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dce993d0b27272e83abe3bd3a1ff2a9917a2c9953bb30e57671216aed001292c
|
4
|
+
data.tar.gz: 0b65093ca670d59065707e122a9964f163fbca2e4201fd75005295b7841e4db1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bb49555a37b7778e37216f267b0e2ab938030ac5428f7bbef60d8462fb83597693bad9a5cd12c43c52a80330de48662151abbcc8edebb7572538f1520539bac
|
7
|
+
data.tar.gz: eaf5690913c21c3b043f5119f2b8b4afe08c16c5a9db8d9d209a42f0a64a72d4f19376da6dee6ed43b04b79d8077f4463a47acb5d18742a6dcb1499b3191db7a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 0.54.1 (2021-09-08)
|
4
|
+
|
5
|
+
* Rewrite `remove` action
|
6
|
+
|
7
|
+
## 0.54.0 (2021-08-28)
|
8
|
+
|
9
|
+
* Change `goto_scope` param from array to string
|
10
|
+
|
11
|
+
## 0.53.0 (2021-08-22)
|
12
|
+
|
13
|
+
* Fix nested child in Node#child_node_range
|
14
|
+
* Rename synvert-core to synvert-core-ruby
|
15
|
+
|
3
16
|
## 0.52.0 (2021-08-21)
|
4
17
|
|
5
18
|
* ``Node#child_node_range`` supports nested child
|
data/README.md
CHANGED
@@ -1,12 +1,11 @@
|
|
1
|
-
#
|
1
|
+
# synvert-core-ruby
|
2
2
|
|
3
|
-
<img src="https://xinminlabs.
|
3
|
+
<img src="https://synvert.xinminlabs.com/img/logo_96.png" alt="logo" width="32" height="32" />
|
4
4
|
|
5
|
-

|
6
|
-
[](https://coveralls.io/r/xinminlabs/synvert-core)
|
5
|
+

|
7
6
|
[](http://badge.fury.io/rb/synvert-core)
|
8
7
|
|
9
|
-
synvert-core provides a dsl to convert ruby source code.
|
8
|
+
synvert-core-ruby provides a dsl to convert ruby source code.
|
10
9
|
|
11
10
|
## Installation
|
12
11
|
|
@@ -31,11 +30,11 @@ Or install it yourself as:
|
|
31
30
|
|
32
31
|
## Contributing
|
33
32
|
|
34
|
-
1. Fork it ( https://github.com/[my-github-username]/synvert-core/fork )
|
33
|
+
1. Fork it ( https://github.com/[my-github-username]/synvert-core-ruby/fork )
|
35
34
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
36
35
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
37
36
|
4. Push to the branch (`git push origin my-new-feature`)
|
38
37
|
5. Create a new Pull Request
|
39
38
|
|
40
|
-
[1]: https://xinminlabs.
|
41
|
-
[2]: https://rubydoc.info/github/xinminlabs/synvert-core/master/frames
|
39
|
+
[1]: https://synvert.xinminlabs.com
|
40
|
+
[2]: https://rubydoc.info/github/xinminlabs/synvert-core-ruby/master/frames
|
@@ -341,7 +341,7 @@ module Parser::AST
|
|
341
341
|
# @param [String] name of child node.
|
342
342
|
# @return [Parser::Source::Range] source range of child node.
|
343
343
|
def child_node_range(child_name)
|
344
|
-
case [type, child_name]
|
344
|
+
case [type, child_name.to_sym]
|
345
345
|
when %i[block pipes], %i[def parentheses], %i[defs parentheses]
|
346
346
|
Parser::Source::Range.new('(string)', arguments.loc.expression.begin_pos, arguments.loc.expression.end_pos)
|
347
347
|
when %i[block arguments], %i[def arguments], %i[defs arguments]
|
@@ -369,35 +369,38 @@ module Parser::AST
|
|
369
369
|
Parser::Source::Range.new('(string)', loc.begin.begin_pos, loc.end.end_pos)
|
370
370
|
end
|
371
371
|
else
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
372
|
+
direct_child_name, nested_child_name = child_name.to_s.split('.', 2)
|
373
|
+
if respond_to?(direct_child_name)
|
374
|
+
child_node = send(direct_child_name)
|
375
|
+
|
376
|
+
return child_node.child_node_range(nested_child_name) if nested_child_name
|
377
|
+
|
378
|
+
return nil if child_node.nil?
|
379
|
+
|
380
|
+
if child_node.is_a?(Parser::AST::Node)
|
381
|
+
return(
|
382
|
+
Parser::Source::Range.new(
|
383
|
+
'(string)',
|
384
|
+
child_node.loc.expression.begin_pos,
|
385
|
+
child_node.loc.expression.end_pos
|
386
|
+
)
|
387
|
+
)
|
380
388
|
end
|
381
|
-
end
|
382
389
|
|
383
|
-
|
390
|
+
# arguments
|
391
|
+
return nil if child_node.empty?
|
392
|
+
|
384
393
|
return(
|
385
394
|
Parser::Source::Range.new(
|
386
395
|
'(string)',
|
387
|
-
child_node.loc.expression.begin_pos,
|
388
|
-
child_node.loc.expression.end_pos
|
396
|
+
child_node.first.loc.expression.begin_pos,
|
397
|
+
child_node.last.loc.expression.end_pos
|
389
398
|
)
|
390
399
|
)
|
391
400
|
end
|
392
401
|
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
Parser::Source::Range.new(
|
397
|
-
'(string)',
|
398
|
-
child_node.first.loc.expression.begin_pos,
|
399
|
-
child_node.last.loc.expression.end_pos
|
400
|
-
)
|
402
|
+
raise Synvert::Core::MethodNotSupported,
|
403
|
+
"child_node_range is not handled for #{debug_info}, child_name: #{child_name}"
|
401
404
|
end
|
402
405
|
end
|
403
406
|
|
@@ -1,21 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Synvert::Core
|
4
|
-
#
|
4
|
+
# DeleteAction to delete child nodes.
|
5
5
|
class Rewriter::DeleteAction < Rewriter::Action
|
6
6
|
def initialize(instance, *selectors)
|
7
7
|
super(instance, nil)
|
8
8
|
@selectors = selectors
|
9
9
|
end
|
10
10
|
|
11
|
-
# Begin position of code to
|
11
|
+
# Begin position of code to delete.
|
12
12
|
#
|
13
13
|
# @return [Integer] begin position.
|
14
14
|
def begin_pos
|
15
15
|
@selectors.map { |selector| @node.child_node_range(selector) }.compact.map(&:begin_pos).min
|
16
16
|
end
|
17
17
|
|
18
|
-
# End position of code to
|
18
|
+
# End position of code to delete.
|
19
19
|
#
|
20
20
|
# @return [Integer] end position.
|
21
21
|
def end_pos
|
@@ -1,29 +1,55 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Synvert::Core
|
4
|
-
# RemoveAction to remove
|
4
|
+
# RemoveAction to remove current node.
|
5
5
|
class Rewriter::RemoveAction < Rewriter::Action
|
6
|
-
def initialize(instance
|
7
|
-
super
|
6
|
+
def initialize(instance)
|
7
|
+
super(instance, nil)
|
8
8
|
end
|
9
9
|
|
10
10
|
# Begin position of code to replace.
|
11
11
|
#
|
12
12
|
# @return [Integer] begin position.
|
13
13
|
def begin_pos
|
14
|
-
|
14
|
+
if take_whole_line?
|
15
|
+
start_index
|
16
|
+
else
|
17
|
+
@node.loc.expression.begin_pos
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
21
|
# End position of code to replace.
|
18
22
|
#
|
19
23
|
# @return [Integer] end position.
|
20
24
|
def end_pos
|
21
|
-
|
25
|
+
if take_whole_line?
|
26
|
+
end_index
|
27
|
+
else
|
28
|
+
@node.loc.expression.end_pos
|
29
|
+
end
|
22
30
|
end
|
23
31
|
|
24
32
|
# The rewritten code, always empty string.
|
25
33
|
def rewritten_code
|
26
34
|
''
|
27
35
|
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def take_whole_line?
|
40
|
+
@node.to_source == file_source[start_index...end_index].strip
|
41
|
+
end
|
42
|
+
|
43
|
+
def start_index
|
44
|
+
file_source[0..@node.loc.expression.begin_pos].rindex("\n") + "\n".length
|
45
|
+
end
|
46
|
+
|
47
|
+
def end_index
|
48
|
+
file_source[@node.loc.expression.end_pos..-1].index("\n") + @node.loc.expression.end_pos + "\n".length
|
49
|
+
end
|
50
|
+
|
51
|
+
def file_source
|
52
|
+
@file_source ||= @instance.file_source
|
53
|
+
end
|
28
54
|
end
|
29
55
|
end
|
@@ -64,6 +64,11 @@ module Synvert::Core
|
|
64
64
|
# @return current filename
|
65
65
|
attr_accessor :current_node, :current_file
|
66
66
|
|
67
|
+
# Current file source
|
68
|
+
def file_source
|
69
|
+
self.class.file_source(current_file)
|
70
|
+
end
|
71
|
+
|
67
72
|
# Initialize an instance.
|
68
73
|
#
|
69
74
|
# @param rewriter [Synvert::Core::Rewriter]
|
@@ -107,7 +112,6 @@ module Synvert::Core
|
|
107
112
|
conflict_actions = get_conflict_actions
|
108
113
|
@actions.reverse_each do |action|
|
109
114
|
source[action.begin_pos...action.end_pos] = action.rewritten_code
|
110
|
-
source = remove_code_or_whole_line(source, action.line)
|
111
115
|
end
|
112
116
|
@actions = []
|
113
117
|
|
@@ -139,7 +143,7 @@ module Synvert::Core
|
|
139
143
|
|
140
144
|
# Set current_node properly, process and set current_node back to original current_node.
|
141
145
|
#
|
142
|
-
# @param node [Parser::AST::Node] node set to
|
146
|
+
# @param node [Parser::AST::Node] node set to other_node
|
143
147
|
# @yield process
|
144
148
|
def process_with_other_node(node)
|
145
149
|
original_node = current_node
|
@@ -177,10 +181,10 @@ module Synvert::Core
|
|
177
181
|
# Parse goto_node dsl, it creates a [Synvert::Core::Rewriter::GotoScope] to go to a child node,
|
178
182
|
# then continue operating on the child node.
|
179
183
|
#
|
180
|
-
# @param
|
184
|
+
# @param child_node_name [Symbol|String] the name of the child nodes.
|
181
185
|
# @param block [Block] block code to continue operating on the matching nodes.
|
182
|
-
def goto_node(
|
183
|
-
Rewriter::GotoScope.new(self,
|
186
|
+
def goto_node(child_node_name, &block)
|
187
|
+
Rewriter::GotoScope.new(self, child_node_name, &block).process
|
184
188
|
end
|
185
189
|
|
186
190
|
# Parse if_exist_node dsl, it creates a [Synvert::Core::Rewriter::IfExistCondition] to check
|
@@ -323,25 +327,6 @@ module Synvert::Core
|
|
323
327
|
conflict_actions
|
324
328
|
end
|
325
329
|
|
326
|
-
# It checks if code is removed and that line is empty.
|
327
|
-
#
|
328
|
-
# @param source [String] source code of file
|
329
|
-
# @param line [String] the line number
|
330
|
-
def remove_code_or_whole_line(source, line)
|
331
|
-
newline_at_end_of_line = source[-1] == "\n"
|
332
|
-
source_arr = source.split("\n")
|
333
|
-
if source_arr[line - 1] && source_arr[line - 1].strip.empty?
|
334
|
-
source_arr.delete_at(line - 1)
|
335
|
-
if source_arr[line - 2] && source_arr[line - 2].strip.empty? && source_arr[line - 1] &&
|
336
|
-
source_arr[line - 1].strip.empty?
|
337
|
-
source_arr.delete_at(line - 1)
|
338
|
-
end
|
339
|
-
source_arr.join("\n") + (newline_at_end_of_line ? "\n" : '')
|
340
|
-
else
|
341
|
-
source
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
330
|
# It updates a file with new source code.
|
346
331
|
#
|
347
332
|
# @param file_path [String] the file path
|
@@ -6,11 +6,11 @@ module Synvert::Core
|
|
6
6
|
# Initialize a scope
|
7
7
|
#
|
8
8
|
# @param instance [Synvert::Core::Rewriter::Instance]
|
9
|
-
# @param
|
9
|
+
# @param child_node_name [Symbol|string]
|
10
10
|
# @param block [Block]
|
11
|
-
def initialize(instance,
|
11
|
+
def initialize(instance, child_node_name, &block)
|
12
12
|
@instance = instance
|
13
|
-
@
|
13
|
+
@child_node_name = child_node_name
|
14
14
|
@block = block
|
15
15
|
end
|
16
16
|
|
@@ -20,7 +20,7 @@ module Synvert::Core
|
|
20
20
|
return unless current_node
|
21
21
|
|
22
22
|
child_node = current_node
|
23
|
-
@
|
23
|
+
@child_node_name.to_s.split('.').each do |child_node_name|
|
24
24
|
child_node = child_node_name.is_a?(Parser::AST::Node) ? child_node_name : child_node.send(child_node_name)
|
25
25
|
end
|
26
26
|
@instance.process_with_other_node child_node do
|
@@ -81,7 +81,7 @@ module Synvert::Core
|
|
81
81
|
def fetch(group, name)
|
82
82
|
group = group.to_s
|
83
83
|
name = name.to_s
|
84
|
-
if
|
84
|
+
if rewriters[group] && rewriters[group][name]
|
85
85
|
rewriters[group][name]
|
86
86
|
else
|
87
87
|
raise RewriterNotFound, "Rewriter #{group} #{name} not found"
|
@@ -96,34 +96,13 @@ module Synvert::Core
|
|
96
96
|
# @return [Synvert::Core::Rewriter] the registered rewriter.
|
97
97
|
# @raise [Synvert::Core::RewriterNotFound] if the registered rewriter is not found.
|
98
98
|
def call(group, name, sandbox = false)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
rewriter = rewriters[group][name]
|
103
|
-
if sandbox
|
104
|
-
rewriter.process_with_sandbox
|
105
|
-
else
|
106
|
-
rewriter.process
|
107
|
-
end
|
108
|
-
rewriter
|
109
|
-
else
|
110
|
-
raise RewriterNotFound, "Rewriter #{group}/#{name} not found"
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
# Check if one rewriter exist.
|
115
|
-
#
|
116
|
-
# @param group [String] the rewriter group.
|
117
|
-
# @param name [String] the rewriter name.
|
118
|
-
# @return [Boolean] true if the rewriter exist.
|
119
|
-
def exist?(group, name)
|
120
|
-
group = group.to_s
|
121
|
-
name = name.to_s
|
122
|
-
if rewriters[group] && rewriters[group][name]
|
123
|
-
true
|
99
|
+
rewriter = fetch(group, name)
|
100
|
+
if sandbox
|
101
|
+
rewriter.process_with_sandbox
|
124
102
|
else
|
125
|
-
|
103
|
+
rewriter.process
|
126
104
|
end
|
105
|
+
rewriter
|
127
106
|
end
|
128
107
|
|
129
108
|
# Get all available rewriters
|
data/lib/synvert/core/version.rb
CHANGED
@@ -526,6 +526,12 @@ describe Parser::AST::Node do
|
|
526
526
|
range = node.child_node_range('caller.receiver')
|
527
527
|
expect(range.to_range).to eq(0...7)
|
528
528
|
end
|
529
|
+
|
530
|
+
it 'checks caller.message' do
|
531
|
+
node = parse('Factory.define :user do |user|; end')
|
532
|
+
range = node.child_node_range('caller.message')
|
533
|
+
expect(range.to_range).to eq(8...14)
|
534
|
+
end
|
529
535
|
end
|
530
536
|
|
531
537
|
context 'class node' do
|
@@ -7,7 +7,7 @@ module Synvert::Core
|
|
7
7
|
subject {
|
8
8
|
source = "user = User.new params[:user]\nuser.save\nrender\n"
|
9
9
|
send_node = Parser::CurrentRuby.parse(source).children[1]
|
10
|
-
instance = double(current_node: send_node)
|
10
|
+
instance = double(current_node: send_node, file_source: source)
|
11
11
|
Rewriter::RemoveAction.new(instance)
|
12
12
|
}
|
13
13
|
|
@@ -16,7 +16,7 @@ module Synvert::Core
|
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'gets end_pos' do
|
19
|
-
expect(subject.end_pos).to eq "user = User.new params[:user]\nuser.save".length
|
19
|
+
expect(subject.end_pos).to eq "user = User.new params[:user]\nuser.save\n".length
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'gets rewritten_code' do
|
@@ -54,9 +54,9 @@ module Synvert::Core
|
|
54
54
|
it 'parses goto_node' do
|
55
55
|
scope = double
|
56
56
|
block = proc {}
|
57
|
-
expect(Rewriter::GotoScope).to receive(:new).with(instance,
|
57
|
+
expect(Rewriter::GotoScope).to receive(:new).with(instance, 'caller.receiver', &block).and_return(scope)
|
58
58
|
expect(scope).to receive(:process)
|
59
|
-
instance.goto_node(
|
59
|
+
instance.goto_node('caller.receiver', &block)
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'parses if_exist_node' do
|
@@ -249,17 +249,6 @@ module Synvert::Core
|
|
249
249
|
expect { Rewriter.call 'group', 'rewriter' }.to raise_error(RewriterNotFound)
|
250
250
|
end
|
251
251
|
|
252
|
-
context 'exist?' do
|
253
|
-
it 'returns true if rewriter exists' do
|
254
|
-
Rewriter.new 'group', 'rewriter'
|
255
|
-
expect(Rewriter.exist?('group', 'rewriter')).to be_truthy
|
256
|
-
end
|
257
|
-
|
258
|
-
it 'returns false if rewriter does not exist' do
|
259
|
-
expect(Rewriter.exist?('group', 'rewriter')).to be_falsey
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
252
|
context 'available' do
|
264
253
|
it 'lists empty rewriters' do
|
265
254
|
expect(Rewriter.availables).to eq({})
|
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.email = ["flyerhzm@gmail.com"]
|
12
12
|
spec.summary = 'convert ruby code to better syntax.'
|
13
13
|
spec.description = 'convert ruby code to better syntax automatically.'
|
14
|
-
spec.homepage = "https://github.com/xinminlabs/synvert-core"
|
14
|
+
spec.homepage = "https://github.com/xinminlabs/synvert-core-ruby"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
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.
|
4
|
+
version: 0.54.1
|
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-08
|
11
|
+
date: 2021-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -198,8 +198,8 @@ files:
|
|
198
198
|
- spec/synvert/core/rewriter/scope_spec.rb
|
199
199
|
- spec/synvert/core/rewriter/warning_spec.rb
|
200
200
|
- spec/synvert/core/rewriter_spec.rb
|
201
|
-
- synvert-core.gemspec
|
202
|
-
homepage: https://github.com/xinminlabs/synvert-core
|
201
|
+
- synvert-core-ruby.gemspec
|
202
|
+
homepage: https://github.com/xinminlabs/synvert-core-ruby
|
203
203
|
licenses:
|
204
204
|
- MIT
|
205
205
|
metadata: {}
|