parser 2.7.1.0 → 2.7.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +10 -11
- data/CHANGELOG.md +70 -1
- data/README.md +2 -2
- data/Rakefile +2 -1
- data/doc/AST_FORMAT.md +107 -3
- data/lib/parser.rb +1 -0
- data/lib/parser/all.rb +1 -0
- data/lib/parser/ast/processor.rb +2 -0
- data/lib/parser/base.rb +6 -5
- data/lib/parser/builders/default.rb +146 -19
- data/lib/parser/context.rb +1 -0
- data/lib/parser/current.rb +9 -0
- data/lib/parser/diagnostic.rb +1 -1
- data/lib/parser/diagnostic/engine.rb +1 -2
- data/lib/parser/lexer.rb +23770 -0
- data/lib/parser/lexer.rl +15 -1
- data/lib/parser/macruby.rb +6149 -0
- data/lib/parser/macruby.y +15 -5
- data/lib/parser/max_numparam_stack.rb +1 -1
- data/lib/parser/messages.rb +17 -0
- data/lib/parser/meta.rb +3 -3
- data/lib/parser/ruby18.rb +5663 -0
- data/lib/parser/ruby18.y +3 -1
- data/lib/parser/ruby19.rb +6092 -0
- data/lib/parser/ruby19.y +15 -5
- data/lib/parser/ruby20.rb +6527 -0
- data/lib/parser/ruby20.y +15 -5
- data/lib/parser/ruby21.rb +6578 -0
- data/lib/parser/ruby21.y +10 -3
- data/lib/parser/ruby22.rb +6613 -0
- data/lib/parser/ruby22.y +10 -3
- data/lib/parser/ruby23.rb +6624 -0
- data/lib/parser/ruby23.y +10 -3
- data/lib/parser/ruby24.rb +6694 -0
- data/lib/parser/ruby24.y +10 -3
- data/lib/parser/ruby25.rb +6662 -0
- data/lib/parser/ruby25.y +10 -3
- data/lib/parser/ruby26.rb +6676 -0
- data/lib/parser/ruby26.y +10 -3
- data/lib/parser/ruby27.rb +7803 -0
- data/lib/parser/ruby27.y +16 -8
- data/lib/parser/ruby30.rb +8052 -0
- data/lib/parser/ruby30.y +3048 -0
- data/lib/parser/rubymotion.rb +6086 -0
- data/lib/parser/rubymotion.y +15 -5
- 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.rb +1 -1
- data/lib/parser/source/comment/associator.rb +14 -4
- data/lib/parser/source/map/method_definition.rb +25 -0
- data/lib/parser/source/range.rb +19 -3
- data/lib/parser/source/tree_rewriter.rb +115 -12
- data/lib/parser/source/tree_rewriter/action.rb +135 -26
- data/lib/parser/tree_rewriter.rb +1 -2
- data/lib/parser/version.rb +1 -1
- data/parser.gemspec +6 -2
- data/test/helper.rb +49 -6
- data/test/parse_helper.rb +49 -40
- 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_parse_helper.rb +12 -9
- data/test/test_parser.rb +612 -56
- 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 +201 -13
- metadata +19 -13
- data/.gitignore +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58735baf961ddf249964c59136cdfc0c5abbb15f09e2d09c591442cad5e559fb
|
4
|
+
data.tar.gz: f77b0c5380882d193b3e20f383eecaa92fd9a3807ca8b85154138677a493b02f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 702a6fe61f52f33fcbd3324a347fa4ffa5f3677503b53324637502db1d762c8007f2e45fdf57745f520d48e2ec1f48913f31ad1b1e5f360115d0fc4634532bb7
|
7
|
+
data.tar.gz: eb549a8defabd4dccd7ee746b32b59886b12380d370a5293dcc3f3ab3cad39b959d65e7cc2c72a8e366fb67102930eaf84cf104ff8361b95a97939eb39c1dc71
|
data/.travis.yml
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
dist: trusty
|
2
2
|
language: ruby
|
3
|
-
|
3
|
+
jobs:
|
4
4
|
include:
|
5
|
-
- name:
|
6
|
-
rvm:
|
5
|
+
- name: jruby-9.1.15.0 / Parser tests
|
6
|
+
rvm: jruby-9.1.15.0
|
7
|
+
script: bundle exec rake test
|
8
|
+
- name: truffleruby / Parser tests
|
9
|
+
rvm: truffleruby
|
10
|
+
script: TRUFFLERUBYOPT=--engine.Mode=latency bundle exec rake test
|
11
|
+
- name: 2.4.10 / Parser tests
|
12
|
+
rvm: 2.4.10
|
7
13
|
script: bundle exec rake test_cov
|
8
14
|
- name: 2.5.8 / Parser tests
|
9
15
|
rvm: 2.5.8
|
@@ -17,12 +23,6 @@ matrix:
|
|
17
23
|
- name: ruby-head / Parser tests
|
18
24
|
rvm: ruby-head
|
19
25
|
script: bundle exec rake test_cov
|
20
|
-
- name: jruby-9.1.15.0 / Parser tests
|
21
|
-
rvm: jruby-9.1.15.0
|
22
|
-
script: bundle exec rake test_cov
|
23
|
-
- name: rbx-2 / Parser tests
|
24
|
-
rvm: rbx-2
|
25
|
-
script: bundle exec rake test_cov
|
26
26
|
- name: 2.5.8 / Rubocop tests
|
27
27
|
rvm: 2.5.8
|
28
28
|
script: ./ci/run_rubocop_specs
|
@@ -34,9 +34,8 @@ matrix:
|
|
34
34
|
script: ./ci/run_rubocop_specs
|
35
35
|
allow_failures:
|
36
36
|
- rvm: ruby-head
|
37
|
-
- rvm:
|
37
|
+
- rvm: truffleruby
|
38
38
|
- script: ./ci/run_rubocop_specs
|
39
39
|
before_install:
|
40
|
-
- gem install bundler -v '< 2'
|
41
40
|
- bundle --version
|
42
41
|
- gem --version
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,78 @@
|
|
1
1
|
Changelog
|
2
2
|
=========
|
3
3
|
|
4
|
-
Not released (2020-
|
4
|
+
Not released (2020-09-24)
|
5
5
|
-------------------------
|
6
6
|
|
7
|
+
API modifications:
|
8
|
+
* right assignment: use existing AST node types (#738) (#739) (Marc-André Lafortune)
|
9
|
+
* ruby28.y -> ruby30.y (#729) (Vladimir Dementyev)
|
10
|
+
|
11
|
+
Features implemented:
|
12
|
+
* Optimize Range#column_range (#741) (Marc-André Lafortune)
|
13
|
+
* ruby30.y: reject endless setter. (#736) (Ilya Bylich)
|
14
|
+
* ruby28.y: reject assignment to numparam. (#725) (Ilya Bylich)
|
15
|
+
* emit "endless method def" as `:def` node. (#716) (Ilya Bylich)
|
16
|
+
|
17
|
+
Bugs fixed:
|
18
|
+
* rename 2.8 to 3.0 everywhere (#732) (Ilya Bylich)
|
19
|
+
* test_current.rb: 2.8 -> 3.0 (#731) (Vladimir Dementyev)
|
20
|
+
* Parser#parse returns nil instead of false if error is thrown (#722) (Marc-André Lafortune)
|
21
|
+
* unify locations for normal and endless method definition (#718) (Marc-André Lafortune)
|
22
|
+
* ruby27.y: accept const names as hash keys for pattern matching (#717) (Koichi ITO)
|
23
|
+
* Fix locations for alias / undef nodes with internal symbols (#715) (Marc-André Lafortune)
|
24
|
+
|
25
|
+
v2.7.1.4 (2020-06-19)
|
26
|
+
---------------------
|
27
|
+
|
28
|
+
Features implemented:
|
29
|
+
* ruby28.y: add find pattern. (#714) (Ilya Bylich)
|
30
|
+
* lexer.rl: reject `->...` and `->(...)` with the same error. (#713) (Ilya Bylich)
|
31
|
+
* ruby28.y: accept leading args before forward arg. (#712) (Ilya Bylich)
|
32
|
+
* Added `emit_forward_arg` compatibility flag. (#710) (Ilya Bylich)
|
33
|
+
* ruby28.y: include entire lambda expr in lambda rule. (#708) (Ilya Bylich)
|
34
|
+
* ruby28.y: extracted excessed_comma rule. (#706) (Ilya Bylich)
|
35
|
+
* Source::TreeRewriter: Improved merging and representations (#703) (Marc-André Lafortune)
|
36
|
+
|
37
|
+
Bugs fixed:
|
38
|
+
* ruby*.y: fixed context inside lambda args and module. (#709) (Ilya Bylich)
|
39
|
+
|
40
|
+
v2.7.1.3 (2020-05-26)
|
41
|
+
---------------------
|
42
|
+
|
43
|
+
API modifications:
|
44
|
+
* fixed all warnings. tests are running in verbose mode now. (#685) (Ilya Bylich)
|
45
|
+
|
46
|
+
Features implemented:
|
47
|
+
* ruby-[parse, rewrite]: add legacy switches (#699) (Marc-André Lafortune)
|
48
|
+
* Added Parser::Source::Range#to_range. (#697) (Ilya Bylich)
|
49
|
+
* ruby28.y: support rescue modifier in endless method definition. (#696) (Ilya Bylich)
|
50
|
+
* ruby28.y: unify kwrest and no-kwrest rules. (#694) (Ilya Bylich)
|
51
|
+
* ruby28.y: add right hand assignment (#682) (Vladimir Dementyev)
|
52
|
+
|
53
|
+
Bugs fixed:
|
54
|
+
* fix Comment.associate for postfix conditions/loops (#688) (Marc-André Lafortune)
|
55
|
+
|
56
|
+
v2.7.1.2 (2020-04-30)
|
57
|
+
---------------------
|
58
|
+
|
59
|
+
Features implemented:
|
60
|
+
* ruby28.y: endless method definition (#676) (Vladimir Dementyev)
|
61
|
+
* ruby28.y: branch parser (#677) (Vladimir Dementyev)
|
62
|
+
|
63
|
+
Bugs fixed:
|
64
|
+
* ruby27.y: reject invalid lvar in pattern matching (#680) (Vladimir Dementyev)
|
65
|
+
|
66
|
+
v2.7.1.1 (2020-04-15)
|
67
|
+
---------------------
|
68
|
+
|
69
|
+
Features implemented:
|
70
|
+
* Add Source::Range#eql? and hash (#675) (Marc-André Lafortune)
|
71
|
+
* Source::TreeRewriter: Add #merge, #merge! and #empty? (#674) (Marc-André Lafortune)
|
72
|
+
|
73
|
+
v2.7.1.0 (2020-04-03)
|
74
|
+
---------------------
|
75
|
+
|
7
76
|
API modifications:
|
8
77
|
* Bump ruby versions to 2.4.10, 2.5.8, 2.6.6, 2.7.1. (#665) (Ilya Bylich)
|
9
78
|
|
data/README.md
CHANGED
@@ -29,6 +29,7 @@ below for explanation of `emit_*` calls):
|
|
29
29
|
Parser::Builders::Default.emit_encoding = true
|
30
30
|
Parser::Builders::Default.emit_index = true
|
31
31
|
Parser::Builders::Default.emit_arg_inside_procarg0 = true
|
32
|
+
Parser::Builders::Default.emit_forward_arg = true
|
32
33
|
|
33
34
|
Parse a chunk of code:
|
34
35
|
|
@@ -59,8 +60,7 @@ Parse a chunk of code and display all diagnostics:
|
|
59
60
|
puts diag.render
|
60
61
|
end
|
61
62
|
|
62
|
-
buffer = Parser::Source::Buffer.new('(string)')
|
63
|
-
buffer.source = "foo *bar"
|
63
|
+
buffer = Parser::Source::Buffer.new('(string)', source: "foo *bar")
|
64
64
|
|
65
65
|
p parser.parse(buffer)
|
66
66
|
# (string):1:5: warning: `*' interpreted as argument prefix
|
data/Rakefile
CHANGED
@@ -11,7 +11,7 @@ task :default => [:test]
|
|
11
11
|
Rake::TestTask.new do |t|
|
12
12
|
t.libs = %w(test/ lib/)
|
13
13
|
t.test_files = FileList["test/**/test_*.rb"]
|
14
|
-
t.warning =
|
14
|
+
t.warning = true
|
15
15
|
end
|
16
16
|
|
17
17
|
task :test_cov do
|
@@ -32,6 +32,7 @@ GENERATED_FILES = %w(lib/parser/lexer.rb
|
|
32
32
|
lib/parser/ruby25.rb
|
33
33
|
lib/parser/ruby26.rb
|
34
34
|
lib/parser/ruby27.rb
|
35
|
+
lib/parser/ruby30.rb
|
35
36
|
lib/parser/macruby.rb
|
36
37
|
lib/parser/rubymotion.rb)
|
37
38
|
|
data/doc/AST_FORMAT.md
CHANGED
@@ -637,7 +637,7 @@ Format:
|
|
637
637
|
(masgn (mlhs (ivasgn :@a) (cvasgn :@@b)) (array (splat (lvar :c))))
|
638
638
|
"@a, @@b = *c"
|
639
639
|
|
640
|
-
(masgn (mlhs (
|
640
|
+
(masgn (mlhs (lvasgn :a) (mlhs (lvasgn :b)) (lvasgn :c)) (lvar :d))
|
641
641
|
"a, (b, c) = d"
|
642
642
|
|
643
643
|
(masgn (mlhs (send (self) :a=) (send (self) :[]= (int 1))) (lvar :a))
|
@@ -730,6 +730,29 @@ Format:
|
|
730
730
|
|
731
731
|
~~~
|
732
732
|
|
733
|
+
### Right-hand assignment
|
734
|
+
|
735
|
+
Format:
|
736
|
+
|
737
|
+
~~~
|
738
|
+
(lvasgn :a (int 1))
|
739
|
+
"1 => a"
|
740
|
+
~~~~~~ expression
|
741
|
+
~ name
|
742
|
+
~~ operator
|
743
|
+
~~~
|
744
|
+
|
745
|
+
#### Multiple right-hand assignment
|
746
|
+
|
747
|
+
Format:
|
748
|
+
|
749
|
+
~~~
|
750
|
+
(masgn (mlhs (lvasgn :a) (lvasgn :b)) (send (int 13) :divmod (int 5)))
|
751
|
+
"13.divmod(5) => a,b"
|
752
|
+
~~~~~~~~~~~~~~~~~~~ expression
|
753
|
+
^^ operator
|
754
|
+
~~~
|
755
|
+
|
733
756
|
## Class and module definition
|
734
757
|
|
735
758
|
### Module
|
@@ -802,6 +825,33 @@ Format:
|
|
802
825
|
~~~~~~~~~~~~~~~~~ expression
|
803
826
|
~~~
|
804
827
|
|
828
|
+
### "Endless" method
|
829
|
+
|
830
|
+
Format:
|
831
|
+
|
832
|
+
~~~
|
833
|
+
(def :foo (args) (int 42))
|
834
|
+
"def foo() = 42"
|
835
|
+
~~~ keyword
|
836
|
+
~~~ name
|
837
|
+
^ assignment
|
838
|
+
~~~~~~~~~~~~~~ expression
|
839
|
+
~~~
|
840
|
+
|
841
|
+
|
842
|
+
### "Endless" singleton method
|
843
|
+
|
844
|
+
Format:
|
845
|
+
|
846
|
+
~~~
|
847
|
+
(defs (self) :foo (args) (int 42))
|
848
|
+
"def self.foo() = 42"
|
849
|
+
~~~ keyword
|
850
|
+
~~~ name
|
851
|
+
^ assignment
|
852
|
+
~~~~~~~~~~~~~~~~~~~ expression
|
853
|
+
~~~
|
854
|
+
|
805
855
|
### Undefinition
|
806
856
|
|
807
857
|
Format:
|
@@ -1115,13 +1165,13 @@ s(:numblock,
|
|
1115
1165
|
|
1116
1166
|
## Forward arguments
|
1117
1167
|
|
1118
|
-
### Method definition accepting forwarding arguments
|
1168
|
+
### Method definition accepting only forwarding arguments
|
1119
1169
|
|
1120
1170
|
Ruby 2.7 introduced a feature called "arguments forwarding".
|
1121
1171
|
When a method takes any arguments for forwarding them in the future
|
1122
1172
|
the whole `args` node gets replaced with `forward-args` node.
|
1123
1173
|
|
1124
|
-
Format:
|
1174
|
+
Format if `emit_forward_arg` compatibility flag is disabled:
|
1125
1175
|
|
1126
1176
|
~~~
|
1127
1177
|
(def :foo
|
@@ -1132,6 +1182,25 @@ Format:
|
|
1132
1182
|
~~~~~ expression
|
1133
1183
|
~~~
|
1134
1184
|
|
1185
|
+
However, Ruby 3.0 added support for leading arguments before `...`, and so
|
1186
|
+
it can't be used as a replacement of the `(args)` node anymore. To solve it
|
1187
|
+
`emit_forward_arg` should be enabled.
|
1188
|
+
|
1189
|
+
Format if `emit_forward_arg` compatibility flag is enabled:
|
1190
|
+
|
1191
|
+
~~~
|
1192
|
+
(def :foo
|
1193
|
+
(args
|
1194
|
+
(forward-arg)) nil)
|
1195
|
+
"def foo(...); end"
|
1196
|
+
~ begin (args)
|
1197
|
+
~ end (args)
|
1198
|
+
~~~~~ expression (args)
|
1199
|
+
~~~ expression (forward_arg)
|
1200
|
+
~~~
|
1201
|
+
|
1202
|
+
Note that the node is called `forward_arg` when emitted separately.
|
1203
|
+
|
1135
1204
|
### Method call taking arguments of the currently forwarding method
|
1136
1205
|
|
1137
1206
|
Format:
|
@@ -2123,6 +2192,24 @@ Format:
|
|
2123
2192
|
~~~ name (match-nil-pattern)
|
2124
2193
|
~~~
|
2125
2194
|
|
2195
|
+
### Matching using find pattern
|
2196
|
+
|
2197
|
+
Format:
|
2198
|
+
|
2199
|
+
~~~
|
2200
|
+
(find-pattern
|
2201
|
+
(match-rest
|
2202
|
+
(match-var :a))
|
2203
|
+
(int 42)
|
2204
|
+
(match-rest))
|
2205
|
+
"in [*, 42, *]"
|
2206
|
+
~ begin
|
2207
|
+
~ end
|
2208
|
+
~~~~~~~~~~ expression
|
2209
|
+
~~~
|
2210
|
+
|
2211
|
+
Note that it can be used as a top-level pattern only when used in a `case` statement. In that case `begin` and `end` are empty.
|
2212
|
+
|
2126
2213
|
### Matching using const pattern
|
2127
2214
|
|
2128
2215
|
#### With array pattern
|
@@ -2178,3 +2265,20 @@ Format:
|
|
2178
2265
|
~ expression (const-pattern.const)
|
2179
2266
|
~~ expression (const-pattern.array_pattern)
|
2180
2267
|
~~~
|
2268
|
+
|
2269
|
+
#### With find pattern
|
2270
|
+
|
2271
|
+
Format:
|
2272
|
+
|
2273
|
+
~~~
|
2274
|
+
(const-pattern
|
2275
|
+
(const nil :X)
|
2276
|
+
(find-pattern
|
2277
|
+
(match-rest)
|
2278
|
+
(int 42)
|
2279
|
+
(match-rest)))
|
2280
|
+
"in X[*, 42, *]"
|
2281
|
+
~ begin
|
2282
|
+
~ end
|
2283
|
+
~~~~~~~~~~~ expression
|
2284
|
+
~~~
|
data/lib/parser.rb
CHANGED
@@ -46,6 +46,7 @@ module Parser
|
|
46
46
|
require 'parser/source/map/variable'
|
47
47
|
require 'parser/source/map/keyword'
|
48
48
|
require 'parser/source/map/definition'
|
49
|
+
require 'parser/source/map/method_definition'
|
49
50
|
require 'parser/source/map/send'
|
50
51
|
require 'parser/source/map/index'
|
51
52
|
require 'parser/source/map/condition'
|
data/lib/parser/all.rb
CHANGED
data/lib/parser/ast/processor.rb
CHANGED
@@ -124,6 +124,7 @@ module Parser
|
|
124
124
|
alias on_kwarg process_argument_node
|
125
125
|
alias on_kwoptarg process_argument_node
|
126
126
|
alias on_kwrestarg process_argument_node
|
127
|
+
alias on_forward_arg process_argument_node
|
127
128
|
|
128
129
|
def on_procarg0(node)
|
129
130
|
if node.children[0].is_a?(Symbol)
|
@@ -250,6 +251,7 @@ module Parser
|
|
250
251
|
alias on_array_pattern_with_tail process_regular_node
|
251
252
|
alias on_hash_pattern process_regular_node
|
252
253
|
alias on_const_pattern process_regular_node
|
254
|
+
alias on_find_pattern process_regular_node
|
253
255
|
|
254
256
|
# @private
|
255
257
|
def process_variable_node(node)
|
data/lib/parser/base.rb
CHANGED
@@ -177,16 +177,16 @@ module Parser
|
|
177
177
|
end
|
178
178
|
|
179
179
|
##
|
180
|
-
# Parses a source buffer and returns the AST.
|
180
|
+
# Parses a source buffer and returns the AST, or `nil` in case of a non fatal error.
|
181
181
|
#
|
182
182
|
# @param [Parser::Source::Buffer] source_buffer The source buffer to parse.
|
183
|
-
# @return [Parser::AST::Node]
|
183
|
+
# @return [Parser::AST::Node, nil]
|
184
184
|
#
|
185
185
|
def parse(source_buffer)
|
186
186
|
@lexer.source_buffer = source_buffer
|
187
187
|
@source_buffer = source_buffer
|
188
188
|
|
189
|
-
do_parse
|
189
|
+
do_parse || nil # Force `false` to `nil`, see https://github.com/ruby/racc/pull/136
|
190
190
|
ensure
|
191
191
|
# Don't keep references to the source file.
|
192
192
|
@source_buffer = nil
|
@@ -210,8 +210,9 @@ module Parser
|
|
210
210
|
|
211
211
|
##
|
212
212
|
# Parses a source buffer and returns the AST, the source code comments,
|
213
|
-
# and the tokens emitted by the lexer.
|
214
|
-
#
|
213
|
+
# and the tokens emitted by the lexer. In case of a fatal error, a {SyntaxError}
|
214
|
+
# is raised, unless `recover` is true. In case of an error
|
215
|
+
# (non-fatal or recovered), `nil` is returned instead of the AST, and
|
215
216
|
# comments as well as tokens are only returned up to the location of
|
216
217
|
# the error.
|
217
218
|
#
|
@@ -80,6 +80,8 @@ module Parser
|
|
80
80
|
attr_accessor :emit_index
|
81
81
|
end
|
82
82
|
|
83
|
+
@emit_index = false
|
84
|
+
|
83
85
|
class << self
|
84
86
|
##
|
85
87
|
# AST compatibility attribute; causes a single non-mlhs
|
@@ -95,7 +97,36 @@ module Parser
|
|
95
97
|
attr_accessor :emit_arg_inside_procarg0
|
96
98
|
end
|
97
99
|
|
98
|
-
@
|
100
|
+
@emit_arg_inside_procarg0 = false
|
101
|
+
|
102
|
+
class << self
|
103
|
+
##
|
104
|
+
# AST compatibility attribute; arguments forwarding initially
|
105
|
+
# didn't have support for leading arguments
|
106
|
+
# (i.e. `def m(a, ...); end` was a syntax error). However, Ruby 3.0
|
107
|
+
# added support for any number of arguments in front of the `...`.
|
108
|
+
#
|
109
|
+
# If set to false (the default):
|
110
|
+
# 1. `def m(...) end` is emitted as
|
111
|
+
# s(:def, :m, s(:forward_args), nil)
|
112
|
+
# 2. `def m(a, b, ...) end` is emitted as
|
113
|
+
# s(:def, :m,
|
114
|
+
# s(:args, s(:arg, :a), s(:arg, :b), s(:forward_arg)))
|
115
|
+
#
|
116
|
+
# If set to true it uses a single format:
|
117
|
+
# 1. `def m(...) end` is emitted as
|
118
|
+
# s(:def, :m, s(:args, s(:forward_arg)))
|
119
|
+
# 2. `def m(a, b, ...) end` is emitted as
|
120
|
+
# s(:def, :m, s(:args, s(:arg, :a), s(:arg, :b), s(:forward_arg)))
|
121
|
+
#
|
122
|
+
# It does't matter that much on 2.7 (because there can't be any leading arguments),
|
123
|
+
# but on 3.0 it should be better enabled to use a single AST format.
|
124
|
+
#
|
125
|
+
# @return [Boolean]
|
126
|
+
attr_accessor :emit_forward_arg
|
127
|
+
end
|
128
|
+
|
129
|
+
@emit_forward_arg = false
|
99
130
|
|
100
131
|
class << self
|
101
132
|
##
|
@@ -106,6 +137,7 @@ module Parser
|
|
106
137
|
@emit_encoding = true
|
107
138
|
@emit_index = true
|
108
139
|
@emit_arg_inside_procarg0 = true
|
140
|
+
@emit_forward_arg = true
|
109
141
|
end
|
110
142
|
end
|
111
143
|
|
@@ -557,7 +589,11 @@ module Parser
|
|
557
589
|
when :ident
|
558
590
|
name, = *node
|
559
591
|
|
560
|
-
|
592
|
+
var_name = node.children[0].to_s
|
593
|
+
name_loc = node.loc.expression
|
594
|
+
|
595
|
+
check_assignment_to_numparam(var_name, name_loc)
|
596
|
+
check_reserved_for_numparam(var_name, name_loc)
|
561
597
|
|
562
598
|
@parser.static_env.declare(name)
|
563
599
|
|
@@ -619,6 +655,14 @@ module Parser
|
|
619
655
|
binary_op_map(lhs, eql_t, rhs))
|
620
656
|
end
|
621
657
|
|
658
|
+
def rassign(lhs, assoc_t, rhs)
|
659
|
+
assign(rhs, assoc_t, lhs)
|
660
|
+
end
|
661
|
+
|
662
|
+
def multi_rassign(lhs, assoc_t, rhs)
|
663
|
+
multi_assign(rhs, assoc_t, lhs)
|
664
|
+
end
|
665
|
+
|
622
666
|
#
|
623
667
|
# Class and module definition
|
624
668
|
#
|
@@ -648,23 +692,38 @@ module Parser
|
|
648
692
|
|
649
693
|
def def_method(def_t, name_t, args,
|
650
694
|
body, end_t)
|
695
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
696
|
+
|
651
697
|
n(:def, [ value(name_t).to_sym, args, body ],
|
652
698
|
definition_map(def_t, nil, name_t, end_t))
|
653
699
|
end
|
654
700
|
|
701
|
+
def def_endless_method(def_t, name_t, args,
|
702
|
+
assignment_t, body)
|
703
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
704
|
+
|
705
|
+
n(:def, [ value(name_t).to_sym, args, body ],
|
706
|
+
endless_definition_map(def_t, nil, name_t, assignment_t, body))
|
707
|
+
end
|
708
|
+
|
655
709
|
def def_singleton(def_t, definee, dot_t,
|
656
710
|
name_t, args,
|
657
711
|
body, end_t)
|
658
|
-
|
659
|
-
|
660
|
-
:regexp, :array, :hash
|
712
|
+
validate_definee(definee)
|
713
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
661
714
|
|
662
|
-
|
715
|
+
n(:defs, [ definee, value(name_t).to_sym, args, body ],
|
716
|
+
definition_map(def_t, dot_t, name_t, end_t))
|
717
|
+
end
|
663
718
|
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
719
|
+
def def_endless_singleton(def_t, definee, dot_t,
|
720
|
+
name_t, args,
|
721
|
+
assignment_t, body)
|
722
|
+
validate_definee(definee)
|
723
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
724
|
+
|
725
|
+
n(:defs, [ definee, value(name_t).to_sym, args, body ],
|
726
|
+
endless_definition_map(def_t, dot_t, name_t, assignment_t, body))
|
668
727
|
end
|
669
728
|
|
670
729
|
def undef_method(undef_t, names)
|
@@ -691,16 +750,30 @@ module Parser
|
|
691
750
|
n(:numargs, [ max_numparam ], nil)
|
692
751
|
end
|
693
752
|
|
694
|
-
def
|
695
|
-
|
753
|
+
def forward_only_args(begin_t, dots_t, end_t)
|
754
|
+
if self.class.emit_forward_arg
|
755
|
+
arg = forward_arg(dots_t)
|
756
|
+
n(:args, [ arg ],
|
757
|
+
collection_map(begin_t, [ arg ], end_t))
|
758
|
+
else
|
759
|
+
n(:forward_args, [], collection_map(begin_t, token_map(dots_t), end_t))
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
763
|
+
def forward_arg(dots_t)
|
764
|
+
n(:forward_arg, [], token_map(dots_t))
|
696
765
|
end
|
697
766
|
|
698
767
|
def arg(name_t)
|
768
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
769
|
+
|
699
770
|
n(:arg, [ value(name_t).to_sym ],
|
700
771
|
variable_map(name_t))
|
701
772
|
end
|
702
773
|
|
703
774
|
def optarg(name_t, eql_t, value)
|
775
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
776
|
+
|
704
777
|
n(:optarg, [ value(name_t).to_sym, value ],
|
705
778
|
variable_map(name_t).
|
706
779
|
with_operator(loc(eql_t)).
|
@@ -709,6 +782,7 @@ module Parser
|
|
709
782
|
|
710
783
|
def restarg(star_t, name_t=nil)
|
711
784
|
if name_t
|
785
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
712
786
|
n(:restarg, [ value(name_t).to_sym ],
|
713
787
|
arg_prefix_map(star_t, name_t))
|
714
788
|
else
|
@@ -718,17 +792,23 @@ module Parser
|
|
718
792
|
end
|
719
793
|
|
720
794
|
def kwarg(name_t)
|
795
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
796
|
+
|
721
797
|
n(:kwarg, [ value(name_t).to_sym ],
|
722
798
|
kwarg_map(name_t))
|
723
799
|
end
|
724
800
|
|
725
801
|
def kwoptarg(name_t, value)
|
802
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
803
|
+
|
726
804
|
n(:kwoptarg, [ value(name_t).to_sym, value ],
|
727
805
|
kwarg_map(name_t, value))
|
728
806
|
end
|
729
807
|
|
730
808
|
def kwrestarg(dstar_t, name_t=nil)
|
731
809
|
if name_t
|
810
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
811
|
+
|
732
812
|
n(:kwrestarg, [ value(name_t).to_sym ],
|
733
813
|
arg_prefix_map(dstar_t, name_t))
|
734
814
|
else
|
@@ -743,11 +823,15 @@ module Parser
|
|
743
823
|
end
|
744
824
|
|
745
825
|
def shadowarg(name_t)
|
826
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
827
|
+
|
746
828
|
n(:shadowarg, [ value(name_t).to_sym ],
|
747
829
|
variable_map(name_t))
|
748
830
|
end
|
749
831
|
|
750
832
|
def blockarg(amper_t, name_t)
|
833
|
+
check_reserved_for_numparam(value(name_t), loc(name_t))
|
834
|
+
|
751
835
|
n(:blockarg, [ value(name_t).to_sym ],
|
752
836
|
arg_prefix_map(amper_t, name_t))
|
753
837
|
end
|
@@ -1239,8 +1323,10 @@ module Parser
|
|
1239
1323
|
|
1240
1324
|
def match_var(name_t)
|
1241
1325
|
name = value(name_t).to_sym
|
1326
|
+
name_l = loc(name_t)
|
1242
1327
|
|
1243
|
-
|
1328
|
+
check_lvar_name(name, name_l)
|
1329
|
+
check_duplicate_pattern_variable(name, name_l)
|
1244
1330
|
@parser.static_env.declare(name)
|
1245
1331
|
|
1246
1332
|
n(:match_var, [ name ],
|
@@ -1253,6 +1339,7 @@ module Parser
|
|
1253
1339
|
expr_l = loc(name_t)
|
1254
1340
|
name_l = expr_l.adjust(end_pos: -1)
|
1255
1341
|
|
1342
|
+
check_lvar_name(name, name_l)
|
1256
1343
|
check_duplicate_pattern_variable(name, name_l)
|
1257
1344
|
@parser.static_env.declare(name)
|
1258
1345
|
|
@@ -1293,6 +1380,9 @@ module Parser
|
|
1293
1380
|
Source::Map::Variable.new(name_l, expr_l))
|
1294
1381
|
when :begin
|
1295
1382
|
match_hash_var_from_str(begin_t, string.children, end_t)
|
1383
|
+
else
|
1384
|
+
# we only can get here if there is an interpolation, e.g., ``in "#{ a }":`
|
1385
|
+
diagnostic :error, :pm_interp_in_var_name, nil, loc(begin_t).join(loc(end_t))
|
1296
1386
|
end
|
1297
1387
|
end
|
1298
1388
|
|
@@ -1334,6 +1424,11 @@ module Parser
|
|
1334
1424
|
collection_map(lbrack_t, elements, rbrack_t))
|
1335
1425
|
end
|
1336
1426
|
|
1427
|
+
def find_pattern(lbrack_t, elements, rbrack_t)
|
1428
|
+
n(:find_pattern, elements,
|
1429
|
+
collection_map(lbrack_t, elements, rbrack_t))
|
1430
|
+
end
|
1431
|
+
|
1337
1432
|
def match_with_trailing_comma(match, comma_t)
|
1338
1433
|
n(:match_with_trailing_comma, [ match ], expr_map(match.loc.expression.join(loc(comma_t))))
|
1339
1434
|
end
|
@@ -1489,8 +1584,10 @@ module Parser
|
|
1489
1584
|
end
|
1490
1585
|
end
|
1491
1586
|
|
1492
|
-
def check_assignment_to_numparam(
|
1493
|
-
|
1587
|
+
def check_assignment_to_numparam(name, loc)
|
1588
|
+
# MRI < 2.7 treats numbered parameters as regular variables
|
1589
|
+
# and so it's allowed to perform assignments like `_1 = 42`.
|
1590
|
+
return if @parser.version < 27
|
1494
1591
|
|
1495
1592
|
assigning_to_numparam =
|
1496
1593
|
@parser.context.in_dynamic_block? &&
|
@@ -1498,7 +1595,17 @@ module Parser
|
|
1498
1595
|
@parser.max_numparam_stack.has_numparams?
|
1499
1596
|
|
1500
1597
|
if assigning_to_numparam
|
1501
|
-
diagnostic :error, :cant_assign_to_numparam, { :name => name },
|
1598
|
+
diagnostic :error, :cant_assign_to_numparam, { :name => name }, loc
|
1599
|
+
end
|
1600
|
+
end
|
1601
|
+
|
1602
|
+
def check_reserved_for_numparam(name, loc)
|
1603
|
+
# MRI < 3.0 accepts assignemnt to variables like _1
|
1604
|
+
# if it's not a numbererd parameter. MRI 3.0 and newer throws an error.
|
1605
|
+
return if @parser.version < 30
|
1606
|
+
|
1607
|
+
if name =~ /\A_([1-9])\z/
|
1608
|
+
diagnostic :error, :reserved_for_numparam, { :name => name }, loc
|
1502
1609
|
end
|
1503
1610
|
end
|
1504
1611
|
|
@@ -1732,9 +1839,17 @@ module Parser
|
|
1732
1839
|
end
|
1733
1840
|
|
1734
1841
|
def definition_map(keyword_t, operator_t, name_t, end_t)
|
1735
|
-
Source::Map::
|
1736
|
-
|
1737
|
-
|
1842
|
+
Source::Map::MethodDefinition.new(loc(keyword_t),
|
1843
|
+
loc(operator_t), loc(name_t),
|
1844
|
+
loc(end_t), nil, nil)
|
1845
|
+
end
|
1846
|
+
|
1847
|
+
def endless_definition_map(keyword_t, operator_t, name_t, assignment_t, body_e)
|
1848
|
+
body_l = body_e.loc.expression
|
1849
|
+
|
1850
|
+
Source::Map::MethodDefinition.new(loc(keyword_t),
|
1851
|
+
loc(operator_t), loc(name_t), nil,
|
1852
|
+
loc(assignment_t), body_l)
|
1738
1853
|
end
|
1739
1854
|
|
1740
1855
|
def send_map(receiver_e, dot_t, selector_t, begin_t=nil, args=[], end_t=nil)
|
@@ -1979,6 +2094,18 @@ module Parser
|
|
1979
2094
|
@parser.send :yyerror
|
1980
2095
|
end
|
1981
2096
|
end
|
2097
|
+
|
2098
|
+
def validate_definee(definee)
|
2099
|
+
case definee.type
|
2100
|
+
when :int, :str, :dstr, :sym, :dsym,
|
2101
|
+
:regexp, :array, :hash
|
2102
|
+
|
2103
|
+
diagnostic :error, :singleton_literal, nil, definee.loc.expression
|
2104
|
+
false
|
2105
|
+
else
|
2106
|
+
true
|
2107
|
+
end
|
2108
|
+
end
|
1982
2109
|
end
|
1983
2110
|
|
1984
2111
|
end
|