Skip to content

Commit acdea44

Browse files
SONARPY-932 Fix parse error: decorators can be any valid expression (#998)
1 parent bcde5a4 commit acdea44

File tree

3 files changed

+17
-2
lines changed

3 files changed

+17
-2
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,7 @@ public static void compoundStatements(LexerfulGrammarBuilder b) {
538538
b.rule(FUN_RETURN_ANNOTATION).is("-", ">", TEST);
539539

540540
b.rule(DECORATORS).is(b.oneOrMore(DECORATOR));
541-
b.rule(DECORATOR).is("@", EXPR, NEWLINE);
541+
b.rule(DECORATOR).is("@", NAMED_EXPR_TEST, NEWLINE);
542542
b.rule(DOTTED_NAME).is(NAME, b.zeroOrMore(".", NAME));
543543

544544
b.rule(CLASSDEF).is(b.optional(DECORATORS), "class", CLASSNAME, b.optional("(", b.optional(ARGLIST), ")"), ":", SUITE);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ public FunctionDef funcDefStatement(AstNode astNode) {
587587

588588
private Decorator decorator(AstNode astNode) {
589589
Token atToken = toPyToken(astNode.getFirstChild(PythonPunctuator.AT).getToken());
590-
Expression expression = expression(astNode.getFirstChild(PythonGrammar.EXPR));
590+
Expression expression = expression(astNode.getFirstChild(PythonGrammar.NAMED_EXPR_TEST));
591591
Token newLineToken = astNode.getFirstChild(PythonTokenType.NEWLINE) == null ? null : toPyToken(astNode.getFirstChild(PythonTokenType.NEWLINE).getToken());
592592
return new DecoratorImpl(atToken, expression, newLineToken);
593593
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,21 @@ public void decorators() {
902902
assertThat(decorator.name().names()).isEmpty();
903903
assertThat(TreeUtils.decoratorNameFromExpression(decorator.expression())).isNull();
904904
assertThat(decorator.expression().is(Kind.QUALIFIED_EXPR)).isTrue();
905+
906+
functionDef = funcDef("@hello() or bye()\ndef func(x): pass");
907+
decorators = functionDef.decorators();
908+
assertThat(decorators).hasSize(1);
909+
decorator = decorators.get(0);
910+
assertThat(decorator.expression().getKind()).isEqualTo(Kind.OR);
911+
BinaryExpression binaryExpression = (BinaryExpression) decorator.expression();
912+
assertThat(binaryExpression.leftOperand().getKind()).isEqualTo(Kind.CALL_EXPR);
913+
assertThat(binaryExpression.rightOperand().getKind()).isEqualTo(Kind.CALL_EXPR);
914+
915+
functionDef = funcDef("@b:=some_decorator\ndef func(x): pass");
916+
decorators = functionDef.decorators();
917+
assertThat(decorators).hasSize(1);
918+
decorator = decorators.get(0);
919+
assertThat(decorator.expression().getKind()).isEqualTo(Kind.ASSIGNMENT_EXPRESSION);
905920
}
906921

907922
private FunctionDef funcDef(String code) {

0 commit comments

Comments
 (0)