diff --git a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java index 4cb1d60d7d16..3a6b55ded90e 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java @@ -21,7 +21,6 @@ import com.intellij.psi.util.QualifiedName; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; -import com.jetbrains.python.PyLanguageFacadeKt; import com.jetbrains.python.codeInsight.imports.AddImportHelper.ImportPriority; import com.jetbrains.python.formatter.PyCodeStyleSettings; import com.jetbrains.python.inspections.PyUnusedImportsInspection; @@ -78,9 +77,7 @@ public final class PyImportOptimizer implements ImportOptimizer { TypeEvalContext context = TypeEvalContext.codeAnalysis(file.getProject(), rfile); PyUnusedImportsInspection inspection = new PyUnusedImportsInspection(); - PyUnusedImportsInspection.Visitor visitor = new PyUnusedImportsInspection.Visitor( - null, inspection, context, PyLanguageFacadeKt.getEffectiveLanguageLevel(file) - ); + PyUnusedImportsInspection.Visitor visitor = new PyUnusedImportsInspection.Visitor(null, inspection, context); file.accept(new PyRecursiveElementVisitor() { @Override public void visitElement(@NotNull PsiElement node) { diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyUnusedImportsInspection.kt b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyUnusedImportsInspection.kt index b2adeafe6fa7..d8ad17331924 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyUnusedImportsInspection.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyUnusedImportsInspection.kt @@ -9,7 +9,6 @@ import com.intellij.lang.annotation.HighlightSeverity import com.intellij.lang.injection.InjectedLanguageManager import com.intellij.openapi.application.ReadAction import com.intellij.openapi.util.Key -import com.intellij.openapi.util.Version import com.intellij.psi.* import com.intellij.psi.util.QualifiedName import com.intellij.psi.util.isAncestor @@ -18,15 +17,15 @@ import com.jetbrains.python.PyPsiBundle import com.jetbrains.python.PythonRuntimeService import com.jetbrains.python.codeInsight.PyCodeInsightSettings import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache +import com.jetbrains.python.codeInsight.controlflow.Reachability import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction +import com.jetbrains.python.codeInsight.controlflow.getReachabilityForInspection import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil import com.jetbrains.python.codeInsight.imports.OptimizeImportsQuickFix -import com.jetbrains.python.getEffectiveLanguageLevel import com.jetbrains.python.inspections.PyInspectionVisitor.getContext import com.jetbrains.python.psi.* import com.jetbrains.python.psi.impl.PyBuiltinCache import com.jetbrains.python.psi.impl.PyPsiUtils -import com.jetbrains.python.psi.impl.stubs.evaluateVersionsForElement import com.jetbrains.python.psi.resolve.ImportedResolveResult import com.jetbrains.python.psi.resolve.PyResolveContext import com.jetbrains.python.psi.resolve.QualifiedNameFinder @@ -38,8 +37,7 @@ class PyUnusedImportsInspection : PyInspection() { override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { val visitor = Visitor(holder = holder, myInspection = this, - typeEvalContext = getContext(session), - languageLevel = getEffectiveLanguageLevel(session.file)) + typeEvalContext = getContext(session)) session.putUserData(KEY, visitor) return visitor } @@ -59,15 +57,12 @@ class PyUnusedImportsInspection : PyInspection() { holder: ProblemsHolder?, private val myInspection: PyInspection, typeEvalContext: TypeEvalContext, - languageLevel: LanguageLevel, - ) : - PyInspectionVisitor(holder, typeEvalContext) { + ) : PyInspectionVisitor(holder, typeEvalContext) { private val myAllImports = mutableSetOf() private val myImportsInsideGuard = mutableSetOf() private val myUsedImports = mutableSetOf() private val myUnresolvedImports = mutableSetOf() - private val myVersion: Version = Version(languageLevel.majorVersion, languageLevel.minorVersion, 0) override fun visitPyImportElement(node: PyImportElement) { super.visitPyImportElement(node) @@ -136,7 +131,8 @@ class PyUnusedImportsInspection : PyInspection() { unresolved = (target == null) } if (unresolved) { - val ignoreUnresolved = ignoreUnresolved(node, reference) || !evaluateVersionsForElement(node).contains(myVersion) + val ignoreUnresolved = ignoreUnresolved(node, reference) || + node.getReachabilityForInspection(myTypeEvalContext) != Reachability.REACHABLE if (!ignoreUnresolved) { val severity = if (reference is PsiReferenceEx) reference.getUnresolvedHighlightSeverity(myTypeEvalContext) @@ -250,7 +246,7 @@ class PyUnusedImportsInspection : PyInspection() { if (PyInspectionExtension.EP_NAME.extensionList.any { it.ignoreUnused(element, myTypeEvalContext) }) { continue } - if (!evaluateVersionsForElement(element).contains(myVersion)) { + if (element.getReachabilityForInspection(myTypeEvalContext) != Reachability.REACHABLE) { continue } if (element.getTextLength() > 0) { diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesVisitor.java b/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesVisitor.java index f0b72f8b7dc4..7b923f4b8c22 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesVisitor.java +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesVisitor.java @@ -42,7 +42,8 @@ import com.jetbrains.python.psi.impl.references.PyFromImportNameReference; import com.jetbrains.python.psi.impl.references.PyImportReference; import com.jetbrains.python.psi.impl.references.PyOperatorReference; import com.jetbrains.python.psi.impl.references.hasattr.PyHasAttrHelper; -import com.jetbrains.python.psi.resolve.*; +import com.jetbrains.python.psi.resolve.PyResolveContext; +import com.jetbrains.python.psi.resolve.QualifiedNameFinder; import com.jetbrains.python.psi.types.*; import one.util.streamex.StreamEx; import org.jetbrains.annotations.NonNls; @@ -54,7 +55,6 @@ import java.util.*; import static com.jetbrains.python.PyNames.END_WILDCARD; import static com.jetbrains.python.psi.PyUtil.as; -import static com.jetbrains.python.psi.impl.stubs.PyVersionSpecificStubBaseKt.evaluateVersionsForElement; public abstract class PyUnresolvedReferencesVisitor extends PyInspectionVisitor { private final ImmutableSet myIgnoredIdentifiers; @@ -139,7 +139,8 @@ public abstract class PyUnresolvedReferencesVisitor extends PyInspectionVisitor unresolved = (target == null); } if (unresolved) { - boolean ignoreUnresolved = ignoreUnresolved(node, reference) || !evaluateVersionsForElement(node).contains(myVersion); + boolean ignoreUnresolved = ignoreUnresolved(node, reference) || + PyDataFlowKt.getReachabilityForInspection(node, myTypeEvalContext) != Reachability.REACHABLE; if (!ignoreUnresolved) { HighlightSeverity severity = reference instanceof PsiReferenceEx ? ((PsiReferenceEx)reference).getUnresolvedHighlightSeverity(myTypeEvalContext) diff --git a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/stubs/PyVersionSpecificStubBase.kt b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/stubs/PyVersionSpecificStubBase.kt index 8057296b3501..1e88039ff2c3 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/psi/impl/stubs/PyVersionSpecificStubBase.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/psi/impl/stubs/PyVersionSpecificStubBase.kt @@ -1,10 +1,6 @@ package com.jetbrains.python.psi.impl.stubs -import com.google.common.collect.BoundType -import com.google.common.collect.ImmutableRangeSet -import com.google.common.collect.Range -import com.google.common.collect.RangeSet -import com.google.common.collect.TreeRangeSet +import com.google.common.collect.* import com.intellij.openapi.util.Version import com.intellij.psi.PsiElement import com.intellij.psi.stubs.* diff --git a/python/testData/inspections/unusedImport/suppressedForUnreachableCode/suppressedForUnreachableCode.py b/python/testData/inspections/unusedImport/suppressedForUnreachableCode/suppressedForUnreachableCode.py new file mode 100644 index 000000000000..69b620c3962a --- /dev/null +++ b/python/testData/inspections/unusedImport/suppressedForUnreachableCode/suppressedForUnreachableCode.py @@ -0,0 +1,4 @@ +from typing import TYPE_CHECKING + +if not TYPE_CHECKING: + import string \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java index 51aff787b3b4..d99f71bd3df2 100644 --- a/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/Py3UnresolvedReferencesInspectionTest.java @@ -500,8 +500,14 @@ public class Py3UnresolvedReferencesInspectionTest extends PyInspectionTestCase if not typing.TYPE_CHECKING: x: str = 'ab' + class A: + if not typing.TYPE_CHECKING: + foo: int = -1 + ... + if not typing.TYPE_CHECKING: _ = x + _ = A.foo """); } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyUnusedImportTest.java b/python/testSrc/com/jetbrains/python/inspections/PyUnusedImportTest.java index 954d30322139..0452e7b77ace 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyUnusedImportTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyUnusedImportTest.java @@ -98,6 +98,10 @@ public class PyUnusedImportTest extends PyTestCase { runWithLanguageLevel(LanguageLevel.PYTHON34, this::doTest); } + public void testSuppressedForUnreachableCode() { + doTest(); + } + private void doTest() { doTest(getTestName(true) + ".py"); }