diff --git a/python/src/com/jetbrains/python/actions/AddIgnoredIdentifierFix.java b/python/src/com/jetbrains/python/actions/AddIgnoredIdentifierFix.java new file mode 100644 index 000000000000..1eb3b7bfb2bb --- /dev/null +++ b/python/src/com/jetbrains/python/actions/AddIgnoredIdentifierFix.java @@ -0,0 +1,43 @@ +package com.jetbrains.python.actions; + +import com.intellij.codeInspection.InspectionProfile; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.openapi.project.Project; +import com.intellij.profile.codeInspection.InspectionProfileManager; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; +import com.jetbrains.python.inspections.PyUnresolvedReferencesInspection; +import org.jetbrains.annotations.NotNull; + +/** + * @author yole + */ +public class AddIgnoredIdentifierFix implements LocalQuickFix { + private final String myIdentifier; + + public AddIgnoredIdentifierFix(String identifier) { + myIdentifier = identifier; + } + + @NotNull + @Override + public String getName() { + return "Ignore unresolved identifier " + myIdentifier; + } + + @NotNull + @Override + public String getFamilyName() { + return "Ignore unresolved identifier"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PyUnresolvedReferencesInspection instance = PyUnresolvedReferencesInspection.getInstance(descriptor.getPsiElement()); + if (!instance.ignoredIdentifiers.contains(myIdentifier)) { + instance.ignoredIdentifiers.add(myIdentifier); + final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); + InspectionProfileManager.getInstance().fireProfileChanged(profile); + } + } +} diff --git a/python/src/com/jetbrains/python/codeInsight/PyImportOptimizer.java b/python/src/com/jetbrains/python/codeInsight/PyImportOptimizer.java index 4dd759bbc5bd..f4602689f57a 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyImportOptimizer.java +++ b/python/src/com/jetbrains/python/codeInsight/PyImportOptimizer.java @@ -8,6 +8,8 @@ import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.psi.PyRecursiveElementVisitor; import org.jetbrains.annotations.NotNull; +import java.util.Collections; + /** * @author yole */ @@ -19,7 +21,7 @@ public class PyImportOptimizer implements ImportOptimizer { @NotNull public Runnable processFile(PsiFile file) { final LocalInspectionToolSession session = new LocalInspectionToolSession(file, 0, file.getTextLength()); - final PyUnresolvedReferencesInspection.Visitor visitor = new PyUnresolvedReferencesInspection.Visitor(null, session); + final PyUnresolvedReferencesInspection.Visitor visitor = new PyUnresolvedReferencesInspection.Visitor(null, session, Collections.emptyList()); file.accept(new PyRecursiveElementVisitor() { @Override public void visitPyElement(PyElement node) { diff --git a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java index 864cc6fc9f22..6cafc0aa345d 100644 --- a/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyUnresolvedReferencesInspection.java @@ -1,9 +1,14 @@ package com.jetbrains.python.inspections; +import com.google.common.collect.ImmutableSet; import com.intellij.codeInspection.*; +import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; +import com.intellij.codeInspection.ui.ListEditForm; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.util.JDOMExternalizableStringList; import com.intellij.openapi.util.Key; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.Consumer; @@ -23,6 +28,7 @@ import com.jetbrains.python.validation.PythonReferenceImporter; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; +import javax.swing.*; import java.util.*; /** @@ -33,6 +39,15 @@ import java.util.*; public class PyUnresolvedReferencesInspection extends PyInspection { private static Key KEY = Key.create("PyUnresolvedReferencesInspection.Visitor"); + public JDOMExternalizableStringList ignoredIdentifiers = new JDOMExternalizableStringList(); + + public static PyUnresolvedReferencesInspection getInstance(PsiElement element) { + final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(element.getProject()).getInspectionProfile(); + final LocalInspectionToolWrapper profileEntry = + (LocalInspectionToolWrapper)inspectionProfile.getInspectionTool(PyUnresolvedReferencesInspection.class.getSimpleName(), element); + return (PyUnresolvedReferencesInspection)profileEntry.getTool(); + } + @Nls @NotNull public String getDisplayName() { @@ -42,7 +57,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { @NotNull @Override public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly, final LocalInspectionToolSession session) { - final Visitor visitor = new Visitor(holder, session); + final Visitor visitor = new Visitor(holder, session, ignoredIdentifiers); session.putUserData(KEY, visitor); return visitor; } @@ -57,12 +72,20 @@ public class PyUnresolvedReferencesInspection extends PyInspection { session.putUserData(KEY, null); } + @Override + public JComponent createOptionsPanel() { + ListEditForm form = new ListEditForm("Ignore identifiers", ignoredIdentifiers); + return form.getContentPanel(); + } + public static class Visitor extends PyInspectionVisitor { private Set myUsedImports = Collections.synchronizedSet(new HashSet()); private Set myAllImports = Collections.synchronizedSet(new HashSet()); + private final ImmutableSet myIgnoredIdentifiers; - public Visitor(final ProblemsHolder holder, LocalInspectionToolSession session) { + public Visitor(final ProblemsHolder holder, LocalInspectionToolSession session, List ignoredIdentifiers) { super(holder, session); + myIgnoredIdentifiers = ImmutableSet.copyOf(ignoredIdentifiers); } @Override @@ -153,6 +176,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection { if (reference.getElement() instanceof PyReferenceExpression) { PyReferenceExpression refex = (PyReferenceExpression)reference.getElement(); String refname = refex.getReferencedName(); + if (myIgnoredIdentifiers.contains(refname)) { + return; + } if (refex.getQualifier() != null) { final PyClassType object_type = PyBuiltinCache.getInstance(node).getObjectType(); if ((object_type != null) && object_type.getPossibleInstanceMembers().contains(refname)) return; @@ -258,6 +284,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { if (GenerateBinaryStubsFix.isApplicable(reference)) { actions.add(new GenerateBinaryStubsFix(reference)); } + actions.add(new AddIgnoredIdentifierFix(ref_text)); addPluginQuickFixes(reference, actions); PsiElement point = node.getLastChild(); // usually the identifier at the end of qual ref