parser 2.7.0.4 → 2.7.1.3
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +18 -29
- data/CHANGELOG.md +53 -1
- data/README.md +6 -6
- data/Rakefile +2 -1
- data/doc/AST_FORMAT.md +54 -5
- data/lib/parser.rb +1 -0
- data/lib/parser/all.rb +1 -0
- data/lib/parser/ast/processor.rb +7 -0
- data/lib/parser/builders/default.rb +63 -14
- data/lib/parser/current.rb +13 -4
- data/lib/parser/diagnostic.rb +1 -1
- data/lib/parser/diagnostic/engine.rb +1 -2
- data/lib/parser/lexer.rl +7 -0
- data/lib/parser/messages.rb +15 -0
- data/lib/parser/meta.rb +2 -2
- data/lib/parser/ruby27.y +16 -5
- data/lib/parser/ruby28.y +3016 -0
- data/lib/parser/runner.rb +26 -2
- data/lib/parser/runner/ruby_rewrite.rb +2 -2
- data/lib/parser/source/buffer.rb +3 -1
- data/lib/parser/source/comment/associator.rb +14 -4
- data/lib/parser/source/map/endless_definition.rb +23 -0
- data/lib/parser/source/range.rb +16 -0
- data/lib/parser/source/tree_rewriter.rb +49 -12
- data/lib/parser/source/tree_rewriter/action.rb +96 -26
- data/lib/parser/tree_rewriter.rb +1 -2
- data/lib/parser/version.rb +1 -1
- data/parser.gemspec +2 -1
- data/test/helper.rb +25 -6
- data/test/parse_helper.rb +11 -17
- data/test/test_ast_processor.rb +32 -0
- data/test/test_base.rb +1 -1
- data/test/test_current.rb +2 -0
- data/test/test_diagnostic.rb +6 -7
- data/test/test_diagnostic_engine.rb +5 -8
- data/test/test_lexer.rb +17 -8
- data/test/test_meta.rb +12 -0
- data/test/test_parser.rb +260 -21
- data/test/test_runner_parse.rb +22 -1
- data/test/test_runner_rewrite.rb +1 -1
- data/test/test_source_buffer.rb +4 -1
- data/test/test_source_comment.rb +2 -2
- data/test/test_source_comment_associator.rb +47 -15
- data/test/test_source_map.rb +1 -2
- data/test/test_source_range.rb +29 -9
- data/test/test_source_rewriter.rb +4 -4
- data/test/test_source_rewriter_action.rb +2 -2
- data/test/test_source_tree_rewriter.rb +96 -6
- metadata +14 -7
data/lib/parser/tree_rewriter.rb
CHANGED
@@ -28,8 +28,7 @@ module Parser
|
|
28
28
|
# EOF
|
29
29
|
#
|
30
30
|
# ast = Parser::CurrentRuby.parse code
|
31
|
-
# buffer = Parser::Source::Buffer.new('(example)')
|
32
|
-
# buffer.source = code
|
31
|
+
# buffer = Parser::Source::Buffer.new('(example)', source: code)
|
33
32
|
# rewriter = RemoveDo.new
|
34
33
|
#
|
35
34
|
# # Rewrite the AST, returns a String with the new form.
|
data/lib/parser/version.rb
CHANGED
data/parser.gemspec
CHANGED
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
lib/parser/ruby25.rb
|
33
33
|
lib/parser/ruby26.rb
|
34
34
|
lib/parser/ruby27.rb
|
35
|
+
lib/parser/ruby28.rb
|
35
36
|
lib/parser/macruby.rb
|
36
37
|
lib/parser/rubymotion.rb
|
37
38
|
)
|
@@ -44,7 +45,7 @@ Gem::Specification.new do |spec|
|
|
44
45
|
spec.add_dependency 'ast', '~> 2.4.0'
|
45
46
|
|
46
47
|
spec.add_development_dependency 'bundler', '>= 1.15', '< 3.0.0'
|
47
|
-
spec.add_development_dependency 'rake', '~>
|
48
|
+
spec.add_development_dependency 'rake', '~> 13.0.1'
|
48
49
|
spec.add_development_dependency 'racc', '= 1.4.15'
|
49
50
|
spec.add_development_dependency 'cliver', '~> 0.3.2'
|
50
51
|
|
data/test/helper.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'tempfile'
|
4
|
-
require 'minitest/test'
|
5
|
-
|
6
4
|
require 'simplecov'
|
7
5
|
|
8
6
|
if ENV.include?('COVERAGE') && SimpleCov.usable?
|
@@ -20,6 +18,7 @@ if ENV.include?('COVERAGE') && SimpleCov.usable?
|
|
20
18
|
ruby25.y
|
21
19
|
ruby26.y
|
22
20
|
ruby27.y
|
21
|
+
ruby28.y
|
23
22
|
),
|
24
23
|
File.expand_path('../../lib/parser', __FILE__))
|
25
24
|
|
@@ -27,9 +26,9 @@ if ENV.include?('COVERAGE') && SimpleCov.usable?
|
|
27
26
|
at_exit { RaccCoverage.stop }
|
28
27
|
|
29
28
|
SimpleCov.start do
|
30
|
-
self.formatter = SimpleCov::Formatter::MultiFormatter
|
31
|
-
SimpleCov::Formatter::HTMLFormatter
|
32
|
-
|
29
|
+
self.formatter = SimpleCov::Formatter::MultiFormatter.new(
|
30
|
+
SimpleCov::Formatter::HTMLFormatter
|
31
|
+
)
|
33
32
|
|
34
33
|
add_group 'Grammars' do |source_file|
|
35
34
|
source_file.filename =~ %r{\.y$}
|
@@ -52,9 +51,29 @@ require 'minitest/autorun'
|
|
52
51
|
$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
|
53
52
|
require 'parser'
|
54
53
|
|
54
|
+
module NodeCollector
|
55
|
+
extend self
|
56
|
+
attr_accessor :callbacks, :nodes
|
57
|
+
self.callbacks = []
|
58
|
+
self.nodes = []
|
59
|
+
|
60
|
+
def check
|
61
|
+
@callbacks.each do |callback|
|
62
|
+
@nodes.each { |node| callback.call(node) }
|
63
|
+
end
|
64
|
+
puts "#{callbacks.size} additional tests on #{nodes.size} nodes ran successfully"
|
65
|
+
end
|
66
|
+
|
67
|
+
Minitest.after_run { check }
|
68
|
+
end
|
69
|
+
|
70
|
+
def for_each_node(&block)
|
71
|
+
NodeCollector.callbacks << block
|
72
|
+
end
|
73
|
+
|
55
74
|
class Parser::AST::Node
|
56
75
|
def initialize(type, *)
|
57
|
-
|
76
|
+
NodeCollector.nodes << self
|
58
77
|
super
|
59
78
|
end
|
60
79
|
end
|
data/test/parse_helper.rb
CHANGED
@@ -7,7 +7,7 @@ module ParseHelper
|
|
7
7
|
require 'parser/macruby'
|
8
8
|
require 'parser/rubymotion'
|
9
9
|
|
10
|
-
ALL_VERSIONS = %w(1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 mac ios)
|
10
|
+
ALL_VERSIONS = %w(1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 mac ios)
|
11
11
|
|
12
12
|
def setup
|
13
13
|
@diagnostics = []
|
@@ -27,6 +27,7 @@ module ParseHelper
|
|
27
27
|
when '2.5' then parser = Parser::Ruby25.new
|
28
28
|
when '2.6' then parser = Parser::Ruby26.new
|
29
29
|
when '2.7' then parser = Parser::Ruby27.new
|
30
|
+
when '2.8' then parser = Parser::Ruby28.new
|
30
31
|
when 'mac' then parser = Parser::MacRuby.new
|
31
32
|
when 'ios' then parser = Parser::RubyMotion.new
|
32
33
|
else raise "Unrecognized Ruby version #{version}"
|
@@ -84,8 +85,7 @@ module ParseHelper
|
|
84
85
|
end
|
85
86
|
|
86
87
|
def try_parsing(ast, code, parser, source_maps, version)
|
87
|
-
source_file = Parser::Source::Buffer.new('(assert_parses)')
|
88
|
-
source_file.source = code
|
88
|
+
source_file = Parser::Source::Buffer.new('(assert_parses)', source: code)
|
89
89
|
|
90
90
|
begin
|
91
91
|
parsed_ast = parser.parse(source_file)
|
@@ -105,8 +105,7 @@ module ParseHelper
|
|
105
105
|
assert_equal ast, parsed_ast,
|
106
106
|
"(#{version}) AST equality"
|
107
107
|
|
108
|
-
parse_source_map_descriptions(source_maps)
|
109
|
-
do |begin_pos, end_pos, map_field, ast_path, line|
|
108
|
+
parse_source_map_descriptions(source_maps) do |begin_pos, end_pos, map_field, ast_path, line|
|
110
109
|
|
111
110
|
astlet = traverse_ast(parsed_ast, ast_path)
|
112
111
|
|
@@ -142,8 +141,7 @@ module ParseHelper
|
|
142
141
|
# ~~~
|
143
142
|
def assert_diagnoses(diagnostic, code, source_maps='', versions=ALL_VERSIONS)
|
144
143
|
with_versions(versions) do |version, parser|
|
145
|
-
source_file = Parser::Source::Buffer.new('(assert_diagnoses)')
|
146
|
-
source_file.source = code
|
144
|
+
source_file = Parser::Source::Buffer.new('(assert_diagnoses)', source: code)
|
147
145
|
|
148
146
|
begin
|
149
147
|
parser = parser.parse(source_file)
|
@@ -159,15 +157,14 @@ module ParseHelper
|
|
159
157
|
|
160
158
|
level, reason, arguments = diagnostic
|
161
159
|
arguments ||= {}
|
162
|
-
message = Parser::
|
160
|
+
message = Parser::Messages.compile(reason, arguments)
|
163
161
|
|
164
162
|
assert_equal level, emitted_diagnostic.level
|
165
163
|
assert_equal reason, emitted_diagnostic.reason
|
166
164
|
assert_equal arguments, emitted_diagnostic.arguments
|
167
165
|
assert_equal message, emitted_diagnostic.message
|
168
166
|
|
169
|
-
parse_source_map_descriptions(source_maps)
|
170
|
-
do |begin_pos, end_pos, map_field, ast_path, line|
|
167
|
+
parse_source_map_descriptions(source_maps) do |begin_pos, end_pos, map_field, ast_path, line|
|
171
168
|
|
172
169
|
case map_field
|
173
170
|
when 'location'
|
@@ -201,8 +198,7 @@ module ParseHelper
|
|
201
198
|
# ~~~
|
202
199
|
def assert_diagnoses_many(diagnostics, code, versions=ALL_VERSIONS)
|
203
200
|
with_versions(versions) do |version, parser|
|
204
|
-
source_file = Parser::Source::Buffer.new('(assert_diagnoses_many)')
|
205
|
-
source_file.source = code
|
201
|
+
source_file = Parser::Source::Buffer.new('(assert_diagnoses_many)', source: code)
|
206
202
|
|
207
203
|
begin
|
208
204
|
parser = parser.parse(source_file)
|
@@ -215,7 +211,7 @@ module ParseHelper
|
|
215
211
|
diagnostics.zip(@diagnostics) do |expected_diagnostic, actual_diagnostic|
|
216
212
|
level, reason, arguments = expected_diagnostic
|
217
213
|
arguments ||= {}
|
218
|
-
message = Parser::
|
214
|
+
message = Parser::Messages.compile(reason, arguments)
|
219
215
|
|
220
216
|
assert_equal level, actual_diagnostic.level
|
221
217
|
assert_equal reason, actual_diagnostic.reason
|
@@ -227,8 +223,7 @@ module ParseHelper
|
|
227
223
|
|
228
224
|
def refute_diagnoses(code, versions=ALL_VERSIONS)
|
229
225
|
with_versions(versions) do |version, parser|
|
230
|
-
source_file = Parser::Source::Buffer.new('(refute_diagnoses)')
|
231
|
-
source_file.source = code
|
226
|
+
source_file = Parser::Source::Buffer.new('(refute_diagnoses)', source: code)
|
232
227
|
|
233
228
|
begin
|
234
229
|
parser = parser.parse(source_file)
|
@@ -244,8 +239,7 @@ module ParseHelper
|
|
244
239
|
|
245
240
|
def assert_context(context, code, versions=ALL_VERSIONS)
|
246
241
|
with_versions(versions) do |version, parser|
|
247
|
-
source_file = Parser::Source::Buffer.new('(assert_context)')
|
248
|
-
source_file.source = code
|
242
|
+
source_file = Parser::Source::Buffer.new('(assert_context)', source: code)
|
249
243
|
|
250
244
|
begin
|
251
245
|
parser.parse(source_file)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
class TestASTProcessor < Minitest::Test
|
6
|
+
LEAF_NODES = %i[
|
7
|
+
sym str int float complex rational
|
8
|
+
true false nil self
|
9
|
+
__FILE__ __LINE__ __ENCODING__
|
10
|
+
cbase regopt zsuper
|
11
|
+
match_with_trailing_comma match_nil_pattern
|
12
|
+
forward_args forwarded_args numargs kwnilarg
|
13
|
+
objc_varargs objc_restarg objc_kwarg
|
14
|
+
ident
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
def setup
|
18
|
+
@traversible = Parser::AST::Processor
|
19
|
+
.instance_methods(false)
|
20
|
+
.map { |mid| mid.to_s.scan(/\Aon_(.*)/) }
|
21
|
+
.flatten
|
22
|
+
.map(&:to_sym)
|
23
|
+
|
24
|
+
@traversible += LEAF_NODES
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_nodes_are_traversible
|
28
|
+
for_each_node do |node|
|
29
|
+
assert_includes @traversible, node.type
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/test/test_base.rb
CHANGED
data/test/test_current.rb
CHANGED
@@ -22,6 +22,8 @@ class TestCurrent < Minitest::Test
|
|
22
22
|
assert_equal Parser::Ruby26, Parser::CurrentRuby
|
23
23
|
when /^2\.7\.\d+/
|
24
24
|
assert_equal Parser::Ruby27, Parser::CurrentRuby
|
25
|
+
when /^2\.8\.\d+/
|
26
|
+
assert_equal Parser::Ruby28, Parser::CurrentRuby
|
25
27
|
else
|
26
28
|
flunk "Update test_current for #{RUBY_VERSION}"
|
27
29
|
end
|
data/test/test_diagnostic.rb
CHANGED
@@ -4,8 +4,8 @@ require 'helper'
|
|
4
4
|
|
5
5
|
class TestDiagnostic < Minitest::Test
|
6
6
|
def setup
|
7
|
-
@buffer = Parser::Source::Buffer.new('(string)'
|
8
|
-
|
7
|
+
@buffer = Parser::Source::Buffer.new('(string)',
|
8
|
+
source: 'if (this is some bad code + bugs)')
|
9
9
|
|
10
10
|
@range1 = Parser::Source::Range.new(@buffer, 0, 2) # if
|
11
11
|
@range2 = Parser::Source::Range.new(@buffer, 4, 8) # this
|
@@ -16,7 +16,7 @@ class TestDiagnostic < Minitest::Test
|
|
16
16
|
Parser::Diagnostic.new(:foobar, :escape_eof, {}, @range1)
|
17
17
|
end
|
18
18
|
|
19
|
-
assert_match
|
19
|
+
assert_match(/level/, error.message)
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_freezes
|
@@ -50,8 +50,8 @@ class TestDiagnostic < Minitest::Test
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def test_multiline_render
|
53
|
-
@buffer = Parser::Source::Buffer.new('(string)'
|
54
|
-
|
53
|
+
@buffer = Parser::Source::Buffer.new('(string)',
|
54
|
+
source: "abc abc abc\ndef def def\nghi ghi ghi\n")
|
55
55
|
|
56
56
|
location = Parser::Source::Range.new(@buffer, 4, 27)
|
57
57
|
|
@@ -80,8 +80,7 @@ class TestDiagnostic < Minitest::Test
|
|
80
80
|
}
|
81
81
|
}
|
82
82
|
CODE
|
83
|
-
@buffer = Parser::Source::Buffer.new('(string)')
|
84
|
-
@buffer.source = source
|
83
|
+
@buffer = Parser::Source::Buffer.new('(string)', source: source)
|
85
84
|
|
86
85
|
location = Parser::Source::Range.new(@buffer, 33, 34)
|
87
86
|
diag = Parser::Diagnostic.new(:error, :unexpected_token, { :token => 'tNL' },
|
@@ -4,9 +4,6 @@ require 'helper'
|
|
4
4
|
|
5
5
|
class TestDiagnosticEngine < Minitest::Test
|
6
6
|
def setup
|
7
|
-
@buffer = Parser::Source::Buffer.new('(source)')
|
8
|
-
@buffer.source = 'foobar'
|
9
|
-
|
10
7
|
@engine = Parser::Diagnostic::Engine.new
|
11
8
|
|
12
9
|
@queue = []
|
@@ -14,7 +11,7 @@ class TestDiagnosticEngine < Minitest::Test
|
|
14
11
|
end
|
15
12
|
|
16
13
|
def test_process_warnings
|
17
|
-
warn = Parser::Diagnostic.new(:warning, :invalid_escape,
|
14
|
+
warn = Parser::Diagnostic.new(:warning, :invalid_escape, {}, 1..2)
|
18
15
|
@engine.process(warn)
|
19
16
|
|
20
17
|
assert_equal [warn], @queue
|
@@ -23,7 +20,7 @@ class TestDiagnosticEngine < Minitest::Test
|
|
23
20
|
def test_ignore_warnings
|
24
21
|
@engine.ignore_warnings = true
|
25
22
|
|
26
|
-
warn = Parser::Diagnostic.new(:warning, :invalid_escape,
|
23
|
+
warn = Parser::Diagnostic.new(:warning, :invalid_escape, {}, 1..2)
|
27
24
|
@engine.process(warn)
|
28
25
|
|
29
26
|
assert_equal [], @queue
|
@@ -32,7 +29,7 @@ class TestDiagnosticEngine < Minitest::Test
|
|
32
29
|
def test_all_errors_are_fatal
|
33
30
|
@engine.all_errors_are_fatal = true
|
34
31
|
|
35
|
-
error = Parser::Diagnostic.new(:error, :invalid_escape,
|
32
|
+
error = Parser::Diagnostic.new(:error, :invalid_escape, {}, 1..2)
|
36
33
|
|
37
34
|
err = assert_raises Parser::SyntaxError do
|
38
35
|
@engine.process(error)
|
@@ -44,14 +41,14 @@ class TestDiagnosticEngine < Minitest::Test
|
|
44
41
|
end
|
45
42
|
|
46
43
|
def test_all_errors_are_collected
|
47
|
-
error = Parser::Diagnostic.new(:error, :invalid_escape,
|
44
|
+
error = Parser::Diagnostic.new(:error, :invalid_escape, {}, 1..2)
|
48
45
|
@engine.process(error)
|
49
46
|
|
50
47
|
assert_equal [error], @queue
|
51
48
|
end
|
52
49
|
|
53
50
|
def test_fatal_error
|
54
|
-
fatal = Parser::Diagnostic.new(:fatal, :invalid_escape,
|
51
|
+
fatal = Parser::Diagnostic.new(:fatal, :invalid_escape, {}, 1..2)
|
55
52
|
|
56
53
|
assert_raises Parser::SyntaxError do
|
57
54
|
@engine.process(fatal)
|
data/test/test_lexer.rb
CHANGED
@@ -37,9 +37,8 @@ class TestLexer < Minitest::Test
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def assert_escape(expected, input)
|
40
|
-
source_buffer = Parser::Source::Buffer.new('(assert_escape)'
|
41
|
-
|
42
|
-
source_buffer.source = "\"\\#{input}\"".encode(input.encoding)
|
40
|
+
source_buffer = Parser::Source::Buffer.new('(assert_escape)',
|
41
|
+
source: "\"\\#{input}\"".encode(input.encoding))
|
43
42
|
|
44
43
|
@lex.reset
|
45
44
|
@lex.source_buffer = source_buffer
|
@@ -71,8 +70,7 @@ class TestLexer < Minitest::Test
|
|
71
70
|
end
|
72
71
|
|
73
72
|
def assert_scanned(input, *args)
|
74
|
-
source_buffer = Parser::Source::Buffer.new('(assert_scanned)')
|
75
|
-
source_buffer.source = input
|
73
|
+
source_buffer = Parser::Source::Buffer.new('(assert_scanned)', source: input)
|
76
74
|
|
77
75
|
@lex.reset(false)
|
78
76
|
@lex.source_buffer = source_buffer
|
@@ -3569,14 +3567,25 @@ class TestLexer < Minitest::Test
|
|
3569
3567
|
:tIDENTIFIER, 're', [1, 3])
|
3570
3568
|
end
|
3571
3569
|
|
3570
|
+
def test_endless_method
|
3571
|
+
setup_lexer(28)
|
3572
|
+
|
3573
|
+
assert_scanned('def foo() = 42',
|
3574
|
+
:kDEF, "def", [0, 3],
|
3575
|
+
:tIDENTIFIER, "foo", [4, 7],
|
3576
|
+
:tLPAREN2, "(", [7, 8],
|
3577
|
+
:tRPAREN, ")", [8, 9],
|
3578
|
+
:tEQL, "=", [10, 11],
|
3579
|
+
:tINTEGER, 42, [12, 14])
|
3580
|
+
end
|
3581
|
+
|
3572
3582
|
def lex_numbered_parameter(input)
|
3573
3583
|
@lex.max_numparam_stack.push
|
3574
3584
|
|
3575
3585
|
@lex.context = Parser::Context.new
|
3576
3586
|
@lex.context.push(:block)
|
3577
3587
|
|
3578
|
-
source_buffer = Parser::Source::Buffer.new('(assert_lex_numbered_parameter)')
|
3579
|
-
source_buffer.source = input
|
3588
|
+
source_buffer = Parser::Source::Buffer.new('(assert_lex_numbered_parameter)', source: input)
|
3580
3589
|
|
3581
3590
|
@lex.source_buffer = source_buffer
|
3582
3591
|
|
@@ -3594,7 +3603,7 @@ class TestLexer < Minitest::Test
|
|
3594
3603
|
|
3595
3604
|
def refute_scanned_numbered_parameter(input, message = nil)
|
3596
3605
|
err = assert_raises Parser::SyntaxError do
|
3597
|
-
|
3606
|
+
_lex_token, (_lex_value, _lex_range) = lex_numbered_parameter(input)
|
3598
3607
|
end
|
3599
3608
|
|
3600
3609
|
if message
|
data/test/test_meta.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
class TestMeta < Minitest::Test
|
6
|
+
def test_NODE_TYPES
|
7
|
+
for_each_node do |node|
|
8
|
+
assert Parser::Meta::NODE_TYPES.include?(node.type),
|
9
|
+
"Type #{node.type} missing from Parser::Meta::NODE_TYPES"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
data/test/test_parser.rb
CHANGED
@@ -29,6 +29,7 @@ class TestParser < Minitest::Test
|
|
29
29
|
SINCE_2_5 = SINCE_2_4 - %w(2.4)
|
30
30
|
SINCE_2_6 = SINCE_2_5 - %w(2.5)
|
31
31
|
SINCE_2_7 = SINCE_2_6 - %w(2.6)
|
32
|
+
SINCE_2_8 = SINCE_2_7 - %w(2.7)
|
32
33
|
|
33
34
|
# Guidelines for test naming:
|
34
35
|
# * Test structure follows structure of AST_FORMAT.md.
|
@@ -5359,8 +5360,7 @@ class TestParser < Minitest::Test
|
|
5359
5360
|
|
5360
5361
|
def test_crlf_line_endings
|
5361
5362
|
with_versions(ALL_VERSIONS) do |_ver, parser|
|
5362
|
-
source_file = Parser::Source::Buffer.new('(comments)')
|
5363
|
-
source_file.source = "\r\nfoo"
|
5363
|
+
source_file = Parser::Source::Buffer.new('(comments)', source: "\r\nfoo")
|
5364
5364
|
|
5365
5365
|
range = lambda do |from, to|
|
5366
5366
|
Parser::Source::Range.new(source_file, from, to)
|
@@ -5433,8 +5433,7 @@ class TestParser < Minitest::Test
|
|
5433
5433
|
with_versions(ALL_VERSIONS) do |_ver, parser|
|
5434
5434
|
parser.builder.emit_file_line_as_literals = false
|
5435
5435
|
|
5436
|
-
source_file = Parser::Source::Buffer.new('(comments)')
|
5437
|
-
source_file.source = "[__FILE__, __LINE__]"
|
5436
|
+
source_file = Parser::Source::Buffer.new('(comments)', source: "[__FILE__, __LINE__]")
|
5438
5437
|
|
5439
5438
|
ast = parser.parse(source_file)
|
5440
5439
|
|
@@ -5518,8 +5517,7 @@ class TestParser < Minitest::Test
|
|
5518
5517
|
|
5519
5518
|
def assert_parses_with_comments(ast_pattern, source, comments_pattern)
|
5520
5519
|
with_versions(ALL_VERSIONS) do |_ver, parser|
|
5521
|
-
source_file = Parser::Source::Buffer.new('(comments)')
|
5522
|
-
source_file.source = source
|
5520
|
+
source_file = Parser::Source::Buffer.new('(comments)', source: source)
|
5523
5521
|
|
5524
5522
|
comments_pattern_here = comments_pattern.map do |(from, to)|
|
5525
5523
|
range = Parser::Source::Range.new(source_file, from, to)
|
@@ -5550,8 +5548,8 @@ class TestParser < Minitest::Test
|
|
5550
5548
|
|
5551
5549
|
def test_tokenize
|
5552
5550
|
with_versions(ALL_VERSIONS) do |_ver, parser|
|
5553
|
-
source_file = Parser::Source::Buffer.new('(tokenize)'
|
5554
|
-
|
5551
|
+
source_file = Parser::Source::Buffer.new('(tokenize)',
|
5552
|
+
source: "1 + # foo\n 2")
|
5555
5553
|
|
5556
5554
|
range = lambda do |from, to|
|
5557
5555
|
Parser::Source::Range.new(source_file, from, to)
|
@@ -5577,8 +5575,8 @@ class TestParser < Minitest::Test
|
|
5577
5575
|
|
5578
5576
|
def test_tokenize_recover
|
5579
5577
|
with_versions(ALL_VERSIONS) do |_ver, parser|
|
5580
|
-
source_file = Parser::Source::Buffer.new('(tokenize)'
|
5581
|
-
|
5578
|
+
source_file = Parser::Source::Buffer.new('(tokenize)',
|
5579
|
+
source: "1 + # foo\n ")
|
5582
5580
|
|
5583
5581
|
range = lambda do |from, to|
|
5584
5582
|
Parser::Source::Range.new(source_file, from, to)
|
@@ -8422,7 +8420,7 @@ class TestParser < Minitest::Test
|
|
8422
8420
|
nil,
|
8423
8421
|
s(:nil)),
|
8424
8422
|
%q{in x, then nil},
|
8425
|
-
%q{
|
8423
|
+
%q{ ~~ expression (in_pattern.array_pattern_with_tail)}
|
8426
8424
|
)
|
8427
8425
|
|
8428
8426
|
assert_parses_pattern_match(
|
@@ -8468,7 +8466,7 @@ class TestParser < Minitest::Test
|
|
8468
8466
|
nil,
|
8469
8467
|
s(:nil)),
|
8470
8468
|
%q{in x, y, then nil},
|
8471
|
-
%q{
|
8469
|
+
%q{ ~~~~~ expression (in_pattern.array_pattern_with_tail)}
|
8472
8470
|
)
|
8473
8471
|
|
8474
8472
|
assert_parses_pattern_match(
|
@@ -8675,6 +8673,18 @@ class TestParser < Minitest::Test
|
|
8675
8673
|
| ~ end (in_pattern.hash_pattern)}
|
8676
8674
|
)
|
8677
8675
|
|
8676
|
+
assert_parses_pattern_match(
|
8677
|
+
s(:in_pattern,
|
8678
|
+
s(:hash_pattern,
|
8679
|
+
s(:pair, s(:sym, :a), s(:int, 1))),
|
8680
|
+
nil,
|
8681
|
+
s(:true)),
|
8682
|
+
%q{in { a: 1, } then true},
|
8683
|
+
%q{ ~~~~~~~~~ expression (in_pattern.hash_pattern)
|
8684
|
+
| ~ begin (in_pattern.hash_pattern)
|
8685
|
+
| ~ end (in_pattern.hash_pattern)}
|
8686
|
+
)
|
8687
|
+
|
8678
8688
|
assert_parses_pattern_match(
|
8679
8689
|
s(:in_pattern,
|
8680
8690
|
s(:hash_pattern,
|
@@ -8746,6 +8756,67 @@ class TestParser < Minitest::Test
|
|
8746
8756
|
%q{in a: 1, _a:, ** then true},
|
8747
8757
|
%q{ ~~~~~~~~~~~~~ expression (in_pattern.hash_pattern)}
|
8748
8758
|
)
|
8759
|
+
|
8760
|
+
assert_parses_pattern_match(
|
8761
|
+
s(:in_pattern,
|
8762
|
+
s(:hash_pattern,
|
8763
|
+
s(:pair,
|
8764
|
+
s(:sym, :a),
|
8765
|
+
s(:int, 1))), nil,
|
8766
|
+
s(:false)),
|
8767
|
+
%q{
|
8768
|
+
in {a: 1
|
8769
|
+
}
|
8770
|
+
false
|
8771
|
+
},
|
8772
|
+
%q{}
|
8773
|
+
)
|
8774
|
+
|
8775
|
+
|
8776
|
+
assert_parses_pattern_match(
|
8777
|
+
s(:in_pattern,
|
8778
|
+
s(:hash_pattern,
|
8779
|
+
s(:pair,
|
8780
|
+
s(:sym, :a),
|
8781
|
+
s(:int, 2))), nil,
|
8782
|
+
s(:false)),
|
8783
|
+
%q{
|
8784
|
+
in {a:
|
8785
|
+
2}
|
8786
|
+
false
|
8787
|
+
},
|
8788
|
+
%q{}
|
8789
|
+
)
|
8790
|
+
|
8791
|
+
assert_parses_pattern_match(
|
8792
|
+
s(:in_pattern,
|
8793
|
+
s(:hash_pattern,
|
8794
|
+
s(:pair,
|
8795
|
+
s(:sym, :a),
|
8796
|
+
s(:hash_pattern,
|
8797
|
+
s(:match_var, :b))),
|
8798
|
+
s(:match_var, :c)), nil,
|
8799
|
+
s(:send, nil, :p,
|
8800
|
+
s(:lvar, :c))),
|
8801
|
+
%q{
|
8802
|
+
in a: {b:}, c:
|
8803
|
+
p c
|
8804
|
+
},
|
8805
|
+
%q{}
|
8806
|
+
)
|
8807
|
+
|
8808
|
+
assert_parses_pattern_match(
|
8809
|
+
s(:in_pattern,
|
8810
|
+
s(:hash_pattern,
|
8811
|
+
s(:match_var, :a)), nil,
|
8812
|
+
s(:true)),
|
8813
|
+
%q{
|
8814
|
+
in {a:
|
8815
|
+
}
|
8816
|
+
true
|
8817
|
+
},
|
8818
|
+
%q{}
|
8819
|
+
)
|
8749
8820
|
end
|
8750
8821
|
|
8751
8822
|
def test_pattern_matching_hash_with_string_keys
|
@@ -8860,6 +8931,22 @@ class TestParser < Minitest::Test
|
|
8860
8931
|
%q{ ~~~~~~~ location},
|
8861
8932
|
SINCE_2_7
|
8862
8933
|
)
|
8934
|
+
|
8935
|
+
assert_diagnoses(
|
8936
|
+
[:error, :pm_interp_in_var_name],
|
8937
|
+
%q{case a; in "#{a}": 1; end},
|
8938
|
+
%q{ ~~~~~~~ location},
|
8939
|
+
SINCE_2_7
|
8940
|
+
)
|
8941
|
+
end
|
8942
|
+
|
8943
|
+
def test_pattern_matching_invalid_lvar_name
|
8944
|
+
assert_diagnoses(
|
8945
|
+
[:error, :lvar_name, { name: :a? }],
|
8946
|
+
%q{case a; in a?:; end},
|
8947
|
+
%q{ ~~ location},
|
8948
|
+
SINCE_2_7
|
8949
|
+
)
|
8863
8950
|
end
|
8864
8951
|
|
8865
8952
|
def test_pattern_matching_keyword_variable
|
@@ -8993,7 +9080,7 @@ class TestParser < Minitest::Test
|
|
8993
9080
|
nil,
|
8994
9081
|
s(:true)),
|
8995
9082
|
%q{in A(1, 2) then true},
|
8996
|
-
%q{
|
9083
|
+
%q{ ~~~~~~~ expression (in_pattern.const_pattern)
|
8997
9084
|
| ~ begin (in_pattern.const_pattern)
|
8998
9085
|
| ~ end (in_pattern.const_pattern)
|
8999
9086
|
| ~ expression (in_pattern.const_pattern.const)
|
@@ -9009,7 +9096,7 @@ class TestParser < Minitest::Test
|
|
9009
9096
|
nil,
|
9010
9097
|
s(:true)),
|
9011
9098
|
%q{in A(x:) then true},
|
9012
|
-
%q{
|
9099
|
+
%q{ ~~~~~ expression (in_pattern.const_pattern)
|
9013
9100
|
| ~ begin (in_pattern.const_pattern)
|
9014
9101
|
| ~ end (in_pattern.const_pattern)
|
9015
9102
|
| ~ expression (in_pattern.const_pattern.const)
|
@@ -9024,7 +9111,7 @@ class TestParser < Minitest::Test
|
|
9024
9111
|
nil,
|
9025
9112
|
s(:true)),
|
9026
9113
|
%q{in A() then true},
|
9027
|
-
%q{
|
9114
|
+
%q{ ~~~ expression (in_pattern.const_pattern)
|
9028
9115
|
| ~ begin (in_pattern.const_pattern)
|
9029
9116
|
| ~ end (in_pattern.const_pattern)
|
9030
9117
|
| ~ expression (in_pattern.const_pattern.const)
|
@@ -9041,7 +9128,7 @@ class TestParser < Minitest::Test
|
|
9041
9128
|
nil,
|
9042
9129
|
s(:true)),
|
9043
9130
|
%q{in A[1, 2] then true},
|
9044
|
-
%q{
|
9131
|
+
%q{ ~~~~~~~ expression (in_pattern.const_pattern)
|
9045
9132
|
| ~ begin (in_pattern.const_pattern)
|
9046
9133
|
| ~ end (in_pattern.const_pattern)
|
9047
9134
|
| ~ expression (in_pattern.const_pattern.const)
|
@@ -9057,7 +9144,7 @@ class TestParser < Minitest::Test
|
|
9057
9144
|
nil,
|
9058
9145
|
s(:true)),
|
9059
9146
|
%q{in A[x:] then true},
|
9060
|
-
%q{
|
9147
|
+
%q{ ~~~~~ expression (in_pattern.const_pattern)
|
9061
9148
|
| ~ begin (in_pattern.const_pattern)
|
9062
9149
|
| ~ end (in_pattern.const_pattern)
|
9063
9150
|
| ~ expression (in_pattern.const_pattern.const)
|
@@ -9072,7 +9159,7 @@ class TestParser < Minitest::Test
|
|
9072
9159
|
nil,
|
9073
9160
|
s(:true)),
|
9074
9161
|
%q{in A[] then true},
|
9075
|
-
%q{
|
9162
|
+
%q{ ~~~ expression (in_pattern.const_pattern)
|
9076
9163
|
| ~ begin (in_pattern.const_pattern)
|
9077
9164
|
| ~ end (in_pattern.const_pattern)
|
9078
9165
|
| ~~ expression (in_pattern.const_pattern.array_pattern)}
|
@@ -9137,8 +9224,7 @@ class TestParser < Minitest::Test
|
|
9137
9224
|
code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
|
9138
9225
|
|
9139
9226
|
with_versions(versions) do |version, parser|
|
9140
|
-
source_file = Parser::Source::Buffer.new('(assert_context)')
|
9141
|
-
source_file.source = code
|
9227
|
+
source_file = Parser::Source::Buffer.new('(assert_context)', source: code)
|
9142
9228
|
|
9143
9229
|
lvar_names.each do |lvar_name|
|
9144
9230
|
refute parser.static_env.declared?(lvar_name),
|
@@ -9148,7 +9234,7 @@ class TestParser < Minitest::Test
|
|
9148
9234
|
before = parser.static_env.instance_variable_get(:@variables).to_a
|
9149
9235
|
|
9150
9236
|
begin
|
9151
|
-
|
9237
|
+
_parsed_ast = parser.parse(source_file)
|
9152
9238
|
rescue Parser::SyntaxError => exc
|
9153
9239
|
backtrace = exc.backtrace
|
9154
9240
|
Exception.instance_method(:initialize).bind(exc).
|
@@ -9354,4 +9440,157 @@ class TestParser < Minitest::Test
|
|
9354
9440
|
%{},
|
9355
9441
|
SINCE_1_9)
|
9356
9442
|
end
|
9443
|
+
|
9444
|
+
def test_endless_method
|
9445
|
+
assert_parses(
|
9446
|
+
s(:def_e, :foo,
|
9447
|
+
s(:args),
|
9448
|
+
s(:int, 42)),
|
9449
|
+
%q{def foo() = 42},
|
9450
|
+
%q{~~~ keyword
|
9451
|
+
| ~~~ name
|
9452
|
+
| ^ assignment
|
9453
|
+
|~~~~~~~~~~~~~~ expression},
|
9454
|
+
SINCE_2_8)
|
9455
|
+
|
9456
|
+
assert_parses(
|
9457
|
+
s(:def_e, :inc,
|
9458
|
+
s(:args, s(:arg, :x)),
|
9459
|
+
s(:send,
|
9460
|
+
s(:lvar, :x), :+,
|
9461
|
+
s(:int, 1))),
|
9462
|
+
%q{def inc(x) = x + 1},
|
9463
|
+
%q{~~~ keyword
|
9464
|
+
| ~~~ name
|
9465
|
+
| ^ assignment
|
9466
|
+
|~~~~~~~~~~~~~~~~~~ expression},
|
9467
|
+
SINCE_2_8)
|
9468
|
+
|
9469
|
+
assert_parses(
|
9470
|
+
s(:defs_e, s(:send, nil, :obj), :foo,
|
9471
|
+
s(:args),
|
9472
|
+
s(:int, 42)),
|
9473
|
+
%q{def obj.foo() = 42},
|
9474
|
+
%q{~~~ keyword
|
9475
|
+
| ^ operator
|
9476
|
+
| ~~~ name
|
9477
|
+
| ^ assignment
|
9478
|
+
|~~~~~~~~~~~~~~~~~~ expression},
|
9479
|
+
SINCE_2_8)
|
9480
|
+
|
9481
|
+
assert_parses(
|
9482
|
+
s(:defs_e, s(:send, nil, :obj), :inc,
|
9483
|
+
s(:args, s(:arg, :x)),
|
9484
|
+
s(:send,
|
9485
|
+
s(:lvar, :x), :+,
|
9486
|
+
s(:int, 1))),
|
9487
|
+
%q{def obj.inc(x) = x + 1},
|
9488
|
+
%q{~~~ keyword
|
9489
|
+
| ~~~ name
|
9490
|
+
| ^ operator
|
9491
|
+
| ^ assignment
|
9492
|
+
|~~~~~~~~~~~~~~~~~~~~~~ expression},
|
9493
|
+
SINCE_2_8)
|
9494
|
+
|
9495
|
+
assert_parses(
|
9496
|
+
s(:def_e, :foo,
|
9497
|
+
s(:forward_args),
|
9498
|
+
s(:send, nil, :bar,
|
9499
|
+
s(:forwarded_args))),
|
9500
|
+
%q{def foo(...) = bar(...)},
|
9501
|
+
%q{~~~ keyword
|
9502
|
+
| ~~~ name
|
9503
|
+
| ^ assignment
|
9504
|
+
|~~~~~~~~~~~~~~~~~~~~~~~ expression},
|
9505
|
+
SINCE_2_8)
|
9506
|
+
end
|
9507
|
+
|
9508
|
+
def test_endless_method_without_brackets
|
9509
|
+
assert_diagnoses(
|
9510
|
+
[:error, :unexpected_token, { :token => 'tEQL' }],
|
9511
|
+
%Q{def foo = 42},
|
9512
|
+
%q{ ^ location},
|
9513
|
+
SINCE_2_8)
|
9514
|
+
|
9515
|
+
assert_diagnoses(
|
9516
|
+
[:error, :unexpected_token, { :token => 'tEQL' }],
|
9517
|
+
%Q{def obj.foo = 42},
|
9518
|
+
%q{ ^ location},
|
9519
|
+
SINCE_2_8
|
9520
|
+
)
|
9521
|
+
end
|
9522
|
+
|
9523
|
+
def test_endless_method_with_rescue_mod
|
9524
|
+
assert_parses(
|
9525
|
+
s(:def_e, :m,
|
9526
|
+
s(:args),
|
9527
|
+
s(:rescue,
|
9528
|
+
s(:int, 1),
|
9529
|
+
s(:resbody, nil, nil,
|
9530
|
+
s(:int, 2)), nil)),
|
9531
|
+
%q{def m() = 1 rescue 2},
|
9532
|
+
%q{},
|
9533
|
+
SINCE_2_8)
|
9534
|
+
|
9535
|
+
assert_parses(
|
9536
|
+
s(:defs_e,
|
9537
|
+
s(:self), :m,
|
9538
|
+
s(:args),
|
9539
|
+
s(:rescue,
|
9540
|
+
s(:int, 1),
|
9541
|
+
s(:resbody, nil, nil,
|
9542
|
+
s(:int, 2)), nil)),
|
9543
|
+
%q{def self.m() = 1 rescue 2},
|
9544
|
+
%q{},
|
9545
|
+
SINCE_2_8)
|
9546
|
+
end
|
9547
|
+
|
9548
|
+
def test_rasgn
|
9549
|
+
assert_parses(
|
9550
|
+
s(:rasgn,
|
9551
|
+
s(:int, 1), s(:lvasgn, :a)),
|
9552
|
+
%q{1 => a},
|
9553
|
+
%q{~~~~~~ expression
|
9554
|
+
| ^^ operator},
|
9555
|
+
SINCE_2_8)
|
9556
|
+
|
9557
|
+
assert_parses(
|
9558
|
+
s(:rasgn,
|
9559
|
+
s(:send, s(:int, 1), :+, s(:int, 2)),
|
9560
|
+
s(:gvasgn, :$a)),
|
9561
|
+
%q{1 + 2 => $a},
|
9562
|
+
%q{~~~~~~~~~~~ expression
|
9563
|
+
| ^^ operator},
|
9564
|
+
SINCE_2_8)
|
9565
|
+
end
|
9566
|
+
|
9567
|
+
def test_mrasgn
|
9568
|
+
assert_parses(
|
9569
|
+
s(:mrasgn,
|
9570
|
+
s(:send, s(:int, 13), :divmod, s(:int, 5)),
|
9571
|
+
s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b))),
|
9572
|
+
%q{13.divmod(5) => a,b},
|
9573
|
+
%q{~~~~~~~~~~~~~~~~~~~ expression
|
9574
|
+
| ^^ operator},
|
9575
|
+
SINCE_2_8)
|
9576
|
+
|
9577
|
+
assert_parses(
|
9578
|
+
s(:mrasgn,
|
9579
|
+
s(:mrasgn,
|
9580
|
+
s(:send, s(:int, 13), :divmod, s(:int, 5)),
|
9581
|
+
s(:mlhs, s(:lvasgn, :a), s(:lvasgn, :b))),
|
9582
|
+
s(:mlhs, s(:lvasgn, :c), s(:lvasgn, :d))),
|
9583
|
+
%q{13.divmod(5) => a,b => c, d},
|
9584
|
+
%q{~~~~~~~~~~~~~~~~~~~ expression (mrasgn)
|
9585
|
+
|~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression},
|
9586
|
+
SINCE_2_8)
|
9587
|
+
end
|
9588
|
+
|
9589
|
+
def test_rasgn_line_continuation
|
9590
|
+
assert_diagnoses(
|
9591
|
+
[:error, :unexpected_token, { :token => 'tASSOC' }],
|
9592
|
+
%Q{13.divmod(5)\n=> a,b; [a, b]},
|
9593
|
+
%{ ^^ location},
|
9594
|
+
SINCE_2_8)
|
9595
|
+
end
|
9357
9596
|
end
|