parser 2.7.0.2 → 2.7.0.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/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:
|