mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
PY-19036 Fixed: Using await in a non-asynchronous nested function not marked as a syntax error
Don't inherit async flag in ParsingScope, pass async flag to function parsing
This commit is contained in:
@@ -34,23 +34,25 @@ public class FunctionParsing extends Parsing {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public void parseFunctionDeclaration(@NotNull PsiBuilder.Marker endMarker) {
|
||||
public void parseFunctionDeclaration(@NotNull PsiBuilder.Marker endMarker, boolean async) {
|
||||
assertCurrentToken(PyTokenTypes.DEF_KEYWORD);
|
||||
parseFunctionInnards(endMarker);
|
||||
parseFunctionInnards(endMarker, async);
|
||||
}
|
||||
|
||||
protected IElementType getFunctionType() {
|
||||
return FUNCTION_TYPE;
|
||||
}
|
||||
|
||||
protected void parseFunctionInnards(@NotNull PsiBuilder.Marker functionMarker) {
|
||||
protected void parseFunctionInnards(@NotNull PsiBuilder.Marker functionMarker, boolean async) {
|
||||
myBuilder.advanceLexer();
|
||||
parseIdentifierOrSkip(PyTokenTypes.LPAR);
|
||||
parseParameterList();
|
||||
parseReturnTypeAnnotation();
|
||||
checkMatches(PyTokenTypes.COLON, message("PARSE.expected.colon"));
|
||||
final ParsingContext context = getParsingContext();
|
||||
context.pushScope(context.getScope().withFunction(true));
|
||||
ParsingScope newScope = context.getScope().withFunction(true);
|
||||
if (async) newScope = newScope.withAsync();
|
||||
context.pushScope(newScope);
|
||||
getStatementParser().parseSuite(functionMarker, getFunctionType());
|
||||
context.popScope();
|
||||
}
|
||||
@@ -98,21 +100,19 @@ public class FunctionParsing extends Parsing {
|
||||
parseDeclarationAfterDecorator(decoratorStartMarker);
|
||||
}
|
||||
|
||||
protected void parseDeclarationAfterDecorator(PsiBuilder.Marker endMarker) {
|
||||
private void parseDeclarationAfterDecorator(PsiBuilder.Marker endMarker) {
|
||||
if (myBuilder.getTokenType() == PyTokenTypes.ASYNC_KEYWORD) {
|
||||
myBuilder.advanceLexer();
|
||||
myContext.pushScope(myContext.getScope().withAsync());
|
||||
parseSyncDeclarationAfterDecorator(endMarker);
|
||||
myContext.popScope();
|
||||
parseDeclarationAfterDecorator(endMarker, true);
|
||||
}
|
||||
else {
|
||||
parseSyncDeclarationAfterDecorator(endMarker);
|
||||
parseDeclarationAfterDecorator(endMarker, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseSyncDeclarationAfterDecorator(PsiBuilder.Marker endMarker) {
|
||||
protected void parseDeclarationAfterDecorator(PsiBuilder.Marker endMarker, boolean async) {
|
||||
if (myBuilder.getTokenType() == PyTokenTypes.DEF_KEYWORD) {
|
||||
parseFunctionInnards(endMarker);
|
||||
parseFunctionInnards(endMarker, async);
|
||||
}
|
||||
else if (myBuilder.getTokenType() == PyTokenTypes.CLASS_KEYWORD) {
|
||||
getStatementParser().parseClassDeclaration(endMarker);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -84,7 +84,6 @@ public class ParsingScope {
|
||||
result.myFunction = myFunction;
|
||||
result.myClass = myClass;
|
||||
result.mySuite = mySuite;
|
||||
result.myAsync = myAsync;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -117,7 +117,7 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
|
||||
return;
|
||||
}
|
||||
if (firstToken == PyTokenTypes.DEF_KEYWORD) {
|
||||
getFunctionParser().parseFunctionDeclaration(myBuilder.mark());
|
||||
getFunctionParser().parseFunctionDeclaration(myBuilder.mark(), false);
|
||||
return;
|
||||
}
|
||||
if (firstToken == PyTokenTypes.AT) {
|
||||
@@ -819,10 +819,7 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
|
||||
myBuilder.advanceLexer();
|
||||
final IElementType token = myBuilder.getTokenType();
|
||||
if (token == PyTokenTypes.DEF_KEYWORD) {
|
||||
final ParsingContext context = getParsingContext();
|
||||
context.pushScope(context.getScope().withAsync());
|
||||
getFunctionParser().parseFunctionDeclaration(marker);
|
||||
context.popScope();
|
||||
getFunctionParser().parseFunctionDeclaration(marker, true);
|
||||
}
|
||||
else if (token == PyTokenTypes.WITH_KEYWORD) {
|
||||
parseWithStatement(marker);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import asyncio
|
||||
|
||||
|
||||
async def connect():
|
||||
def callback():
|
||||
return await asyncio.sleep(5)
|
||||
|
||||
return await asyncio.sleep(5)
|
||||
@@ -0,0 +1,68 @@
|
||||
PyFile:AwaitInNonAsyncNestedFunction.py
|
||||
PyImportStatement
|
||||
PsiElement(Py:IMPORT_KEYWORD)('import')
|
||||
PsiWhiteSpace(' ')
|
||||
PyImportElement:asyncio
|
||||
PyReferenceExpression: asyncio
|
||||
PsiElement(Py:IDENTIFIER)('asyncio')
|
||||
PsiWhiteSpace('\n\n\n')
|
||||
PyFunction('connect')
|
||||
PsiElement(Py:ASYNC_KEYWORD)('async')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:IDENTIFIER)('connect')
|
||||
PyParameterList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyFunction('callback')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:IDENTIFIER)('callback')
|
||||
PyParameterList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyReturnStatement
|
||||
PsiElement(Py:RETURN_KEYWORD)('return')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: await
|
||||
PsiElement(Py:IDENTIFIER)('await')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PyExpressionStatement
|
||||
PyCallExpression: asyncio.sleep
|
||||
PyReferenceExpression: sleep
|
||||
PyReferenceExpression: asyncio
|
||||
PsiElement(Py:IDENTIFIER)('asyncio')
|
||||
PsiElement(Py:DOT)('.')
|
||||
PsiElement(Py:IDENTIFIER)('sleep')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('5')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiWhiteSpace('\n\n ')
|
||||
PyReturnStatement
|
||||
PsiElement(Py:RETURN_KEYWORD)('return')
|
||||
PsiWhiteSpace(' ')
|
||||
PyPrefixExpression
|
||||
PsiElement(Py:AWAIT_KEYWORD)('await')
|
||||
PsiWhiteSpace(' ')
|
||||
PyCallExpression: asyncio.sleep
|
||||
PyReferenceExpression: sleep
|
||||
PyReferenceExpression: asyncio
|
||||
PsiElement(Py:IDENTIFIER)('asyncio')
|
||||
PsiElement(Py:DOT)('.')
|
||||
PsiElement(Py:IDENTIFIER)('sleep')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('5')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -506,6 +506,11 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest(LanguageLevel.PYTHON35);
|
||||
}
|
||||
|
||||
// PY-19036
|
||||
public void testAwaitInNonAsyncNestedFunction() {
|
||||
doTest(LanguageLevel.PYTHON35);
|
||||
}
|
||||
|
||||
public void testUnpackingExpressions() {
|
||||
doTest(LanguageLevel.PYTHON35);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user