mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 05:21:29 +07:00
PY-64304 EA-247016 Don't report illegal "await" expressions used as assignment targets during parsing
Instead, parse them as usual and later report in the dedicated AssignTargetAnnotator and TypeAnnotationTargetAnnotator. This way, a PsiError element appearing in the PSI tree of a type declaration statement doesn't cause PyAstTypeDeclarationStatement.getTarget nullability contract violation. GitOrigin-RevId: a3e90088cfac7938c398d4d293a72dbd127a2cd0
This commit is contained in:
committed by
intellij-monorepo-bot
parent
37e44bd3ec
commit
b9d7fee816
@@ -64,7 +64,6 @@ tuple.expression.expected=Tuple expression expected
|
||||
value.expression.expected=Value expression expected
|
||||
unexpected.expression.part=Unexpected expression part
|
||||
unexpected.f.string.token=Unexpected f-string token
|
||||
can.t.assign.to.await.expression=Cannot assign to await expression
|
||||
for.expected='for' expected
|
||||
rarrow.expected='->' expected
|
||||
unexpected.tokens=Unexpected tokens
|
||||
|
||||
@@ -1189,12 +1189,7 @@ public class ExpressionParsing extends Parsing {
|
||||
expr.done(PyElementTypes.PREFIX_EXPRESSION);
|
||||
}
|
||||
else {
|
||||
if (isTargetExpression) {
|
||||
expr.error(message("can.t.assign.to.await.expression"));
|
||||
}
|
||||
else {
|
||||
expr.done(PyElementTypes.PREFIX_EXPRESSION);
|
||||
}
|
||||
expr.done(PyElementTypes.PREFIX_EXPRESSION);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -95,6 +95,7 @@ ANN.cant.aug.assign.starred.assignment.target.must.be.in.list.or.tuple=Starred a
|
||||
ANN.cant.assign.to.literal=Cannot assign to literal
|
||||
ANN.cant.delete.literal=Cannot delete literal
|
||||
ANN.cant.assign.to.lambda=Cannot assign to lambda
|
||||
ANN.cant.assign.to.await.expr=Cannot assign to await expression
|
||||
|
||||
ANN.break.outside.loop='break' outside loop
|
||||
ANN.continue.outside.loop='continue' outside loop
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -118,7 +118,9 @@ public class AssignTargetAnnotator extends PyAnnotator {
|
||||
|
||||
node.getForComponents().forEach(
|
||||
it -> {
|
||||
checkNotAssignmentExpression(it.getIteratorVariable(), targetMessage);
|
||||
PyExpression iteratorVariable = it.getIteratorVariable();
|
||||
iteratorVariable.accept(new ExprVisitor(Operation.For));
|
||||
checkNotAssignmentExpression(iteratorVariable, targetMessage);
|
||||
checkNoAssignmentExpressionAsChild(it.getIteratedList(), iterableMessage);
|
||||
}
|
||||
);
|
||||
@@ -294,5 +296,12 @@ public class AssignTargetAnnotator extends PyAnnotator {
|
||||
public void visitPyBoolLiteralExpression(@NotNull PyBoolLiteralExpression node) {
|
||||
getHolder().newAnnotation(HighlightSeverity.ERROR, message("ANN.assignment.to.keyword")).range(node).create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyPrefixExpression(@NotNull PyPrefixExpression node) {
|
||||
if (node.getOperator() == PyTokenTypes.AWAIT_KEYWORD && node.getOperand() != null) {
|
||||
getHolder().newAnnotation(HighlightSeverity.ERROR, message("ANN.cant.assign.to.await.expr")).range(node).create();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,3 +12,7 @@ a, *b, c = seq
|
||||
|
||||
() = []
|
||||
[] = []
|
||||
|
||||
async def f():
|
||||
<error descr="Cannot assign to await expression">await foo()</error> = 1
|
||||
<error descr="An illegal target for a variable annotation"><error descr="Cannot assign to await expression">await foo()</error></error>: int = 1
|
||||
|
||||
@@ -5,6 +5,8 @@ f(42).attr: dict
|
||||
|
||||
<error descr="An illegal target for a variable annotation">2 ** 8</error>: int
|
||||
<error descr="An illegal target for a variable annotation">f()</error>: bool
|
||||
async def f():
|
||||
<error descr="An illegal target for a variable annotation">await foo()</error>: int
|
||||
<error descr="A variable annotation cannot be combined with tuple unpacking">x, y, z</error>: Tuple[int, ...]
|
||||
(<error descr="A variable annotation cannot be combined with tuple unpacking">x, y, z</error>): Tuple[int, int, int]
|
||||
<error descr="A variable annotation cannot be combined with tuple unpacking">[x, y, z]</error>: Tuple[Any, Any, Any]
|
||||
|
||||
@@ -35,7 +35,7 @@ PyFile:Await.py
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyAssignmentStatement
|
||||
PsiErrorElement:Cannot assign to await expression
|
||||
PyPrefixExpression
|
||||
PsiElement(Py:AWAIT_KEYWORD)('await')
|
||||
PsiWhiteSpace(' ')
|
||||
PyTargetExpression: x
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
async def f():
|
||||
await foo(42): int
|
||||
@@ -0,0 +1,30 @@
|
||||
PyFile:VariableAnnotationRecoveryAwaitExpressionAsTarget.py
|
||||
PyFunction('f')
|
||||
PsiElement(Py:ASYNC_KEYWORD)('async')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:IDENTIFIER)('f')
|
||||
PyParameterList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyTypeDeclarationStatement
|
||||
PyPrefixExpression
|
||||
PsiElement(Py:AWAIT_KEYWORD)('await')
|
||||
PsiWhiteSpace(' ')
|
||||
PyCallExpression: foo
|
||||
PyTargetExpression: foo
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyArgumentList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PyAnnotation
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: int
|
||||
PsiElement(Py:IDENTIFIER)('int')
|
||||
@@ -72,7 +72,7 @@ public class PythonHighlightingTest extends PyTestCase {
|
||||
}
|
||||
|
||||
public void testAssignmentTargets3K() {
|
||||
doTest(LanguageLevel.PYTHON34, true, false);
|
||||
doTest(LanguageLevel.getLatest(), true, false);
|
||||
}
|
||||
|
||||
public void testBreakOutsideOfLoop() {
|
||||
|
||||
@@ -893,6 +893,11 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest(LanguageLevel.PYTHON36);
|
||||
}
|
||||
|
||||
// PY-64304 EA-247016
|
||||
public void testVariableAnnotationRecoveryAwaitExpressionAsTarget() {
|
||||
doTest(LanguageLevel.PYTHON36);
|
||||
}
|
||||
|
||||
// PY-20770
|
||||
public void testAsyncComprehensions() {
|
||||
doTest(LanguageLevel.PYTHON36);
|
||||
@@ -1322,7 +1327,7 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
public void testTypeKeywordAsIdentifier() {
|
||||
doTest(LanguageLevel.PYTHON312);
|
||||
}
|
||||
|
||||
|
||||
public void doTest() {
|
||||
doTest(LanguageLevel.PYTHON26);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user