synvert-core 0.63.1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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