parser 2.7.0.1 → 2.7.1.0
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 +14 -17
- data/CHANGELOG.md +32 -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/current.rb +4 -4
- data/lib/parser/lexer.rl +6 -2
- data/lib/parser/messages.rb +1 -0
- data/lib/parser/meta.rb +1 -0
- data/lib/parser/ruby27.y +25 -7
- 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 +145 -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: 46184af7a1e0d843e62e720cd7795bb196972603e588eed69f47791b3c799288
|
4
|
+
data.tar.gz: 1a9d809fc7443fb09deb3a36ea19ad418ff56119040b14a292c9ed8d112d1f29
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a91995ac131a4048976358a7bce1bd09b09893bb0b13fa39f2128c47fb0b1179f830a4adbb766df768bfbd2f89a1c5a5ee437dc1433ccaf5ad2307ff7c09d77
|
7
|
+
data.tar.gz: 4fe835bc9fe1ff030d57e9a4d9a4657a0d244db23bac3c117e8f78bfc51d9dc330f51257e04c8ba5ef737d3feab11152db2e1ecde1e8b136d4fcc4f253ed549d
|
data/.travis.yml
CHANGED
@@ -2,23 +2,17 @@ dist: trusty
|
|
2
2
|
language: ruby
|
3
3
|
matrix:
|
4
4
|
include:
|
5
|
-
- name: 2.0.0 / Parser tests
|
6
|
-
rvm: 2.0.0
|
7
|
-
script: bundle exec rake test_cov
|
8
|
-
- name: 2.2.10 / Parser tests
|
9
|
-
rvm: 2.2.10
|
10
|
-
script: bundle exec rake test_cov
|
11
|
-
- name: 2.3.8 / Parser tests
|
12
|
-
rvm: 2.3.8
|
13
|
-
script: bundle exec rake test_cov
|
14
5
|
- name: 2.4.9 / Parser tests
|
15
6
|
rvm: 2.4.9
|
16
7
|
script: bundle exec rake test_cov
|
17
|
-
- name: 2.5.
|
18
|
-
rvm: 2.5.
|
8
|
+
- name: 2.5.8 / Parser tests
|
9
|
+
rvm: 2.5.8
|
19
10
|
script: bundle exec rake test_cov
|
20
|
-
- name: 2.6.
|
21
|
-
rvm: 2.6.
|
11
|
+
- name: 2.6.6 / Parser tests
|
12
|
+
rvm: 2.6.6
|
13
|
+
script: bundle exec rake test_cov
|
14
|
+
- name: 2.7.1 / Parser tests
|
15
|
+
rvm: 2.7.1
|
22
16
|
script: bundle exec rake test_cov
|
23
17
|
- name: ruby-head / Parser tests
|
24
18
|
rvm: ruby-head
|
@@ -29,11 +23,14 @@ matrix:
|
|
29
23
|
- name: rbx-2 / Parser tests
|
30
24
|
rvm: rbx-2
|
31
25
|
script: bundle exec rake test_cov
|
32
|
-
- name: 2.5.
|
33
|
-
rvm: 2.5.
|
26
|
+
- name: 2.5.8 / Rubocop tests
|
27
|
+
rvm: 2.5.8
|
28
|
+
script: ./ci/run_rubocop_specs
|
29
|
+
- name: 2.6.6 / Rubocop tests
|
30
|
+
rvm: 2.6.6
|
34
31
|
script: ./ci/run_rubocop_specs
|
35
|
-
- name: 2.
|
36
|
-
rvm: 2.
|
32
|
+
- name: 2.7.1 / Rubocop tests
|
33
|
+
rvm: 2.7.1
|
37
34
|
script: ./ci/run_rubocop_specs
|
38
35
|
allow_failures:
|
39
36
|
- rvm: ruby-head
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,40 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
-
Not released (
|
4
|
+
Not released (2020-04-03)
|
5
5
|
-------------------------
|
6
6
|
|
7
|
+
API modifications:
|
8
|
+
* Bump ruby versions to 2.4.10, 2.5.8, 2.6.6, 2.7.1. (#665) (Ilya Bylich)
|
9
|
+
|
10
|
+
Features implemented:
|
11
|
+
* ruby27.y: allow newlines inside braced pattern. (#664) (Ilya Bylich)
|
12
|
+
* ruby27.y: Allow trailing comma in hash pattern (#661) (Koichi ITO)
|
13
|
+
|
14
|
+
v2.7.0.5 (2020-03-20)
|
15
|
+
---------------------
|
16
|
+
|
17
|
+
Features implemented:
|
18
|
+
* ruby27.y: fix array pattern with tail source map (#659) (Vladimir Dementyev)
|
19
|
+
|
20
|
+
Bugs fixed:
|
21
|
+
* builder.rb: fix constant_pattern source map (#660) (Vladimir Dementyev)
|
22
|
+
|
23
|
+
v2.7.0.4 (2020-03-02)
|
24
|
+
---------------------
|
25
|
+
|
26
|
+
Bugs fixed:
|
27
|
+
* lexer.rl: allow spaces before comments-before-leading-dot. (#654) (Ilya Bylich)
|
28
|
+
|
29
|
+
v2.7.0.2 (2020-01-08)
|
30
|
+
---------------------
|
31
|
+
|
32
|
+
Bugs fixed:
|
33
|
+
* lexer.rl: fix paren_nest for curly braces (#646) (Ilya Bylich)
|
34
|
+
|
35
|
+
v2.7.0.1 (2019-12-30)
|
36
|
+
---------------------
|
37
|
+
|
7
38
|
Bugs fixed:
|
8
39
|
* dedenter.rb: prevent `ArgumentError` when processing binary en… (#642) (Koichi ITO)
|
9
40
|
|
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/current.rb
CHANGED
@@ -48,7 +48,7 @@ module Parser
|
|
48
48
|
CurrentRuby = Ruby23
|
49
49
|
|
50
50
|
when /^2\.4\./
|
51
|
-
current_version = '2.4.
|
51
|
+
current_version = '2.4.10'
|
52
52
|
if RUBY_VERSION != current_version
|
53
53
|
warn_syntax_deviation 'parser/ruby24', current_version
|
54
54
|
end
|
@@ -57,7 +57,7 @@ module Parser
|
|
57
57
|
CurrentRuby = Ruby24
|
58
58
|
|
59
59
|
when /^2\.5\./
|
60
|
-
current_version = '2.5.
|
60
|
+
current_version = '2.5.8'
|
61
61
|
if RUBY_VERSION != current_version
|
62
62
|
warn_syntax_deviation 'parser/ruby25', current_version
|
63
63
|
end
|
@@ -66,7 +66,7 @@ module Parser
|
|
66
66
|
CurrentRuby = Ruby25
|
67
67
|
|
68
68
|
when /^2\.6\./
|
69
|
-
current_version = '2.6.
|
69
|
+
current_version = '2.6.6'
|
70
70
|
if RUBY_VERSION != current_version
|
71
71
|
warn_syntax_deviation 'parser/ruby26', current_version
|
72
72
|
end
|
@@ -75,7 +75,7 @@ module Parser
|
|
75
75
|
CurrentRuby = Ruby26
|
76
76
|
|
77
77
|
when /^2\.7\./
|
78
|
-
current_version = '2.7.
|
78
|
+
current_version = '2.7.1'
|
79
79
|
if RUBY_VERSION != current_version
|
80
80
|
warn_syntax_deviation 'parser/ruby27', current_version
|
81
81
|
end
|
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.
|
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
|
{
|
@@ -1875,13 +1877,16 @@ opt_block_args_tail:
|
|
1875
1877
|
| tLBRACE
|
1876
1878
|
{
|
1877
1879
|
@pattern_hash_keys.push
|
1880
|
+
result = @lexer.in_kwarg
|
1881
|
+
@lexer.in_kwarg = false
|
1878
1882
|
}
|
1879
|
-
p_kwargs
|
1883
|
+
p_kwargs rbrace
|
1880
1884
|
{
|
1881
1885
|
@pattern_hash_keys.pop
|
1886
|
+
@lexer.in_kwarg = val[1]
|
1882
1887
|
result = @builder.hash_pattern(val[0], val[2], val[3])
|
1883
1888
|
}
|
1884
|
-
| tLBRACE
|
1889
|
+
| tLBRACE rbrace
|
1885
1890
|
{
|
1886
1891
|
result = @builder.hash_pattern(val[0], [], val[1])
|
1887
1892
|
}
|
@@ -1932,7 +1937,7 @@ opt_block_args_tail:
|
|
1932
1937
|
# array patterns that end with comma
|
1933
1938
|
# like [1, 2,]
|
1934
1939
|
# must be emitted as `array_pattern_with_tail`
|
1935
|
-
item = @builder.match_with_trailing_comma(val[0])
|
1940
|
+
item = @builder.match_with_trailing_comma(val[0], val[1])
|
1936
1941
|
result = [ item ]
|
1937
1942
|
}
|
1938
1943
|
| p_args_head p_arg tCOMMA
|
@@ -1940,7 +1945,7 @@ opt_block_args_tail:
|
|
1940
1945
|
# array patterns that end with comma
|
1941
1946
|
# like [1, 2,]
|
1942
1947
|
# must be emitted as `array_pattern_with_tail`
|
1943
|
-
last_item = @builder.match_with_trailing_comma(val[1])
|
1948
|
+
last_item = @builder.match_with_trailing_comma(val[1], val[2])
|
1944
1949
|
result = [ *val[0], last_item ]
|
1945
1950
|
}
|
1946
1951
|
|
@@ -1984,6 +1989,10 @@ opt_block_args_tail:
|
|
1984
1989
|
{
|
1985
1990
|
result = val[0]
|
1986
1991
|
}
|
1992
|
+
| p_kwarg tCOMMA
|
1993
|
+
{
|
1994
|
+
result = val[0]
|
1995
|
+
}
|
1987
1996
|
| p_kwrest
|
1988
1997
|
{
|
1989
1998
|
result = val[0]
|
@@ -2096,6 +2105,11 @@ opt_block_args_tail:
|
|
2096
2105
|
|
2097
2106
|
p_var_ref: tCARET tIDENTIFIER
|
2098
2107
|
{
|
2108
|
+
name = val[1][0]
|
2109
|
+
unless static_env.declared?(name)
|
2110
|
+
diagnostic :error, :undefined_lvar, { :name => name }, val[1]
|
2111
|
+
end
|
2112
|
+
|
2099
2113
|
lvar = @builder.accessible(@builder.ident(val[1]))
|
2100
2114
|
result = @builder.pin(val[0], lvar)
|
2101
2115
|
}
|
@@ -2891,6 +2905,10 @@ keyword_variable: kNIL
|
|
2891
2905
|
{
|
2892
2906
|
result = val[1]
|
2893
2907
|
}
|
2908
|
+
rbrace: opt_nl tRCURLY
|
2909
|
+
{
|
2910
|
+
result = val[1]
|
2911
|
+
}
|
2894
2912
|
trailer: | tNL | tCOMMA
|
2895
2913
|
|
2896
2914
|
term: tSEMI
|
@@ -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(
|
@@ -8661,6 +8675,18 @@ class TestParser < Minitest::Test
|
|
8661
8675
|
| ~ end (in_pattern.hash_pattern)}
|
8662
8676
|
)
|
8663
8677
|
|
8678
|
+
assert_parses_pattern_match(
|
8679
|
+
s(:in_pattern,
|
8680
|
+
s(:hash_pattern,
|
8681
|
+
s(:pair, s(:sym, :a), s(:int, 1))),
|
8682
|
+
nil,
|
8683
|
+
s(:true)),
|
8684
|
+
%q{in { a: 1, } then true},
|
8685
|
+
%q{ ~~~~~~~~~ expression (in_pattern.hash_pattern)
|
8686
|
+
| ~ begin (in_pattern.hash_pattern)
|
8687
|
+
| ~ end (in_pattern.hash_pattern)}
|
8688
|
+
)
|
8689
|
+
|
8664
8690
|
assert_parses_pattern_match(
|
8665
8691
|
s(:in_pattern,
|
8666
8692
|
s(:hash_pattern,
|
@@ -8732,6 +8758,67 @@ class TestParser < Minitest::Test
|
|
8732
8758
|
%q{in a: 1, _a:, ** then true},
|
8733
8759
|
%q{ ~~~~~~~~~~~~~ expression (in_pattern.hash_pattern)}
|
8734
8760
|
)
|
8761
|
+
|
8762
|
+
assert_parses_pattern_match(
|
8763
|
+
s(:in_pattern,
|
8764
|
+
s(:hash_pattern,
|
8765
|
+
s(:pair,
|
8766
|
+
s(:sym, :a),
|
8767
|
+
s(:int, 1))), nil,
|
8768
|
+
s(:false)),
|
8769
|
+
%q{
|
8770
|
+
in {a: 1
|
8771
|
+
}
|
8772
|
+
false
|
8773
|
+
},
|
8774
|
+
%q{}
|
8775
|
+
)
|
8776
|
+
|
8777
|
+
|
8778
|
+
assert_parses_pattern_match(
|
8779
|
+
s(:in_pattern,
|
8780
|
+
s(:hash_pattern,
|
8781
|
+
s(:pair,
|
8782
|
+
s(:sym, :a),
|
8783
|
+
s(:int, 2))), nil,
|
8784
|
+
s(:false)),
|
8785
|
+
%q{
|
8786
|
+
in {a:
|
8787
|
+
2}
|
8788
|
+
false
|
8789
|
+
},
|
8790
|
+
%q{}
|
8791
|
+
)
|
8792
|
+
|
8793
|
+
assert_parses_pattern_match(
|
8794
|
+
s(:in_pattern,
|
8795
|
+
s(:hash_pattern,
|
8796
|
+
s(:pair,
|
8797
|
+
s(:sym, :a),
|
8798
|
+
s(:hash_pattern,
|
8799
|
+
s(:match_var, :b))),
|
8800
|
+
s(:match_var, :c)), nil,
|
8801
|
+
s(:send, nil, :p,
|
8802
|
+
s(:lvar, :c))),
|
8803
|
+
%q{
|
8804
|
+
in a: {b:}, c:
|
8805
|
+
p c
|
8806
|
+
},
|
8807
|
+
%q{}
|
8808
|
+
)
|
8809
|
+
|
8810
|
+
assert_parses_pattern_match(
|
8811
|
+
s(:in_pattern,
|
8812
|
+
s(:hash_pattern,
|
8813
|
+
s(:match_var, :a)), nil,
|
8814
|
+
s(:true)),
|
8815
|
+
%q{
|
8816
|
+
in {a:
|
8817
|
+
}
|
8818
|
+
true
|
8819
|
+
},
|
8820
|
+
%q{}
|
8821
|
+
)
|
8735
8822
|
end
|
8736
8823
|
|
8737
8824
|
def test_pattern_matching_hash_with_string_keys
|
@@ -8839,6 +8926,15 @@ class TestParser < Minitest::Test
|
|
8839
8926
|
)
|
8840
8927
|
end
|
8841
8928
|
|
8929
|
+
def test_pattern_matching_hash_with_string_interpolation_keys
|
8930
|
+
assert_diagnoses(
|
8931
|
+
[:error, :pm_interp_in_var_name],
|
8932
|
+
%q{case a; in "#{a}": 1; end},
|
8933
|
+
%q{ ~~~~~~~ location},
|
8934
|
+
SINCE_2_7
|
8935
|
+
)
|
8936
|
+
end
|
8937
|
+
|
8842
8938
|
def test_pattern_matching_keyword_variable
|
8843
8939
|
assert_parses_pattern_match(
|
8844
8940
|
s(:in_pattern,
|
@@ -8970,7 +9066,7 @@ class TestParser < Minitest::Test
|
|
8970
9066
|
nil,
|
8971
9067
|
s(:true)),
|
8972
9068
|
%q{in A(1, 2) then true},
|
8973
|
-
%q{
|
9069
|
+
%q{ ~~~~~~~ expression (in_pattern.const_pattern)
|
8974
9070
|
| ~ begin (in_pattern.const_pattern)
|
8975
9071
|
| ~ end (in_pattern.const_pattern)
|
8976
9072
|
| ~ expression (in_pattern.const_pattern.const)
|
@@ -8986,7 +9082,7 @@ class TestParser < Minitest::Test
|
|
8986
9082
|
nil,
|
8987
9083
|
s(:true)),
|
8988
9084
|
%q{in A(x:) then true},
|
8989
|
-
%q{
|
9085
|
+
%q{ ~~~~~ expression (in_pattern.const_pattern)
|
8990
9086
|
| ~ begin (in_pattern.const_pattern)
|
8991
9087
|
| ~ end (in_pattern.const_pattern)
|
8992
9088
|
| ~ expression (in_pattern.const_pattern.const)
|
@@ -8997,13 +9093,15 @@ class TestParser < Minitest::Test
|
|
8997
9093
|
s(:in_pattern,
|
8998
9094
|
s(:const_pattern,
|
8999
9095
|
s(:const, nil, :A),
|
9000
|
-
|
9096
|
+
s(:array_pattern)),
|
9001
9097
|
nil,
|
9002
9098
|
s(:true)),
|
9003
9099
|
%q{in A() then true},
|
9004
|
-
%q{
|
9100
|
+
%q{ ~~~ expression (in_pattern.const_pattern)
|
9005
9101
|
| ~ begin (in_pattern.const_pattern)
|
9006
|
-
| ~ end (in_pattern.const_pattern)
|
9102
|
+
| ~ end (in_pattern.const_pattern)
|
9103
|
+
| ~ expression (in_pattern.const_pattern.const)
|
9104
|
+
| ~~ expression (in_pattern.const_pattern.array_pattern)}
|
9007
9105
|
)
|
9008
9106
|
|
9009
9107
|
assert_parses_pattern_match(
|
@@ -9016,7 +9114,7 @@ class TestParser < Minitest::Test
|
|
9016
9114
|
nil,
|
9017
9115
|
s(:true)),
|
9018
9116
|
%q{in A[1, 2] then true},
|
9019
|
-
%q{
|
9117
|
+
%q{ ~~~~~~~ expression (in_pattern.const_pattern)
|
9020
9118
|
| ~ begin (in_pattern.const_pattern)
|
9021
9119
|
| ~ end (in_pattern.const_pattern)
|
9022
9120
|
| ~ expression (in_pattern.const_pattern.const)
|
@@ -9032,7 +9130,7 @@ class TestParser < Minitest::Test
|
|
9032
9130
|
nil,
|
9033
9131
|
s(:true)),
|
9034
9132
|
%q{in A[x:] then true},
|
9035
|
-
%q{
|
9133
|
+
%q{ ~~~~~ expression (in_pattern.const_pattern)
|
9036
9134
|
| ~ begin (in_pattern.const_pattern)
|
9037
9135
|
| ~ end (in_pattern.const_pattern)
|
9038
9136
|
| ~ expression (in_pattern.const_pattern.const)
|
@@ -9043,13 +9141,14 @@ class TestParser < Minitest::Test
|
|
9043
9141
|
s(:in_pattern,
|
9044
9142
|
s(:const_pattern,
|
9045
9143
|
s(:const, nil, :A),
|
9046
|
-
|
9144
|
+
s(:array_pattern)),
|
9047
9145
|
nil,
|
9048
9146
|
s(:true)),
|
9049
9147
|
%q{in A[] then true},
|
9050
|
-
%q{
|
9148
|
+
%q{ ~~~ expression (in_pattern.const_pattern)
|
9051
9149
|
| ~ begin (in_pattern.const_pattern)
|
9052
|
-
| ~ end (in_pattern.const_pattern)
|
9150
|
+
| ~ end (in_pattern.const_pattern)
|
9151
|
+
| ~~ expression (in_pattern.const_pattern.array_pattern)}
|
9053
9152
|
)
|
9054
9153
|
end
|
9055
9154
|
|
@@ -9093,6 +9192,20 @@ class TestParser < Minitest::Test
|
|
9093
9192
|
)
|
9094
9193
|
end
|
9095
9194
|
|
9195
|
+
def test_pattern_matching_blank_else
|
9196
|
+
assert_parses(
|
9197
|
+
s(:case_match,
|
9198
|
+
s(:int, 1),
|
9199
|
+
s(:in_pattern,
|
9200
|
+
s(:int, 2), nil,
|
9201
|
+
s(:int, 3)),
|
9202
|
+
s(:empty_else)),
|
9203
|
+
%q{case 1; in 2; 3; else; end},
|
9204
|
+
%q{ ~~~~ else},
|
9205
|
+
SINCE_2_7
|
9206
|
+
)
|
9207
|
+
end
|
9208
|
+
|
9096
9209
|
def assert_pattern_matching_defines_local_variables(match_code, lvar_names, versions = SINCE_2_7)
|
9097
9210
|
code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
|
9098
9211
|
|
@@ -9294,4 +9407,24 @@ class TestParser < Minitest::Test
|
|
9294
9407
|
%{ ^^ location},
|
9295
9408
|
SINCE_2_7)
|
9296
9409
|
end
|
9410
|
+
|
9411
|
+
def test_pattern_matching_required_bound_variable_before_pin
|
9412
|
+
assert_diagnoses(
|
9413
|
+
[:error, :undefined_lvar, { :name => 'a' }],
|
9414
|
+
%{case 0; in ^a; true; end},
|
9415
|
+
%{ ^ location},
|
9416
|
+
SINCE_2_7)
|
9417
|
+
end
|
9418
|
+
|
9419
|
+
def test_parser_bug_645
|
9420
|
+
assert_parses(
|
9421
|
+
s(:block,
|
9422
|
+
s(:lambda),
|
9423
|
+
s(:args,
|
9424
|
+
s(:optarg, :arg,
|
9425
|
+
s(:hash))), nil),
|
9426
|
+
'-> (arg={}) {}',
|
9427
|
+
%{},
|
9428
|
+
SINCE_1_9)
|
9429
|
+
end
|
9297
9430
|
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.1.0
|
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-04-03 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.1.0/CHANGELOG.md
|
301
|
+
documentation_uri: https://www.rubydoc.info/gems/parser/2.7.1.0
|
302
|
+
source_code_uri: https://github.com/whitequark/parser/tree/v2.7.1.0
|
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.
|