diff --git a/python/src/com/jetbrains/python/parsing/FunctionParsing.java b/python/src/com/jetbrains/python/parsing/FunctionParsing.java index 2c8b7dff584b..6ea9a38558de 100644 --- a/python/src/com/jetbrains/python/parsing/FunctionParsing.java +++ b/python/src/com/jetbrains/python/parsing/FunctionParsing.java @@ -99,6 +99,18 @@ public class FunctionParsing extends Parsing { } protected void parseDeclarationAfterDecorator(PsiBuilder.Marker endMarker) { + if (myBuilder.getTokenType() == PyTokenTypes.ASYNC_KEYWORD) { + myBuilder.advanceLexer(); + myContext.pushScope(myContext.getScope().withAsync()); + parseSyncDeclarationAfterDecorator(endMarker); + myContext.popScope(); + } + else { + parseSyncDeclarationAfterDecorator(endMarker); + } + } + + private void parseSyncDeclarationAfterDecorator(PsiBuilder.Marker endMarker) { if (myBuilder.getTokenType() == PyTokenTypes.DEF_KEYWORD) { parseFunctionInnards(endMarker); } diff --git a/python/testData/psi/DecoratedAsyncDef.py b/python/testData/psi/DecoratedAsyncDef.py new file mode 100644 index 000000000000..c2bfe7f6c0ba --- /dev/null +++ b/python/testData/psi/DecoratedAsyncDef.py @@ -0,0 +1,9 @@ +@foo +async def bar(): + await x + return 0 + + +@baz(x, y) +async def quux(): + return await x diff --git a/python/testData/psi/DecoratedAsyncDef.txt b/python/testData/psi/DecoratedAsyncDef.txt new file mode 100644 index 000000000000..c8b35f5b486e --- /dev/null +++ b/python/testData/psi/DecoratedAsyncDef.txt @@ -0,0 +1,69 @@ +PyFile:DecoratedAsyncDef.py + PyFunction('bar') + PyDecoratorList + PyDecorator: @foo + PsiElement(Py:AT)('@') + PyReferenceExpression: foo + PsiElement(Py:IDENTIFIER)('foo') + PyArgumentList + + PsiWhiteSpace('\n') + PsiElement(Py:ASYNC_KEYWORD)('async') + PsiWhiteSpace(' ') + PsiElement(Py:DEF_KEYWORD)('def') + PsiWhiteSpace(' ') + PsiElement(Py:IDENTIFIER)('bar') + PyParameterList + PsiElement(Py:LPAR)('(') + PsiElement(Py:RPAR)(')') + PsiElement(Py:COLON)(':') + PsiWhiteSpace('\n ') + PyStatementList + PyExpressionStatement + PyPrefixExpression + PsiElement(Py:AWAIT_KEYWORD)('await') + PsiWhiteSpace(' ') + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiWhiteSpace('\n ') + PyReturnStatement + PsiElement(Py:RETURN_KEYWORD)('return') + PsiWhiteSpace(' ') + PyNumericLiteralExpression + PsiElement(Py:INTEGER_LITERAL)('0') + PsiWhiteSpace('\n\n\n') + PyFunction('quux') + PyDecoratorList + PyDecorator: @baz + PsiElement(Py:AT)('@') + PyReferenceExpression: baz + PsiElement(Py:IDENTIFIER)('baz') + PyArgumentList + PsiElement(Py:LPAR)('(') + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiElement(Py:COMMA)(',') + PsiWhiteSpace(' ') + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiElement(Py:RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(Py:ASYNC_KEYWORD)('async') + PsiWhiteSpace(' ') + PsiElement(Py:DEF_KEYWORD)('def') + PsiWhiteSpace(' ') + PsiElement(Py:IDENTIFIER)('quux') + PyParameterList + PsiElement(Py:LPAR)('(') + PsiElement(Py:RPAR)(')') + PsiElement(Py:COLON)(':') + PsiWhiteSpace('\n ') + PyStatementList + PyReturnStatement + PsiElement(Py:RETURN_KEYWORD)('return') + PsiWhiteSpace(' ') + PyPrefixExpression + PsiElement(Py:AWAIT_KEYWORD)('await') + PsiWhiteSpace(' ') + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java index 99172dce2e48..a96a6d2c5706 100644 --- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java +++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java @@ -502,6 +502,10 @@ public class PythonParsingTest extends ParsingTestCase { doTest(LanguageLevel.PYTHON35); } + public void testDecoratedAsyncDef() { + doTest(LanguageLevel.PYTHON35); + } + public void doTest(LanguageLevel languageLevel) { LanguageLevel prev = myLanguageLevel; myLanguageLevel = languageLevel;