parser 2.7.1.5 → 3.0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/lib/parser/all.rb +1 -0
  3. data/lib/parser/ast/processor.rb +3 -0
  4. data/lib/parser/base.rb +1 -0
  5. data/lib/parser/builders/default.rb +126 -13
  6. data/lib/parser/context.rb +4 -0
  7. data/lib/parser/current.rb +16 -7
  8. data/lib/parser/current_arg_stack.rb +5 -2
  9. data/lib/parser/lexer.rb +872 -802
  10. data/lib/parser/max_numparam_stack.rb +12 -4
  11. data/lib/parser/messages.rb +1 -0
  12. data/lib/parser/meta.rb +4 -3
  13. data/lib/parser/ruby18.rb +6 -2
  14. data/lib/parser/ruby27.rb +3763 -3704
  15. data/lib/parser/ruby28.rb +8047 -0
  16. data/lib/parser/ruby30.rb +3657 -3649
  17. data/lib/parser/ruby31.rb +8226 -0
  18. data/lib/parser/runner.rb +6 -1
  19. data/lib/parser/source/buffer.rb +50 -27
  20. data/lib/parser/source/comment.rb +13 -0
  21. data/lib/parser/source/comment/associator.rb +17 -4
  22. data/lib/parser/source/tree_rewriter.rb +27 -0
  23. data/lib/parser/static_environment.rb +4 -0
  24. data/lib/parser/variables_stack.rb +4 -0
  25. data/lib/parser/version.rb +1 -1
  26. data/parser.gemspec +1 -20
  27. metadata +8 -95
  28. data/.travis.yml +0 -41
  29. data/.yardopts +0 -21
  30. data/CHANGELOG.md +0 -1137
  31. data/CONTRIBUTING.md +0 -17
  32. data/Gemfile +0 -10
  33. data/README.md +0 -309
  34. data/Rakefile +0 -167
  35. data/ci/run_rubocop_specs +0 -14
  36. data/doc/AST_FORMAT.md +0 -2284
  37. data/doc/CUSTOMIZATION.md +0 -37
  38. data/doc/INTERNALS.md +0 -21
  39. data/doc/css/.gitkeep +0 -0
  40. data/doc/css/common.css +0 -68
  41. data/lib/parser/lexer.rl +0 -2550
  42. data/lib/parser/macruby.y +0 -2208
  43. data/lib/parser/ruby18.y +0 -1936
  44. data/lib/parser/ruby19.y +0 -2185
  45. data/lib/parser/ruby20.y +0 -2363
  46. data/lib/parser/ruby21.y +0 -2364
  47. data/lib/parser/ruby22.y +0 -2371
  48. data/lib/parser/ruby23.y +0 -2377
  49. data/lib/parser/ruby24.y +0 -2415
  50. data/lib/parser/ruby25.y +0 -2412
  51. data/lib/parser/ruby26.y +0 -2420
  52. data/lib/parser/ruby27.y +0 -2949
  53. data/lib/parser/ruby30.y +0 -3048
  54. data/lib/parser/rubymotion.y +0 -2192
  55. data/test/bug_163/fixtures/input.rb +0 -5
  56. data/test/bug_163/fixtures/output.rb +0 -5
  57. data/test/bug_163/rewriter.rb +0 -20
  58. data/test/helper.rb +0 -103
  59. data/test/parse_helper.rb +0 -328
  60. data/test/racc_coverage_helper.rb +0 -133
  61. data/test/test_ast_processor.rb +0 -32
  62. data/test/test_base.rb +0 -31
  63. data/test/test_current.rb +0 -31
  64. data/test/test_diagnostic.rb +0 -95
  65. data/test/test_diagnostic_engine.rb +0 -59
  66. data/test/test_encoding.rb +0 -99
  67. data/test/test_lexer.rb +0 -3617
  68. data/test/test_lexer_stack_state.rb +0 -78
  69. data/test/test_meta.rb +0 -12
  70. data/test/test_parse_helper.rb +0 -83
  71. data/test/test_parser.rb +0 -9986
  72. data/test/test_runner_parse.rb +0 -56
  73. data/test/test_runner_rewrite.rb +0 -47
  74. data/test/test_source_buffer.rb +0 -165
  75. data/test/test_source_comment.rb +0 -36
  76. data/test/test_source_comment_associator.rb +0 -399
  77. data/test/test_source_map.rb +0 -14
  78. data/test/test_source_range.rb +0 -192
  79. data/test/test_source_rewriter.rb +0 -541
  80. data/test/test_source_rewriter_action.rb +0 -46
  81. data/test/test_source_tree_rewriter.rb +0 -361
  82. data/test/test_static_environment.rb +0 -45
  83. data/test/using_tree_rewriter/fixtures/input.rb +0 -3
  84. data/test/using_tree_rewriter/fixtures/output.rb +0 -3
  85. data/test/using_tree_rewriter/using_tree_rewriter.rb +0 -9
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
-
5
- class TestSourceRewriterAction < Minitest::Test
6
- def setup
7
- @buf = Parser::Source::Buffer.new('(rewriter_action)',
8
- source: 'foo bar baz')
9
- end
10
-
11
- def range(from, len)
12
- Parser::Source::Range.new(@buf, from, from + len)
13
- end
14
-
15
- def action(range, replacement)
16
- Parser::Source::Rewriter::Action.new(range, replacement)
17
- end
18
-
19
- def test_accessors
20
- action = action(range(1, 10), 'foo')
21
-
22
- assert action.frozen?
23
- assert_equal range(1, 10), action.range
24
- assert_equal 'foo', action.replacement
25
- end
26
-
27
- def test_to_s_replace
28
- action = action(range(3, 1), 'foo')
29
- assert_equal "replace 1 character(s) with \"foo\"", action.to_s
30
- end
31
-
32
- def test_to_s_insert
33
- action = action(range(3, 0), 'foo')
34
- assert_equal "insert \"foo\"", action.to_s
35
- end
36
-
37
- def test_to_s_remove
38
- action = action(range(3, 2), '')
39
- assert_equal 'remove 2 character(s)', action.to_s
40
- end
41
-
42
- def test_to_s_nop
43
- action = action(range(3, 0), '')
44
- assert_equal 'do nothing', action.to_s
45
- end
46
- end
@@ -1,361 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
-
5
- class TestSourceTreeRewriter < Minitest::Test
6
- module Setup
7
- def setup
8
- @buf = Parser::Source::Buffer.new('(rewriter)',
9
- source: 'puts(:hello, :world)')
10
-
11
- @hello = range(5, 6)
12
- @ll = range(8, 2)
13
- @comma_space = range(11,2)
14
- @world = range(13,6)
15
- @whole = range(0, @buf.source.length)
16
- end
17
-
18
- def range(from, len = nil)
19
- from, len = from.begin, from.end - from.begin unless len
20
- Parser::Source::Range.new(@buf, from, from + len)
21
- end
22
- end
23
-
24
- include Setup
25
-
26
- # Returns either:
27
- # - yield rewriter
28
- # - [diagnostic, ...] (Diagnostics)
29
- # - Parser::ClobberingError
30
- #
31
- def build(actions, **policy)
32
- diagnostics = []
33
- diags = -> { diagnostics.flatten.map(&:strip).join("\n") }
34
- rewriter = Parser::Source::TreeRewriter.new(@buf, **policy)
35
- rewriter.diagnostics.consumer = -> diag { diagnostics << diag.render }
36
- actions.each do |action, range, *args|
37
- rewriter.public_send(action, range, *args)
38
- end
39
- if diagnostics.empty?
40
- yield rewriter
41
- else
42
- diags.call
43
- end
44
- rescue ::Parser::ClobberingError => _e
45
- [::Parser::ClobberingError, diags.call]
46
- end
47
-
48
- # Returns either:
49
- # - String (Normal operation)
50
- # - [diagnostic, ...] (Diagnostics)
51
- # - Parser::ClobberingError
52
- #
53
- def apply(actions, **policy)
54
- build(actions, **policy) { |rewriter| rewriter.process }
55
- end
56
-
57
- # Expects ordered actions to be grouped together
58
- def check_actions(expected, grouped_actions, **policy)
59
- grouped_actions.permutation do |sequence|
60
- # [action, [action, action]] => [action, action, action]
61
- # except we can't use flatten because "action" are arrays themselves
62
- actions = sequence.flat_map { |group| group.first.is_a?(Array) ? group : [group] }
63
- assert_equal(expected, apply(actions, **policy))
64
- end
65
- end
66
-
67
- def assert_actions_result(expected, *actions, **rest)
68
- if expected == :raise
69
- diagnostic = rest.values.first
70
- check_actions([::Parser::ClobberingError, diagnostic], actions)
71
- elsif rest.empty?
72
- check_actions(expected, actions)
73
- else
74
- policy, diagnostic = rest.first
75
- check_actions(expected, actions, policy => :accept)
76
- check_actions(diagnostic, actions, policy => :warn)
77
- diagnostic.gsub!(/warning: /, 'error: ')
78
- check_actions([::Parser::ClobberingError, diagnostic], actions, policy => :raise)
79
- end
80
- end
81
-
82
- ### Simple cases
83
-
84
- def test_remove
85
- assert_actions_result 'puts(, :world)', [:remove, @hello]
86
- end
87
-
88
- def test_insert_before
89
- assert_actions_result 'puts(:hello, 42, :world)', [:insert_before, @world, '42, ']
90
- end
91
-
92
- def test_insert_after
93
- assert_actions_result 'puts(:hello, 42, :world)', [:insert_after, @hello, ', 42']
94
- end
95
-
96
- def test_wrap
97
- assert_actions_result 'puts([:hello], :world)', [:wrap, @hello, '[', ']']
98
- end
99
-
100
- def test_replace
101
- assert_actions_result 'puts(:hi, :world)', [:replace, @hello, ':hi']
102
- end
103
-
104
- #
105
- # All other cases, as per doc
106
- #
107
-
108
- def test_crossing_non_deletions
109
- check = [
110
- [:wrap, '(', ')'],
111
- [:remove],
112
- [:replace, 'xx'],
113
- ]
114
- check.combination(2) do |(action, *args), (action_b, *args_b)|
115
- next if action == :remove && action_b == :remove
116
- assert_actions_result :raise,
117
- [[action, @hello.join(@comma_space), *args],
118
- [action_b, @world.join(@comma_space), *args_b]],
119
- diagnostic: <<-DIAGNOSTIC.chomp
120
- (rewriter):1:12: error: the rewriting action on:
121
- (rewriter):1: puts(:hello, :world)
122
- (rewriter):1: ^~~~~~~~
123
- (rewriter):1:6: error: is crossing that on:
124
- (rewriter):1: puts(:hello, :world)
125
- (rewriter):1: ^~~~~~~~
126
- DIAGNOSTIC
127
- end
128
- end
129
-
130
-
131
- def test_crossing_deletions
132
- assert_actions_result 'puts()',
133
- [[:remove, @hello.join(@comma_space)],
134
- [:remove, @world.join(@comma_space)]],
135
- crossing_deletions: <<-DIAGNOSTIC.chomp
136
- (rewriter):1:12: warning: the deletion of:
137
- (rewriter):1: puts(:hello, :world)
138
- (rewriter):1: ^~~~~~~~
139
- (rewriter):1:6: warning: is crossing:
140
- (rewriter):1: puts(:hello, :world)
141
- (rewriter):1: ^~~~~~~~
142
- DIAGNOSTIC
143
- end
144
-
145
- def test_multiple_actions
146
- assert_actions_result 'puts({:hello => [:everybody]})',
147
- [:replace, @comma_space, ' => '],
148
- [:wrap, @hello.join(@world), '{', '}'],
149
- [:replace, @world, ':everybody'],
150
- [:wrap, @world, '[', ']']
151
- end
152
-
153
- def test_wraps_same_range
154
- assert_actions_result 'puts([(:hello)], :world)',
155
- [[:wrap, @hello, '(', ')'],
156
- [:wrap, @hello, '[', ']']]
157
- end
158
-
159
- def test_inserts_on_empty_ranges
160
- assert_actions_result 'puts({x}:hello[y], :world)',
161
- [:insert_before, @hello.begin, '{'],
162
- [:replace, @hello.begin, 'x'],
163
- [:insert_after, @hello.begin, '}'],
164
- [:insert_before, @hello.end, '['],
165
- [:replace, @hello.end, 'y'],
166
- [:insert_after, @hello.end, ']']
167
- end
168
-
169
- def test_replace_same_range
170
- assert_actions_result 'puts(:hey, :world)',
171
- [[:replace, @hello, ':hi'],
172
- [:replace, @hello, ':hey']],
173
- different_replacements: <<-DIAGNOSTIC.chomp
174
- (rewriter):1:6: warning: different replacements: :hey vs :hi
175
- (rewriter):1: puts(:hello, :world)
176
- (rewriter):1: ^~~~~~
177
- DIAGNOSTIC
178
- end
179
-
180
- def test_swallowed_insertions
181
- assert_actions_result 'puts(:hi)',
182
- [[:wrap, @hello.adjust(begin_pos: 1), '__', '__'],
183
- [:replace, @world.adjust(end_pos: -2), 'xx'],
184
- [:replace, @hello.join(@world), ':hi']],
185
- swallowed_insertions: <<-DIAGNOSTIC.chomp
186
- (rewriter):1:6: warning: this replacement:
187
- (rewriter):1: puts(:hello, :world)
188
- (rewriter):1: ^~~~~~~~~~~~~~
189
- (rewriter):1:7: warning: swallows some inner rewriting actions:
190
- (rewriter):1: puts(:hello, :world)
191
- (rewriter):1: ^~~~~ ~~~~
192
- DIAGNOSTIC
193
- end
194
-
195
- def test_out_of_range_ranges
196
- rewriter = Parser::Source::TreeRewriter.new(@buf)
197
- assert_raises(IndexError) { rewriter.insert_before(range(0, 100), 'hola') }
198
- end
199
-
200
- def test_empty
201
- rewriter = Parser::Source::TreeRewriter.new(@buf)
202
- assert_equal true, rewriter.empty?
203
-
204
- # This is a trivial wrap
205
- rewriter.wrap(range(2,3), '', '')
206
- assert_equal true, rewriter.empty?
207
-
208
- # This is a trivial deletion
209
- rewriter.remove(range(2,0))
210
- assert_equal true, rewriter.empty?
211
-
212
- rewriter.remove(range(2,3))
213
- assert_equal false, rewriter.empty?
214
- end
215
-
216
- # splits array into two groups, yield all such possible pairs of groups
217
- # each_split([1, 2, 3, 4]) yields [1, 2], [3, 4];
218
- # then [1, 3], [2, 4]
219
- # ...
220
- # and finally [3, 4], [1, 2]
221
- def each_split(array)
222
- n = array.size
223
- first_split_size = n.div(2)
224
- splitting = (0...n).to_set
225
- splitting.to_a.combination(first_split_size) do |indices|
226
- yield array.values_at(*indices),
227
- array.values_at(*(splitting - indices))
228
- end
229
- end
230
-
231
- # Checks that `actions+extra` give the same result when
232
- # made in order or from subgroups that are later merged.
233
- # The `extra` actions are always added at the end of the second group.
234
- #
235
- def check_all_merge_possibilities(actions, extra, **policy)
236
- expected = apply(actions + extra, **policy)
237
-
238
- each_split(actions) do |actions_1, actions_2|
239
- build(actions_1, **policy) do |rewriter_1|
240
- build(actions_2 + extra, **policy) do |rewriter_2|
241
- result = rewriter_1.merge(rewriter_2).process
242
- assert_equal(expected, result,
243
- "Group 1: #{actions_1.inspect}\n\n" +
244
- "Group 2: #{(actions_2 + extra).inspect}"
245
- )
246
- end
247
- end
248
- end
249
- end
250
-
251
- def test_merge
252
- check_all_merge_possibilities([
253
- [:wrap, @whole, '<', '>'],
254
- [:replace, @comma_space, ' => '],
255
- [:wrap, @hello, '!', '!'],
256
- # Following two wraps must have same value as they
257
- # will be applied in different orders...
258
- [:wrap, @hello.join(@world), '{', '}'],
259
- [:wrap, @hello.join(@world), '{', '}'],
260
- [:remove, @ll],
261
- [:replace, @world, ':everybody'],
262
- [:wrap, @world, '[', ']']
263
- ],
264
- [ # ... but this one is always going to be applied last (extra)
265
- [:wrap, @hello.join(@world), '@', '@'],
266
- ])
267
- end
268
-
269
- def representation_example
270
- Parser::Source::TreeRewriter.new(@buf)
271
- .wrap(range(1...10), '(', ')')
272
- .insert_after(range(2...6), '!')
273
- .replace(range(2...4), 'foo')
274
- .remove(range(5...6))
275
- end
276
-
277
- def test_nested_actions
278
- result = representation_example.as_nested_actions
279
-
280
- assert_equal( [ [:wrap, 1...10, '(', ')'],
281
- [:wrap, 2...6, '', '!'], # aka "insert_after"
282
- [:replace, 2...4, 'foo'],
283
- [:replace, 5...6, ''], # aka "removal"
284
- ],
285
- result.each {|arr| arr[1] = arr[1].to_range }
286
- )
287
- end
288
-
289
- def test_ordered_replacements
290
- result = representation_example.as_replacements
291
-
292
- assert_equal( [ [ 1...1, '('],
293
- [ 2...4, 'foo'],
294
- [ 5...6, ''],
295
- [ 6...6, '!'],
296
- [ 10...10, ')'],
297
- ],
298
- result.map {|r, s| [r.to_range, s]}
299
- )
300
- end
301
- end
302
-
303
- class TestSourceTreeRewriterImport < Minitest::Test
304
- include TestSourceTreeRewriter::Setup
305
- def setup
306
- super
307
- @buf2 = Parser::Source::Buffer.new('(rewriter 2)',
308
- source: ':hello')
309
-
310
- @rewriter = Parser::Source::TreeRewriter.new(@buf)
311
-
312
- @rewriter2 = Parser::Source::TreeRewriter.new(@buf2)
313
-
314
- @hello2 = range2(0, 6)
315
- @ll2 = range2(3, 2)
316
- end
317
-
318
- def range2(from, len)
319
- Parser::Source::Range.new(@buf2, from, from + len)
320
- end
321
-
322
- def test_import_with_offset
323
- @rewriter2.wrap(@hello2, '[', ']')
324
- @rewriter.wrap(@hello.join(@world), '{', '}')
325
- @rewriter.import!(@rewriter2, offset: @hello.begin_pos)
326
- assert_equal 'puts({[:hello], :world})', @rewriter.process
327
- end
328
-
329
- def test_import_with_offset_from_bigger_source
330
- @rewriter2.wrap(@ll2, '[', ']')
331
- @rewriter.wrap(@hello, '{', '}')
332
- @rewriter2.import!(@rewriter, offset: -@hello.begin_pos)
333
- assert_equal '{:he[ll]o}', @rewriter2.process
334
- end
335
-
336
- def test_import_with_offset_and_self
337
- @rewriter.wrap(@ll, '[', ']')
338
- @rewriter.import!(@rewriter, offset: +3)
339
- @rewriter.replace(range(8,1), '**')
340
- assert_equal 'puts(:he[**l]o[, ]:world)', @rewriter.process
341
- @rewriter.import!(@rewriter, offset: -6)
342
- assert_equal 'pu[**s]([:h]e[**l]o[, ]:world)', @rewriter.process
343
- end
344
-
345
- def test_import_with_invalid_offset
346
- @rewriter.wrap(@ll, '[', ']')
347
- m = @rewriter.dup.import!(@rewriter, offset: -@ll.begin_pos)
348
- assert_equal '[pu]ts(:he[ll]o, :world)', m.process
349
- off = @buf.source.size - @ll.end_pos
350
- m = @rewriter.dup.import!(@rewriter, offset: off)
351
- assert_equal 'puts(:he[ll]o, :worl[d)]', m.process
352
- assert_raises { @rewriter.import!(@rewriter, offset: -@ll.begin_pos - 1) }
353
- assert_raises { @rewriter.import!(@rewriter, offset: off + 1) }
354
- assert_equal 'puts(:he[ll]o, :world)', @rewriter.process # Test atomicity of import!
355
- end
356
-
357
- def test_empty_import
358
- assert_equal @rewriter, @rewriter.import!(@rewriter2)
359
- assert_equal @rewriter, @rewriter.import!(@rewriter, offset: 42)
360
- end
361
- end
@@ -1,45 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'helper'
4
-
5
- class TestStaticEnvironment < Minitest::Test
6
- def setup
7
- @env = Parser::StaticEnvironment.new
8
- end
9
-
10
- def test_declare
11
- refute @env.declared?(:foo)
12
-
13
- @env.declare :foo
14
-
15
- assert @env.declared?(:foo)
16
- end
17
-
18
- def test_extend_static
19
- @env.declare :foo
20
- @env.extend_static
21
- @env.declare :bar
22
-
23
- refute @env.declared?(:foo)
24
- assert @env.declared?(:bar)
25
- end
26
-
27
- def test_extend_dynamic
28
- @env.declare :foo
29
- @env.extend_dynamic
30
- @env.declare :bar
31
-
32
- assert @env.declared?(:foo)
33
- assert @env.declared?(:bar)
34
- end
35
-
36
- def test_unextend
37
- @env.declare :foo
38
- @env.extend_dynamic
39
- @env.declare :bar
40
- @env.unextend
41
-
42
- assert @env.declared?(:foo)
43
- refute @env.declared?(:bar)
44
- end
45
- end