Skip to content

Commit a62deca

Browse files
authored
SONARPY-1573: Fix parse error of unparenthesized walrus in set literals and comprehension (#2026)
* SONARPY-1573 parse set comprehension with unparenthesized walrus * SONARPY-1573 adress PR feedback
1 parent 4fa5308 commit a62deca

File tree

4 files changed

+25
-3
lines changed

4 files changed

+25
-3
lines changed

python-frontend/src/main/java/org/sonar/python/api/PythonGrammarBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ protected void grammar(LexerfulGrammarBuilder b) {
145145
b.sequence(
146146
b.firstOf(b.sequence(TEST, ":", TEST), b.sequence("**", EXPR)),
147147
b.firstOf(COMP_FOR, b.sequence(b.zeroOrMore(",", b.firstOf(b.sequence(TEST, ":", TEST), b.sequence("**", EXPR))), b.optional(",")))),
148-
b.sequence(b.firstOf(TEST, STAR_EXPR), b.firstOf(COMP_FOR, b.sequence(b.zeroOrMore(",", b.firstOf(TEST, STAR_EXPR)), b.optional(","))))));
148+
b.sequence(STAR_NAMED_EXPRESSION, b.firstOf(COMP_FOR, b.sequence(b.zeroOrMore(",", STAR_NAMED_EXPRESSION), b.optional(","))))));
149149

150150
b.rule(ARGLIST).is(ARGUMENT, b.zeroOrMore(",", ARGUMENT), b.optional(","));
151151
b.rule(ARGUMENT).is(b.firstOf(

python-frontend/src/main/java/org/sonar/python/tree/PythonTreeMaker.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,7 +1339,7 @@ private Expression dictOrSetLiteral(AstNode astNode) {
13391339
Expression valueExpression = expression(dictOrSetMaker.getLastChild(PythonGrammar.TEST));
13401340
return new DictCompExpressionImpl(lCurlyBrace, keyExpression, toPyToken(colon.getToken()), valueExpression, compFor, rCurlyBrace);
13411341
} else {
1342-
Expression resultExpression = expression(dictOrSetMaker.getFirstChild(PythonGrammar.TEST, PythonGrammar.STAR_EXPR));
1342+
Expression resultExpression = expression(dictOrSetMaker.getFirstChild(PythonGrammar.STAR_NAMED_EXPRESSION));
13431343
return new ComprehensionExpressionImpl(Tree.Kind.SET_COMPREHENSION, lCurlyBrace, resultExpression, compFor, rCurlyBrace);
13441344
}
13451345
}
@@ -1360,7 +1360,7 @@ private Expression dictOrSetLiteral(AstNode astNode) {
13601360
}
13611361
return new DictionaryLiteralImpl(lCurlyBrace, commas, dictionaryLiteralElements, rCurlyBrace);
13621362
}
1363-
List<Expression> expressions = dictOrSetMaker.getChildren(PythonGrammar.TEST, PythonGrammar.STAR_EXPR).stream().map(this::expression).toList();
1363+
List<Expression> expressions = dictOrSetMaker.getChildren(PythonGrammar.STAR_NAMED_EXPRESSION).stream().map(this::expression).toList();
13641364
return new SetLiteralImpl(lCurlyBrace, expressions, commas, rCurlyBrace);
13651365
}
13661366

python-frontend/src/test/java/org/sonar/python/tree/PythonTreeMakerTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2574,6 +2574,11 @@ void set_literal() {
25742574
assertThat(tree.children()).hasSize(6).containsExactly(tree.lCurlyBrace(), tree.elements().get(0), tree.commas().get(0),
25752575
tree.elements().get(1), tree.commas().get(1), tree.rCurlyBrace());
25762576

2577+
tree = (SetLiteral) parse("{ first := x, second := y }", treeMaker::expression);
2578+
assertThat(tree.elements()).hasSize(2);
2579+
assertThat(tree.children()).hasSize(5).containsExactly(tree.lCurlyBrace(), tree.elements().get(0), tree.commas().get(0),
2580+
tree.elements().get(1), tree.rCurlyBrace());
2581+
25772582
tree = (SetLiteral) parse("{ *x }", treeMaker::expression);
25782583
assertThat(tree.elements()).hasSize(1);
25792584
element = tree.elements().iterator().next();
@@ -2592,8 +2597,21 @@ void set_comprehension() {
25922597
assertThat(comprehension.children()).hasSize(4);
25932598
assertThat(((Token) comprehension.children().get(0)).value()).isEqualTo("{");
25942599
assertThat(((Token) comprehension.children().get(3)).value()).isEqualTo("}");
2600+
}
2601+
2602+
@Test
2603+
void set_comprehension_with_walrus_operator() {
2604+
setRootRule(PythonGrammar.TEST);
2605+
ComprehensionExpression comprehension =
2606+
(ComprehensionExpression) parse("{last := x-1 for x in [42, 43]}", treeMaker::expression);
25952607
assertThat(comprehension.firstToken().value()).isEqualTo("{");
25962608
assertThat(comprehension.lastToken().value()).isEqualTo("}");
2609+
assertThat(comprehension.getKind()).isEqualTo(Tree.Kind.SET_COMPREHENSION);
2610+
assertThat(comprehension.resultExpression().getKind()).isEqualTo(Kind.ASSIGNMENT_EXPRESSION);
2611+
assertThat(((AssignmentExpression) comprehension.resultExpression()).operator().value()).isEqualTo(":=");
2612+
assertThat(comprehension.children()).hasSize(4);
2613+
assertThat(((Token) comprehension.children().get(0)).value()).isEqualTo("{");
2614+
assertThat(((Token) comprehension.children().get(3)).value()).isEqualTo("}");
25972615
}
25982616

25992617
@Test
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{x for x in range(7)}
2+
{(x4 := x**5) for x in range(7)}
3+
{x4 := x**5 for x in range(7)}
4+
{x := 1, 2, 3}

0 commit comments

Comments
 (0)