PY-50642 Suppress PyUnusedImportsInspection, PyUnresolvedReferencesInspection for unreachable code

GitOrigin-RevId: 0ab88155b4b2f22587e4894f318c5df242f21232
This commit is contained in:
Petr
2025-11-29 02:34:46 +00:00
committed by intellij-monorepo-bot
parent 1985036914
commit cf11c2f822
7 changed files with 27 additions and 23 deletions
@@ -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) {
@@ -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<PyImportedNameDefiner>()
private val myImportsInsideGuard = mutableSetOf<PyImportedNameDefiner>()
private val myUsedImports = mutableSetOf<PyImportedNameDefiner>()
private val myUnresolvedImports = mutableSetOf<PyImportedNameDefiner>()
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) {
@@ -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<String> 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)
@@ -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.*
@@ -0,0 +1,4 @@
from typing import TYPE_CHECKING
if not TYPE_CHECKING:
import string
@@ -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
""");
}
@@ -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");
}