synvert-core 0.63.1 → 1.0.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/.github/workflows/main.yml +1 -1
- data/.gitignore +4 -0
- data/CHANGELOG.md +9 -1
- data/Guardfile +11 -2
- data/README.md +74 -34
- data/Rakefile +15 -1
- data/lib/synvert/core/array_ext.rb +41 -0
- data/lib/synvert/core/configuration.rb +12 -0
- data/lib/synvert/core/engine/erb.rb +9 -8
- data/lib/synvert/core/exceptions.rb +0 -4
- data/lib/synvert/core/node_ext.rb +232 -128
- data/lib/synvert/core/node_query/compiler/array.rb +34 -0
- data/lib/synvert/core/node_query/compiler/attribute.rb +51 -0
- data/lib/synvert/core/node_query/compiler/attribute_list.rb +24 -0
- data/lib/synvert/core/node_query/compiler/boolean.rb +23 -0
- data/lib/synvert/core/node_query/compiler/comparable.rb +79 -0
- data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +51 -0
- data/lib/synvert/core/node_query/compiler/expression.rb +88 -0
- data/lib/synvert/core/node_query/compiler/float.rb +23 -0
- data/lib/synvert/core/node_query/compiler/identifier.rb +41 -0
- data/lib/synvert/core/node_query/compiler/integer.rb +23 -0
- data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +7 -0
- data/lib/synvert/core/node_query/compiler/nil.rb +23 -0
- data/lib/synvert/core/node_query/compiler/parse_error.rb +7 -0
- data/lib/synvert/core/node_query/compiler/regexp.rb +37 -0
- data/lib/synvert/core/node_query/compiler/selector.rb +51 -0
- data/lib/synvert/core/node_query/compiler/string.rb +34 -0
- data/lib/synvert/core/node_query/compiler/symbol.rb +23 -0
- data/lib/synvert/core/node_query/compiler.rb +24 -0
- data/lib/synvert/core/node_query/lexer.rex +96 -0
- data/lib/synvert/core/node_query/lexer.rex.rb +293 -0
- data/lib/synvert/core/node_query/parser.racc.rb +518 -0
- data/lib/synvert/core/node_query/parser.y +84 -0
- data/lib/synvert/core/node_query.rb +36 -0
- data/lib/synvert/core/rewriter/action/append_action.rb +4 -3
- data/lib/synvert/core/rewriter/action/delete_action.rb +17 -8
- data/lib/synvert/core/rewriter/action/insert_action.rb +16 -7
- data/lib/synvert/core/rewriter/action/insert_after_action.rb +3 -2
- data/lib/synvert/core/rewriter/action/prepend_action.rb +3 -2
- data/lib/synvert/core/rewriter/action/remove_action.rb +16 -10
- data/lib/synvert/core/rewriter/action/replace_action.rb +15 -5
- data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +18 -11
- data/lib/synvert/core/rewriter/action/replace_with_action.rb +6 -5
- data/lib/synvert/core/rewriter/action/wrap_action.rb +16 -7
- data/lib/synvert/core/rewriter/action.rb +22 -10
- data/lib/synvert/core/rewriter/any_value.rb +1 -0
- data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +4 -0
- data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +4 -0
- data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +4 -0
- data/lib/synvert/core/rewriter/condition.rb +11 -3
- data/lib/synvert/core/rewriter/gem_spec.rb +6 -3
- data/lib/synvert/core/rewriter/helper.rb +7 -4
- data/lib/synvert/core/rewriter/instance.rb +217 -104
- data/lib/synvert/core/rewriter/ruby_version.rb +4 -4
- data/lib/synvert/core/rewriter/scope/goto_scope.rb +5 -6
- data/lib/synvert/core/rewriter/scope/query_scope.rb +36 -0
- data/lib/synvert/core/rewriter/scope/within_scope.rb +10 -5
- data/lib/synvert/core/rewriter/scope.rb +8 -0
- data/lib/synvert/core/rewriter/warning.rb +1 -1
- data/lib/synvert/core/rewriter.rb +91 -43
- data/lib/synvert/core/version.rb +1 -1
- data/lib/synvert/core.rb +22 -6
- data/spec/synvert/core/engine/erb_spec.rb +2 -2
- data/spec/synvert/core/node_ext_spec.rb +36 -12
- data/spec/synvert/core/node_query/lexer_spec.rb +512 -0
- data/spec/synvert/core/node_query/parser_spec.rb +270 -0
- data/spec/synvert/core/rewriter/action_spec.rb +0 -4
- data/spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb +1 -6
- data/spec/synvert/core/rewriter/gem_spec_spec.rb +1 -1
- data/spec/synvert/core/rewriter/helper_spec.rb +4 -1
- data/spec/synvert/core/rewriter/instance_spec.rb +31 -20
- data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +74 -0
- data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +12 -9
- data/spec/synvert/core/rewriter_spec.rb +4 -2
- data/synvert-core-ruby.gemspec +7 -2
- metadata +91 -4
@@ -0,0 +1,270 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Synvert::Core::NodeQuery
|
4
|
+
RSpec.describe Parser do
|
5
|
+
let(:parser) { described_class.new }
|
6
|
+
|
7
|
+
def assert_parser(source)
|
8
|
+
expect(parser.parse(source).to_s).to eq source
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'parses one selector' do
|
12
|
+
source = '.send[message=:create]'
|
13
|
+
assert_parser(source)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'parses two selectors' do
|
17
|
+
source = '.class[name=Synvert] .def[name="foobar"]'
|
18
|
+
assert_parser(source)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'parses three selectors' do
|
22
|
+
source = '.class[name=Synvert] .def[name="foobar"] .send[message=create]'
|
23
|
+
assert_parser(source)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'parses child selector' do
|
27
|
+
source = '.class[name=Synvert] > .def[name="foobar"]'
|
28
|
+
assert_parser(source)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'parses :first-child' do
|
32
|
+
source = '.class .def:first-child'
|
33
|
+
assert_parser(source)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'parses :last-child' do
|
37
|
+
source = '.class .def:last-child'
|
38
|
+
assert_parser(source)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'parses :nth-child(n)' do
|
42
|
+
source = '.class .def:nth-child(2)'
|
43
|
+
assert_parser(source)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'parses :nth-last-child(n)' do
|
47
|
+
source = '.class .def:nth-last-child(2)'
|
48
|
+
assert_parser(source)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'parses :has selector' do
|
52
|
+
source = '.class:has(> .def)'
|
53
|
+
assert_parser(source)
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'parses multiple attributes' do
|
57
|
+
source = '.send[receiver=nil][message=:create]'
|
58
|
+
assert_parser(source)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'parses nested attributes' do
|
62
|
+
source = '.send[receiver.message=:create]'
|
63
|
+
assert_parser(source)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'parses selector value' do
|
67
|
+
source = '.send[receiver=.send[message=:create]]'
|
68
|
+
assert_parser(source)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'parses not equal operator' do
|
72
|
+
source = '.send[receiver=.send[message!=:create]]'
|
73
|
+
assert_parser(source)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'parses greater than operator' do
|
77
|
+
source = '.send[receiver=.send[arguments.size>1]]'
|
78
|
+
assert_parser(source)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'parses greater than or equal operator' do
|
82
|
+
source = '.send[receiver=.send[arguments.size>=1]]'
|
83
|
+
assert_parser(source)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'parses less than operator' do
|
87
|
+
source = '.send[receiver=.send[arguments.size<1]]'
|
88
|
+
assert_parser(source)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'parses less than or equal operator' do
|
92
|
+
source = '.send[receiver=.send[arguments.size<=1]]'
|
93
|
+
assert_parser(source)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'parses in operator' do
|
97
|
+
source = '.def[name in (foo, bar)]'
|
98
|
+
assert_parser(source)
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'parses not_in operator' do
|
102
|
+
source = '.def[name not in (foo, bar)]'
|
103
|
+
assert_parser(source)
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'parses includes operator' do
|
107
|
+
source = '.def[arguments includes &block]'
|
108
|
+
assert_parser(source)
|
109
|
+
end
|
110
|
+
|
111
|
+
describe '#query_nodes' do
|
112
|
+
let(:node) {
|
113
|
+
parse(<<~EOS)
|
114
|
+
class Synvert
|
115
|
+
def foo
|
116
|
+
FactoryBot.create(:user, name: 'foo')
|
117
|
+
end
|
118
|
+
|
119
|
+
def bar
|
120
|
+
FactoryBot.create(:user, name: 'bar')
|
121
|
+
end
|
122
|
+
|
123
|
+
def foobar(a, b)
|
124
|
+
{ a: a, b: b }
|
125
|
+
foo.merge(bar)
|
126
|
+
arr[index]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
EOS
|
130
|
+
}
|
131
|
+
|
132
|
+
it 'matches class node' do
|
133
|
+
expression = parser.parse('.class[name=Synvert]')
|
134
|
+
expect(expression.query_nodes(node)).to eq [node]
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'matches def node' do
|
138
|
+
expression = parser.parse('.def')
|
139
|
+
expect(expression.query_nodes(node)).to eq node.body
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'matches first def node' do
|
143
|
+
expression = parser.parse('.def:first-child')
|
144
|
+
expect(expression.query_nodes(node)).to eq [node.body.first]
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'matches nested first node' do
|
148
|
+
expression = parser.parse('.def[arguments.size=0] .send:first-child')
|
149
|
+
expect(expression.query_nodes(node)).to eq [node.body.first.body.first, node.body.second.body.first]
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'matches last def node' do
|
153
|
+
expression = parser.parse('.def:last-child')
|
154
|
+
expect(expression.query_nodes(node)).to eq [node.body.last]
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'matches nth-child node' do
|
158
|
+
expression = parser.parse('.def:nth-child(2)')
|
159
|
+
expect(expression.query_nodes(node)).to eq [node.body.second]
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'matches nth-last-child node' do
|
163
|
+
expression = parser.parse('.def:nth-last-child(2)')
|
164
|
+
expect(expression.query_nodes(node)).to eq [node.body[-2]]
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'matches not equal' do
|
168
|
+
expression = parser.parse('.def[name!=foobar]')
|
169
|
+
expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second]
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'matches in' do
|
173
|
+
expression = parser.parse('.def[name IN (foo, bar)]')
|
174
|
+
expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second]
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'matches not in' do
|
178
|
+
expression = parser.parse('.def[name NOT IN (foo, bar)]')
|
179
|
+
expect(expression.query_nodes(node)).to eq [node.body.last]
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'matches includes' do
|
183
|
+
expression = parser.parse('.def[arguments INCLUDES a]')
|
184
|
+
expect(expression.query_nodes(node)).to eq [node.body.last]
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'matches equal array' do
|
188
|
+
expression = parser.parse('.def[arguments=(a, b)]')
|
189
|
+
expect(expression.query_nodes(node)).to eq [node.body.last]
|
190
|
+
|
191
|
+
expression = parser.parse('.def[arguments=(b, a)]')
|
192
|
+
expect(expression.query_nodes(node)).to eq []
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'matches not equal array' do
|
196
|
+
expression = parser.parse('.def[arguments!=(a, b)]')
|
197
|
+
expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second]
|
198
|
+
|
199
|
+
expression = parser.parse('.def[arguments!=(b, a)]')
|
200
|
+
expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second, node.body.last]
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'matches descendant node' do
|
204
|
+
expression = parser.parse('.class .send[message=:create]')
|
205
|
+
expect(expression.query_nodes(node)).to eq [node.body.first.children.last, node.body.second.children.last]
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'matches three level descendant node' do
|
209
|
+
expression = parser.parse('.class .def .send[message=:create]')
|
210
|
+
expect(expression.query_nodes(node)).to eq [node.body.first.children.last, node.body.second.children.last]
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'matches child node' do
|
214
|
+
expression = parser.parse('.def > .send[message=:create]')
|
215
|
+
expect(expression.query_nodes(node)).to eq [node.body.first.children.last, node.body.second.children.last]
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'matches next sibling node' do
|
219
|
+
expression = parser.parse('.def[name=foo] + .def[name=bar]')
|
220
|
+
expect(expression.query_nodes(node)).to eq [node.body.second]
|
221
|
+
end
|
222
|
+
|
223
|
+
it 'matches sebsequent sibling node' do
|
224
|
+
expression = parser.parse('.def[name=foo] ~ .def[name=foobar]')
|
225
|
+
expect(expression.query_nodes(node)).to eq [node.body.last]
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'matches has selector' do
|
229
|
+
expression = parser.parse('.def:has(> .send[receiver=FactoryBot])')
|
230
|
+
expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second]
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'matches arguments.size' do
|
234
|
+
expression = parser.parse('.send[arguments.size=2]')
|
235
|
+
expect(expression.query_nodes(node)).to eq [node.body.first.children.last, node.body.second.children.last]
|
236
|
+
expression = parser.parse('.send[arguments.size>2]')
|
237
|
+
expect(expression.query_nodes(node)).to eq []
|
238
|
+
expression = parser.parse('.send[arguments.size>=2]')
|
239
|
+
expect(expression.query_nodes(node)).to eq [node.body.first.children.last, node.body.second.children.last]
|
240
|
+
end
|
241
|
+
|
242
|
+
it 'matches arguments' do
|
243
|
+
expression = parser.parse('.send[arguments=[size=2][first=.sym][last=.hash]]')
|
244
|
+
expect(expression.query_nodes(node)).to eq [node.body.first.children.last, node.body.second.children.last]
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'matches regexp value' do
|
248
|
+
expression = parser.parse('.def[name=~/foo/]')
|
249
|
+
expect(expression.query_nodes(node)).to eq [node.body.first, node.body.last]
|
250
|
+
expression = parser.parse('.def[name!~/bar/]')
|
251
|
+
expect(expression.query_nodes(node)).to eq [node.body.first]
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'matches attribute value' do
|
255
|
+
expression = parser.parse('.pair[key={{value}}]')
|
256
|
+
expect(expression.query_nodes(node)).to eq node.body.last.body.first.children
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'matches identifier' do
|
260
|
+
expression = parser.parse('.send[receiver=foo][message=merge]')
|
261
|
+
expect(expression.query_nodes(node)).to eq [node.body.last.body.second]
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'matches []' do
|
265
|
+
expression = parser.parse('.send[message="[]"]')
|
266
|
+
expect(expression.query_nodes(node)).to eq [node.body.last.body.third]
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
@@ -17,12 +17,7 @@ module Synvert::Core
|
|
17
17
|
|
18
18
|
describe '#process' do
|
19
19
|
it 'gets matching nodes' do
|
20
|
-
source =
|
21
|
-
'
|
22
|
-
RSpec.configure do |config|
|
23
|
-
config.include EmailSpec::Helpers
|
24
|
-
end
|
25
|
-
'
|
20
|
+
source = ' RSpec.configure do |config| config.include EmailSpec::Helpers end '
|
26
21
|
node = Parser::CurrentRuby.parse(source)
|
27
22
|
instance = double(current_node: node)
|
28
23
|
run = false
|
@@ -46,7 +46,7 @@ module Synvert::Core
|
|
46
46
|
expect(gem_spec).not_to be_match
|
47
47
|
end
|
48
48
|
|
49
|
-
it '
|
49
|
+
it 'returns true if Gemfile.lock does not exist' do
|
50
50
|
expect(File).to receive(:exist?).with(lock_path).and_return(false)
|
51
51
|
gem_spec = Rewriter::GemSpec.new('ast', '1.1.0')
|
52
52
|
expect(gem_spec).to be_match
|
@@ -4,7 +4,10 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
module Synvert::Core
|
6
6
|
describe Rewriter::Helper do
|
7
|
-
let(:dummy_instance) {
|
7
|
+
let(:dummy_instance) {
|
8
|
+
Class.new { include Rewriter::Helper }
|
9
|
+
.new
|
10
|
+
}
|
8
11
|
let(:instance) do
|
9
12
|
rewriter = Rewriter.new('foo', 'bar')
|
10
13
|
Rewriter::Instance.new rewriter, 'spec/**/*_spec.rb' do
|
@@ -11,54 +11,52 @@ module Synvert::Core
|
|
11
11
|
Rewriter::Instance.new(rewriter, ['file pattern'])
|
12
12
|
}
|
13
13
|
|
14
|
-
it 'parses
|
14
|
+
it 'parses find_node' do
|
15
15
|
scope = double
|
16
16
|
block = proc {}
|
17
|
-
expect(Rewriter::
|
18
|
-
.with(instance, { type: 'send', message: 'create' }, { stop_when_match: false }, &block)
|
19
|
-
.and_return(scope)
|
17
|
+
expect(Rewriter::QueryScope).to receive(:new).with(instance, '.send[message=create]', &block).and_return(scope)
|
20
18
|
expect(scope).to receive(:process)
|
21
|
-
instance.
|
19
|
+
instance.find_node('.send[message=create]', &block)
|
22
20
|
end
|
23
21
|
|
24
|
-
it 'parses
|
22
|
+
it 'parses within_node' do
|
25
23
|
scope = double
|
26
24
|
block = proc {}
|
27
25
|
expect(Rewriter::WithinScope).to receive(:new)
|
28
|
-
.with(instance, { type: 'send', message: 'create' }, { stop_when_match: false }, &block)
|
26
|
+
.with(instance, { type: 'send', message: 'create' }, { stop_when_match: false, direct: false }, &block)
|
29
27
|
.and_return(scope)
|
30
28
|
expect(scope).to receive(:process)
|
31
|
-
instance.
|
29
|
+
instance.within_node(type: 'send', message: 'create', &block)
|
32
30
|
end
|
33
31
|
|
34
|
-
it 'parses
|
32
|
+
it 'parses with_node' do
|
35
33
|
scope = double
|
36
34
|
block = proc {}
|
37
35
|
expect(Rewriter::WithinScope).to receive(:new)
|
38
|
-
.with(instance, { type: 'send', message: 'create' }, { stop_when_match:
|
36
|
+
.with(instance, { type: 'send', message: 'create' }, { stop_when_match: false, direct: false }, &block)
|
39
37
|
.and_return(scope)
|
40
38
|
expect(scope).to receive(:process)
|
41
|
-
instance.
|
39
|
+
instance.with_node(type: 'send', message: 'create', &block)
|
42
40
|
end
|
43
41
|
|
44
|
-
it 'parses
|
42
|
+
it 'parses within_node with stop_when_match true' do
|
45
43
|
scope = double
|
46
44
|
block = proc {}
|
47
45
|
expect(Rewriter::WithinScope).to receive(:new)
|
48
|
-
.with(instance, { type: 'send', message: 'create' }, {
|
46
|
+
.with(instance, { type: 'send', message: 'create' }, { stop_when_match: true, direct: false }, &block)
|
49
47
|
.and_return(scope)
|
50
48
|
expect(scope).to receive(:process)
|
51
|
-
instance.
|
49
|
+
instance.within_node({ type: 'send', message: 'create' }, { stop_when_match: true }, &block)
|
52
50
|
end
|
53
51
|
|
54
|
-
it 'parses
|
52
|
+
it 'parses within_node with direct true' do
|
55
53
|
scope = double
|
56
54
|
block = proc {}
|
57
55
|
expect(Rewriter::WithinScope).to receive(:new)
|
58
|
-
.with(instance, { type: 'send', message: 'create' }, { direct: true }, &block)
|
56
|
+
.with(instance, { type: 'send', message: 'create' }, { stop_when_match: false, direct: true }, &block)
|
59
57
|
.and_return(scope)
|
60
58
|
expect(scope).to receive(:process)
|
61
|
-
instance.
|
59
|
+
instance.within_node({ type: 'send', message: 'create' }, { direct: true }, &block)
|
62
60
|
end
|
63
61
|
|
64
62
|
it 'parses goto_node' do
|
@@ -101,7 +99,10 @@ module Synvert::Core
|
|
101
99
|
|
102
100
|
it 'parses append' do
|
103
101
|
action = double
|
104
|
-
expect(Rewriter::AppendAction).to receive(:new).with(
|
102
|
+
expect(Rewriter::AppendAction).to receive(:new).with(
|
103
|
+
instance,
|
104
|
+
'include FactoryGirl::Syntax::Methods'
|
105
|
+
).and_return(action)
|
105
106
|
expect(action).to receive(:process)
|
106
107
|
instance.append 'include FactoryGirl::Syntax::Methods'
|
107
108
|
end
|
@@ -118,14 +119,24 @@ module Synvert::Core
|
|
118
119
|
|
119
120
|
it 'parses insert at end' do
|
120
121
|
action = double
|
121
|
-
expect(Rewriter::InsertAction).to receive(:new).with(
|
122
|
+
expect(Rewriter::InsertAction).to receive(:new).with(
|
123
|
+
instance,
|
124
|
+
'.first',
|
125
|
+
at: 'end',
|
126
|
+
to: 'receiver'
|
127
|
+
).and_return(action)
|
122
128
|
expect(action).to receive(:process)
|
123
129
|
instance.insert '.first', to: 'receiver'
|
124
130
|
end
|
125
131
|
|
126
132
|
it 'parses insert at beginning' do
|
127
133
|
action = double
|
128
|
-
expect(Rewriter::InsertAction).to receive(:new).with(
|
134
|
+
expect(Rewriter::InsertAction).to receive(:new).with(
|
135
|
+
instance,
|
136
|
+
'URI.',
|
137
|
+
at: 'beginning',
|
138
|
+
to: nil
|
139
|
+
).and_return(action)
|
129
140
|
expect(action).to receive(:process)
|
130
141
|
instance.insert 'URI.', at: 'beginning'
|
131
142
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
module Synvert::Core
|
6
|
+
describe Rewriter::QueryScope do
|
7
|
+
let(:instance) {
|
8
|
+
rewriter = Rewriter.new('foo', 'bar')
|
9
|
+
Rewriter::Instance.new(rewriter, 'file pattern')
|
10
|
+
}
|
11
|
+
let(:source) { <<~EOS }
|
12
|
+
describe Post do
|
13
|
+
it 'gets post' do
|
14
|
+
FactoryGirl.create :post
|
15
|
+
end
|
16
|
+
end
|
17
|
+
EOS
|
18
|
+
|
19
|
+
let(:node) { Parser::CurrentRuby.parse(source) }
|
20
|
+
|
21
|
+
before do
|
22
|
+
Rewriter::Instance.reset
|
23
|
+
instance.current_node = node
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#process' do
|
27
|
+
it 'not call block if no matching node' do
|
28
|
+
run = false
|
29
|
+
scope =
|
30
|
+
described_class.new instance, '.send[message=missing]' do
|
31
|
+
run = true
|
32
|
+
end
|
33
|
+
scope.process
|
34
|
+
expect(run).to be_falsey
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'call block if there is matching node' do
|
38
|
+
run = false
|
39
|
+
type_in_scope = nil
|
40
|
+
scope =
|
41
|
+
described_class.new instance, '.send[receiver=FactoryGirl][message=create][arguments=(:post)]' do
|
42
|
+
run = true
|
43
|
+
type_in_scope = node.type
|
44
|
+
end
|
45
|
+
scope.process
|
46
|
+
expect(run).to be_truthy
|
47
|
+
expect(type_in_scope).to eq :send
|
48
|
+
expect(instance.current_node.type).to eq :block
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'matches multiple block nodes' do
|
52
|
+
block_nodes = []
|
53
|
+
scope =
|
54
|
+
described_class.new(instance, '.block') do
|
55
|
+
block_nodes << node
|
56
|
+
end
|
57
|
+
scope.process
|
58
|
+
expect(block_nodes.size).to eq 2
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'raises ParseError' do
|
62
|
+
scope = described_class.new(instance, 'hello world') {}
|
63
|
+
expect {
|
64
|
+
scope.process
|
65
|
+
}.to raise_error(NodeQuery::Compiler::ParseError)
|
66
|
+
|
67
|
+
scope = described_class.new(instance, '.type[key IN value]') {}
|
68
|
+
expect {
|
69
|
+
scope.process
|
70
|
+
}.to raise_error(NodeQuery::Compiler::ParseError)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -54,27 +54,30 @@ module Synvert::Core
|
|
54
54
|
|
55
55
|
it 'matches multiple block nodes' do
|
56
56
|
block_nodes = []
|
57
|
-
scope =
|
58
|
-
|
59
|
-
|
57
|
+
scope =
|
58
|
+
Rewriter::WithinScope.new(instance, { type: 'block' }, { stop_when_match: false }) do
|
59
|
+
block_nodes << node
|
60
|
+
end
|
60
61
|
scope.process
|
61
62
|
expect(block_nodes.size).to eq 2
|
62
63
|
end
|
63
64
|
|
64
65
|
it 'matches only one block node if no recursive' do
|
65
66
|
block_nodes = []
|
66
|
-
scope =
|
67
|
-
|
68
|
-
|
67
|
+
scope =
|
68
|
+
Rewriter::WithinScope.new(instance, { type: 'block' }, { stop_when_match: true }) do
|
69
|
+
block_nodes << node
|
70
|
+
end
|
69
71
|
scope.process
|
70
72
|
expect(block_nodes.size).to eq 1
|
71
73
|
end
|
72
74
|
|
73
75
|
it 'matches only one direct node' do
|
74
76
|
block_nodes = []
|
75
|
-
scope =
|
76
|
-
|
77
|
-
|
77
|
+
scope =
|
78
|
+
Rewriter::WithinScope.new(instance, { type: 'block' }, { direct: true }) do
|
79
|
+
block_nodes << node
|
80
|
+
end
|
78
81
|
scope.process
|
79
82
|
expect(block_nodes.size).to eq 1
|
80
83
|
end
|
@@ -191,7 +191,8 @@ module Synvert::Core
|
|
191
191
|
Rewriter.new 'group', 'name' do
|
192
192
|
add_snippet :group, :not_exist
|
193
193
|
end
|
194
|
-
expect { rewriter.process }
|
194
|
+
expect { rewriter.process }
|
195
|
+
.to raise_error(RewriterNotFound)
|
195
196
|
end
|
196
197
|
end
|
197
198
|
|
@@ -248,7 +249,8 @@ module Synvert::Core
|
|
248
249
|
end
|
249
250
|
|
250
251
|
it 'raises RewriterNotFound if rewriter not found' do
|
251
|
-
expect { Rewriter.call 'group', 'rewriter' }
|
252
|
+
expect { Rewriter.call 'group', 'rewriter' }
|
253
|
+
.to raise_error(RewriterNotFound)
|
252
254
|
end
|
253
255
|
|
254
256
|
context 'available' do
|
data/synvert-core-ruby.gemspec
CHANGED
@@ -14,7 +14,8 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.homepage = "https://github.com/xinminlabs/synvert-core-ruby"
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
|
-
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.files = `git ls-files -z`.split("\x0") +
|
18
|
+
%w[lib/synvert/core/node_query/lexer.rex.rb lib/synvert/core/node_query/parser.racc.rb]
|
18
19
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
20
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
21
|
spec.require_paths = ["lib"]
|
@@ -26,6 +27,10 @@ Gem::Specification.new do |spec|
|
|
26
27
|
spec.add_development_dependency "bundler"
|
27
28
|
spec.add_development_dependency "guard"
|
28
29
|
spec.add_development_dependency "guard-rspec"
|
30
|
+
spec.add_development_dependency "guard-rake"
|
31
|
+
spec.add_development_dependency "oedipus_lex"
|
32
|
+
spec.add_development_dependency "racc"
|
29
33
|
spec.add_development_dependency "rake"
|
30
|
-
spec.add_development_dependency "rspec"
|
34
|
+
spec.add_development_dependency "rspec", "3.10.0"
|
35
|
+
spec.add_development_dependency "rspec-mocks", "3.10.2" # rspec-mocks 3.10.3 breaks tests
|
31
36
|
end
|