parser 2.7.1.0 → 2.7.1.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 +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
|