Skip to content

Commit ab47414

Browse files
authored
Merge pull request #3843 from thomasmarshall/error-recovery-nodes
Validate expected nodes
2 parents 3448ab6 + 5933877 commit ab47414

33 files changed

Lines changed: 744 additions & 529 deletions

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ jobs:
5151
with:
5252
ruby-version: "3.4"
5353
bundler-cache: true
54-
- name: Check Sorbet
55-
run: bundle exec rake typecheck:tapioca typecheck:sorbet
54+
# - name: Check Sorbet
55+
# run: bundle exec rake typecheck:tapioca typecheck:sorbet
5656
- name: Check Steep
5757
run: bundle exec rake typecheck:steep
5858
- name: Check field kinds

config.yml

Lines changed: 11 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -814,8 +814,6 @@ nodes:
814814
- GlobalVariableReadNode
815815
- BackReferenceReadNode
816816
- NumberedReferenceReadNode
817-
- on error: SymbolNode # alias $a b
818-
- on error: MissingNode # alias $a 42
819817
comment: |
820818
Represents the old name of the global variable that can be used before aliasing.
821819
@@ -856,8 +854,6 @@ nodes:
856854
kind:
857855
- SymbolNode
858856
- InterpolatedSymbolNode
859-
- on error: GlobalVariableReadNode # alias a $b
860-
- on error: MissingNode # alias a 42
861857
comment: |
862858
Represents the old name of the method that will be aliased.
863859
@@ -1871,7 +1867,6 @@ nodes:
18711867
kind:
18721868
- ConstantReadNode
18731869
- ConstantPathNode
1874-
- on error: CallNode # class 0.X end
18751870
- name: inheritance_operator_loc
18761871
type: location?
18771872
comment: |
@@ -2425,6 +2420,15 @@ nodes:
24252420
^^^^^^
24262421
bar
24272422
end
2423+
- name: ErrorRecoveryNode
2424+
fields:
2425+
- name: unexpected
2426+
type: node?
2427+
kind: Node
2428+
comment: |
2429+
The unexpected node that was found in the tree, if there was one.
2430+
comment: |
2431+
Represents a node that is either missing or unexpected and results in a syntax error.
24282432
- name: FalseNode
24292433
comment: |
24302434
Represents the use of the literal `false` keyword.
@@ -2467,9 +2471,7 @@ nodes:
24672471
^^^^^^
24682472
- name: right
24692473
type: node
2470-
kind:
2471-
- SplatNode
2472-
- on error: MissingNode
2474+
kind: SplatNode
24732475
comment: |
24742476
Represents the second wildcard node in the pattern.
24752477
@@ -2552,9 +2554,6 @@ nodes:
25522554
- CallTargetNode
25532555
- IndexTargetNode
25542556
- MultiTargetNode
2555-
- on error: BackReferenceReadNode # for $& in a end
2556-
- on error: NumberedReferenceReadNode # for $1 in a end
2557-
- on error: MissingNode # for in 1..10; end
25582557
comment: |
25592558
The index expression for `for` loops.
25602559
@@ -3308,10 +3307,6 @@ nodes:
33083307
- EmbeddedStatementsNode
33093308
- EmbeddedVariableNode
33103309
- InterpolatedStringNode # `"a" "#{b}"`
3311-
- on error: XStringNode # `<<`FOO` "bar"
3312-
- on error: InterpolatedXStringNode
3313-
- on error: SymbolNode
3314-
- on error: InterpolatedSymbolNode
33153310
- name: closing_loc
33163311
type: location?
33173312
newline: parts
@@ -3689,9 +3684,6 @@ nodes:
36893684
36903685
/(?<foo>bar)/ =~ baz
36913686
^^^^^^^^^^^^^^^^^^^^
3692-
- name: MissingNode
3693-
comment: |
3694-
Represents a node that is missing from the source and results in a syntax error.
36953687
- name: ModuleNode
36963688
fields:
36973689
- name: locals
@@ -3703,7 +3695,6 @@ nodes:
37033695
kind:
37043696
- ConstantReadNode
37053697
- ConstantPathNode
3706-
- on error: MissingNode # module Parent module end
37073698
- name: body
37083699
type: node?
37093700
kind:
@@ -3733,8 +3724,6 @@ nodes:
37333724
- IndexTargetNode
37343725
- MultiTargetNode
37353726
- RequiredParameterNode # def m((a,b)); end
3736-
- on error: BackReferenceReadNode # a, (b, $&) = z
3737-
- on error: NumberedReferenceReadNode # a, (b, $1) = z
37383727
comment: |
37393728
Represents the targets expressions before a splat node.
37403729
@@ -3778,8 +3767,6 @@ nodes:
37783767
- IndexTargetNode
37793768
- MultiTargetNode
37803769
- RequiredParameterNode # def m((*,b)); end
3781-
- on error: BackReferenceReadNode # a, (*, $&) = z
3782-
- on error: NumberedReferenceReadNode # a, (*, $1) = z
37833770
comment: |
37843771
Represents the targets expressions after a splat node.
37853772
@@ -3823,8 +3810,6 @@ nodes:
38233810
- CallTargetNode
38243811
- IndexTargetNode
38253812
- MultiTargetNode
3826-
- on error: BackReferenceReadNode # $&, = z
3827-
- on error: NumberedReferenceReadNode # $1, = z
38283813
comment: |
38293814
Represents the targets expressions before a splat node.
38303815
@@ -3867,8 +3852,6 @@ nodes:
38673852
- CallTargetNode
38683853
- IndexTargetNode
38693854
- MultiTargetNode
3870-
- on error: BackReferenceReadNode # *, $& = z
3871-
- on error: NumberedReferenceReadNode # *, $1 = z
38723855
comment: |
38733856
Represents the targets expressions after a splat node.
38743857
@@ -4066,14 +4049,6 @@ nodes:
40664049
kind:
40674050
- RequiredParameterNode
40684051
- MultiTargetNode
4069-
# On parsing error of `f(**kwargs, ...)` or `f(**nil, ...)`, the keyword_rest value is moved here:
4070-
- on error: KeywordRestParameterNode
4071-
- on error: NoKeywordsParameterNode
4072-
# On parsing error of `f(..., ...)`, the first forwarding parameter is moved here:
4073-
- on error: ForwardingParameterNode
4074-
# On parsing error of `f(&nil, &foo)`/`f(&foo, &nil)`, the first forwarding parameter is moved here:
4075-
- on error: BlockParameterNode
4076-
- on error: NoBlockParameterNode
40774052
- name: keywords
40784053
type: node[]
40794054
kind:
@@ -4160,7 +4135,6 @@ nodes:
41604135
- BackReferenceReadNode # foo in ^$&
41614136
- NumberedReferenceReadNode # foo in ^$1
41624137
- ItLocalVariableReadNode # proc { 1 in ^it }
4163-
- on error: MissingNode # foo in ^Bar
41644138
comment: |
41654139
The variable used in the pinned expression
41664140
@@ -4243,7 +4217,7 @@ nodes:
42434217
42444218
1...foo
42454219
^^^
4246-
If neither right-hand or left-hand side was included, this will be a MissingNode.
4220+
If neither right-hand or left-hand side was included, this will be an ErrorRecoveryNode.
42474221
- name: operator_loc
42484222
type: location
42494223
comment: |
@@ -4358,9 +4332,6 @@ nodes:
43584332
- ConstantPathTargetNode
43594333
- CallTargetNode
43604334
- IndexTargetNode
4361-
- on error: BackReferenceReadNode # => begin; rescue => $&; end
4362-
- on error: NumberedReferenceReadNode # => begin; rescue => $1; end
4363-
- on error: MissingNode # begin; rescue =>; end
43644335
- name: then_keyword_loc
43654336
type: location?
43664337
- name: statements

docs/mapping.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,6 @@ The following table shows how the various CRuby nodes are mapped to prism nodes.
112112
| `NODE_ARYPTN` | `PM_ARRAY_PATTERN_NODE` |
113113
| `NODE_HSHPTN` | `PM_HASH_PATTERN_NODE` |
114114
| `NODE_FNDPTN` | `PM_FIND_PATTERN_NODE` |
115-
| `NODE_ERROR` | `PM_MISSING_NODE` |
115+
| `NODE_ERROR` | `PM_ERROR_RECOVERY_NODE` |
116116
| `NODE_LAST` | |
117117
```

lib/prism/node_ext.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,10 @@ class ConstantPathNode < Node
221221
# local variable
222222
class DynamicPartsInConstantPathError < StandardError; end
223223

224-
# An error class raised when missing nodes are found while computing a
224+
# An error class raised when error recovery nodes are found while computing a
225225
# constant path's full name. For example:
226226
# Foo:: -> raises because the constant path is missing the last part
227-
class MissingNodesInConstantPathError < StandardError; end
227+
class ErrorRecoveryNodesInConstantPathError < StandardError; end
228228

229229
# Returns the list of parts for the full name of this constant path.
230230
# For example: [:Foo, :Bar]
@@ -237,7 +237,7 @@ def full_name_parts
237237
while current.is_a?(ConstantPathNode)
238238
name = current.name
239239
if name.nil?
240-
raise MissingNodesInConstantPathError, "Constant path contains missing nodes. Cannot compute full name"
240+
raise ErrorRecoveryNodesInConstantPathError, "Constant path contains error recovery nodes. Cannot compute full name"
241241
end
242242

243243
parts.unshift(name)
@@ -277,7 +277,7 @@ def full_name_parts
277277
end
278278

279279
if (name = self.name).nil?
280-
raise ConstantPathNode::MissingNodesInConstantPathError, "Constant target path contains missing nodes. Cannot compute full name"
280+
raise ConstantPathNode::ErrorRecoveryNodesInConstantPathError, "Constant target path contains error recovery nodes. Cannot compute full name"
281281
end
282282

283283
parts.push(name)

lib/prism/translation/parser/compiler.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1324,7 +1324,7 @@ def visit_match_write_node(node)
13241324
# A node that is missing from the syntax tree. This is only used in the
13251325
# case of a syntax error. The parser gem doesn't have such a concept, so
13261326
# we invent our own here.
1327-
def visit_missing_node(node)
1327+
def visit_error_recovery_node(node)
13281328
::AST::Node.new(:missing, [], location: ::Parser::Source::Map.new(srange(node.location)))
13291329
end
13301330

lib/prism/translation/ripper.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2511,8 +2511,8 @@ def visit_match_write_node(node)
25112511

25122512
# A node that is missing from the syntax tree. This is only used in the
25132513
# case of a syntax error.
2514-
def visit_missing_node(node)
2515-
raise "Cannot visit missing nodes directly."
2514+
def visit_error_recovery_node(node)
2515+
raise "Cannot visit error recovery nodes directly."
25162516
end
25172517

25182518
# module Foo; end

lib/prism/translation/ruby_parser.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,8 +1071,8 @@ def visit_match_write_node(node)
10711071
# A node that is missing from the syntax tree. This is only used in the
10721072
# case of a syntax error. The parser gem doesn't have such a concept, so
10731073
# we invent our own here.
1074-
def visit_missing_node(node)
1075-
raise "Cannot visit missing node directly"
1074+
def visit_error_recovery_node(node)
1075+
raise "Cannot visit error recovery node directly"
10761076
end
10771077

10781078
# module Foo; end

rakelib/lint.rake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ task :lint do
2929
exit(1)
3030
end
3131

32-
if (uncommented = nodes.select { |node| !%w[MissingNode ProgramNode].include?(node.fetch("name")) && !node.fetch("comment").match?(/^\s{4}/) }).any?
32+
if (uncommented = nodes.select { |node| !%w[ErrorRecoveryNode ProgramNode].include?(node.fetch("name")) && !node.fetch("comment").match?(/^\s{4}/) }).any?
3333
names = uncommented.map { |node| node.fetch("name") }
3434
warn("Expected all nodes to have an example, missing comments for #{names.join(", ")}")
3535
exit(1)

rbi/generated/prism/compiler.rbi

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rbi/generated/prism/dispatcher.rbi

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)