From 0334bb96f7eff3d4cedd5990d8ac49bb89b4b17a Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 12 Mar 2012 21:31:20 +0400 Subject: [PATCH] fixed PY-5588 Compatibility inspection: highlight using keyword argument in the list of base classes as errors under py2 --- .../PyCompatibilityInspection.java | 24 +++++++++++++++++-- .../validation/CompatibilityVisitor.java | 17 ++++++++----- .../classBaseList.py | 8 +++++++ .../PyCompatibilityInspectionTest.java | 4 ++++ 4 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 python/testData/inspections/PyCompatibilityInspection/classBaseList.py diff --git a/python/src/com/jetbrains/python/inspections/PyCompatibilityInspection.java b/python/src/com/jetbrains/python/inspections/PyCompatibilityInspection.java index f37f5d1e2904..ac5931e7c214 100644 --- a/python/src/com/jetbrains/python/inspections/PyCompatibilityInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyCompatibilityInspection.java @@ -1,6 +1,7 @@ package com.jetbrains.python.inspections; import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.roots.ProjectFileIndex; @@ -115,9 +116,10 @@ public class PyCompatibilityInspection extends PyInspection { myHolder = holder; } + @Override protected final void registerProblem(@Nullable final PsiElement element, @NotNull final String message, - final LocalQuickFix quickFix, boolean asError){ + @Nullable final LocalQuickFix quickFix, final boolean asError){ if (element == null || element.getTextLength() == 0){ return; } @@ -215,5 +217,23 @@ public class PyCompatibilityInspection extends PyInspection { len, source, null, false); } } + + @Override + public void visitPyArgumentList(final PyArgumentList node) { //PY-5588 + final List problemElements = new ArrayList(); + if (node.getParent() instanceof PyClass) { + for (final PyExpression expression : node.getArguments()) { + if (expression instanceof PyKeywordArgument) + problemElements.add(expression); + } + } + final String errorMessage = "This syntax available only since py3"; + final boolean isPy3 = LanguageLevel.forElement(node).isPy3K(); + if (compatibleWithPy2() || !isPy3) { + for (final PyElement problemElement : problemElements) + myHolder.registerProblem(problemElement, errorMessage, isPy3? ProblemHighlightType.GENERIC_ERROR_OR_WARNING : + ProblemHighlightType.GENERIC_ERROR); + } + } } -} +} \ No newline at end of file diff --git a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java index ff57bb3da4fb..8b0e56c6baf1 100644 --- a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java +++ b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java @@ -12,6 +12,7 @@ import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.actions.*; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyQualifiedName; +import org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.List; @@ -455,13 +456,13 @@ public abstract class CompatibilityVisitor extends PyAnnotator { return false; } - protected abstract void registerProblem(PsiElement node, String s, LocalQuickFix localQuickFix, boolean asError); + protected abstract void registerProblem(PsiElement node, String s, @Nullable LocalQuickFix localQuickFix, boolean asError); - protected void registerProblem(PsiElement node, String s, LocalQuickFix localQuickFix) { + protected void registerProblem(final PsiElement node, final String s, @Nullable final LocalQuickFix localQuickFix) { registerProblem(node, s, localQuickFix, true); } - protected void registerProblem(PsiElement node, String s) { + protected void registerProblem(final PsiElement node, final String s) { registerProblem(node, s, null); } @@ -492,10 +493,14 @@ public abstract class CompatibilityVisitor extends PyAnnotator { } @Override - public void visitPyNonlocalStatement(PyNonlocalStatement node) { - if (myVersionsToProcess.contains(LanguageLevel.PYTHON24) || myVersionsToProcess.contains(LanguageLevel.PYTHON25) || - myVersionsToProcess.contains(LanguageLevel.PYTHON26) || myVersionsToProcess.contains(LanguageLevel.PYTHON27)) { + public void visitPyNonlocalStatement(final PyNonlocalStatement node) { + if (compatibleWithPy2()) { registerProblem(node, "nonlocal keyword available only since py3", null, false); } } + + protected boolean compatibleWithPy2() { + return myVersionsToProcess.contains(LanguageLevel.PYTHON24) || myVersionsToProcess.contains(LanguageLevel.PYTHON25) || + myVersionsToProcess.contains(LanguageLevel.PYTHON26) || myVersionsToProcess.contains(LanguageLevel.PYTHON27); + } } diff --git a/python/testData/inspections/PyCompatibilityInspection/classBaseList.py b/python/testData/inspections/PyCompatibilityInspection/classBaseList.py new file mode 100644 index 000000000000..a32e1067dacc --- /dev/null +++ b/python/testData/inspections/PyCompatibilityInspection/classBaseList.py @@ -0,0 +1,8 @@ +class Foo(base1, base2, metaclass=mymeta): + pass + +class Foo(base1, base2): + pass + +def foo(base1, base2, metaclass=mymeta): + pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java index f78f7b84b179..87769e81fb10 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java @@ -110,6 +110,10 @@ public class PyCompatibilityInspectionTest extends PyTestCase { doTest(); } + public void testClassBaseList() { + doTest(); + } + private void doTest() { myFixture.configureByFile("inspections/PyCompatibilityInspection/" + getTestName(true) + ".py"); myFixture.enableInspections(PyCompatibilityInspection.class);