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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -1
  3. data/.gitignore +4 -0
  4. data/CHANGELOG.md +9 -1
  5. data/Guardfile +11 -2
  6. data/README.md +74 -34
  7. data/Rakefile +15 -1
  8. data/lib/synvert/core/array_ext.rb +41 -0
  9. data/lib/synvert/core/configuration.rb +12 -0
  10. data/lib/synvert/core/engine/erb.rb +9 -8
  11. data/lib/synvert/core/exceptions.rb +0 -4
  12. data/lib/synvert/core/node_ext.rb +232 -128
  13. data/lib/synvert/core/node_query/compiler/array.rb +34 -0
  14. data/lib/synvert/core/node_query/compiler/attribute.rb +51 -0
  15. data/lib/synvert/core/node_query/compiler/attribute_list.rb +24 -0
  16. data/lib/synvert/core/node_query/compiler/boolean.rb +23 -0
  17. data/lib/synvert/core/node_query/compiler/comparable.rb +79 -0
  18. data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +51 -0
  19. data/lib/synvert/core/node_query/compiler/expression.rb +88 -0
  20. data/lib/synvert/core/node_query/compiler/float.rb +23 -0
  21. data/lib/synvert/core/node_query/compiler/identifier.rb +41 -0
  22. data/lib/synvert/core/node_query/compiler/integer.rb +23 -0
  23. data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +7 -0
  24. data/lib/synvert/core/node_query/compiler/nil.rb +23 -0
  25. data/lib/synvert/core/node_query/compiler/parse_error.rb +7 -0
  26. data/lib/synvert/core/node_query/compiler/regexp.rb +37 -0
  27. data/lib/synvert/core/node_query/compiler/selector.rb +51 -0
  28. data/lib/synvert/core/node_query/compiler/string.rb +34 -0
  29. data/lib/synvert/core/node_query/compiler/symbol.rb +23 -0
  30. data/lib/synvert/core/node_query/compiler.rb +24 -0
  31. data/lib/synvert/core/node_query/lexer.rex +96 -0
  32. data/lib/synvert/core/node_query/lexer.rex.rb +293 -0
  33. data/lib/synvert/core/node_query/parser.racc.rb +518 -0
  34. data/lib/synvert/core/node_query/parser.y +84 -0
  35. data/lib/synvert/core/node_query.rb +36 -0
  36. data/lib/synvert/core/rewriter/action/append_action.rb +4 -3
  37. data/lib/synvert/core/rewriter/action/delete_action.rb +17 -8
  38. data/lib/synvert/core/rewriter/action/insert_action.rb +16 -7
  39. data/lib/synvert/core/rewriter/action/insert_after_action.rb +3 -2
  40. data/lib/synvert/core/rewriter/action/prepend_action.rb +3 -2
  41. data/lib/synvert/core/rewriter/action/remove_action.rb +16 -10
  42. data/lib/synvert/core/rewriter/action/replace_action.rb +15 -5
  43. data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +18 -11
  44. data/lib/synvert/core/rewriter/action/replace_with_action.rb +6 -5
  45. data/lib/synvert/core/rewriter/action/wrap_action.rb +16 -7
  46. data/lib/synvert/core/rewriter/action.rb +22 -10
  47. data/lib/synvert/core/rewriter/any_value.rb +1 -0
  48. data/lib/synvert/core/rewriter/condition/if_exist_condition.rb +4 -0
  49. data/lib/synvert/core/rewriter/condition/if_only_exist_condition.rb +4 -0
  50. data/lib/synvert/core/rewriter/condition/unless_exist_condition.rb +4 -0
  51. data/lib/synvert/core/rewriter/condition.rb +11 -3
  52. data/lib/synvert/core/rewriter/gem_spec.rb +6 -3
  53. data/lib/synvert/core/rewriter/helper.rb +7 -4
  54. data/lib/synvert/core/rewriter/instance.rb +217 -104
  55. data/lib/synvert/core/rewriter/ruby_version.rb +4 -4
  56. data/lib/synvert/core/rewriter/scope/goto_scope.rb +5 -6
  57. data/lib/synvert/core/rewriter/scope/query_scope.rb +36 -0
  58. data/lib/synvert/core/rewriter/scope/within_scope.rb +10 -5
  59. data/lib/synvert/core/rewriter/scope.rb +8 -0
  60. data/lib/synvert/core/rewriter/warning.rb +1 -1
  61. data/lib/synvert/core/rewriter.rb +91 -43
  62. data/lib/synvert/core/version.rb +1 -1
  63. data/lib/synvert/core.rb +22 -6
  64. data/spec/synvert/core/engine/erb_spec.rb +2 -2
  65. data/spec/synvert/core/node_ext_spec.rb +36 -12
  66. data/spec/synvert/core/node_query/lexer_spec.rb +512 -0
  67. data/spec/synvert/core/node_query/parser_spec.rb +270 -0
  68. data/spec/synvert/core/rewriter/action_spec.rb +0 -4
  69. data/spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb +1 -6
  70. data/spec/synvert/core/rewriter/gem_spec_spec.rb +1 -1
  71. data/spec/synvert/core/rewriter/helper_spec.rb +4 -1
  72. data/spec/synvert/core/rewriter/instance_spec.rb +31 -20
  73. data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +74 -0
  74. data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +12 -9
  75. data/spec/synvert/core/rewriter_spec.rb +4 -2
  76. data/synvert-core-ruby.gemspec +7 -2
  77. 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
@@ -10,9 +10,5 @@ module Synvert::Core
10
10
  instance = double(current_node: block_node)
11
11
  Rewriter::Action.new(instance, source)
12
12
  }
13
-
14
- it 'gets line' do
15
- expect(subject.line).to eq 2
16
- end
17
13
  end
18
14
  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 'raise Synvert::Core::GemfileLockNotFound if Gemfile.lock does not exist' do
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) { Class.new { include Rewriter::Helper }.new }
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 within_node' do
14
+ it 'parses find_node' do
15
15
  scope = double
16
16
  block = proc {}
17
- expect(Rewriter::WithinScope).to receive(:new)
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.within_node(type: 'send', message: 'create', &block)
19
+ instance.find_node('.send[message=create]', &block)
22
20
  end
23
21
 
24
- it 'parses with_node' do
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.with_node(type: 'send', message: 'create', &block)
29
+ instance.within_node(type: 'send', message: 'create', &block)
32
30
  end
33
31
 
34
- it 'parses within_node with recursive false' do
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: true }, &block)
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.within_node({ type: 'send', message: 'create' }, { stop_when_match: true }, &block)
39
+ instance.with_node(type: 'send', message: 'create', &block)
42
40
  end
43
41
 
44
- it 'parses within_direct_node' do
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' }, { direct: true }, &block)
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.within_direct_node(type: 'send', message: 'create', &block)
49
+ instance.within_node({ type: 'send', message: 'create' }, { stop_when_match: true }, &block)
52
50
  end
53
51
 
54
- it 'parses with_direct_node' do
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.with_direct_node(type: 'send', message: 'create', &block)
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(instance, 'include FactoryGirl::Syntax::Methods').and_return(action)
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(instance, '.first', at: 'end', to: 'receiver').and_return(action)
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(instance, 'URI.', at: 'beginning', to: nil).and_return(action)
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 = Rewriter::WithinScope.new(instance, { type: 'block' }, { stop_when_match: false }) do
58
- block_nodes << node
59
- end
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 = Rewriter::WithinScope.new(instance, { type: 'block' } , { stop_when_match: true }) do
67
- block_nodes << node
68
- end
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 = Rewriter::WithinScope.new(instance, { type: 'block' } , { direct: true }) do
76
- block_nodes << node
77
- end
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 }.to raise_error(RewriterNotFound)
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' }.to raise_error(RewriterNotFound)
252
+ expect { Rewriter.call 'group', 'rewriter' }
253
+ .to raise_error(RewriterNotFound)
252
254
  end
253
255
 
254
256
  context 'available' do
@@ -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