Skip to content

Commit ca1e444

Browse files
GDScript: Do phrase level recovery when parsing faulty dictionaries
1 parent 134da37 commit ca1e444

30 files changed

+177
-4
lines changed

modules/gdscript/gdscript_parser.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3123,13 +3123,9 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode
31233123
case DictionaryNode::LUA_TABLE:
31243124
if (key != nullptr && key->type != Node::IDENTIFIER && key->type != Node::LITERAL) {
31253125
push_error(R"(Expected identifier or string as Lua-style dictionary key (e.g "{ key = value }").)");
3126-
advance();
3127-
break;
31283126
}
31293127
if (key != nullptr && key->type == Node::LITERAL && static_cast<LiteralNode *>(key)->value.get_type() != Variant::STRING) {
31303128
push_error(R"(Expected identifier or string as Lua-style dictionary key (e.g "{ key = value }").)");
3131-
advance();
3132-
break;
31333129
}
31343130
if (!match(GDScriptTokenizer::Token::EQUAL)) {
31353131
if (match(GDScriptTokenizer::Token::COLON)) {
@@ -3169,6 +3165,21 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode
31693165
if (key != nullptr && value != nullptr) {
31703166
dictionary->elements.push_back({ key, value });
31713167
}
3168+
3169+
// Do phrase level recovery by inserting an imaginary expression for missing keys or values.
3170+
// This ensures the successfully parsed expression is part of the AST and can be analyzed.
3171+
if (key != nullptr && value == nullptr) {
3172+
LiteralNode *dummy = alloc_recovery_node<LiteralNode>();
3173+
dummy->value = Variant();
3174+
3175+
dictionary->elements.push_back({ key, dummy });
3176+
} else if (key == nullptr && value != nullptr) {
3177+
LiteralNode *dummy = alloc_recovery_node<LiteralNode>();
3178+
dummy->value = Variant();
3179+
3180+
dictionary->elements.push_back({ dummy, value });
3181+
}
3182+
31723183
} while (match(GDScriptTokenizer::Token::COMMA) && !is_at_end());
31733184
}
31743185
pop_multiline();

modules/gdscript/gdscript_parser.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,6 +1453,18 @@ class GDScriptParser {
14531453

14541454
return node;
14551455
}
1456+
1457+
// Allocates a node for patching up the parse tree when an error occurred.
1458+
// Such nodes don't track their extents as they don't relate to actual tokens.
1459+
template <typename T>
1460+
T *alloc_recovery_node() {
1461+
T *node = memnew(T);
1462+
node->next = list;
1463+
list = node;
1464+
1465+
return node;
1466+
}
1467+
14561468
void clear();
14571469
void push_error(const String &p_message, const Node *p_origin = nullptr);
14581470
#ifdef DEBUG_ENABLED
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[output]
2+
exclude=[
3+
{"display": "AUTO_TRANSLATE_MODE_INHERIT"},
4+
]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extends Node
2+
3+
var test = {
4+
t = 1,
5+
AutoTranslateMode.➡
6+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[output]
2+
exclude=[
3+
{"display": "VALUE"},
4+
]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
extends Node
2+
3+
enum TestEnum {
4+
VALUE,
5+
}
6+
7+
var test = {
8+
t = 1,
9+
TestEnum.➡ = 1,
10+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[output]
2+
include=[
3+
{"display": "AUTO_TRANSLATE_MODE_INHERIT"},
4+
]
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
extends Node
2+
3+
var test = {
4+
t = AutoTranslateMode.➡
5+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[output]
2+
include=[
3+
{"display": "VALUE"},
4+
]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extends Node
2+
3+
enum TestEnum {
4+
VALUE,
5+
}
6+
7+
var test = {
8+
= TestEnum.➡
9+
}

0 commit comments

Comments
 (0)