mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
PY-32067: Highlight 'await' outside async functions as errors
GitOrigin-RevId: 9862d18848b3a826ba11e9c0e15e56a2c94bcc9e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
324032d5f3
commit
3afa041f1b
@@ -163,6 +163,8 @@ ANN.try.except.can.not.have.except.and.star.except=Try statement cannot contain
|
||||
ANN.exception.group.in.star.except=ExceptionGroup cannot be used in except*
|
||||
ANN.continue.break.or.return.in.star.except='break', 'continue' and 'return' cannot appear in an except* block
|
||||
|
||||
ANN.await.outside.async.function='await' outside async function
|
||||
|
||||
### parsing
|
||||
PARSE.expected.expression=Expression expected
|
||||
PARSE.expected.rbracket=']' expected
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.jetbrains.python.validation;
|
||||
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.psi.PyFunction;
|
||||
import com.jetbrains.python.psi.PyPrefixExpression;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public final class PyAsyncAwaitAnnotator extends PyAnnotator {
|
||||
@Override
|
||||
public void visitPyPrefixExpression(@NotNull PyPrefixExpression node) {
|
||||
super.visitPyPrefixExpression(node);
|
||||
if (node.getOperator() == PyTokenTypes.AWAIT_KEYWORD) {
|
||||
var scopeOwner = ScopeUtil.getScopeOwner(node);
|
||||
if (!(scopeOwner instanceof PyFunction pyFunction && pyFunction.isAsync())) {
|
||||
markError(node.getFirstChild(), PyPsiBundle.message("ANN.await.outside.async.function"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,8 @@ public class PyAnnotatingVisitor implements Annotator {
|
||||
GlobalAnnotator.class,
|
||||
ImportAnnotator.class,
|
||||
PyBuiltinAnnotator.class,
|
||||
UnsupportedFeatures.class
|
||||
UnsupportedFeatures.class,
|
||||
PyAsyncAwaitAnnotator.class
|
||||
};
|
||||
|
||||
private final PyAnnotator[] myAnnotators;
|
||||
|
||||
12
python/testData/highlighting/awaitInAsyncIterator.py
Normal file
12
python/testData/highlighting/awaitInAsyncIterator.py
Normal file
@@ -0,0 +1,12 @@
|
||||
import asyncio
|
||||
|
||||
class AsyncIterator:
|
||||
def __init__(self, data):
|
||||
pass
|
||||
|
||||
def __aiter__(self):
|
||||
<error descr="'await' outside async function">await</error> asyncio.sleep(1)
|
||||
|
||||
def __anext__(self):
|
||||
<error descr="'await' outside async function">await</error> asyncio.sleep(1)
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
def example(y):
|
||||
return [x async for x in <error descr="'await' outside async function">await</error> y]
|
||||
|
||||
async def example_correct(y):
|
||||
return [x async for x in await y]
|
||||
@@ -0,0 +1,14 @@
|
||||
import asyncio
|
||||
|
||||
def useless_decorator(param):
|
||||
def decorator(func):
|
||||
pass
|
||||
return decorator
|
||||
|
||||
@useless_decorator(param=(<error descr="'await' outside async function">await</error> asyncio.sleep(1)))
|
||||
def fun():
|
||||
pass
|
||||
|
||||
@useless_decorator(param=(<error descr="'await' outside async function">await</error> asyncio.sleep(1)))
|
||||
async def fun2():
|
||||
pass
|
||||
@@ -0,0 +1,5 @@
|
||||
import asyncio
|
||||
|
||||
async def async_func():
|
||||
def non_async_local(x=(await asyncio.sleep(10))):
|
||||
pass
|
||||
@@ -0,0 +1,7 @@
|
||||
import asyncio
|
||||
|
||||
def f(a=<error descr="'await' outside async function">await</error> asyncio.sleep(3) if True else 0):
|
||||
return a
|
||||
|
||||
async def f2(a=<error descr="'await' outside async function">await</error> asyncio.sleep(3) if True else 0):
|
||||
return a
|
||||
@@ -0,0 +1,7 @@
|
||||
def example(x):
|
||||
async for i in <error descr="'await' outside async function">await</error> x:
|
||||
yield i
|
||||
|
||||
async def example_correct(x):
|
||||
async for i in await x:
|
||||
yield i
|
||||
7
python/testData/highlighting/awaitInNonAsyncFunction.py
Normal file
7
python/testData/highlighting/awaitInNonAsyncFunction.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import asyncio
|
||||
|
||||
def example():
|
||||
<error descr="'await' outside async function">await</error> asyncio.sleep(1)
|
||||
|
||||
async def example_correct():
|
||||
await asyncio.sleep(1)
|
||||
@@ -0,0 +1,4 @@
|
||||
import asyncio
|
||||
|
||||
def example():
|
||||
await<error descr="End of statement expected"> </error>asyncio.sleep(1)
|
||||
@@ -0,0 +1,11 @@
|
||||
async def my_function():
|
||||
def subfunction(x):
|
||||
<error descr="'await' outside async function">await</error> x
|
||||
|
||||
async def my_function_correct():
|
||||
async def subfunction(x):
|
||||
await x
|
||||
|
||||
def my_non_async_function_correct():
|
||||
async def subfunction(x):
|
||||
await x
|
||||
@@ -0,0 +1,9 @@
|
||||
import asyncio
|
||||
|
||||
async def f():
|
||||
await (await asyncio.sleep(1))
|
||||
|
||||
def f2():
|
||||
<error descr="'await' outside async function">await</error> (<error descr="'await' outside async function">await</error> asyncio.sleep(1))
|
||||
|
||||
<error descr="'await' outside async function">await</error> (<error descr="'await' outside async function">await</error> asyncio.sleep(1))
|
||||
7
python/testData/highlighting/awaitOutsideFunction.py
Normal file
7
python/testData/highlighting/awaitOutsideFunction.py
Normal file
@@ -0,0 +1,7 @@
|
||||
import asyncio
|
||||
|
||||
a = <error descr="'await' outside async function">await</error> asyncio.sleep(1)
|
||||
|
||||
class C:
|
||||
b = <error descr="'await' outside async function">await</error> asyncio.sleep(1)
|
||||
|
||||
@@ -119,6 +119,62 @@ public class Py3HighlightingTest extends PyTestCase {
|
||||
doTestWithLanguageLevel(LanguageLevel.PYTHON39, false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInNonAsyncFunction() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInLoopInNonAsyncFunction() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInComprehensionInNonAsyncFunction() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInNonAsyncInnerFunctionOfAsyncFunction() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInAsyncIterator() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInFunctionDefaultArg() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitOutsideFunction() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInNonAsyncFunctionPy27() {
|
||||
doTestWithLanguageLevel(LanguageLevel.PYTHON27, false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInDefaultArgOfInnerNonAsyncFunction() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInDefaultArgOfFunctionDecorator() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
// PY-32067
|
||||
public void testAwaitInsideAwaitExpression() {
|
||||
doTest(false, false);
|
||||
}
|
||||
|
||||
|
||||
private void doTestWithLanguageLevel(LanguageLevel languageLevel, boolean checkWarnings, boolean checkInfos) {
|
||||
runWithLanguageLevel(languageLevel, () -> doTest(checkWarnings, checkInfos));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user