synvert-core 0.64.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +1 -1
  3. data/.gitignore +4 -0
  4. data/CHANGELOG.md +5 -0
  5. data/Guardfile +11 -2
  6. data/README.md +2 -2
  7. data/Rakefile +15 -1
  8. data/lib/synvert/core/array_ext.rb +41 -0
  9. data/lib/synvert/core/engine/erb.rb +9 -8
  10. data/lib/synvert/core/node_ext.rb +47 -44
  11. data/lib/synvert/core/node_query/compiler/array.rb +34 -0
  12. data/lib/synvert/core/node_query/compiler/attribute.rb +51 -0
  13. data/lib/synvert/core/node_query/compiler/attribute_list.rb +24 -0
  14. data/lib/synvert/core/node_query/compiler/boolean.rb +23 -0
  15. data/lib/synvert/core/node_query/compiler/comparable.rb +79 -0
  16. data/lib/synvert/core/node_query/compiler/dynamic_attribute.rb +51 -0
  17. data/lib/synvert/core/node_query/compiler/expression.rb +88 -0
  18. data/lib/synvert/core/node_query/compiler/float.rb +23 -0
  19. data/lib/synvert/core/node_query/compiler/identifier.rb +41 -0
  20. data/lib/synvert/core/node_query/compiler/integer.rb +23 -0
  21. data/lib/synvert/core/node_query/compiler/invalid_operator_error.rb +7 -0
  22. data/lib/synvert/core/node_query/compiler/nil.rb +23 -0
  23. data/lib/synvert/core/node_query/compiler/parse_error.rb +7 -0
  24. data/lib/synvert/core/node_query/compiler/regexp.rb +37 -0
  25. data/lib/synvert/core/node_query/compiler/selector.rb +51 -0
  26. data/lib/synvert/core/node_query/compiler/string.rb +34 -0
  27. data/lib/synvert/core/node_query/compiler/symbol.rb +23 -0
  28. data/lib/synvert/core/node_query/compiler.rb +24 -0
  29. data/lib/synvert/core/node_query/lexer.rex +96 -0
  30. data/lib/synvert/core/node_query/lexer.rex.rb +293 -0
  31. data/lib/synvert/core/node_query/parser.racc.rb +518 -0
  32. data/lib/synvert/core/node_query/parser.y +84 -0
  33. data/lib/synvert/core/node_query.rb +36 -0
  34. data/lib/synvert/core/rewriter/action/delete_action.rb +4 -2
  35. data/lib/synvert/core/rewriter/action/replace_action.rb +4 -2
  36. data/lib/synvert/core/rewriter/action/replace_erb_stmt_with_expr_action.rb +2 -2
  37. data/lib/synvert/core/rewriter/action/wrap_action.rb +3 -2
  38. data/lib/synvert/core/rewriter/action.rb +2 -1
  39. data/lib/synvert/core/rewriter/helper.rb +5 -2
  40. data/lib/synvert/core/rewriter/instance.rb +25 -13
  41. data/lib/synvert/core/rewriter/scope/query_scope.rb +36 -0
  42. data/lib/synvert/core/rewriter/scope/within_scope.rb +1 -1
  43. data/lib/synvert/core/rewriter.rb +1 -0
  44. data/lib/synvert/core/version.rb +1 -1
  45. data/lib/synvert/core.rb +22 -5
  46. data/spec/synvert/core/engine/erb_spec.rb +2 -2
  47. data/spec/synvert/core/node_ext_spec.rb +36 -5
  48. data/spec/synvert/core/node_query/lexer_spec.rb +512 -0
  49. data/spec/synvert/core/node_query/parser_spec.rb +270 -0
  50. data/spec/synvert/core/rewriter/condition/if_only_exist_condition_spec.rb +1 -6
  51. data/spec/synvert/core/rewriter/helper_spec.rb +4 -1
  52. data/spec/synvert/core/rewriter/instance_spec.rb +24 -3
  53. data/spec/synvert/core/rewriter/scope/query_scope_spec.rb +74 -0
  54. data/spec/synvert/core/rewriter/scope/within_scope_spec.rb +12 -9
  55. data/spec/synvert/core/rewriter_spec.rb +4 -2
  56. data/synvert-core-ruby.gemspec +5 -1
  57. metadata +75 -2
@@ -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
@@ -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,6 +11,14 @@ module Synvert::Core
11
11
  Rewriter::Instance.new(rewriter, ['file pattern'])
12
12
  }
13
13
 
14
+ it 'parses find_node' do
15
+ scope = double
16
+ block = proc {}
17
+ expect(Rewriter::QueryScope).to receive(:new).with(instance, '.send[message=create]', &block).and_return(scope)
18
+ expect(scope).to receive(:process)
19
+ instance.find_node('.send[message=create]', &block)
20
+ end
21
+
14
22
  it 'parses within_node' do
15
23
  scope = double
16
24
  block = proc {}
@@ -91,7 +99,10 @@ module Synvert::Core
91
99
 
92
100
  it 'parses append' do
93
101
  action = double
94
- 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)
95
106
  expect(action).to receive(:process)
96
107
  instance.append 'include FactoryGirl::Syntax::Methods'
97
108
  end
@@ -108,14 +119,24 @@ module Synvert::Core
108
119
 
109
120
  it 'parses insert at end' do
110
121
  action = double
111
- 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)
112
128
  expect(action).to receive(:process)
113
129
  instance.insert '.first', to: 'receiver'
114
130
  end
115
131
 
116
132
  it 'parses insert at beginning' do
117
133
  action = double
118
- 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)
119
140
  expect(action).to receive(:process)
120
141
  instance.insert 'URI.', at: 'beginning'
121
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,9 @@ 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
34
  spec.add_development_dependency "rspec", "3.10.0"
31
35
  spec.add_development_dependency "rspec-mocks", "3.10.2" # rspec-mocks 3.10.3 breaks tests
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: synvert-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.64.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Huang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-04-02 00:00:00.000000000 Z
11
+ date: 2022-04-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -94,6 +94,48 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
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'
97
139
  - !ruby/object:Gem::Dependency
98
140
  name: rake
99
141
  requirement: !ruby/object:Gem::Requirement
@@ -153,11 +195,35 @@ files:
153
195
  - README.md
154
196
  - Rakefile
155
197
  - lib/synvert/core.rb
198
+ - lib/synvert/core/array_ext.rb
156
199
  - lib/synvert/core/configuration.rb
157
200
  - lib/synvert/core/engine.rb
158
201
  - lib/synvert/core/engine/erb.rb
159
202
  - lib/synvert/core/exceptions.rb
160
203
  - lib/synvert/core/node_ext.rb
204
+ - lib/synvert/core/node_query.rb
205
+ - lib/synvert/core/node_query/compiler.rb
206
+ - lib/synvert/core/node_query/compiler/array.rb
207
+ - lib/synvert/core/node_query/compiler/attribute.rb
208
+ - lib/synvert/core/node_query/compiler/attribute_list.rb
209
+ - lib/synvert/core/node_query/compiler/boolean.rb
210
+ - lib/synvert/core/node_query/compiler/comparable.rb
211
+ - lib/synvert/core/node_query/compiler/dynamic_attribute.rb
212
+ - lib/synvert/core/node_query/compiler/expression.rb
213
+ - lib/synvert/core/node_query/compiler/float.rb
214
+ - lib/synvert/core/node_query/compiler/identifier.rb
215
+ - lib/synvert/core/node_query/compiler/integer.rb
216
+ - lib/synvert/core/node_query/compiler/invalid_operator_error.rb
217
+ - lib/synvert/core/node_query/compiler/nil.rb
218
+ - lib/synvert/core/node_query/compiler/parse_error.rb
219
+ - lib/synvert/core/node_query/compiler/regexp.rb
220
+ - lib/synvert/core/node_query/compiler/selector.rb
221
+ - lib/synvert/core/node_query/compiler/string.rb
222
+ - lib/synvert/core/node_query/compiler/symbol.rb
223
+ - lib/synvert/core/node_query/lexer.rex
224
+ - lib/synvert/core/node_query/lexer.rex.rb
225
+ - lib/synvert/core/node_query/parser.racc.rb
226
+ - lib/synvert/core/node_query/parser.y
161
227
  - lib/synvert/core/rewriter.rb
162
228
  - lib/synvert/core/rewriter/action.rb
163
229
  - lib/synvert/core/rewriter/action/append_action.rb
@@ -181,6 +247,7 @@ files:
181
247
  - lib/synvert/core/rewriter/ruby_version.rb
182
248
  - lib/synvert/core/rewriter/scope.rb
183
249
  - lib/synvert/core/rewriter/scope/goto_scope.rb
250
+ - lib/synvert/core/rewriter/scope/query_scope.rb
184
251
  - lib/synvert/core/rewriter/scope/within_scope.rb
185
252
  - lib/synvert/core/rewriter/warning.rb
186
253
  - lib/synvert/core/version.rb
@@ -188,6 +255,8 @@ files:
188
255
  - spec/support/parser_helper.rb
189
256
  - spec/synvert/core/engine/erb_spec.rb
190
257
  - spec/synvert/core/node_ext_spec.rb
258
+ - spec/synvert/core/node_query/lexer_spec.rb
259
+ - spec/synvert/core/node_query/parser_spec.rb
191
260
  - spec/synvert/core/rewriter/action/append_action_spec.rb
192
261
  - spec/synvert/core/rewriter/action/delete_action_spec.rb
193
262
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
@@ -208,6 +277,7 @@ files:
208
277
  - spec/synvert/core/rewriter/instance_spec.rb
209
278
  - spec/synvert/core/rewriter/ruby_version_spec.rb
210
279
  - spec/synvert/core/rewriter/scope/goto_scope_spec.rb
280
+ - spec/synvert/core/rewriter/scope/query_scope_spec.rb
211
281
  - spec/synvert/core/rewriter/scope/within_scope_spec.rb
212
282
  - spec/synvert/core/rewriter/scope_spec.rb
213
283
  - spec/synvert/core/rewriter/warning_spec.rb
@@ -241,6 +311,8 @@ test_files:
241
311
  - spec/support/parser_helper.rb
242
312
  - spec/synvert/core/engine/erb_spec.rb
243
313
  - spec/synvert/core/node_ext_spec.rb
314
+ - spec/synvert/core/node_query/lexer_spec.rb
315
+ - spec/synvert/core/node_query/parser_spec.rb
244
316
  - spec/synvert/core/rewriter/action/append_action_spec.rb
245
317
  - spec/synvert/core/rewriter/action/delete_action_spec.rb
246
318
  - spec/synvert/core/rewriter/action/insert_action_spec.rb
@@ -261,6 +333,7 @@ test_files:
261
333
  - spec/synvert/core/rewriter/instance_spec.rb
262
334
  - spec/synvert/core/rewriter/ruby_version_spec.rb
263
335
  - spec/synvert/core/rewriter/scope/goto_scope_spec.rb
336
+ - spec/synvert/core/rewriter/scope/query_scope_spec.rb
264
337
  - spec/synvert/core/rewriter/scope/within_scope_spec.rb
265
338
  - spec/synvert/core/rewriter/scope_spec.rb
266
339
  - spec/synvert/core/rewriter/warning_spec.rb