mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge decoupled inspections
GitOrigin-RevId: bdd58f7021b0d946ccc1a0b801050eca3856b397
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6b5ad3adc4
commit
3e9f6983a8
@@ -188,8 +188,9 @@
|
||||
<localInspection language="Python" shortName="PyProtocolInspection" suppressId="PyProtocol" bundle="messages.PyPsiBundle" key="INSP.protocol.definition.and.usages" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyProtocolInspection"/>
|
||||
<localInspection language="Python" shortName="PyTypeHintsInspection" suppressId="PyTypeHints" bundle="messages.PyPsiBundle" key="INSP.type.hints" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyTypeHintsInspection"/>
|
||||
<localInspection language="Python" shortName="PyTypedDictInspection" suppressId="PyTypedDict" bundle="messages.PyPsiBundle" key="INSP.typed.dict" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyTypedDictInspection"/>
|
||||
|
||||
|
||||
<localInspection language="Python" shortName="PyChainedComparisonsInspection" suppressId="PyChainedComparisons" bundle="messages.PyPsiBundle" key="INSP.NAME.chained.comparisons" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyChainedComparisonsInspection"/>
|
||||
<localInspection language="Python" shortName="PyPep8NamingInspection" suppressId="PyPep8Naming" bundle="messages.PyPsiBundle" key="INSP.pep8.naming" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyPep8NamingInspection"/>
|
||||
<localInspection language="Python" shortName="PyShadowingBuiltinsInspection" suppressId="PyShadowingBuiltins" bundle="messages.PyPsiBundle" key="INSP.shadowing.builtins" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyShadowingBuiltinsInspection"/>
|
||||
</extensions>
|
||||
|
||||
<extensionPoints>
|
||||
|
||||
@@ -42,7 +42,11 @@ public class PythonUiService {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void runRenameProcessor(Project project, PsiElement element, String newName, boolean searchInComments, boolean searchTextOccurrences) {}
|
||||
public void runRenameProcessor(Project project,
|
||||
PsiElement element,
|
||||
String newName,
|
||||
boolean searchInComments,
|
||||
boolean searchTextOccurrences) {}
|
||||
|
||||
public LocalQuickFix createPyChangeSignatureQuickFixForMismatchingMethods(PyFunction function, PyFunction method) {
|
||||
return null;
|
||||
@@ -66,11 +70,11 @@ public class PythonUiService {
|
||||
|
||||
@NotNull
|
||||
public JComponent createEncodingsOptionsPanel(String[] possibleEncodings,
|
||||
String defaultEncoding,
|
||||
String[] possibleFormats,
|
||||
int formatIndex,
|
||||
Consumer<String> encodingChanged,
|
||||
Consumer<Integer> formatIndexChanged) {
|
||||
String defaultEncoding,
|
||||
String[] possibleFormats,
|
||||
int formatIndex,
|
||||
Consumer<String> encodingChanged,
|
||||
Consumer<Integer> formatIndexChanged) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -90,6 +94,10 @@ public class PythonUiService {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JComponent onePixelSplitter(boolean b, JComponent first, JComponent second) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PythonUiService getInstance() {
|
||||
return ServiceManager.getService(PythonUiService.class);
|
||||
}
|
||||
@@ -106,4 +114,7 @@ public class PythonUiService {
|
||||
Consumer<Object> selectedItemChanged) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void showPopup(Project project, List<String> items, String title, Consumer<String> callback) {
|
||||
}
|
||||
}
|
||||
|
||||
+40
-3
@@ -1,4 +1,18 @@
|
||||
// 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.
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.inspections;
|
||||
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
@@ -10,6 +24,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.PythonUiService;
|
||||
import com.jetbrains.python.inspections.quickfix.ChainedComparisonsQuickFix;
|
||||
import com.jetbrains.python.psi.PyBinaryExpression;
|
||||
import com.jetbrains.python.psi.PyElementType;
|
||||
@@ -19,13 +34,35 @@ import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
|
||||
public class PyPsiChainedComparisonsInspection extends PyInspection {
|
||||
/**
|
||||
* User: catherine
|
||||
*
|
||||
* Inspection to detect chained comparisons which can be simplified
|
||||
* For instance, a < b and b < c --> a < b < c
|
||||
*/
|
||||
public class PyChainedComparisonsInspection extends PyInspection {
|
||||
|
||||
protected static final String ourIgnoreConstantOptionText = "Ignore statements with a constant in the middle";
|
||||
private static final String INSPECTION_SHORT_NAME = "PyChainedComparisonsInspection";
|
||||
public boolean ignoreConstantInTheMiddle = false;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
JCheckBox checkBox = PythonUiService.getInstance().createInspectionCheckBox(ourIgnoreConstantOptionText, this, "ignoreConstantInTheMiddle");
|
||||
final JPanel rootPanel = new JPanel(new BorderLayout());
|
||||
if (checkBox != null) {
|
||||
rootPanel.add(checkBox,
|
||||
BorderLayout.PAGE_START);
|
||||
}
|
||||
return rootPanel;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
|
||||
@@ -210,7 +247,7 @@ public class PyPsiChainedComparisonsInspection extends PyInspection {
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiFile file = descriptor.getStartElement().getContainingFile();
|
||||
InspectionProfileModifiableModelKt.modifyAndCommitProjectProfile(project, it ->
|
||||
((PyPsiChainedComparisonsInspection)it.getUnwrappedTool(INSPECTION_SHORT_NAME, file)).ignoreConstantInTheMiddle = true);
|
||||
((PyChainedComparisonsInspection)it.getUnwrappedTool(INSPECTION_SHORT_NAME, file)).ignoreConstantInTheMiddle = true);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-3
@@ -62,11 +62,12 @@ public class PyMandatoryEncodingInspection extends PyInspection {
|
||||
|
||||
final String charsetString = PythonFileType.getCharsetFromEncodingDeclaration(node);
|
||||
if (charsetString == null) {
|
||||
TextRange tr = new TextRange(0,0);
|
||||
TextRange tr = new TextRange(0, 0);
|
||||
ProblemsHolder holder = getHolder();
|
||||
if (holder != null)
|
||||
if (holder != null) {
|
||||
holder.registerProblem(node, tr, PyPsiBundle.message("INSP.mandatory.encoding.no.encoding.specified.for.file"),
|
||||
new AddEncodingQuickFix(myDefaultEncoding, myEncodingFormatIndex));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,7 +120,11 @@ public class PyMandatoryEncodingInspection extends PyInspection {
|
||||
@NotNull
|
||||
private JPanel onlyPython2Box() {
|
||||
final JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||
panel.add(PythonUiService.getInstance().createInspectionCheckBox(PyPsiBundle.message("enable.in.python.3"), this, "myAllPythons"));
|
||||
JCheckBox checkBox =
|
||||
PythonUiService.getInstance().createInspectionCheckBox(PyPsiBundle.message("enable.in.python.3"), this, "myAllPythons");
|
||||
if (checkBox != null) {
|
||||
panel.add(checkBox);
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
|
||||
+126
-42
@@ -17,7 +17,10 @@ import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.QualifiedName;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PythonUiService;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ControlFlowCache;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
|
||||
import com.jetbrains.python.psi.*;
|
||||
@@ -28,13 +31,19 @@ import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class PyPsiPep8NamingInspection extends PyInspection {
|
||||
/**
|
||||
* User : ktisha
|
||||
*/
|
||||
public class PyPep8NamingInspection extends PyInspection {
|
||||
|
||||
protected static final String INSPECTION_SHORT_NAME = "PyPep8NamingInspection";
|
||||
private static final Pattern LOWERCASE_REGEX = Pattern.compile("[_\\p{javaLowerCase}][_\\p{javaLowerCase}0-9]*");
|
||||
private static final Pattern UPPERCASE_REGEX = Pattern.compile("[_\\p{javaUpperCase}][_\\p{javaUpperCase}0-9]*");
|
||||
@@ -54,6 +63,59 @@ public class PyPsiPep8NamingInspection extends PyInspection {
|
||||
public boolean ignoreOverriddenFunctions = true;
|
||||
public final List<String> ignoredBaseClasses = Lists.newArrayList("unittest.TestCase", "unittest.case.TestCase");
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
final JPanel rootPanel = new JPanel(new BorderLayout());
|
||||
JCheckBox checkBox = PythonUiService.getInstance()
|
||||
.createInspectionCheckBox(PyPsiBundle.message("ignore.overridden.functions"), this, "ignoreOverriddenFunctions");
|
||||
if (checkBox != null) {
|
||||
rootPanel.add(checkBox, BorderLayout.NORTH);
|
||||
}
|
||||
|
||||
JComponent classes = PythonUiService.getInstance().createListEditForm("Excluded base classes", ignoredBaseClasses);
|
||||
JComponent errors = PythonUiService.getInstance().createListEditForm("Ignored errors", ignoredErrors);
|
||||
|
||||
if (classes != null && errors != null) {
|
||||
JComponent splitter = PythonUiService.getInstance().onePixelSplitter(false, classes, errors);
|
||||
|
||||
if (splitter != null) {
|
||||
rootPanel.add(splitter, BorderLayout.CENTER);
|
||||
}
|
||||
}
|
||||
|
||||
return rootPanel;
|
||||
}
|
||||
|
||||
protected void addFunctionQuickFixes(ProblemsHolder holder,
|
||||
PyClass containingClass,
|
||||
ASTNode nameNode,
|
||||
List<LocalQuickFix> quickFixes, TypeEvalContext typeEvalContext) {
|
||||
if (holder != null && holder.isOnTheFly()) {
|
||||
LocalQuickFix qf = PythonUiService.getInstance().createPyRenameElementQuickFix(nameNode.getPsi());
|
||||
if (qf != null) {
|
||||
quickFixes.add(qf);
|
||||
}
|
||||
}
|
||||
|
||||
if (containingClass != null) {
|
||||
quickFixes.add(new PyPep8NamingInspection.IgnoreBaseClassQuickFix(containingClass, typeEvalContext));
|
||||
}
|
||||
}
|
||||
|
||||
protected LocalQuickFix[] createRenameAndIngoreErrorQuickFixes(@Nullable PsiElement node,
|
||||
String errorCode) {
|
||||
List<LocalQuickFix> fixes = Lists.newArrayList();
|
||||
if (node != null) {
|
||||
LocalQuickFix qf = PythonUiService.getInstance().createPyRenameElementQuickFix(node);
|
||||
if (qf != null) {
|
||||
fixes.add(qf);
|
||||
}
|
||||
fixes.add(new IgnoreErrorFix(errorCode));
|
||||
}
|
||||
return fixes.toArray(new LocalQuickFix[fixes.size()]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
|
||||
@@ -62,6 +124,68 @@ public class PyPsiPep8NamingInspection extends PyInspection {
|
||||
return new Visitor(holder, session);
|
||||
}
|
||||
|
||||
private static class IgnoreBaseClassQuickFix implements LocalQuickFix {
|
||||
private final List<String> myBaseClassNames;
|
||||
|
||||
IgnoreBaseClassQuickFix(@NotNull PyClass baseClass, @NotNull TypeEvalContext context) {
|
||||
myBaseClassNames = new ArrayList<>();
|
||||
ContainerUtil.addIfNotNull(getBaseClassNames(), baseClass.getQualifiedName());
|
||||
for (PyClass ancestor : baseClass.getAncestorClasses(context)) {
|
||||
ContainerUtil.addIfNotNull(getBaseClassNames(), ancestor.getQualifiedName());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return PyPsiBundle.message("INSP.pep8.ignore.method.names.for.descendants.of.class");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
|
||||
PythonUiService.getInstance().showPopup(project, getBaseClassNames(), PyPsiBundle.message("INSP.pep8.ignore.base.class"),
|
||||
(selectedValue) -> InspectionProfileModifiableModelKt
|
||||
.modifyAndCommitProjectProfile(project, it -> {
|
||||
PyPep8NamingInspection inspection =
|
||||
(PyPep8NamingInspection)it
|
||||
.getUnwrappedTool(PyPep8NamingInspection.class.getSimpleName(),
|
||||
descriptor.getPsiElement());
|
||||
ContainerUtil.addIfNotNull(inspection.ignoredBaseClasses, selectedValue);
|
||||
}));
|
||||
}
|
||||
|
||||
public List<String> getBaseClassNames() {
|
||||
return myBaseClassNames;
|
||||
}
|
||||
}
|
||||
|
||||
protected static class IgnoreErrorFix implements LocalQuickFix {
|
||||
private final String myCode;
|
||||
private static final String myText = "Ignore errors like this";
|
||||
|
||||
IgnoreErrorFix(String code) {
|
||||
myCode = code;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiFile file = descriptor.getStartElement().getContainingFile();
|
||||
InspectionProfileModifiableModelKt.modifyAndCommitProjectProfile(project, model -> {
|
||||
PyPep8NamingInspection tool = (PyPep8NamingInspection)model.getUnwrappedTool(INSPECTION_SHORT_NAME, file);
|
||||
if (!tool.ignoredErrors.contains(myCode)) {
|
||||
tool.ignoredErrors.add(myCode);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class Visitor extends PyInspectionVisitor {
|
||||
public Visitor(ProblemsHolder holder, LocalInspectionToolSession session) {
|
||||
super(holder, session);
|
||||
@@ -175,7 +299,7 @@ public class PyPsiPep8NamingInspection extends PyInspection {
|
||||
|
||||
private boolean isContextManager(PyClass node) {
|
||||
final String[] contextManagerFunctionNames = {PyNames.ENTER, PyNames.EXIT};
|
||||
for (String name: contextManagerFunctionNames) {
|
||||
for (String name : contextManagerFunctionNames) {
|
||||
if (node.findMethodByName(name, false, myTypeEvalContext) == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -217,44 +341,4 @@ public class PyPsiPep8NamingInspection extends PyInspection {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected LocalQuickFix[] createRenameAndIngoreErrorQuickFixes(@Nullable PsiElement node,
|
||||
String errorCode) {
|
||||
//TODO: extract PyRenameElementQuickFix
|
||||
return new LocalQuickFix[]{new IgnoreErrorFix(errorCode)};
|
||||
}
|
||||
|
||||
protected static class IgnoreErrorFix implements LocalQuickFix {
|
||||
private final String myCode;
|
||||
private static final String myText = "Ignore errors like this";
|
||||
|
||||
IgnoreErrorFix(String code) {
|
||||
myCode = code;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiFile file = descriptor.getStartElement().getContainingFile();
|
||||
InspectionProfileModifiableModelKt.modifyAndCommitProjectProfile(project, model -> {
|
||||
PyPsiPep8NamingInspection tool = (PyPsiPep8NamingInspection)model.getUnwrappedTool(INSPECTION_SHORT_NAME, file);
|
||||
if (!tool.ignoredErrors.contains(myCode)) {
|
||||
tool.ignoredErrors.add(myCode);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected void addFunctionQuickFixes(ProblemsHolder holder,
|
||||
PyClass containingClass,
|
||||
ASTNode nameNode,
|
||||
List<LocalQuickFix> quickFixes, TypeEvalContext typeEvalContext) {
|
||||
}
|
||||
}
|
||||
-89
@@ -1,89 +0,0 @@
|
||||
// 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.google.common.collect.ImmutableSet;
|
||||
import com.intellij.codeInspection.LocalInspectionToolSession;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class PyPsiShadowingBuiltinsInspection extends PyInspection {
|
||||
// Persistent settings
|
||||
public List<String> ignoredNames = new ArrayList<>();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
|
||||
boolean isOnTheFly,
|
||||
@NotNull LocalInspectionToolSession session) {
|
||||
return new Visitor(holder, session, ignoredNames);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected LocalQuickFix[] createQuickFixes(String name, PsiElement problemElement) {
|
||||
return LocalQuickFix.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private class Visitor extends PyInspectionVisitor {
|
||||
private final Set<String> myIgnoredNames;
|
||||
|
||||
Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session, @NotNull Collection<String> ignoredNames) {
|
||||
super(holder, session);
|
||||
myIgnoredNames = ImmutableSet.copyOf(ignoredNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyClass(@NotNull PyClass node) {
|
||||
processElement(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyFunction(@NotNull PyFunction node) {
|
||||
processElement(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyNamedParameter(@NotNull PyNamedParameter node) {
|
||||
processElement(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyTargetExpression(@NotNull PyTargetExpression node) {
|
||||
if (!node.isQualified()) {
|
||||
processElement(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void processElement(@NotNull PsiNameIdentifierOwner element) {
|
||||
final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
|
||||
if (owner instanceof PyClass) {
|
||||
return;
|
||||
}
|
||||
final String name = element.getName();
|
||||
if (name != null && !myIgnoredNames.contains(name)) {
|
||||
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(element);
|
||||
final PsiElement builtin = builtinCache.getByName(name);
|
||||
if (builtin != null && !PyUtil.inSameFile(builtin, element)) {
|
||||
final PsiElement identifier = element.getNameIdentifier();
|
||||
final PsiElement problemElement = identifier != null ? identifier : element;
|
||||
registerProblem(problemElement, String.format("Shadows built-in name '%s'", name),
|
||||
ProblemHighlightType.WEAK_WARNING, null, createQuickFixes(name, problemElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+73
-4
@@ -15,29 +15,41 @@
|
||||
*/
|
||||
package com.jetbrains.python.inspections;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.codeInsight.intention.LowPriorityAction;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.ex.InspectionProfileModifiableModelKt;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.PythonUiService;
|
||||
import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
|
||||
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import com.jetbrains.python.psi.impl.PyBuiltinCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Warns about shadowing built-in names.
|
||||
*
|
||||
* @author vlan
|
||||
*/
|
||||
public class PyShadowingBuiltinsInspection extends PyPsiShadowingBuiltinsInspection {
|
||||
public class PyShadowingBuiltinsInspection extends PyInspection {
|
||||
|
||||
// Persistent settings
|
||||
public List<String> ignoredNames = new ArrayList<>();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LocalQuickFix[] createQuickFixes(String name, PsiElement problemElement) {
|
||||
List<LocalQuickFix> fixes = Lists.newArrayList();
|
||||
LocalQuickFix qf = PythonUiService.getInstance().createPyRenameElementQuickFix(problemElement);
|
||||
@@ -53,6 +65,14 @@ public class PyShadowingBuiltinsInspection extends PyPsiShadowingBuiltinsInspect
|
||||
return PythonUiService.getInstance().createListEditForm("Ignore built-ins", ignoredNames);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
|
||||
boolean isOnTheFly,
|
||||
@NotNull LocalInspectionToolSession session) {
|
||||
return new Visitor(holder, session, ignoredNames);
|
||||
}
|
||||
|
||||
private static class PyIgnoreBuiltinQuickFix implements LocalQuickFix, LowPriorityAction {
|
||||
@NotNull private final String myName;
|
||||
|
||||
@@ -93,5 +113,54 @@ public class PyShadowingBuiltinsInspection extends PyPsiShadowingBuiltinsInspect
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Visitor extends PyInspectionVisitor {
|
||||
private final Set<String> myIgnoredNames;
|
||||
|
||||
Visitor(@Nullable ProblemsHolder holder, @NotNull LocalInspectionToolSession session, @NotNull Collection<String> ignoredNames) {
|
||||
super(holder, session);
|
||||
myIgnoredNames = ImmutableSet.copyOf(ignoredNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyClass(@NotNull PyClass node) {
|
||||
processElement(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyFunction(@NotNull PyFunction node) {
|
||||
processElement(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyNamedParameter(@NotNull PyNamedParameter node) {
|
||||
processElement(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyTargetExpression(@NotNull PyTargetExpression node) {
|
||||
if (!node.isQualified()) {
|
||||
processElement(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void processElement(@NotNull PsiNameIdentifierOwner element) {
|
||||
final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
|
||||
if (owner instanceof PyClass) {
|
||||
return;
|
||||
}
|
||||
final String name = element.getName();
|
||||
if (name != null && !myIgnoredNames.contains(name)) {
|
||||
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(element);
|
||||
final PsiElement builtin = builtinCache.getByName(name);
|
||||
if (builtin != null && !PyUtil.inSameFile(builtin, element)) {
|
||||
final PsiElement identifier = element.getNameIdentifier();
|
||||
final PsiElement problemElement = identifier != null ? identifier : element;
|
||||
registerProblem(problemElement, String.format("Shadows built-in name '%s'", name),
|
||||
ProblemHighlightType.WEAK_WARNING, null, createQuickFixes(name, problemElement));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -328,9 +328,6 @@
|
||||
<localInspection shortName="PyPackageRequirementsInspection" suppressId="PyPackageRequirements" bundle="messages.PyPsiBundle" key="INSP.NAME.requirements" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyPackageRequirementsInspection"/>
|
||||
<localInspection language="Python" shortName="PyPep8Inspection" suppressId="PyPep8" bundle="messages.PyPsiBundle" key="INSP.pep8.coding.style.violation" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyPep8Inspection" unfair="true"/>
|
||||
<localInspection language="Python" shortName="PyInterpreterInspection" suppressId="PyInterpreter" bundle="messages.PyPsiBundle" key="INSP.NAME.invalid.interpreter" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.inspections.PyInterpreterInspection"/>
|
||||
<localInspection language="Python" shortName="PyPep8NamingInspection" suppressId="PyPep8Naming" bundle="messages.PyPsiBundle" key="INSP.pep8.naming" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyPep8NamingInspection"/>
|
||||
<localInspection language="Python" shortName="PyChainedComparisonsInspection" suppressId="PyChainedComparisons" bundle="messages.PyPsiBundle" key="INSP.NAME.chained.comparisons" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyChainedComparisonsInspection"/>
|
||||
<localInspection language="Python" shortName="PyShadowingBuiltinsInspection" suppressId="PyShadowingBuiltins" bundle="messages.PyPsiBundle" key="INSP.shadowing.builtins" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WEAK WARNING" implementationClass="com.jetbrains.python.inspections.PyShadowingBuiltinsInspection"/>
|
||||
<localInspection language="Python" shortName="PyStubPackagesCompatibilityInspection" suppressId="PyStubPackagesCompatibility" bundle="messages.PyPsiBundle" key="INSP.stub.packages.compatibility" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.codeInsight.typing.PyStubPackagesCompatibilityInspection"/>
|
||||
<localInspection language="Python" shortName="PyStubPackagesAdvertiser" suppressId="PyStubPackagesAdvertiser" bundle="messages.PyPsiBundle" key="INSP.stub.packages" groupKey="INSP.GROUP.python" enabledByDefault="true" level="WARNING" implementationClass="com.jetbrains.python.codeInsight.typing.PyStubPackagesAdvertiser"/>
|
||||
|
||||
|
||||
@@ -3,9 +3,12 @@ package com.jetbrains.python;
|
||||
|
||||
import com.intellij.codeInspection.InspectionProfileEntry;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ex.InspectionProfileModifiableModelKt;
|
||||
import com.intellij.codeInspection.ui.ListEditForm;
|
||||
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.ide.util.ElementsChooser;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
@@ -13,15 +16,18 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.util.JDOMExternalizableStringList;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.refactoring.rename.RenameProcessor;
|
||||
import com.intellij.ui.OnePixelSplitter;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.CheckBox;
|
||||
import com.jetbrains.python.codeInsight.intentions.PyAnnotateTypesIntention;
|
||||
import com.jetbrains.python.inspections.PyMandatoryEncodingInspection;
|
||||
import com.jetbrains.python.inspections.PyPep8NamingInspection;
|
||||
import com.jetbrains.python.inspections.quickfix.PyChangeSignatureQuickFix;
|
||||
import com.jetbrains.python.inspections.quickfix.PyImplementMethodsQuickFix;
|
||||
import com.jetbrains.python.inspections.quickfix.PyRenameElementQuickFix;
|
||||
@@ -231,4 +237,24 @@ public class PythonUiServiceImpl extends PythonUiService {
|
||||
root.add(option, BorderLayout.PAGE_START);
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent onePixelSplitter(boolean vertical, JComponent first, JComponent second) {
|
||||
final OnePixelSplitter splitter = new OnePixelSplitter(vertical);
|
||||
|
||||
splitter.setFirstComponent(first);
|
||||
splitter.setSecondComponent(second);
|
||||
|
||||
return splitter;
|
||||
}
|
||||
|
||||
public void showPopup(Project project, List<String> items, String title, Consumer<String> callback) {
|
||||
DataManager.getInstance().getDataContextFromFocus().doWhenDone((Consumer<DataContext>)dataContext ->
|
||||
JBPopupFactory.getInstance().createPopupChooserBuilder(items)
|
||||
.setTitle(title)
|
||||
.setItemChosenCallback(callback)
|
||||
.setNamerForFiltering(o -> o)
|
||||
.createPopup()
|
||||
.showInBestPositionFor(dataContext));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.inspections;
|
||||
|
||||
import com.intellij.util.ui.CheckBox;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* User: catherine
|
||||
*
|
||||
* Inspection to detect chained comparisons which can be simplified
|
||||
* For instance, a < b and b < c --> a < b < c
|
||||
*/
|
||||
public class PyChainedComparisonsInspection extends PyPsiChainedComparisonsInspection {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
final JPanel rootPanel = new JPanel(new BorderLayout());
|
||||
rootPanel.add(new CheckBox(ourIgnoreConstantOptionText, this, "ignoreConstantInTheMiddle"),
|
||||
BorderLayout.PAGE_START);
|
||||
|
||||
return rootPanel;
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
// 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.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.codeInspection.ex.InspectionProfileModifiableModelKt;
|
||||
import com.intellij.codeInspection.ui.ListEditForm;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.ui.OnePixelSplitter;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.CheckBox;
|
||||
import com.jetbrains.python.PyPsiBundle;
|
||||
import com.jetbrains.python.inspections.quickfix.PyRenameElementQuickFix;
|
||||
import com.jetbrains.python.psi.PyClass;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User : ktisha
|
||||
*/
|
||||
public class PyPep8NamingInspection extends PyPsiPep8NamingInspection {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent createOptionsPanel() {
|
||||
final JPanel rootPanel = new JPanel(new BorderLayout());
|
||||
rootPanel.add(new CheckBox(PyPsiBundle.message("ignore.overridden.functions"), this, "ignoreOverriddenFunctions"), BorderLayout.NORTH);
|
||||
|
||||
final OnePixelSplitter splitter = new OnePixelSplitter(false);
|
||||
splitter.setFirstComponent(new ListEditForm("Excluded base classes", ignoredBaseClasses).getContentPanel());
|
||||
splitter.setSecondComponent(new ListEditForm("Ignored errors", ignoredErrors).getContentPanel());
|
||||
rootPanel.add(splitter, BorderLayout.CENTER);
|
||||
|
||||
return rootPanel;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addFunctionQuickFixes(ProblemsHolder holder,
|
||||
PyClass containingClass,
|
||||
ASTNode nameNode,
|
||||
List<LocalQuickFix> quickFixes, TypeEvalContext typeEvalContext) {
|
||||
if (holder != null && holder.isOnTheFly()) {
|
||||
quickFixes.add(new PyRenameElementQuickFix(nameNode.getPsi()));
|
||||
}
|
||||
|
||||
if (containingClass != null) {
|
||||
quickFixes.add(new PyPep8NamingInspection.IgnoreBaseClassQuickFix(containingClass, typeEvalContext));
|
||||
}
|
||||
}
|
||||
|
||||
protected LocalQuickFix[] createRenameAndIngoreErrorQuickFixes(@Nullable PsiElement node,
|
||||
String errorCode) {
|
||||
return new LocalQuickFix[]{new PyRenameElementQuickFix(node), new IgnoreErrorFix(errorCode)};
|
||||
}
|
||||
|
||||
private static class IgnoreBaseClassQuickFix implements LocalQuickFix {
|
||||
private final List<String> myBaseClassNames;
|
||||
|
||||
IgnoreBaseClassQuickFix(@NotNull PyClass baseClass, @NotNull TypeEvalContext context) {
|
||||
myBaseClassNames = new ArrayList<>();
|
||||
ContainerUtil.addIfNotNull(getBaseClassNames(), baseClass.getQualifiedName());
|
||||
for (PyClass ancestor : baseClass.getAncestorClasses(context)) {
|
||||
ContainerUtil.addIfNotNull(getBaseClassNames(), ancestor.getQualifiedName());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return PyPsiBundle.message("INSP.pep8.ignore.method.names.for.descendants.of.class");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
|
||||
DataManager.getInstance().getDataContextFromFocus().doWhenDone((Consumer<DataContext>)dataContext ->
|
||||
JBPopupFactory.getInstance().createPopupChooserBuilder(getBaseClassNames())
|
||||
.setTitle(PyPsiBundle.message("INSP.pep8.ignore.base.class"))
|
||||
.setItemChosenCallback((selectedValue) -> InspectionProfileModifiableModelKt.modifyAndCommitProjectProfile(project, it -> {
|
||||
PyPep8NamingInspection inspection =
|
||||
(PyPep8NamingInspection)it.getUnwrappedTool(PyPep8NamingInspection.class.getSimpleName(), descriptor.getPsiElement());
|
||||
ContainerUtil.addIfNotNull(inspection.ignoredBaseClasses, selectedValue);
|
||||
}))
|
||||
.setNamerForFiltering(o -> o)
|
||||
.createPopup()
|
||||
.showInBestPositionFor(dataContext));
|
||||
}
|
||||
|
||||
public List<String> getBaseClassNames() {
|
||||
return myBaseClassNames;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user