Skip to content

Commit 74177d7

Browse files
bitwise-aidenakien-mga
authored andcommitted
Fix multiline array/dictionary match statements
Currently array and dictionary expressions cannot be spread over multiple lines in match statements. Adding mutliline push/pop while parsing the pattern for bracket and brace enables the ability for these to be multiline. This enables more complex patterns to be matched without exceeding line limits. Fixes godotengine#90372
1 parent b2f425f commit 74177d7

File tree

5 files changed

+82
-15
lines changed

5 files changed

+82
-15
lines changed

modules/gdscript/gdscript_parser.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,28 +2270,31 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_
22702270
break;
22712271
case GDScriptTokenizer::Token::BRACKET_OPEN: {
22722272
// Array.
2273+
push_multiline(true);
22732274
advance();
22742275
pattern->pattern_type = PatternNode::PT_ARRAY;
2275-
2276-
if (!check(GDScriptTokenizer::Token::BRACKET_CLOSE)) {
2277-
do {
2278-
PatternNode *sub_pattern = parse_match_pattern(p_root_pattern != nullptr ? p_root_pattern : pattern);
2279-
if (sub_pattern == nullptr) {
2280-
continue;
2281-
}
2282-
if (pattern->rest_used) {
2283-
push_error(R"(The ".." pattern must be the last element in the pattern array.)");
2284-
} else if (sub_pattern->pattern_type == PatternNode::PT_REST) {
2285-
pattern->rest_used = true;
2286-
}
2287-
pattern->array.push_back(sub_pattern);
2288-
} while (match(GDScriptTokenizer::Token::COMMA));
2289-
}
2276+
do {
2277+
if (is_at_end() || check(GDScriptTokenizer::Token::BRACKET_CLOSE)) {
2278+
break;
2279+
}
2280+
PatternNode *sub_pattern = parse_match_pattern(p_root_pattern != nullptr ? p_root_pattern : pattern);
2281+
if (sub_pattern == nullptr) {
2282+
continue;
2283+
}
2284+
if (pattern->rest_used) {
2285+
push_error(R"(The ".." pattern must be the last element in the pattern array.)");
2286+
} else if (sub_pattern->pattern_type == PatternNode::PT_REST) {
2287+
pattern->rest_used = true;
2288+
}
2289+
pattern->array.push_back(sub_pattern);
2290+
} while (match(GDScriptTokenizer::Token::COMMA));
22902291
consume(GDScriptTokenizer::Token::BRACKET_CLOSE, R"(Expected "]" to close the array pattern.)");
2292+
pop_multiline();
22912293
break;
22922294
}
22932295
case GDScriptTokenizer::Token::BRACE_OPEN: {
22942296
// Dictionary.
2297+
push_multiline(true);
22952298
advance();
22962299
pattern->pattern_type = PatternNode::PT_DICTIONARY;
22972300
do {
@@ -2334,6 +2337,7 @@ GDScriptParser::PatternNode *GDScriptParser::parse_match_pattern(PatternNode *p_
23342337
}
23352338
} while (match(GDScriptTokenizer::Token::COMMA));
23362339
consume(GDScriptTokenizer::Token::BRACE_CLOSE, R"(Expected "}" to close the dictionary pattern.)");
2340+
pop_multiline();
23372341
break;
23382342
}
23392343
default: {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
func foo(x):
2+
match x:
3+
["value1"]:
4+
print('["value1"]')
5+
["value1", "value2"]:
6+
print('["value1", "value2"]')
7+
8+
func bar(x):
9+
match x:
10+
[
11+
"value1"
12+
]:
13+
print('multiline ["value1"]')
14+
[
15+
"value1",
16+
"value2",
17+
]:
18+
print('multiline ["value1", "value2",]')
19+
[
20+
"value1",
21+
[
22+
"value2",
23+
..,
24+
],
25+
]:
26+
print('multiline ["value1", ["value2", ..,],]')
27+
28+
func test():
29+
foo(["value1"])
30+
foo(["value1", "value2"])
31+
bar(["value1"])
32+
bar(["value1", "value2"])
33+
bar(["value1", ["value2", "value3"]])
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
GDTEST_OK
2+
["value1"]
3+
["value1", "value2"]
4+
multiline ["value1"]
5+
multiline ["value1", "value2",]
6+
multiline ["value1", ["value2", ..,],]

modules/gdscript/tests/scripts/parser/features/match_dictionary.gd

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,24 @@ func bar(x):
2626
_:
2727
print("wildcard")
2828

29+
func baz(x):
30+
match x:
31+
{
32+
"key1": "value1"
33+
}:
34+
print('multiline {"key1": "value1"}')
35+
{
36+
"key2": "value2",
37+
}:
38+
print('multiline {"key2": "value2",}')
39+
{
40+
"key3": {
41+
"key1",
42+
..,
43+
},
44+
}:
45+
print('multiline {"key3": {"key1", ..,},}')
46+
2947
func test():
3048
foo({"key1": "value1", "key2": "value2"})
3149
foo({"key1": "value1", "key2": ""})
@@ -41,3 +59,6 @@ func test():
4159
bar({1: "1"})
4260
bar({2: "2"})
4361
bar({3: "3"})
62+
baz({"key1": "value1"})
63+
baz({"key2": "value2"})
64+
baz({"key3": {"key1": "value1", "key2": "value2"}})

modules/gdscript/tests/scripts/parser/features/match_dictionary.out

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,6 @@ wildcard
1313
1
1414
2
1515
wildcard
16+
multiline {"key1": "value1"}
17+
multiline {"key2": "value2",}
18+
multiline {"key3": {"key1", ..,},}

0 commit comments

Comments
 (0)