synvert-core 1.1.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,131 +1,158 @@
1
1
  require 'spec_helper'
2
2
 
3
+ def assert_parser(source)
4
+ expect(parser.parse(source).to_s).to eq source
5
+ end
6
+
3
7
  module Synvert::Core::NodeQuery
4
8
  RSpec.describe Parser do
5
9
  let(:parser) { described_class.new }
6
10
 
7
- def assert_parser(source)
8
- expect(parser.parse(source).to_s).to eq source
9
- end
11
+ describe '#toString' do
12
+ it 'parses one selector' do
13
+ source = '.send[message=:create]'
14
+ assert_parser(source)
15
+ end
10
16
 
11
- it 'parses one selector' do
12
- source = '.send[message=:create]'
13
- assert_parser(source)
14
- end
17
+ it 'parses two selectors' do
18
+ source = '.class[name=Synvert] .def[name="foobar"]'
19
+ assert_parser(source)
20
+ end
15
21
 
16
- it 'parses two selectors' do
17
- source = '.class[name=Synvert] .def[name="foobar"]'
18
- assert_parser(source)
19
- end
22
+ it 'parses three selectors' do
23
+ source = '.class[name=Synvert] .def[name="foobar"] .send[message=create]'
24
+ assert_parser(source)
25
+ end
20
26
 
21
- it 'parses three selectors' do
22
- source = '.class[name=Synvert] .def[name="foobar"] .send[message=create]'
23
- assert_parser(source)
24
- end
27
+ it 'parses child selector' do
28
+ source = '.class[name=Synvert] > .def[name="foobar"]'
29
+ assert_parser(source)
30
+ end
25
31
 
26
- it 'parses child selector' do
27
- source = '.class[name=Synvert] > .def[name="foobar"]'
28
- assert_parser(source)
29
- end
32
+ it 'parses scope' do
33
+ source = '.block <body> > .send'
34
+ assert_parser(source)
35
+ end
30
36
 
31
- it 'parses :first-child' do
32
- source = '.class .def:first-child'
33
- assert_parser(source)
34
- end
37
+ it 'parses :first-child' do
38
+ source = '.class .def:first-child'
39
+ assert_parser(source)
40
+ end
35
41
 
36
- it 'parses :last-child' do
37
- source = '.class .def:last-child'
38
- assert_parser(source)
39
- end
42
+ it 'parses :last-child' do
43
+ source = '.class .def:last-child'
44
+ assert_parser(source)
45
+ end
40
46
 
41
- it 'parses :nth-child(n)' do
42
- source = '.class .def:nth-child(2)'
43
- assert_parser(source)
44
- end
47
+ it 'parses :nth-child(n)' do
48
+ source = '.class .def:nth-child(2)'
49
+ assert_parser(source)
50
+ end
45
51
 
46
- it 'parses :nth-last-child(n)' do
47
- source = '.class .def:nth-last-child(2)'
48
- assert_parser(source)
49
- end
52
+ it 'parses :nth-last-child(n)' do
53
+ source = '.class .def:nth-last-child(2)'
54
+ assert_parser(source)
55
+ end
50
56
 
51
- it 'parses :has selector' do
52
- source = '.class:has(> .def)'
53
- assert_parser(source)
54
- end
57
+ it 'parses :has selector' do
58
+ source = '.class:has(> .def)'
59
+ assert_parser(source)
60
+ end
55
61
 
56
- it 'parses :not_has selector' do
57
- source = '.class:not_has(> .def)'
58
- assert_parser(source)
59
- end
62
+ it 'parses :not_has selector' do
63
+ source = '.class:not_has(> .def)'
64
+ assert_parser(source)
65
+ end
60
66
 
61
- it 'parses multiple attributes' do
62
- source = '.send[receiver=nil][message=:create]'
63
- assert_parser(source)
64
- end
67
+ it 'parses root :has selector' do
68
+ source = ':has(.def)'
69
+ assert_parser(source)
70
+ end
65
71
 
66
- it 'parses nested attributes' do
67
- source = '.send[receiver.message=:create]'
68
- assert_parser(source)
69
- end
72
+ it 'parses multiple attributes' do
73
+ source = '.send[receiver=nil][message=:create]'
74
+ assert_parser(source)
75
+ end
70
76
 
71
- it 'parses selector value' do
72
- source = '.send[receiver=.send[message=:create]]'
73
- assert_parser(source)
74
- end
77
+ it 'parses nested attributes' do
78
+ source = '.send[receiver.message=:create]'
79
+ assert_parser(source)
80
+ end
75
81
 
76
- it 'parses not equal operator' do
77
- source = '.send[receiver=.send[message!=:create]]'
78
- assert_parser(source)
79
- end
82
+ it 'parses selector value' do
83
+ source = '.send[receiver=.send[message=:create]]'
84
+ assert_parser(source)
85
+ end
80
86
 
81
- it 'parses greater than operator' do
82
- source = '.send[receiver=.send[arguments.size>1]]'
83
- assert_parser(source)
84
- end
87
+ it 'parses start with operator' do
88
+ source = '.def[name^=synvert]'
89
+ assert_parser(source)
90
+ end
85
91
 
86
- it 'parses greater than or equal operator' do
87
- source = '.send[receiver=.send[arguments.size>=1]]'
88
- assert_parser(source)
89
- end
92
+ it 'parses end with operator' do
93
+ source = '.def[name$=synvert]'
94
+ assert_parser(source)
95
+ end
90
96
 
91
- it 'parses less than operator' do
92
- source = '.send[receiver=.send[arguments.size<1]]'
93
- assert_parser(source)
94
- end
97
+ it 'parses contain operator' do
98
+ source = '.def[name*=synvert]'
99
+ assert_parser(source)
100
+ end
95
101
 
96
- it 'parses less than or equal operator' do
97
- source = '.send[receiver=.send[arguments.size<=1]]'
98
- assert_parser(source)
99
- end
102
+ it 'parses not equal operator' do
103
+ source = '.send[receiver=.send[message!=:create]]'
104
+ assert_parser(source)
105
+ end
100
106
 
101
- it 'parses in operator' do
102
- source = '.def[name in (foo, bar)]'
103
- assert_parser(source)
104
- end
107
+ it 'parses greater than operator' do
108
+ source = '.send[receiver=.send[arguments.size>1]]'
109
+ assert_parser(source)
110
+ end
105
111
 
106
- it 'parses not_in operator' do
107
- source = '.def[name not in (foo, bar)]'
108
- assert_parser(source)
109
- end
112
+ it 'parses greater than or equal operator' do
113
+ source = '.send[receiver=.send[arguments.size>=1]]'
114
+ assert_parser(source)
115
+ end
110
116
 
111
- it 'parses includes operator' do
112
- source = '.def[arguments includes &block]'
113
- assert_parser(source)
114
- end
117
+ it 'parses less than operator' do
118
+ source = '.send[receiver=.send[arguments.size<1]]'
119
+ assert_parser(source)
120
+ end
115
121
 
116
- it 'parses empty string' do
117
- source = '.send[arguments.first=""]'
118
- assert_parser(source)
119
- end
122
+ it 'parses less than or equal operator' do
123
+ source = '.send[receiver=.send[arguments.size<=1]]'
124
+ assert_parser(source)
125
+ end
120
126
 
121
- it 'parses []=' do
122
- source = '.send[message=[]=]'
123
- assert_parser(source)
124
- end
127
+ it 'parses in operator' do
128
+ source = '.def[name in (foo bar)]'
129
+ assert_parser(source)
130
+ end
131
+
132
+ it 'parses not_in operator' do
133
+ source = '.def[name not in (foo bar)]'
134
+ assert_parser(source)
135
+ end
136
+
137
+ it 'parses includes operator' do
138
+ source = '.def[arguments includes &block]'
139
+ assert_parser(source)
140
+ end
125
141
 
126
- it 'parses :[]' do
127
- source = '.send[message=:[]]'
128
- assert_parser(source)
142
+ it 'parses empty string' do
143
+ source = '.send[arguments.first=""]'
144
+ assert_parser(source)
145
+ end
146
+
147
+ it 'parses []=' do
148
+ source = '.send[message=[]=]'
149
+ assert_parser(source)
150
+ end
151
+
152
+ it 'parses :[]' do
153
+ source = '.send[message=:[]]'
154
+ assert_parser(source)
155
+ end
129
156
  end
130
157
 
131
158
  describe '#query_nodes' do
@@ -142,15 +169,22 @@ module Synvert::Core::NodeQuery
142
169
 
143
170
  def foobar(a, b)
144
171
  { a: a, b: b }
145
- foo.merge(bar)
146
172
  arr[index]
147
173
  arr[index] = value
174
+ nil?
148
175
  call('')
149
176
  end
150
177
  end
151
178
  EOS
152
179
  }
153
180
 
181
+ let(:test_node) {
182
+ parse(<<~EOS)
183
+ RSpec.describe Synvert do
184
+ end
185
+ EOS
186
+ }
187
+
154
188
  it 'matches class node' do
155
189
  expression = parser.parse('.class[name=Synvert]')
156
190
  expect(expression.query_nodes(node)).to eq [node]
@@ -186,18 +220,33 @@ module Synvert::Core::NodeQuery
186
220
  expect(expression.query_nodes(node)).to eq [node.body[-2]]
187
221
  end
188
222
 
223
+ it 'matches start with' do
224
+ expression = parser.parse('.def[name^=foo]')
225
+ expect(expression.query_nodes(node)).to eq [node.body.first, node.body.last]
226
+ end
227
+
228
+ it 'matches end with' do
229
+ expression = parser.parse('.def[name$=bar]')
230
+ expect(expression.query_nodes(node)).to eq [node.body.second, node.body.last]
231
+ end
232
+
233
+ it 'matches contain' do
234
+ expression = parser.parse('.def[name*=oob]')
235
+ expect(expression.query_nodes(node)).to eq [node.body.last]
236
+ end
237
+
189
238
  it 'matches not equal' do
190
239
  expression = parser.parse('.def[name!=foobar]')
191
240
  expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second]
192
241
  end
193
242
 
194
243
  it 'matches in' do
195
- expression = parser.parse('.def[name IN (foo, bar)]')
244
+ expression = parser.parse('.def[name IN (foo bar)]')
196
245
  expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second]
197
246
  end
198
247
 
199
248
  it 'matches not in' do
200
- expression = parser.parse('.def[name NOT IN (foo, bar)]')
249
+ expression = parser.parse('.def[name NOT IN (foo bar)]')
201
250
  expect(expression.query_nodes(node)).to eq [node.body.last]
202
251
  end
203
252
 
@@ -207,18 +256,18 @@ module Synvert::Core::NodeQuery
207
256
  end
208
257
 
209
258
  it 'matches equal array' do
210
- expression = parser.parse('.def[arguments=(a, b)]')
259
+ expression = parser.parse('.def[arguments=(a b)]')
211
260
  expect(expression.query_nodes(node)).to eq [node.body.last]
212
261
 
213
- expression = parser.parse('.def[arguments=(b, a)]')
262
+ expression = parser.parse('.def[arguments=(b a)]')
214
263
  expect(expression.query_nodes(node)).to eq []
215
264
  end
216
265
 
217
266
  it 'matches not equal array' do
218
- expression = parser.parse('.def[arguments!=(a, b)]')
267
+ expression = parser.parse('.def[arguments!=(a b)]')
219
268
  expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second]
220
269
 
221
- expression = parser.parse('.def[arguments!=(b, a)]')
270
+ expression = parser.parse('.def[arguments!=(b a)]')
222
271
  expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second, node.body.last]
223
272
  end
224
273
 
@@ -247,6 +296,19 @@ module Synvert::Core::NodeQuery
247
296
  expect(expression.query_nodes(node)).to eq [node.body.last]
248
297
  end
249
298
 
299
+ it 'matches goto scope' do
300
+ expression = parser.parse('.def <body> > .send[message=:create]')
301
+ expect(expression.query_nodes(node)).to eq [node.body.first.body.last, node.body.second.body.last]
302
+
303
+ expression = parser.parse('.def <body> .send[message=:create]')
304
+ expect(expression.query_nodes(node)).to eq [node.body.first.body.last, node.body.second.body.last]
305
+ end
306
+
307
+ it 'matches multiple goto scope' do
308
+ expression = parser.parse('.block <caller.arguments> .const[name=Synvert]')
309
+ expect(expression.query_nodes(test_node)).to eq [test_node.caller.arguments.first]
310
+ end
311
+
250
312
  it 'matches has selector' do
251
313
  expression = parser.parse('.def:has(> .send[receiver=FactoryBot])')
252
314
  expect(expression.query_nodes(node)).to eq [node.body.first, node.body.second]
@@ -257,12 +319,17 @@ module Synvert::Core::NodeQuery
257
319
  expect(expression.query_nodes(node)).to eq [node.body.last]
258
320
  end
259
321
 
322
+ it 'matches root has selector' do
323
+ expression = parser.parse(':has(.def[name=foobar])')
324
+ expect(expression.query_nodes(node)).to eq [node]
325
+ end
326
+
260
327
  it 'matches arguments.size' do
261
328
  expression = parser.parse('.def .send[arguments.size=2]')
262
329
  expect(expression.query_nodes(node)).to eq [
263
330
  node.body.first.body.last,
264
331
  node.body.second.body.last,
265
- node.body.third.body.fourth
332
+ node.body.third.body.third
266
333
  ]
267
334
  expression = parser.parse('.def .send[arguments.size>2]')
268
335
  expect(expression.query_nodes(node)).to eq []
@@ -270,12 +337,12 @@ module Synvert::Core::NodeQuery
270
337
  expect(expression.query_nodes(node)).to eq [
271
338
  node.body.first.body.last,
272
339
  node.body.second.body.last,
273
- node.body.third.body.fourth
340
+ node.body.third.body.third
274
341
  ]
275
342
  end
276
343
 
277
344
  it 'matches arguments' do
278
- expression = parser.parse('.send[arguments=[size=2][first=.sym][last=.hash]]')
345
+ expression = parser.parse('.send[arguments.size=2][arguments.first=.sym][arguments.last=.hash]')
279
346
  expect(expression.query_nodes(node)).to eq [node.body.first.body.last, node.body.second.body.last]
280
347
  end
281
348
 
@@ -291,18 +358,18 @@ module Synvert::Core::NodeQuery
291
358
  expect(expression.query_nodes(node)).to eq node.body.last.body.first.children
292
359
  end
293
360
 
294
- it 'matches identifier' do
295
- expression = parser.parse('.send[receiver=foo][message=merge]')
296
- expect(expression.query_nodes(node)).to eq [node.body.last.body.second]
297
- end
298
-
299
361
  it 'matches []' do
300
362
  expression = parser.parse('.send[message=[]]')
301
- expect(expression.query_nodes(node)).to eq [node.body.last.body.third]
363
+ expect(expression.query_nodes(node)).to eq [node.body.last.body.second]
302
364
  end
303
365
 
304
366
  it 'matches []=' do
305
367
  expression = parser.parse('.send[message=:[]=]')
368
+ expect(expression.query_nodes(node)).to eq [node.body.last.body.third]
369
+ end
370
+
371
+ it 'matches nil and nil?' do
372
+ expression = parser.parse('.send[receiver=nil][message=nil?]')
306
373
  expect(expression.query_nodes(node)).to eq [node.body.last.body.fourth]
307
374
  end
308
375
 
@@ -71,7 +71,7 @@ module Synvert::Core
71
71
  condition = double
72
72
  block = proc {}
73
73
  expect(Rewriter::IfExistCondition).to receive(:new)
74
- .with(instance, type: 'send', message: 'create', &block)
74
+ .with(instance, { type: 'send', message: 'create' }, &block)
75
75
  .and_return(condition)
76
76
  expect(condition).to receive(:process)
77
77
  instance.if_exist_node(type: 'send', message: 'create', &block)
@@ -81,7 +81,7 @@ module Synvert::Core
81
81
  condition = double
82
82
  block = proc {}
83
83
  expect(Rewriter::UnlessExistCondition).to receive(:new)
84
- .with(instance, type: 'send', message: 'create', &block)
84
+ .with(instance, { type: 'send', message: 'create' }, &block)
85
85
  .and_return(condition)
86
86
  expect(condition).to receive(:process)
87
87
  instance.unless_exist_node(type: 'send', message: 'create', &block)
@@ -91,7 +91,7 @@ module Synvert::Core
91
91
  condition = double
92
92
  block = proc {}
93
93
  expect(Rewriter::IfOnlyExistCondition).to receive(:new)
94
- .with(instance, type: 'send', message: 'create', &block)
94
+ .with(instance, { type: 'send', message: 'create' }, &block)
95
95
  .and_return(condition)
96
96
  expect(condition).to receive(:process)
97
97
  instance.if_only_exist_node(type: 'send', message: 'create', &block)
@@ -59,15 +59,15 @@ module Synvert::Core
59
59
  end
60
60
 
61
61
  it 'raises ParseError' do
62
- scope = described_class.new(instance, 'hello world') {}
62
+ scope = described_class.new(instance, 'synvert') {}
63
63
  expect {
64
64
  scope.process
65
65
  }.to raise_error(NodeQuery::Compiler::ParseError)
66
66
 
67
- scope = described_class.new(instance, '.type[key IN value]') {}
67
+ scope = described_class.new(instance, '.send[receiver IN FactoryGirl]') {}
68
68
  expect {
69
69
  scope.process
70
- }.to raise_error(NodeQuery::Compiler::ParseError)
70
+ }.to raise_error(NodeQuery::Compiler::InvalidOperatorError)
71
71
  end
72
72
  end
73
73
  end
@@ -23,14 +23,4 @@ Gem::Specification.new do |spec|
23
23
  spec.add_runtime_dependency "activesupport"
24
24
  spec.add_runtime_dependency "erubis"
25
25
  spec.add_runtime_dependency "parser"
26
-
27
- spec.add_development_dependency "bundler"
28
- spec.add_development_dependency "guard"
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"
33
- spec.add_development_dependency "rake"
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
36
26
  end
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: 1.1.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-27 00:00:00.000000000 Z
11
+ date: 2022-05-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -52,132 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: guard
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: guard-rspec
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: guard-rake
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: oedipus_lex
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: racc
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: rake
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: rspec
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - '='
158
- - !ruby/object:Gem::Version
159
- version: 3.10.0
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - '='
165
- - !ruby/object:Gem::Version
166
- version: 3.10.0
167
- - !ruby/object:Gem::Dependency
168
- name: rspec-mocks
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - '='
172
- - !ruby/object:Gem::Version
173
- version: 3.10.2
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - '='
179
- - !ruby/object:Gem::Version
180
- version: 3.10.2
181
55
  description: convert ruby code to better syntax automatically.
182
56
  email:
183
57
  - flyerhzm@gmail.com
@@ -218,6 +92,7 @@ files:
218
92
  - lib/synvert/core/node_query/compiler/parse_error.rb
219
93
  - lib/synvert/core/node_query/compiler/regexp.rb
220
94
  - lib/synvert/core/node_query/compiler/selector.rb
95
+ - lib/synvert/core/node_query/compiler/simple_selector.rb
221
96
  - lib/synvert/core/node_query/compiler/string.rb
222
97
  - lib/synvert/core/node_query/compiler/symbol.rb
223
98
  - lib/synvert/core/node_query/lexer.rex