parser 2.7.0.2 → 2.7.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -2
- data/README.md +1 -1
- data/doc/AST_FORMAT.md +38 -0
- data/lib/parser/ast/processor.rb +4 -0
- data/lib/parser/builders/default.rb +7 -2
- data/lib/parser/messages.rb +1 -0
- data/lib/parser/meta.rb +1 -0
- data/lib/parser/ruby27.y +9 -2
- data/lib/parser/source/tree_rewriter/action.rb +2 -2
- data/lib/parser/version.rb +1 -1
- data/parser.gemspec +7 -0
- data/test/test_parser.rb +38 -4
- data/test/test_source_comment_associator.rb +20 -20
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2801cd6adbcd161d1a3b643dca79b9a9f7ff13210439bf632fcc22072837dffa
|
4
|
+
data.tar.gz: 20a0402b20903555a7cc29507205f7bf7176b26dfe039df79bf17fd503ed951e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b254886d186ac704cb8a6dcc6bfdce7d2f9f079ce83edb456646a0ec04336a2893c140f1b525e8cea89f34c52bf01c1e6849dc8ce80d9f4f3fdb0af072e15ac2
|
7
|
+
data.tar.gz: 627b678f07bf6ad130235f3ab1440d563905cf671e0618f2cb3b549e0f34dc341e70f5659580d731259d8caa97fd3d221868b966b5df5188c5c985db836ecc2a
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -234,7 +234,7 @@ Parser implements the MacRuby 0.12 and RubyMotion mid-2015 parsers precisely. Ho
|
|
234
234
|
|
235
235
|
## Known issues
|
236
236
|
|
237
|
-
Adding support for the following Ruby MRI features in Parser would needlessly complicate it, and as they all are very specific and rarely
|
237
|
+
Adding support for the following Ruby MRI features in Parser would needlessly complicate it, and as they all are very specific and rarely occurring corner cases, this is not done.
|
238
238
|
|
239
239
|
Parser has been extensively tested; in particular, it parses almost entire [Rubygems][rg] corpus. For every issue, a breakdown of affected gems is offered.
|
240
240
|
|
data/doc/AST_FORMAT.md
CHANGED
@@ -1870,6 +1870,27 @@ Format:
|
|
1870
1870
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression
|
1871
1871
|
~~~
|
1872
1872
|
|
1873
|
+
#### With empty else
|
1874
|
+
|
1875
|
+
Empty `else` differs from the missing (or _implicit_) `else` for pattern matching, since
|
1876
|
+
the latter one raises a `NoMatchingPattern` exception. Thus, we need a way to distinguish this
|
1877
|
+
two cases in the resulting AST.
|
1878
|
+
|
1879
|
+
Format:
|
1880
|
+
|
1881
|
+
~~~
|
1882
|
+
(case-match,
|
1883
|
+
(str "str")
|
1884
|
+
(in-pattern
|
1885
|
+
(match-var :foo)
|
1886
|
+
(lvar :bar))
|
1887
|
+
(empty-else))
|
1888
|
+
"case "str"; in foo; bar; else; end"
|
1889
|
+
~~~~ keyword ~~~~ else
|
1890
|
+
~~~ end
|
1891
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression
|
1892
|
+
~~~
|
1893
|
+
|
1873
1894
|
### In clause
|
1874
1895
|
|
1875
1896
|
Format:
|
@@ -2140,3 +2161,20 @@ Format:
|
|
2140
2161
|
~ name (const-pattern.const)
|
2141
2162
|
~ expression (const-pattern.const)
|
2142
2163
|
~~~
|
2164
|
+
|
2165
|
+
#### With array pattern without elements
|
2166
|
+
|
2167
|
+
Format:
|
2168
|
+
|
2169
|
+
~~~
|
2170
|
+
(const-pattern
|
2171
|
+
(const nil :X)
|
2172
|
+
(array-pattern))
|
2173
|
+
"in X[]"
|
2174
|
+
~ begin (const-pattern)
|
2175
|
+
~ end (const-pattern)
|
2176
|
+
~~ expression (const-pattern)
|
2177
|
+
~ name (const-pattern.const)
|
2178
|
+
~ expression (const-pattern.const)
|
2179
|
+
~~ expression (const-pattern.array_pattern)
|
2180
|
+
~~~
|
data/lib/parser/ast/processor.rb
CHANGED
@@ -1213,6 +1213,7 @@ module Parser
|
|
1213
1213
|
#
|
1214
1214
|
|
1215
1215
|
def case_match(case_t, expr, in_bodies, else_t, else_body, end_t)
|
1216
|
+
else_body = n(:empty_else, nil, token_map(else_t)) if else_t && !else_body
|
1216
1217
|
n(:case_match, [ expr, *(in_bodies << else_body)],
|
1217
1218
|
condition_map(case_t, expr, nil, nil, else_t, else_body, end_t))
|
1218
1219
|
end
|
@@ -1313,6 +1314,8 @@ module Parser
|
|
1313
1314
|
end
|
1314
1315
|
|
1315
1316
|
def array_pattern(lbrack_t, elements, rbrack_t)
|
1317
|
+
return n(:array_pattern, nil, collection_map(lbrack_t, [], rbrack_t)) if elements.nil?
|
1318
|
+
|
1316
1319
|
trailing_comma = false
|
1317
1320
|
|
1318
1321
|
elements = elements.map do |element|
|
@@ -1369,11 +1372,13 @@ module Parser
|
|
1369
1372
|
pair_keyword(label, value)
|
1370
1373
|
else
|
1371
1374
|
begin_t, parts, end_t = label
|
1375
|
+
label_loc = loc(begin_t).join(loc(end_t))
|
1372
1376
|
|
1373
1377
|
# quoted label like "label": value
|
1374
1378
|
if (var_name = static_string(parts))
|
1375
|
-
|
1376
|
-
|
1379
|
+
check_duplicate_pattern_key(var_name, label_loc)
|
1380
|
+
else
|
1381
|
+
diagnostic :error, :pm_interp_in_var_name, nil, label_loc
|
1377
1382
|
end
|
1378
1383
|
|
1379
1384
|
pair_quoted(begin_t, parts, end_t, value)
|
data/lib/parser/messages.rb
CHANGED
@@ -70,6 +70,7 @@ module Parser
|
|
70
70
|
:circular_argument_reference => 'circular argument reference %{var_name}',
|
71
71
|
:pm_interp_in_var_name => 'symbol literal with interpolation is not allowed',
|
72
72
|
:lvar_name => "`%{name}' is not allowed as a local variable name",
|
73
|
+
:undefined_lvar => "no such local variable: `%{name}'",
|
73
74
|
:duplicate_variable_name => 'duplicate variable name %{name}',
|
74
75
|
:duplicate_pattern_key => 'duplicate hash pattern key %{name}',
|
75
76
|
|
data/lib/parser/meta.rb
CHANGED
data/lib/parser/ruby27.y
CHANGED
@@ -1841,7 +1841,8 @@ opt_block_args_tail:
|
|
1841
1841
|
}
|
1842
1842
|
| p_const tLPAREN2 rparen
|
1843
1843
|
{
|
1844
|
-
|
1844
|
+
pattern = @builder.array_pattern(val[1], nil, val[2])
|
1845
|
+
result = @builder.const_pattern(val[0], val[1], pattern, val[2])
|
1845
1846
|
}
|
1846
1847
|
| p_const p_lbracket p_args rbracket
|
1847
1848
|
{
|
@@ -1857,7 +1858,8 @@ opt_block_args_tail:
|
|
1857
1858
|
}
|
1858
1859
|
| p_const tLBRACK2 rbracket
|
1859
1860
|
{
|
1860
|
-
|
1861
|
+
pattern = @builder.array_pattern(val[1], nil, val[2])
|
1862
|
+
result = @builder.const_pattern(val[0], val[1], pattern, val[2])
|
1861
1863
|
}
|
1862
1864
|
| tLBRACK
|
1863
1865
|
{
|
@@ -2096,6 +2098,11 @@ opt_block_args_tail:
|
|
2096
2098
|
|
2097
2099
|
p_var_ref: tCARET tIDENTIFIER
|
2098
2100
|
{
|
2101
|
+
name = val[1][0]
|
2102
|
+
unless static_env.declared?(name)
|
2103
|
+
diagnostic :error, :undefined_lvar, { :name => name }, val[1]
|
2104
|
+
end
|
2105
|
+
|
2099
2106
|
lvar = @builder.accessible(@builder.ident(val[1]))
|
2100
2107
|
result = @builder.pin(val[0], lvar)
|
2101
2108
|
}
|
@@ -56,11 +56,11 @@ module Parser
|
|
56
56
|
if action.range == @range
|
57
57
|
merge(action)
|
58
58
|
else
|
59
|
-
|
59
|
+
place_in_hierarchy(action)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
63
|
+
def place_in_hierarchy(action)
|
64
64
|
family = @children.group_by { |child| child.relationship_with(action) }
|
65
65
|
|
66
66
|
if family[:fusible]
|
data/lib/parser/version.rb
CHANGED
data/parser.gemspec
CHANGED
@@ -13,6 +13,13 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = 'https://github.com/whitequark/parser'
|
14
14
|
spec.license = 'MIT'
|
15
15
|
|
16
|
+
spec.metadata = {
|
17
|
+
'bug_tracker_uri' => 'https://github.com/whitequark/parser/issues',
|
18
|
+
'changelog_uri' => "https://github.com/whitequark/parser/blob/v#{spec.version}/CHANGELOG.md",
|
19
|
+
'documentation_uri' => "https://www.rubydoc.info/gems/parser/#{spec.version}",
|
20
|
+
'source_code_uri' => "https://github.com/whitequark/parser/tree/v#{spec.version}"
|
21
|
+
}
|
22
|
+
|
16
23
|
spec.files = `git ls-files`.split + %w(
|
17
24
|
lib/parser/lexer.rb
|
18
25
|
lib/parser/ruby18.rb
|
data/test/test_parser.rb
CHANGED
@@ -8839,6 +8839,15 @@ class TestParser < Minitest::Test
|
|
8839
8839
|
)
|
8840
8840
|
end
|
8841
8841
|
|
8842
|
+
def test_pattern_matching_hash_with_string_interpolation_keys
|
8843
|
+
assert_diagnoses(
|
8844
|
+
[:error, :pm_interp_in_var_name],
|
8845
|
+
%q{case a; in "#{a}": 1; end},
|
8846
|
+
%q{ ~~~~~~~ location},
|
8847
|
+
SINCE_2_7
|
8848
|
+
)
|
8849
|
+
end
|
8850
|
+
|
8842
8851
|
def test_pattern_matching_keyword_variable
|
8843
8852
|
assert_parses_pattern_match(
|
8844
8853
|
s(:in_pattern,
|
@@ -8997,13 +9006,15 @@ class TestParser < Minitest::Test
|
|
8997
9006
|
s(:in_pattern,
|
8998
9007
|
s(:const_pattern,
|
8999
9008
|
s(:const, nil, :A),
|
9000
|
-
|
9009
|
+
s(:array_pattern)),
|
9001
9010
|
nil,
|
9002
9011
|
s(:true)),
|
9003
9012
|
%q{in A() then true},
|
9004
9013
|
%q{ ~~ expression (in_pattern.const_pattern)
|
9005
9014
|
| ~ begin (in_pattern.const_pattern)
|
9006
|
-
| ~ end (in_pattern.const_pattern)
|
9015
|
+
| ~ end (in_pattern.const_pattern)
|
9016
|
+
| ~ expression (in_pattern.const_pattern.const)
|
9017
|
+
| ~~ expression (in_pattern.const_pattern.array_pattern)}
|
9007
9018
|
)
|
9008
9019
|
|
9009
9020
|
assert_parses_pattern_match(
|
@@ -9043,13 +9054,14 @@ class TestParser < Minitest::Test
|
|
9043
9054
|
s(:in_pattern,
|
9044
9055
|
s(:const_pattern,
|
9045
9056
|
s(:const, nil, :A),
|
9046
|
-
|
9057
|
+
s(:array_pattern)),
|
9047
9058
|
nil,
|
9048
9059
|
s(:true)),
|
9049
9060
|
%q{in A[] then true},
|
9050
9061
|
%q{ ~~ expression (in_pattern.const_pattern)
|
9051
9062
|
| ~ begin (in_pattern.const_pattern)
|
9052
|
-
| ~ end (in_pattern.const_pattern)
|
9063
|
+
| ~ end (in_pattern.const_pattern)
|
9064
|
+
| ~~ expression (in_pattern.const_pattern.array_pattern)}
|
9053
9065
|
)
|
9054
9066
|
end
|
9055
9067
|
|
@@ -9093,6 +9105,20 @@ class TestParser < Minitest::Test
|
|
9093
9105
|
)
|
9094
9106
|
end
|
9095
9107
|
|
9108
|
+
def test_pattern_matching_blank_else
|
9109
|
+
assert_parses(
|
9110
|
+
s(:case_match,
|
9111
|
+
s(:int, 1),
|
9112
|
+
s(:in_pattern,
|
9113
|
+
s(:int, 2), nil,
|
9114
|
+
s(:int, 3)),
|
9115
|
+
s(:empty_else)),
|
9116
|
+
%q{case 1; in 2; 3; else; end},
|
9117
|
+
%q{ ~~~~ else},
|
9118
|
+
SINCE_2_7
|
9119
|
+
)
|
9120
|
+
end
|
9121
|
+
|
9096
9122
|
def assert_pattern_matching_defines_local_variables(match_code, lvar_names, versions = SINCE_2_7)
|
9097
9123
|
code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
|
9098
9124
|
|
@@ -9295,6 +9321,14 @@ class TestParser < Minitest::Test
|
|
9295
9321
|
SINCE_2_7)
|
9296
9322
|
end
|
9297
9323
|
|
9324
|
+
def test_pattern_matching_required_bound_variable_before_pin
|
9325
|
+
assert_diagnoses(
|
9326
|
+
[:error, :undefined_lvar, { :name => 'a' }],
|
9327
|
+
%{case 0; in ^a; true; end},
|
9328
|
+
%{ ^ location},
|
9329
|
+
SINCE_2_7)
|
9330
|
+
end
|
9331
|
+
|
9298
9332
|
def test_parser_bug_645
|
9299
9333
|
assert_parses(
|
9300
9334
|
s(:block,
|
@@ -31,16 +31,16 @@ class TestSourceCommentAssociator < Minitest::Test
|
|
31
31
|
ast, associations = associate(<<-END)
|
32
32
|
#!/usr/bin/env ruby
|
33
33
|
# coding: utf-8
|
34
|
-
# class
|
35
|
-
# another class
|
34
|
+
# class preceding
|
35
|
+
# another class preceding
|
36
36
|
class Foo # class keyword line
|
37
|
-
# method foo
|
37
|
+
# method foo preceding
|
38
38
|
def foo
|
39
39
|
puts 'foo'
|
40
40
|
end # method foo decorating
|
41
|
-
# method bar
|
41
|
+
# method bar preceding
|
42
42
|
def bar
|
43
|
-
# expression
|
43
|
+
# expression preceding
|
44
44
|
1 + # 1 decorating
|
45
45
|
2
|
46
46
|
# method bar sparse
|
@@ -58,8 +58,8 @@ end # class decorating
|
|
58
58
|
|
59
59
|
assert_equal 6, associations.size
|
60
60
|
assert_equal [
|
61
|
-
'# class
|
62
|
-
'# another class
|
61
|
+
'# class preceding',
|
62
|
+
'# another class preceding',
|
63
63
|
'# class sparse',
|
64
64
|
'# class decorating'
|
65
65
|
], associations[klass_node].map(&:text)
|
@@ -67,16 +67,16 @@ end # class decorating
|
|
67
67
|
'# class keyword line'
|
68
68
|
], associations[klass_name_node].map(&:text)
|
69
69
|
assert_equal [
|
70
|
-
'# method foo
|
70
|
+
'# method foo preceding',
|
71
71
|
'# method foo decorating'
|
72
72
|
], associations[foo_node].map(&:text)
|
73
73
|
assert_equal [
|
74
|
-
'# method bar
|
74
|
+
'# method bar preceding',
|
75
75
|
'# method bar sparse',
|
76
76
|
'# method bar decorating'
|
77
77
|
], associations[bar_node].map(&:text)
|
78
78
|
assert_equal [
|
79
|
-
'# expression
|
79
|
+
'# expression preceding'
|
80
80
|
], associations[expr_node].map(&:text)
|
81
81
|
assert_equal [
|
82
82
|
'# 1 decorating'
|
@@ -112,16 +112,16 @@ end
|
|
112
112
|
ast, associations = associate_locations(<<-END)
|
113
113
|
#!/usr/bin/env ruby
|
114
114
|
# coding: utf-8
|
115
|
-
# class
|
116
|
-
# another class
|
115
|
+
# class preceding
|
116
|
+
# another class preceding
|
117
117
|
class Foo # class keyword line
|
118
|
-
# method foo
|
118
|
+
# method foo preceding
|
119
119
|
def foo
|
120
120
|
puts 'foo'
|
121
121
|
end # method foo decorating
|
122
|
-
# method bar
|
122
|
+
# method bar preceding
|
123
123
|
def bar
|
124
|
-
# expression
|
124
|
+
# expression preceding
|
125
125
|
1 + # 1 decorating
|
126
126
|
2
|
127
127
|
# method bar sparse
|
@@ -139,8 +139,8 @@ end # class decorating
|
|
139
139
|
|
140
140
|
assert_equal 6, associations.size
|
141
141
|
assert_equal [
|
142
|
-
'# class
|
143
|
-
'# another class
|
142
|
+
'# class preceding',
|
143
|
+
'# another class preceding',
|
144
144
|
'# class sparse',
|
145
145
|
'# class decorating'
|
146
146
|
], associations[klass_node.loc].map(&:text)
|
@@ -148,16 +148,16 @@ end # class decorating
|
|
148
148
|
'# class keyword line'
|
149
149
|
], associations[klass_name_node.loc].map(&:text)
|
150
150
|
assert_equal [
|
151
|
-
'# method foo
|
151
|
+
'# method foo preceding',
|
152
152
|
'# method foo decorating'
|
153
153
|
], associations[foo_node.loc].map(&:text)
|
154
154
|
assert_equal [
|
155
|
-
'# method bar
|
155
|
+
'# method bar preceding',
|
156
156
|
'# method bar sparse',
|
157
157
|
'# method bar decorating'
|
158
158
|
], associations[bar_node.loc].map(&:text)
|
159
159
|
assert_equal [
|
160
|
-
'# expression
|
160
|
+
'# expression preceding'
|
161
161
|
], associations[expr_node.loc].map(&:text)
|
162
162
|
assert_equal [
|
163
163
|
'# 1 decorating'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.7.0.
|
4
|
+
version: 2.7.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- whitequark
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ast
|
@@ -295,7 +295,11 @@ files:
|
|
295
295
|
homepage: https://github.com/whitequark/parser
|
296
296
|
licenses:
|
297
297
|
- MIT
|
298
|
-
metadata:
|
298
|
+
metadata:
|
299
|
+
bug_tracker_uri: https://github.com/whitequark/parser/issues
|
300
|
+
changelog_uri: https://github.com/whitequark/parser/blob/v2.7.0.3/CHANGELOG.md
|
301
|
+
documentation_uri: https://www.rubydoc.info/gems/parser/2.7.0.3
|
302
|
+
source_code_uri: https://github.com/whitequark/parser/tree/v2.7.0.3
|
299
303
|
post_install_message:
|
300
304
|
rdoc_options: []
|
301
305
|
require_paths:
|