From 210fd9eb451bb2125d7b991311c7af9ea60fefc9 Mon Sep 17 00:00:00 2001 From: Petr Golubev Date: Thu, 3 Dec 2020 21:25:19 +0300 Subject: [PATCH] LAB-31: extracted optimize imports quick fix GitOrigin-RevId: 0011495a43d4afe392c907fad710390a66953bef --- .../com/intellij/lang/ImportOptimizer.java | 0 .../messages/PyBundle.properties | 2 - .../resources/messages/PyPsiBundle.properties | 1 + .../imports/OptimizeImportsQuickFix.java | 4 +- .../imports/PyImportOptimizer.java | 8 +- .../PyUnresolvedReferencesInspectionBase.java | 49 ++++++++ .../PyUnresolvedReferencesVisitor.java | 52 ++++++++- ...implePyUnresolvedReferencesInspection.java | 24 +--- python/src/META-INF/python-core-common.xml | 1 + ...edReferenceDefaultInspectionExtension.java | 31 +++++ .../PyUnresolvedReferencesInspection.java | 110 ++---------------- 11 files changed, 155 insertions(+), 127 deletions(-) rename platform/{lang-api => analysis-api}/src/com/intellij/lang/ImportOptimizer.java (100%) rename python/{ => python-psi-impl}/src/com/jetbrains/python/codeInsight/imports/OptimizeImportsQuickFix.java (95%) rename python/{ => python-psi-impl}/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java (97%) create mode 100644 python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspectionBase.java create mode 100644 python/src/com/jetbrains/python/inspections/PyUnresolvedReferenceDefaultInspectionExtension.java diff --git a/platform/lang-api/src/com/intellij/lang/ImportOptimizer.java b/platform/analysis-api/src/com/intellij/lang/ImportOptimizer.java similarity index 100% rename from platform/lang-api/src/com/intellij/lang/ImportOptimizer.java rename to platform/analysis-api/src/com/intellij/lang/ImportOptimizer.java diff --git a/python/pluginResources/messages/PyBundle.properties b/python/pluginResources/messages/PyBundle.properties index fd4a380c2729..e3145e35f10b 100644 --- a/python/pluginResources/messages/PyBundle.properties +++ b/python/pluginResources/messages/PyBundle.properties @@ -1,6 +1,4 @@ ### Quick fixes ### -QFIX.optimize.imports=Optimize imports - QFIX.add.import.add.import=Add "''{0}''" #PyImplementMethodsQuickFix diff --git a/python/python-psi-impl/resources/messages/PyPsiBundle.properties b/python/python-psi-impl/resources/messages/PyPsiBundle.properties index fd8f58cf73a7..05f38e1d2a13 100644 --- a/python/python-psi-impl/resources/messages/PyPsiBundle.properties +++ b/python/python-psi-impl/resources/messages/PyPsiBundle.properties @@ -329,6 +329,7 @@ QFIX.create.class=Create class QFIX.create.class.0=Create class ''{0}'' QFIX.create.class.in.module=Create class ''{0}'' in module {1} +QFIX.optimize.imports=Optimize imports QFIX.unresolved.reference=Replace ''{0}'' with ''{1}.{0}'' QFIX.NAME.unresolved.reference.add.param=Create parameter for reference diff --git a/python/src/com/jetbrains/python/codeInsight/imports/OptimizeImportsQuickFix.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/OptimizeImportsQuickFix.java similarity index 95% rename from python/src/com/jetbrains/python/codeInsight/imports/OptimizeImportsQuickFix.java rename to python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/OptimizeImportsQuickFix.java index 9b01983f963c..0504de200050 100644 --- a/python/src/com/jetbrains/python/codeInsight/imports/OptimizeImportsQuickFix.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/OptimizeImportsQuickFix.java @@ -12,7 +12,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.IncorrectOperationException; -import com.jetbrains.python.PyBundle; +import com.jetbrains.python.PyPsiBundle; import com.jetbrains.python.psi.PyFile; import org.jetbrains.annotations.NotNull; @@ -30,7 +30,7 @@ public class OptimizeImportsQuickFix implements LocalQuickFix, IntentionAction, @Override @NotNull public String getFamilyName() { - return PyBundle.message("QFIX.optimize.imports"); + return PyPsiBundle.message("QFIX.optimize.imports"); } @Override diff --git a/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java similarity index 97% rename from python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java rename to python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java index 2a4abe184766..f9380f07771a 100644 --- a/python/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java +++ b/python/python-psi-impl/src/com/jetbrains/python/codeInsight/imports/PyImportOptimizer.java @@ -21,8 +21,8 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.jetbrains.python.codeInsight.imports.AddImportHelper.ImportPriority; import com.jetbrains.python.formatter.PyCodeStyleSettings; -import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesInspection; import com.jetbrains.python.inspections.unresolvedReference.PyUnresolvedReferencesVisitor; +import com.jetbrains.python.inspections.unresolvedReference.SimplePyUnresolvedReferencesInspection; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyPsiUtils; import one.util.streamex.StreamEx; @@ -56,10 +56,8 @@ public class PyImportOptimizer implements ImportOptimizer { @NotNull public Runnable processFile(@NotNull final PsiFile file) { final LocalInspectionToolSession session = new LocalInspectionToolSession(file, 0, file.getTextLength()); - final PyUnresolvedReferencesInspection.Visitor visitor = new PyUnresolvedReferencesInspection.Visitor(null, - session, - Collections.emptyList()); - session.putUserData(PyUnresolvedReferencesVisitor.INSPECTION, new PyUnresolvedReferencesInspection()); + final PyUnresolvedReferencesVisitor visitor = new SimplePyUnresolvedReferencesInspection.Visitor(null, session); + session.putUserData(PyUnresolvedReferencesVisitor.INSPECTION, new SimplePyUnresolvedReferencesInspection()); file.accept(new PyRecursiveElementVisitor() { @Override public void visitElement(@NotNull PsiElement node) { diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspectionBase.java b/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspectionBase.java new file mode 100644 index 000000000000..94d3e6d803d1 --- /dev/null +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspectionBase.java @@ -0,0 +1,49 @@ +package com.jetbrains.python.inspections.unresolvedReference; + +import com.intellij.codeInspection.LocalInspectionToolSession; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.openapi.util.Key; +import com.intellij.psi.PsiElementVisitor; +import com.jetbrains.python.codeInsight.PyCodeInsightSettings; +import com.jetbrains.python.inspections.PyInspection; +import org.intellij.lang.annotations.Pattern; +import org.jetbrains.annotations.NotNull; + +public abstract class PyUnresolvedReferencesInspectionBase extends PyInspection { + private static final Key KEY = Key.create("PyUnresolvedReferencesInspection.Visitor"); + + @Pattern(VALID_ID_PATTERN) + @Override + public @NotNull String getID() { + return "PyUnresolvedReferences"; + } + + @NotNull + @Override + public final PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, + final boolean isOnTheFly, + @NotNull final LocalInspectionToolSession session) { + final PyUnresolvedReferencesVisitor visitor = createVisitor(holder, session); + // buildVisitor() will be called on injected files in the same session - don't overwrite if we already have one + final PyUnresolvedReferencesVisitor existingVisitor = session.getUserData(KEY); + if (existingVisitor == null) { + session.putUserData(KEY, visitor); + } + session.putUserData(PyUnresolvedReferencesVisitor.INSPECTION, this); + return visitor; + } + + @Override + public final void inspectionFinished(@NotNull LocalInspectionToolSession session, @NotNull ProblemsHolder holder) { + final PyUnresolvedReferencesVisitor visitor = session.getUserData(KEY); + assert visitor != null; + if (PyCodeInsightSettings.getInstance().HIGHLIGHT_UNUSED_IMPORTS) { + visitor.highlightUnusedImports(); + } + visitor.highlightImportsInsideGuards(); + session.putUserData(KEY, null); + } + + protected abstract PyUnresolvedReferencesVisitor createVisitor(@NotNull ProblemsHolder holder, + @NotNull LocalInspectionToolSession session); +} 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 9f8c68c64b07..b7a747c5f88a 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 @@ -3,6 +3,7 @@ package com.jetbrains.python.inspections.unresolvedReference; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Sets; import com.intellij.codeInsight.controlflow.ControlFlow; import com.intellij.codeInsight.controlflow.ControlFlowUtil; import com.intellij.codeInsight.controlflow.Instruction; @@ -30,6 +31,7 @@ import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache; import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; +import com.jetbrains.python.codeInsight.imports.OptimizeImportsQuickFix; import com.jetbrains.python.codeInsight.typing.PyTypingTypeProvider; import com.jetbrains.python.documentation.docstrings.DocStringParameterReference; import com.jetbrains.python.documentation.docstrings.DocStringTypeReference; @@ -65,6 +67,7 @@ public abstract class PyUnresolvedReferencesVisitor extends PyInspectionVisitor private final Set myImportsInsideGuard = Collections.synchronizedSet(new HashSet<>()); private final Set myUsedImports = Collections.synchronizedSet(new HashSet<>()); private final ImmutableSet myIgnoredIdentifiers; + private volatile Boolean myIsEnabled = null; public static final Key INSPECTION = Key.create("PyUnresolvedReferencesVisitor.inspection"); @@ -511,7 +514,54 @@ public abstract class PyUnresolvedReferencesVisitor extends PyInspectionVisitor return false; } - abstract boolean isEnabled(@NotNull PsiElement anchor); + private boolean isEnabled(@NotNull PsiElement anchor) { + if (myIsEnabled == null) { + Boolean overridden = overriddenUnresolvedReferenceInspection(anchor.getContainingFile()); + myIsEnabled = Objects.requireNonNullElse(overridden, true); + } + return myIsEnabled; + } + + private static @Nullable Boolean overriddenUnresolvedReferenceInspection(@NotNull PsiFile file) { + return PyInspectionExtension.EP_NAME.getExtensionList().stream() + .map(e -> e.overrideUnresolvedReferenceInspection(file)) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + + public void highlightUnusedImports() { + final List extensions = PyInspectionExtension.EP_NAME.getExtensionList(); + final List unused = collectUnusedImportElements(); + for (PsiElement element : unused) { + if (extensions.stream().anyMatch(extension -> extension.ignoreUnused(element, myTypeEvalContext))) { + continue; + } + if (element.getTextLength() > 0) { + OptimizeImportsQuickFix fix = new OptimizeImportsQuickFix(); + registerProblem(element, PyPsiBundle.message("INSP.unused.import.statement"), ProblemHighlightType.LIKE_UNUSED_SYMBOL, null, fix); + } + } + } + + public void highlightImportsInsideGuards() { + HashSet usedImportsInsideImportGuards = Sets.newHashSet(getImportsInsideGuard()); + usedImportsInsideImportGuards.retainAll(getUsedImports()); + + for (PyImportedNameDefiner definer : usedImportsInsideImportGuards) { + + PyImportElement importElement = PyUtil.as(definer, PyImportElement.class); + if (importElement == null) { + continue; + } + final PyTargetExpression asElement = importElement.getAsNameElement(); + final PyElement toHighlight = asElement != null ? asElement : importElement.getImportReferenceExpression(); + registerProblem(toHighlight, + PyPsiBundle.message("INSP.try.except.import.error", + importElement.getVisibleName()), + ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); + } + } public void optimizeImports() { final List elementsToDelete = collectUnusedImportElements(); diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/SimplePyUnresolvedReferencesInspection.java b/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/SimplePyUnresolvedReferencesInspection.java index f47e1a9d67bd..736a0a4bd6c2 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/SimplePyUnresolvedReferencesInspection.java +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/unresolvedReference/SimplePyUnresolvedReferencesInspection.java @@ -4,12 +4,10 @@ import com.intellij.codeInspection.LocalInspectionToolSession; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiReference; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.codeInsight.imports.AutoImportQuickFix; import com.jetbrains.python.codeInsight.imports.PythonImportUtils; -import com.jetbrains.python.inspections.PyInspection; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.psi.PyFunction; import org.jetbrains.annotations.NotNull; @@ -19,34 +17,24 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class SimplePyUnresolvedReferencesInspection extends PyInspection { - @NotNull +public class SimplePyUnresolvedReferencesInspection extends PyUnresolvedReferencesInspectionBase { @Override - public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, - boolean isOnTheFly, - @NotNull LocalInspectionToolSession session) { - Visitor visitor = new Visitor(holder, session); - session.putUserData(PyUnresolvedReferencesVisitor.INSPECTION, this); - return visitor; + protected PyUnresolvedReferencesVisitor createVisitor(@NotNull ProblemsHolder holder, + @NotNull LocalInspectionToolSession session) { + return new Visitor(holder, session); } @Nullable @Override public String getStaticDescription() { - return ""; + return null; } public static class Visitor extends PyUnresolvedReferencesVisitor { - public Visitor(@Nullable ProblemsHolder holder, - @NotNull LocalInspectionToolSession session) { + public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session) { super(holder, session, Collections.emptyList()); } - @Override - boolean isEnabled(@NotNull PsiElement anchor) { - return true; - } - @Override Iterable getAutoImportFixes(PyElement node, PsiReference reference, PsiElement element) { List fixes = new ArrayList<>(); diff --git a/python/src/META-INF/python-core-common.xml b/python/src/META-INF/python-core-common.xml index e18ea396623b..62adb87d6a25 100644 --- a/python/src/META-INF/python-core-common.xml +++ b/python/src/META-INF/python-core-common.xml @@ -552,6 +552,7 @@ + diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferenceDefaultInspectionExtension.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferenceDefaultInspectionExtension.java new file mode 100644 index 000000000000..0b21a12d7a08 --- /dev/null +++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferenceDefaultInspectionExtension.java @@ -0,0 +1,31 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.jetbrains.python.inspections; + +import com.intellij.psi.PsiFile; +import com.intellij.util.PlatformUtils; +import com.jetbrains.python.PythonRuntimeService; +import com.jetbrains.python.sdk.PythonSdkUtil; +import com.jetbrains.python.sdk.skeletons.PySkeletonRefresher; +import org.jetbrains.annotations.NotNull; + +/** + * The default behavior of enabling "unresolved reference" inspection that can be overridden. + * Must be registered last. + * Keeping it here instead of the inspection class itself is necessary for decoupling intellij.python.psi.impl. + */ +public class PyUnresolvedReferenceDefaultInspectionExtension extends PyInspectionExtension { + @Override + public Boolean overrideUnresolvedReferenceInspection(@NotNull PsiFile file) { + boolean result; + if (PySkeletonRefresher.isGeneratingSkeletons()) { + result = false; + } + else if (PlatformUtils.isPyCharm()) { + result = PythonSdkUtil.findPythonSdk(file) != null || PythonRuntimeService.getInstance().isInScratchFile(file); + } + else { + result = true; + } + return result; + } +} diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java index dce04c79f179..b896177a5d52 100644 --- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java @@ -1,8 +1,10 @@ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.jetbrains.python.inspections.unresolvedReference; -import com.google.common.collect.Sets; -import com.intellij.codeInspection.*; +import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.LocalInspectionToolSession; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemsHolder; import com.intellij.codeInspection.ui.ListEditForm; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.module.Module; @@ -11,24 +13,18 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Key; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.QualifiedName; -import com.intellij.util.PlatformUtils; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyPsiBundle; import com.jetbrains.python.PyPsiPackageUtil; -import com.jetbrains.python.PythonRuntimeService; import com.jetbrains.python.codeInsight.PyCodeInsightSettings; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.codeInsight.imports.AutoImportHintAction; import com.jetbrains.python.codeInsight.imports.AutoImportQuickFix; -import com.jetbrains.python.codeInsight.imports.OptimizeImportsQuickFix; import com.jetbrains.python.codeInsight.imports.PythonImportUtils; -import com.jetbrains.python.inspections.PyInspection; -import com.jetbrains.python.inspections.PyInspectionExtension; import com.jetbrains.python.inspections.PyPackageRequirementsInspection; import com.jetbrains.python.inspections.PyUnresolvedReferenceQuickFixProvider; import com.jetbrains.python.inspections.quickfix.AddIgnoredIdentifierQuickFix; @@ -40,20 +36,20 @@ import com.jetbrains.python.packaging.PyRequirementsKt; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.references.PyImportReference; import com.jetbrains.python.sdk.PythonSdkUtil; -import com.jetbrains.python.sdk.skeletons.PySkeletonRefresher; import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * Marks references that fail to resolve. Also tracks unused imports and provides "optimize imports" support. * User: dcheryasov */ -public class PyUnresolvedReferencesInspection extends PyInspection { - private static final Key KEY = Key.create("PyUnresolvedReferencesInspection.Visitor"); +public class PyUnresolvedReferencesInspection extends PyUnresolvedReferencesInspectionBase { public static final Key SHORT_NAME_KEY = Key.create(PyUnresolvedReferencesInspection.class.getSimpleName()); @@ -64,30 +60,10 @@ public class PyUnresolvedReferencesInspection extends PyInspection { return (PyUnresolvedReferencesInspection)inspectionProfile.getUnwrappedTool(SHORT_NAME_KEY.toString(), element); } + @Override @NotNull - @Override - public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, - final boolean isOnTheFly, - @NotNull final LocalInspectionToolSession session) { - final Visitor visitor = new Visitor(holder, session, ignoredIdentifiers); - // buildVisitor() will be called on injected files in the same session - don't overwrite if we already have one - final Visitor existingVisitor = session.getUserData(KEY); - if (existingVisitor == null) { - session.putUserData(KEY, visitor); - } - session.putUserData(PyUnresolvedReferencesVisitor.INSPECTION, this); - return visitor; - } - - @Override - public void inspectionFinished(@NotNull LocalInspectionToolSession session, @NotNull ProblemsHolder holder) { - final Visitor visitor = session.getUserData(KEY); - assert visitor != null; - if (PyCodeInsightSettings.getInstance().HIGHLIGHT_UNUSED_IMPORTS) { - visitor.highlightUnusedImports(); - } - visitor.highlightImportsInsideGuards(); - session.putUserData(KEY, null); + protected PyUnresolvedReferencesVisitor createVisitor(@NotNull ProblemsHolder holder, @NotNull LocalInspectionToolSession session) { + return new Visitor(holder, session, ignoredIdentifiers); } @Override @@ -98,74 +74,10 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } public static class Visitor extends PyUnresolvedReferencesVisitor { - private volatile Boolean myIsEnabled = null; - public Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session, List ignoredIdentifiers) { super(holder, session, ignoredIdentifiers); } - @Override - public boolean isEnabled(@NotNull PsiElement anchor) { - if (myIsEnabled == null) { - final boolean isPyCharm = PlatformUtils.isPyCharm(); - Boolean overridden = overriddenUnresolvedReferenceInspection(anchor.getContainingFile()); - if (overridden != null) { - myIsEnabled = overridden; - } - else if (PySkeletonRefresher.isGeneratingSkeletons()) { - myIsEnabled = false; - } - else if (isPyCharm) { - myIsEnabled = PythonSdkUtil.findPythonSdk(anchor) != null || PythonRuntimeService.getInstance().isInScratchFile(anchor); - } - else { - myIsEnabled = true; - } - } - return myIsEnabled; - } - - private static @Nullable Boolean overriddenUnresolvedReferenceInspection(@NotNull PsiFile file) { - return PyInspectionExtension.EP_NAME.getExtensionList().stream() - .map(e -> e.overrideUnresolvedReferenceInspection(file)) - .filter(Objects::nonNull) - .findFirst() - .orElse(null); - } - - public void highlightUnusedImports() { - final List extensions = PyInspectionExtension.EP_NAME.getExtensionList(); - final List unused = collectUnusedImportElements(); - for (PsiElement element : unused) { - if (extensions.stream().anyMatch(extension -> extension.ignoreUnused(element, myTypeEvalContext))) { - continue; - } - if (element.getTextLength() > 0) { - OptimizeImportsQuickFix fix = new OptimizeImportsQuickFix(); - registerProblem(element, PyPsiBundle.message("INSP.unused.import.statement"), ProblemHighlightType.LIKE_UNUSED_SYMBOL, null, fix); - } - } - } - - public void highlightImportsInsideGuards() { - HashSet usedImportsInsideImportGuards = Sets.newHashSet(getImportsInsideGuard()); - usedImportsInsideImportGuards.retainAll(getUsedImports()); - - for (PyImportedNameDefiner definer : usedImportsInsideImportGuards) { - - PyImportElement importElement = PyUtil.as(definer, PyImportElement.class); - if (importElement == null) { - continue; - } - final PyTargetExpression asElement = importElement.getAsNameElement(); - final PyElement toHighlight = asElement != null ? asElement : importElement.getImportReferenceExpression(); - registerProblem(toHighlight, - PyPsiBundle.message("INSP.try.except.import.error", - importElement.getVisibleName()), - ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); - } - } - @Override public Iterable getInstallPackageQuickFixes(@NotNull PyElement node, @NotNull PsiReference reference,