diff --git a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java index 67f7494e5893..fbff5c2d8a00 100644 --- a/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java +++ b/python/src/com/jetbrains/python/codeInsight/controlflow/PyControlFlowBuilder.java @@ -164,6 +164,16 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { myBuilder.checkPending(readWriteInstruction); } + @Override + public void visitPyTypeDeclarationStatement(PyTypeDeclarationStatement node) { + myBuilder.startNode(node); + final PyAnnotation annotation = node.getAnnotation(); + if (annotation != null) { + annotation.accept(this); + } + node.getTarget().accept(this); + } + @Override public void visitPyAssignmentStatement(final PyAssignmentStatement node) { myBuilder.startNode(node); @@ -171,6 +181,10 @@ public class PyControlFlowBuilder extends PyRecursiveElementVisitor { if (value != null) { value.accept(this); } + final PyAnnotation annotation = node.getAnnotation(); + if (annotation != null) { + annotation.accept(this); + } for (PyExpression expression : node.getRawTargets()) { expression.accept(this); } diff --git a/python/testData/codeInsight/controlflow/variableannotations.py b/python/testData/codeInsight/controlflow/variableannotations.py new file mode 100644 index 000000000000..10a123df4506 --- /dev/null +++ b/python/testData/codeInsight/controlflow/variableannotations.py @@ -0,0 +1,2 @@ +x: int +xs: List = [] diff --git a/python/testData/codeInsight/controlflow/variableannotations.txt b/python/testData/codeInsight/controlflow/variableannotations.txt new file mode 100644 index 000000000000..2424a846814b --- /dev/null +++ b/python/testData/codeInsight/controlflow/variableannotations.txt @@ -0,0 +1,8 @@ +0(1) element: null +1(2) element: PyTypeDeclarationStatement +2(3) READ ACCESS: int +3(4) WRITE ACCESS: x +4(5) element: PyAssignmentStatement +5(6) READ ACCESS: List +6(7) WRITE ACCESS: xs +7() element: null \ No newline at end of file diff --git a/python/testData/resolve/LocalVariableAnnotationWithInnerClass.py b/python/testData/resolve/LocalVariableAnnotationWithInnerClass.py new file mode 100644 index 000000000000..3503548cd845 --- /dev/null +++ b/python/testData/resolve/LocalVariableAnnotationWithInnerClass.py @@ -0,0 +1,6 @@ +def f(): + class MyType: + pass + + xs: MyType = None + \ No newline at end of file diff --git a/python/testData/resolve/TopLevelVariableAnnotationFromTyping.py b/python/testData/resolve/TopLevelVariableAnnotationFromTyping.py new file mode 100644 index 000000000000..22ee7be946f7 --- /dev/null +++ b/python/testData/resolve/TopLevelVariableAnnotationFromTyping.py @@ -0,0 +1,4 @@ +from typing import List + +xs: List = [] + \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/Py3ResolveTest.java b/python/testSrc/com/jetbrains/python/Py3ResolveTest.java index 9bfe1c5848d8..3369463514e1 100644 --- a/python/testSrc/com/jetbrains/python/Py3ResolveTest.java +++ b/python/testSrc/com/jetbrains/python/Py3ResolveTest.java @@ -354,4 +354,15 @@ public class Py3ResolveTest extends PyResolveTestCase { public void testDunderClassInDeclarationInsideFunction() { assertUnresolved(); } + + // PY-20864 + public void testTopLevelVariableAnnotationFromTyping() { + myFixture.copyDirectoryToProject("typing", ""); + runWithLanguageLevel(LanguageLevel.PYTHON36, () -> assertResolvesTo(PyClass.class, "List")); + } + + // PY-20864 + public void testLocalVariableAnnotationWithInnerClass() { + runWithLanguageLevel(LanguageLevel.PYTHON36, () -> assertResolvesTo(PyClass.class, "MyType")); + } } diff --git a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java index 203b462c5a44..eae31579f153 100644 --- a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java +++ b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java @@ -239,6 +239,11 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase { doTest(); } + // PY-20744, PY-20864 + public void testVariableAnnotations() { + runWithLanguageLevel(LanguageLevel.PYTHON36, this::doTest); + } + private void doTestFirstStatement() { final String testName = getTestName(false).toLowerCase(); configureByFile(testName + ".py");