Merge decoupled inspections

GitOrigin-RevId: bdd58f7021b0d946ccc1a0b801050eca3856b397
This commit is contained in:
Dmitry Trofimov
2020-03-31 18:46:10 +00:00
committed by intellij-monorepo-bot
parent 6b5ad3adc4
commit 3e9f6983a8
11 changed files with 293 additions and 298 deletions
@@ -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) {
}
}
@@ -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);
}
}
}
@@ -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;
}
@@ -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) {
}
}
@@ -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));
}
}
}
}
}
@@ -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;
}
}
}