From 83a321b60902f2c77ea505b86c3768dee6f6495b Mon Sep 17 00:00:00 2001 From: Semyon Proshev Date: Mon, 12 Mar 2018 21:42:43 +0300 Subject: [PATCH] Remove dead code that resolves forward references in annotations --- .../psi/impl/references/PyReferenceImpl.java | 88 ++++++++----------- .../forwardReference/ForwardReference.pyi | 4 + .../jetbrains/python/pyi/PyiResolveTest.java | 4 + 3 files changed, 47 insertions(+), 49 deletions(-) create mode 100644 python/testData/pyi/resolve/forwardReference/ForwardReference.pyi diff --git a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java index 95433c612a13..4688a1742249 100644 --- a/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/references/PyReferenceImpl.java @@ -260,9 +260,9 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference } protected final List getResultsFromProcessor(@NotNull String referencedName, - @NotNull PyResolveProcessor processor, - @Nullable PsiElement realContext, - @Nullable PsiElement resolveRoof) { + @NotNull PyResolveProcessor processor, + @Nullable PsiElement realContext, + @Nullable PsiElement resolveRoof) { boolean unreachableLocalDeclaration = false; boolean resolveInParentScope = false; final ResolveResultList resultList = new ResolveResultList(); @@ -270,57 +270,47 @@ public class PyReferenceImpl implements PsiReferenceEx, PsiPolyVariantReference final TypeEvalContext typeEvalContext = myContext.getTypeEvalContext(); ScopeOwner resolvedOwner = processor.getOwner(); - if (resolvedOwner != null && !processor.getResults().isEmpty()) { - final Collection resolvedElements = processor.getElements(); - final Scope resolvedScope = ControlFlowCache.getScope(resolvedOwner); + final Collection resolvedElements = processor.getElements(); + if (resolvedOwner != null && !resolvedElements.isEmpty() && !ControlFlowCache.getScope(resolvedOwner).isGlobal(referencedName)) { + if (resolvedOwner == referenceOwner) { + final List instructions = getLatestDefinitions(referencedName, resolvedOwner, realContext); + // TODO: Use the results from the processor as a cache for resolving to latest defs + final ResolveResultList latestDefs = resolveToLatestDefs(instructions, realContext, referencedName, typeEvalContext); + if (!latestDefs.isEmpty()) { + if (ContainerUtil.exists(latestDefs, result -> result.getElement() instanceof PyCallable)) { + return StreamEx + .of(resolvedElements) + .nonNull() + .filter(element -> PyiUtil.isOverload(element, typeEvalContext)) + .map(element -> new RatedResolveResult(getRate(element, typeEvalContext), element)) + .prepend(latestDefs) + .toList(); + } - if (!resolvedScope.isGlobal(referencedName)) { - if (resolvedOwner == referenceOwner) { - final List instructions = getLatestDefinitions(referencedName, resolvedOwner, realContext); - // TODO: Use the results from the processor as a cache for resolving to latest defs - final ResolveResultList latestDefs = resolveToLatestDefs(instructions, realContext, referencedName, typeEvalContext); - if (!latestDefs.isEmpty()) { - if (ContainerUtil.exists(latestDefs, result -> result.getElement() instanceof PyCallable)) { - return StreamEx - .of(processor.getResults().keySet()) - .nonNull() - .filter(element -> PyiUtil.isOverload(element, typeEvalContext)) - .map(element -> new RatedResolveResult(getRate(element, typeEvalContext), element)) - .prepend(latestDefs) - .toList(); - } + return latestDefs; + } + else if (resolvedOwner instanceof PyClass || instructions.isEmpty() && allInOwnScopeComprehensions(resolvedElements)) { + resolveInParentScope = true; + } + else { + unreachableLocalDeclaration = true; + } + } + else if (referenceOwner != null) { + if (!allowsForwardOutgoingReferencesInClass(myElement)) { + final PyClass outermostNestedClass = outermostNestedClass(referenceOwner, resolvedOwner); - return latestDefs; - } - else if (resolvedOwner instanceof PyClass || instructions.isEmpty() && allInOwnScopeComprehensions(resolvedElements)) { - resolveInParentScope = true; - } - else if (PyiUtil.isInsideStubAnnotation(myElement)) { - for (PsiElement element : resolvedElements) { - resultList.poke(element, getRate(element, typeEvalContext)); - } - return resultList; - } - else { - unreachableLocalDeclaration = true; + if (outermostNestedClass != null) { + final List instructions = + PyDefUseUtil.getLatestDefs(resolvedOwner, referencedName, outermostNestedClass, false, true); + + return resolveToLatestDefs(instructions, outermostNestedClass, referencedName, typeEvalContext); } } - else if (referenceOwner != null) { - if (!allowsForwardOutgoingReferencesInClass(myElement)) { - final PyClass outermostNestedClass = outermostNestedClass(referenceOwner, resolvedOwner); - if (outermostNestedClass != null) { - final List instructions = - PyDefUseUtil.getLatestDefs(resolvedOwner, referencedName, outermostNestedClass, false, true); - - return resolveToLatestDefs(instructions, outermostNestedClass, referencedName, typeEvalContext); - } - } - - final Scope referenceScope = ControlFlowCache.getScope(referenceOwner); - if (referenceScope.containsDeclaration(referencedName)) { - unreachableLocalDeclaration = true; - } + final Scope referenceScope = ControlFlowCache.getScope(referenceOwner); + if (referenceScope.containsDeclaration(referencedName)) { + unreachableLocalDeclaration = true; } } } diff --git a/python/testData/pyi/resolve/forwardReference/ForwardReference.pyi b/python/testData/pyi/resolve/forwardReference/ForwardReference.pyi new file mode 100644 index 000000000000..e8b7ef704bfb --- /dev/null +++ b/python/testData/pyi/resolve/forwardReference/ForwardReference.pyi @@ -0,0 +1,4 @@ +def f(x: C) -> C: ... + + +class C: ... \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/pyi/PyiResolveTest.java b/python/testSrc/com/jetbrains/python/pyi/PyiResolveTest.java index 5ee72c43ba0c..aac58d77df56 100644 --- a/python/testSrc/com/jetbrains/python/pyi/PyiResolveTest.java +++ b/python/testSrc/com/jetbrains/python/pyi/PyiResolveTest.java @@ -61,4 +61,8 @@ public class PyiResolveTest extends PyMultiFileResolveTestCase { public void testGenericAttribute() { assertResolvesTo(PyTargetExpression.class, "foo"); } + + public void testForwardReference() { + assertResolvesTo(PyClass.class, "C"); + } }