parser 2.7.0.0 → 2.7.0.5
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/.travis.yml +6 -0
- data/CHANGELOG.md +28 -1
- data/README.md +6 -5
- data/doc/AST_FORMAT.md +41 -3
- data/lib/parser/ast/processor.rb +4 -0
- data/lib/parser/builders/default.rb +17 -7
- data/lib/parser/lexer.rl +6 -2
- data/lib/parser/lexer/dedenter.rb +5 -1
- data/lib/parser/messages.rb +1 -0
- data/lib/parser/meta.rb +1 -0
- data/lib/parser/ruby27.y +12 -5
- data/lib/parser/source/tree_rewriter/action.rb +2 -2
- data/lib/parser/version.rb +1 -1
- data/parser.gemspec +7 -0
- data/test/parse_helper.rb +3 -0
- data/test/test_parser.rb +72 -12
- data/test/test_source_comment_associator.rb +20 -20
- metadata +8 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 00a9bc5b2d70892e4743417168e53dc469c80328c3983e71b41f312becd116b0
|
|
4
|
+
data.tar.gz: 1abbc88751dc8d3b7c28d2df69b71a773533ed2d3726de50df8cfaaa79887aaa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 32455424b4003ba1510d53b162aa8691bdaea5708b4d88d392d6c89cfa3b6479f1d47c9f42fedd40e663366192434aaf851dbe65cbd1a629c54b7681cfb37879
|
|
7
|
+
data.tar.gz: 0c464e9acd5cf95161e18552e4680230417a05e7ad14e805b8661e4bb2ee7a99f4ad2f4e0212c48b35bc9f3ed8549b6723925f0b194e0a57873a2eb472450dbb
|
data/.travis.yml
CHANGED
|
@@ -20,6 +20,9 @@ matrix:
|
|
|
20
20
|
- name: 2.6.5 / Parser tests
|
|
21
21
|
rvm: 2.6.5
|
|
22
22
|
script: bundle exec rake test_cov
|
|
23
|
+
- name: 2.7.0 / Parser tests
|
|
24
|
+
rvm: 2.7.0
|
|
25
|
+
script: bundle exec rake test_cov
|
|
23
26
|
- name: ruby-head / Parser tests
|
|
24
27
|
rvm: ruby-head
|
|
25
28
|
script: bundle exec rake test_cov
|
|
@@ -35,6 +38,9 @@ matrix:
|
|
|
35
38
|
- name: 2.6.5 / Rubocop tests
|
|
36
39
|
rvm: 2.6.5
|
|
37
40
|
script: ./ci/run_rubocop_specs
|
|
41
|
+
- name: 2.7.0 / Rubocop tests
|
|
42
|
+
rvm: 2.7.0
|
|
43
|
+
script: ./ci/run_rubocop_specs
|
|
38
44
|
allow_failures:
|
|
39
45
|
- rvm: ruby-head
|
|
40
46
|
- rvm: rbx-2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,36 @@
|
|
|
1
1
|
Changelog
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
-
Not released (
|
|
4
|
+
Not released (2020-03-20)
|
|
5
5
|
-------------------------
|
|
6
6
|
|
|
7
|
+
Features implemented:
|
|
8
|
+
* ruby27.y: fix array pattern with tail source map (#659) (Vladimir Dementyev)
|
|
9
|
+
|
|
10
|
+
Bugs fixed:
|
|
11
|
+
* builder.rb: fix constant_pattern source map (#660) (Vladimir Dementyev)
|
|
12
|
+
|
|
13
|
+
v2.7.0.4 (2020-03-02)
|
|
14
|
+
---------------------
|
|
15
|
+
|
|
16
|
+
Bugs fixed:
|
|
17
|
+
* lexer.rl: allow spaces before comments-before-leading-dot. (#654) (Ilya Bylich)
|
|
18
|
+
|
|
19
|
+
v2.7.0.2 (2020-01-08)
|
|
20
|
+
---------------------
|
|
21
|
+
|
|
22
|
+
Bugs fixed:
|
|
23
|
+
* lexer.rl: fix paren_nest for curly braces (#646) (Ilya Bylich)
|
|
24
|
+
|
|
25
|
+
v2.7.0.1 (2019-12-30)
|
|
26
|
+
---------------------
|
|
27
|
+
|
|
28
|
+
Bugs fixed:
|
|
29
|
+
* dedenter.rb: prevent `ArgumentError` when processing binary en… (#642) (Koichi ITO)
|
|
30
|
+
|
|
31
|
+
v2.7.0.0 (2019-12-26)
|
|
32
|
+
---------------------
|
|
33
|
+
|
|
7
34
|
API modifications:
|
|
8
35
|
* README.md: documented compatibility issue with EOF chars after… (#637) (Ilya Bylich)
|
|
9
36
|
* ruby27.y: refactor logic around 'circular argument reference'(#628) (Ilya Bylich)
|
data/README.md
CHANGED
|
@@ -24,10 +24,11 @@ below for explanation of `emit_*` calls):
|
|
|
24
24
|
|
|
25
25
|
require 'parser/current'
|
|
26
26
|
# opt-in to most recent AST format:
|
|
27
|
-
Parser::Builders::Default.emit_lambda
|
|
28
|
-
Parser::Builders::Default.emit_procarg0
|
|
29
|
-
Parser::Builders::Default.emit_encoding
|
|
30
|
-
Parser::Builders::Default.emit_index
|
|
27
|
+
Parser::Builders::Default.emit_lambda = true
|
|
28
|
+
Parser::Builders::Default.emit_procarg0 = true
|
|
29
|
+
Parser::Builders::Default.emit_encoding = true
|
|
30
|
+
Parser::Builders::Default.emit_index = true
|
|
31
|
+
Parser::Builders::Default.emit_arg_inside_procarg0 = true
|
|
31
32
|
|
|
32
33
|
Parse a chunk of code:
|
|
33
34
|
|
|
@@ -234,7 +235,7 @@ Parser implements the MacRuby 0.12 and RubyMotion mid-2015 parsers precisely. Ho
|
|
|
234
235
|
|
|
235
236
|
## Known issues
|
|
236
237
|
|
|
237
|
-
Adding support for the following Ruby MRI features in Parser would needlessly complicate it, and as they all are very specific and rarely
|
|
238
|
+
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
239
|
|
|
239
240
|
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
241
|
|
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:
|
|
@@ -2047,7 +2068,7 @@ so a single item match with comma gets interpreted as an array.
|
|
|
2047
2068
|
(array-pattern-with-tail
|
|
2048
2069
|
(match-var :foo))
|
|
2049
2070
|
"in foo,"
|
|
2050
|
-
|
|
2071
|
+
~~~~ expression
|
|
2051
2072
|
~~~
|
|
2052
2073
|
|
|
2053
2074
|
### Matching using hash pattern
|
|
@@ -2118,7 +2139,7 @@ Format:
|
|
|
2118
2139
|
"in X[^foo bar]"
|
|
2119
2140
|
~ begin (const-pattern)
|
|
2120
2141
|
~ end (const-pattern)
|
|
2121
|
-
|
|
2142
|
+
~~~~~~~~~~~~ expression (const-pattern)
|
|
2122
2143
|
~ name (const-pattern.const)
|
|
2123
2144
|
~ expression (const-pattern.const)
|
|
2124
2145
|
~~~
|
|
@@ -2136,7 +2157,24 @@ Format:
|
|
|
2136
2157
|
"in X[foo:, bar:]"
|
|
2137
2158
|
~ begin (const-pattern)
|
|
2138
2159
|
~ end (const-pattern)
|
|
2139
|
-
|
|
2160
|
+
~~~~~~~~~~~~~ expression (const-pattern)
|
|
2161
|
+
~ name (const-pattern.const)
|
|
2162
|
+
~ expression (const-pattern.const)
|
|
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)
|
|
2140
2177
|
~ name (const-pattern.const)
|
|
2141
2178
|
~ expression (const-pattern.const)
|
|
2179
|
+
~~ expression (const-pattern.array_pattern)
|
|
2142
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,9 +1314,11 @@ 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
|
+
node_elements = elements.map do |element|
|
|
1319
1322
|
if element.type == :match_with_trailing_comma
|
|
1320
1323
|
trailing_comma = true
|
|
1321
1324
|
element.children.first
|
|
@@ -1326,17 +1329,22 @@ module Parser
|
|
|
1326
1329
|
end
|
|
1327
1330
|
|
|
1328
1331
|
node_type = trailing_comma ? :array_pattern_with_tail : :array_pattern
|
|
1329
|
-
|
|
1332
|
+
|
|
1333
|
+
n(node_type, node_elements,
|
|
1330
1334
|
collection_map(lbrack_t, elements, rbrack_t))
|
|
1331
1335
|
end
|
|
1332
1336
|
|
|
1333
|
-
def match_with_trailing_comma(match)
|
|
1334
|
-
n(:match_with_trailing_comma, [ match ],
|
|
1337
|
+
def match_with_trailing_comma(match, comma_t)
|
|
1338
|
+
n(:match_with_trailing_comma, [ match ], expr_map(match.loc.expression.join(loc(comma_t))))
|
|
1335
1339
|
end
|
|
1336
1340
|
|
|
1337
1341
|
def const_pattern(const, ldelim_t, pattern, rdelim_t)
|
|
1338
1342
|
n(:const_pattern, [const, pattern],
|
|
1339
|
-
|
|
1343
|
+
Source::Map::Collection.new(
|
|
1344
|
+
loc(ldelim_t), loc(rdelim_t),
|
|
1345
|
+
const.loc.expression.join(loc(rdelim_t))
|
|
1346
|
+
)
|
|
1347
|
+
)
|
|
1340
1348
|
end
|
|
1341
1349
|
|
|
1342
1350
|
def pin(pin_t, var)
|
|
@@ -1369,11 +1377,13 @@ module Parser
|
|
|
1369
1377
|
pair_keyword(label, value)
|
|
1370
1378
|
else
|
|
1371
1379
|
begin_t, parts, end_t = label
|
|
1380
|
+
label_loc = loc(begin_t).join(loc(end_t))
|
|
1372
1381
|
|
|
1373
1382
|
# quoted label like "label": value
|
|
1374
1383
|
if (var_name = static_string(parts))
|
|
1375
|
-
|
|
1376
|
-
|
|
1384
|
+
check_duplicate_pattern_key(var_name, label_loc)
|
|
1385
|
+
else
|
|
1386
|
+
diagnostic :error, :pm_interp_in_var_name, nil, label_loc
|
|
1377
1387
|
end
|
|
1378
1388
|
|
|
1379
1389
|
pair_quoted(begin_t, parts, end_t, value)
|
data/lib/parser/lexer.rl
CHANGED
|
@@ -1064,7 +1064,6 @@ class Parser::Lexer
|
|
|
1064
1064
|
emit(:tRCURLY, '}'.freeze, p - 1, p)
|
|
1065
1065
|
@cond.lexpop
|
|
1066
1066
|
@cmdarg.lexpop
|
|
1067
|
-
@paren_nest -= 1
|
|
1068
1067
|
else
|
|
1069
1068
|
emit(:tSTRING_DEND, '}'.freeze, p - 1, p)
|
|
1070
1069
|
end
|
|
@@ -1079,6 +1078,8 @@ class Parser::Lexer
|
|
|
1079
1078
|
fbreak;
|
|
1080
1079
|
end
|
|
1081
1080
|
end
|
|
1081
|
+
|
|
1082
|
+
@paren_nest -= 1
|
|
1082
1083
|
};
|
|
1083
1084
|
|
|
1084
1085
|
action extend_interp_code {
|
|
@@ -2165,6 +2166,9 @@ class Parser::Lexer
|
|
|
2165
2166
|
emit_do
|
|
2166
2167
|
end
|
|
2167
2168
|
end
|
|
2169
|
+
if tok == '{'.freeze
|
|
2170
|
+
@paren_nest += 1
|
|
2171
|
+
end
|
|
2168
2172
|
@command_start = true
|
|
2169
2173
|
|
|
2170
2174
|
fnext expr_value; fbreak;
|
|
@@ -2469,7 +2473,7 @@ class Parser::Lexer
|
|
|
2469
2473
|
|
|
2470
2474
|
# Here we use '\n' instead of w_newline to not modify @newline_s
|
|
2471
2475
|
# and eventually properly emit tNL
|
|
2472
|
-
(w_space_comment '\n')+
|
|
2476
|
+
(c_space* w_space_comment '\n')+
|
|
2473
2477
|
=> {
|
|
2474
2478
|
if @version < 27
|
|
2475
2479
|
# Ruby before 2.7 doesn't support comments before leading dot.
|
|
@@ -34,7 +34,11 @@ module Parser
|
|
|
34
34
|
# Of course, lexer could do it but once again: it's all because of dedenting.
|
|
35
35
|
#
|
|
36
36
|
def dedent(string)
|
|
37
|
-
|
|
37
|
+
original_encoding = string.encoding
|
|
38
|
+
# Prevent the following error when processing binary encoded source.
|
|
39
|
+
# "\xC0".split # => ArgumentError (invalid byte sequence in UTF-8)
|
|
40
|
+
lines = string.force_encoding(Encoding::BINARY).split("\\\n")
|
|
41
|
+
lines.map! {|s| s.force_encoding(original_encoding) }
|
|
38
42
|
|
|
39
43
|
if @at_line_begin
|
|
40
44
|
lines_to_dedent = lines
|
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
|
@@ -1784,7 +1784,7 @@ opt_block_args_tail:
|
|
|
1784
1784
|
# array patterns that end with comma
|
|
1785
1785
|
# like 1, 2,
|
|
1786
1786
|
# must be emitted as `array_pattern_with_tail`
|
|
1787
|
-
item = @builder.match_with_trailing_comma(val[0])
|
|
1787
|
+
item = @builder.match_with_trailing_comma(val[0], val[1])
|
|
1788
1788
|
result = @builder.array_pattern(nil, [ item ], nil)
|
|
1789
1789
|
}
|
|
1790
1790
|
| p_expr tCOMMA p_args
|
|
@@ -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
|
{
|
|
@@ -1932,7 +1934,7 @@ opt_block_args_tail:
|
|
|
1932
1934
|
# array patterns that end with comma
|
|
1933
1935
|
# like [1, 2,]
|
|
1934
1936
|
# must be emitted as `array_pattern_with_tail`
|
|
1935
|
-
item = @builder.match_with_trailing_comma(val[0])
|
|
1937
|
+
item = @builder.match_with_trailing_comma(val[0], val[1])
|
|
1936
1938
|
result = [ item ]
|
|
1937
1939
|
}
|
|
1938
1940
|
| p_args_head p_arg tCOMMA
|
|
@@ -1940,7 +1942,7 @@ opt_block_args_tail:
|
|
|
1940
1942
|
# array patterns that end with comma
|
|
1941
1943
|
# like [1, 2,]
|
|
1942
1944
|
# must be emitted as `array_pattern_with_tail`
|
|
1943
|
-
last_item = @builder.match_with_trailing_comma(val[1])
|
|
1945
|
+
last_item = @builder.match_with_trailing_comma(val[1], val[2])
|
|
1944
1946
|
result = [ *val[0], last_item ]
|
|
1945
1947
|
}
|
|
1946
1948
|
|
|
@@ -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/parse_helper.rb
CHANGED
|
@@ -127,6 +127,9 @@ module ParseHelper
|
|
|
127
127
|
|
|
128
128
|
assert parser.instance_eval { @lexer }.cmdarg.empty?,
|
|
129
129
|
"(#{version}) expected cmdarg to be empty after parsing"
|
|
130
|
+
|
|
131
|
+
assert_equal 0, parser.instance_eval { @lexer.instance_eval { @paren_nest } },
|
|
132
|
+
"(#{version}) expected paren_nest to be 0 after parsing"
|
|
130
133
|
end
|
|
131
134
|
|
|
132
135
|
# Use like this:
|
data/test/test_parser.rb
CHANGED
|
@@ -7644,12 +7644,26 @@ class TestParser < Minitest::Test
|
|
|
7644
7644
|
%q{},
|
|
7645
7645
|
SINCE_2_7)
|
|
7646
7646
|
|
|
7647
|
+
assert_parses(
|
|
7648
|
+
s(:send,
|
|
7649
|
+
s(:send, nil, :a), :foo),
|
|
7650
|
+
%Q{a #\n #\n.foo\n},
|
|
7651
|
+
%q{},
|
|
7652
|
+
SINCE_2_7)
|
|
7653
|
+
|
|
7647
7654
|
assert_parses(
|
|
7648
7655
|
s(:csend,
|
|
7649
7656
|
s(:send, nil, :a), :foo),
|
|
7650
7657
|
%Q{a #\n#\n&.foo\n},
|
|
7651
7658
|
%q{},
|
|
7652
7659
|
SINCE_2_7)
|
|
7660
|
+
|
|
7661
|
+
assert_parses(
|
|
7662
|
+
s(:csend,
|
|
7663
|
+
s(:send, nil, :a), :foo),
|
|
7664
|
+
%Q{a #\n #\n&.foo\n},
|
|
7665
|
+
%q{},
|
|
7666
|
+
SINCE_2_7)
|
|
7653
7667
|
end
|
|
7654
7668
|
|
|
7655
7669
|
def test_comments_before_leading_dot__before_27
|
|
@@ -8408,7 +8422,7 @@ class TestParser < Minitest::Test
|
|
|
8408
8422
|
nil,
|
|
8409
8423
|
s(:nil)),
|
|
8410
8424
|
%q{in x, then nil},
|
|
8411
|
-
%q{
|
|
8425
|
+
%q{ ~~ expression (in_pattern.array_pattern_with_tail)}
|
|
8412
8426
|
)
|
|
8413
8427
|
|
|
8414
8428
|
assert_parses_pattern_match(
|
|
@@ -8454,7 +8468,7 @@ class TestParser < Minitest::Test
|
|
|
8454
8468
|
nil,
|
|
8455
8469
|
s(:nil)),
|
|
8456
8470
|
%q{in x, y, then nil},
|
|
8457
|
-
%q{
|
|
8471
|
+
%q{ ~~~~~ expression (in_pattern.array_pattern_with_tail)}
|
|
8458
8472
|
)
|
|
8459
8473
|
|
|
8460
8474
|
assert_parses_pattern_match(
|
|
@@ -8839,6 +8853,15 @@ class TestParser < Minitest::Test
|
|
|
8839
8853
|
)
|
|
8840
8854
|
end
|
|
8841
8855
|
|
|
8856
|
+
def test_pattern_matching_hash_with_string_interpolation_keys
|
|
8857
|
+
assert_diagnoses(
|
|
8858
|
+
[:error, :pm_interp_in_var_name],
|
|
8859
|
+
%q{case a; in "#{a}": 1; end},
|
|
8860
|
+
%q{ ~~~~~~~ location},
|
|
8861
|
+
SINCE_2_7
|
|
8862
|
+
)
|
|
8863
|
+
end
|
|
8864
|
+
|
|
8842
8865
|
def test_pattern_matching_keyword_variable
|
|
8843
8866
|
assert_parses_pattern_match(
|
|
8844
8867
|
s(:in_pattern,
|
|
@@ -8970,7 +8993,7 @@ class TestParser < Minitest::Test
|
|
|
8970
8993
|
nil,
|
|
8971
8994
|
s(:true)),
|
|
8972
8995
|
%q{in A(1, 2) then true},
|
|
8973
|
-
%q{
|
|
8996
|
+
%q{ ~~~~~~~ expression (in_pattern.const_pattern)
|
|
8974
8997
|
| ~ begin (in_pattern.const_pattern)
|
|
8975
8998
|
| ~ end (in_pattern.const_pattern)
|
|
8976
8999
|
| ~ expression (in_pattern.const_pattern.const)
|
|
@@ -8986,7 +9009,7 @@ class TestParser < Minitest::Test
|
|
|
8986
9009
|
nil,
|
|
8987
9010
|
s(:true)),
|
|
8988
9011
|
%q{in A(x:) then true},
|
|
8989
|
-
%q{
|
|
9012
|
+
%q{ ~~~~~ expression (in_pattern.const_pattern)
|
|
8990
9013
|
| ~ begin (in_pattern.const_pattern)
|
|
8991
9014
|
| ~ end (in_pattern.const_pattern)
|
|
8992
9015
|
| ~ expression (in_pattern.const_pattern.const)
|
|
@@ -8997,13 +9020,15 @@ class TestParser < Minitest::Test
|
|
|
8997
9020
|
s(:in_pattern,
|
|
8998
9021
|
s(:const_pattern,
|
|
8999
9022
|
s(:const, nil, :A),
|
|
9000
|
-
|
|
9023
|
+
s(:array_pattern)),
|
|
9001
9024
|
nil,
|
|
9002
9025
|
s(:true)),
|
|
9003
9026
|
%q{in A() then true},
|
|
9004
|
-
%q{
|
|
9027
|
+
%q{ ~~~ expression (in_pattern.const_pattern)
|
|
9005
9028
|
| ~ begin (in_pattern.const_pattern)
|
|
9006
|
-
| ~ end (in_pattern.const_pattern)
|
|
9029
|
+
| ~ end (in_pattern.const_pattern)
|
|
9030
|
+
| ~ expression (in_pattern.const_pattern.const)
|
|
9031
|
+
| ~~ expression (in_pattern.const_pattern.array_pattern)}
|
|
9007
9032
|
)
|
|
9008
9033
|
|
|
9009
9034
|
assert_parses_pattern_match(
|
|
@@ -9016,7 +9041,7 @@ class TestParser < Minitest::Test
|
|
|
9016
9041
|
nil,
|
|
9017
9042
|
s(:true)),
|
|
9018
9043
|
%q{in A[1, 2] then true},
|
|
9019
|
-
%q{
|
|
9044
|
+
%q{ ~~~~~~~ expression (in_pattern.const_pattern)
|
|
9020
9045
|
| ~ begin (in_pattern.const_pattern)
|
|
9021
9046
|
| ~ end (in_pattern.const_pattern)
|
|
9022
9047
|
| ~ expression (in_pattern.const_pattern.const)
|
|
@@ -9032,7 +9057,7 @@ class TestParser < Minitest::Test
|
|
|
9032
9057
|
nil,
|
|
9033
9058
|
s(:true)),
|
|
9034
9059
|
%q{in A[x:] then true},
|
|
9035
|
-
%q{
|
|
9060
|
+
%q{ ~~~~~ expression (in_pattern.const_pattern)
|
|
9036
9061
|
| ~ begin (in_pattern.const_pattern)
|
|
9037
9062
|
| ~ end (in_pattern.const_pattern)
|
|
9038
9063
|
| ~ expression (in_pattern.const_pattern.const)
|
|
@@ -9043,13 +9068,14 @@ class TestParser < Minitest::Test
|
|
|
9043
9068
|
s(:in_pattern,
|
|
9044
9069
|
s(:const_pattern,
|
|
9045
9070
|
s(:const, nil, :A),
|
|
9046
|
-
|
|
9071
|
+
s(:array_pattern)),
|
|
9047
9072
|
nil,
|
|
9048
9073
|
s(:true)),
|
|
9049
9074
|
%q{in A[] then true},
|
|
9050
|
-
%q{
|
|
9075
|
+
%q{ ~~~ expression (in_pattern.const_pattern)
|
|
9051
9076
|
| ~ begin (in_pattern.const_pattern)
|
|
9052
|
-
| ~ end (in_pattern.const_pattern)
|
|
9077
|
+
| ~ end (in_pattern.const_pattern)
|
|
9078
|
+
| ~~ expression (in_pattern.const_pattern.array_pattern)}
|
|
9053
9079
|
)
|
|
9054
9080
|
end
|
|
9055
9081
|
|
|
@@ -9093,6 +9119,20 @@ class TestParser < Minitest::Test
|
|
|
9093
9119
|
)
|
|
9094
9120
|
end
|
|
9095
9121
|
|
|
9122
|
+
def test_pattern_matching_blank_else
|
|
9123
|
+
assert_parses(
|
|
9124
|
+
s(:case_match,
|
|
9125
|
+
s(:int, 1),
|
|
9126
|
+
s(:in_pattern,
|
|
9127
|
+
s(:int, 2), nil,
|
|
9128
|
+
s(:int, 3)),
|
|
9129
|
+
s(:empty_else)),
|
|
9130
|
+
%q{case 1; in 2; 3; else; end},
|
|
9131
|
+
%q{ ~~~~ else},
|
|
9132
|
+
SINCE_2_7
|
|
9133
|
+
)
|
|
9134
|
+
end
|
|
9135
|
+
|
|
9096
9136
|
def assert_pattern_matching_defines_local_variables(match_code, lvar_names, versions = SINCE_2_7)
|
|
9097
9137
|
code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
|
|
9098
9138
|
|
|
@@ -9294,4 +9334,24 @@ class TestParser < Minitest::Test
|
|
|
9294
9334
|
%{ ^^ location},
|
|
9295
9335
|
SINCE_2_7)
|
|
9296
9336
|
end
|
|
9337
|
+
|
|
9338
|
+
def test_pattern_matching_required_bound_variable_before_pin
|
|
9339
|
+
assert_diagnoses(
|
|
9340
|
+
[:error, :undefined_lvar, { :name => 'a' }],
|
|
9341
|
+
%{case 0; in ^a; true; end},
|
|
9342
|
+
%{ ^ location},
|
|
9343
|
+
SINCE_2_7)
|
|
9344
|
+
end
|
|
9345
|
+
|
|
9346
|
+
def test_parser_bug_645
|
|
9347
|
+
assert_parses(
|
|
9348
|
+
s(:block,
|
|
9349
|
+
s(:lambda),
|
|
9350
|
+
s(:args,
|
|
9351
|
+
s(:optarg, :arg,
|
|
9352
|
+
s(:hash))), nil),
|
|
9353
|
+
'-> (arg={}) {}',
|
|
9354
|
+
%{},
|
|
9355
|
+
SINCE_1_9)
|
|
9356
|
+
end
|
|
9297
9357
|
end
|
|
@@ -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.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- whitequark
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2020-03-20 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.5/CHANGELOG.md
|
|
301
|
+
documentation_uri: https://www.rubydoc.info/gems/parser/2.7.0.5
|
|
302
|
+
source_code_uri: https://github.com/whitequark/parser/tree/v2.7.0.5
|
|
299
303
|
post_install_message:
|
|
300
304
|
rdoc_options: []
|
|
301
305
|
require_paths:
|
|
@@ -311,7 +315,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
311
315
|
- !ruby/object:Gem::Version
|
|
312
316
|
version: '0'
|
|
313
317
|
requirements: []
|
|
314
|
-
rubygems_version: 3.0.
|
|
318
|
+
rubygems_version: 3.0.6
|
|
315
319
|
signing_key:
|
|
316
320
|
specification_version: 4
|
|
317
321
|
summary: A Ruby parser written in pure Ruby.
|