mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
added PY-2952 "Unnecessary backslash" inspection
This commit is contained in:
@@ -66,6 +66,9 @@ QFIX.introduce.variable=Introduce variable for statement
|
||||
|
||||
QFIX.unresolved.reference.add.future=Add 'from __future__ import with_statement''
|
||||
|
||||
# RemoveUnnecessaryBackslashQuickFix
|
||||
QFIX.remove.unnecessary.backslash=Remove unnecessary backslash in expression
|
||||
|
||||
# Intentions: INTN
|
||||
INTN.Family.convert.import.unqualify=Convert 'import module' to 'from module import'
|
||||
INTN.Family.convert.import.qualify=Convert 'from module import' to 'import module'
|
||||
@@ -348,6 +351,8 @@ INSP.NAME.oldstyle.class=Old-style class contains new-style class features
|
||||
# PyCompatibilityInspection
|
||||
INSP.NAME.compatibility=Code compatibility inspection
|
||||
|
||||
# PyUnnecessaryBackslashInspection
|
||||
INSP.NAME.unnecessary.backslash=Unnecessary backslash
|
||||
|
||||
# Refactoring
|
||||
# introduce
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.jetbrains.python.actions;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: catherine
|
||||
*
|
||||
* QuickFix to remove all unnecessary backslashes in expression
|
||||
*/
|
||||
public class RemoveUnnecessaryBackslashQuickFix implements LocalQuickFix {
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return PyBundle.message("QFIX.remove.unnecessary.backslash");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return PyBundle.message("INSP.GROUP.python");
|
||||
}
|
||||
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement problemElement = descriptor.getPsiElement();
|
||||
if (problemElement != null) {
|
||||
PyElement parent = PsiTreeUtil.getParentOfType(problemElement, PySequenceExpression.class, PyDictLiteralExpression.class,
|
||||
PyParenthesizedExpression.class, PyArgumentList.class, PyParameterList.class);
|
||||
removeBackSlash(parent);
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeBackSlash(PyElement parent) {
|
||||
if (parent != null) {
|
||||
Stack<PsiElement> stack = new Stack<PsiElement>();
|
||||
if (parent instanceof PyParenthesizedExpression)
|
||||
stack.push(((PyParenthesizedExpression)parent).getContainedExpression());
|
||||
else
|
||||
stack.push(parent);
|
||||
while (!stack.isEmpty()) {
|
||||
PsiElement el = stack.pop();
|
||||
PsiWhiteSpace[] children = PsiTreeUtil.getChildrenOfType(el, PsiWhiteSpace.class);
|
||||
if (children != null) {
|
||||
for (PsiWhiteSpace ws : children) {
|
||||
if (ws.getText().contains("\\")) {
|
||||
ws.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (PsiElement psiElement : el.getChildren()) {
|
||||
stack.push(psiElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.jetbrains.python.inspections;
|
||||
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.actions.RemoveUnnecessaryBackslashQuickFix;
|
||||
import com.jetbrains.python.psi.*;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: catherine
|
||||
*
|
||||
* Inspection to highlight backslashes in places where line continuation is implicit (inside (), [], {}).
|
||||
*/
|
||||
public class PyUnnecessaryBackslashInspection extends PyInspection {
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return PyBundle.message("INSP.NAME.unnecessary.backslash");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
return new Visitor(holder);
|
||||
}
|
||||
|
||||
private static class Visitor extends PyInspectionVisitor {
|
||||
public Visitor(ProblemsHolder holder) {
|
||||
super(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyParameterList(final PyParameterList list) {
|
||||
findProblem(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyArgumentList(final PyArgumentList list) {
|
||||
findProblem(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyParenthesizedExpression(final PyParenthesizedExpression expression) {
|
||||
Stack<PsiElement> stack = new Stack<PsiElement>();
|
||||
stack.push(expression.getContainedExpression());
|
||||
while (!stack.isEmpty()) {
|
||||
PsiElement element = stack.pop();
|
||||
findProblem(element);
|
||||
for (PsiElement psiElement : element.getChildren()) {
|
||||
stack.push(psiElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyDictLiteralExpression(final PyDictLiteralExpression expression) {
|
||||
findProblem(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPyListLiteralExpression(final PyListLiteralExpression expression) {
|
||||
findProblem(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPySetLiteralExpression(final PySetLiteralExpression expression) {
|
||||
findProblem(expression);
|
||||
}
|
||||
|
||||
private void findProblem (final PsiElement expression) {
|
||||
PsiWhiteSpace[] children = PsiTreeUtil.getChildrenOfType(expression, PsiWhiteSpace.class);
|
||||
if (children != null) {
|
||||
for (PsiWhiteSpace ws : children) {
|
||||
if (ws.getText().contains("\\")) {
|
||||
registerProblem(ws, "Unnecessary backslash in expression.", new RemoveUnnecessaryBackslashQuickFix());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ public class PythonInspectionToolProvider implements InspectionToolProvider {
|
||||
PyOldStyleClassesInspection.class,
|
||||
PyCompatibilityInspection.class,
|
||||
PyListCreationInspection.class,
|
||||
PyUnnecessaryBackslashInspection.class,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
|
||||
def foo(year, month, day, hour, minute, second):
|
||||
if 1900 < year < 2100 and 1 <= month <= 12 \
|
||||
and 1 <= day <= 31 and 0 <= hour < 24 \
|
||||
and 0 <= minute < 60 and 0 <= second < 60: # Looks like a valid date
|
||||
return 1
|
||||
|
||||
|
||||
if (True<warning descr="Unnecessary backslash in expression."> \</warning>
|
||||
or True<warning descr="Unnecessary backslash in expression."> \</warning>
|
||||
or False):
|
||||
print("false")
|
||||
|
||||
var1 = (1,1,<warning descr="Unnecessary backslash in expression.">\</warning>
|
||||
2,<warning descr="Unnecessary backslash in expression.">\</warning>
|
||||
3,
|
||||
4)
|
||||
|
||||
var2 = [1,2,<warning descr="Unnecessary backslash in expression.">\</warning>
|
||||
3,<warning descr="Unnecessary backslash in expression.">\</warning>
|
||||
4]
|
||||
|
||||
var3 = <warning descr="Python version 2.5 does not support set literal expressions">{1, 2,<warning descr="Unnecessary backslash in expression.">\</warning>
|
||||
3,4}</warning>
|
||||
|
||||
var4 = {1:1, 2:2,<warning descr="Unnecessary backslash in expression.">\</warning>
|
||||
3:3,
|
||||
4:4}
|
||||
|
||||
|
||||
assert (val>4,<warning descr="Unnecessary backslash in expression."> \</warning>
|
||||
"val is too small")
|
||||
|
||||
var5 = (val1 < 20) and \
|
||||
(val2 < 30) and \
|
||||
(val3 < 40)
|
||||
|
||||
var6 = ('1' + '2' + '3' +<warning descr="Unnecessary backslash in expression."> \</warning>
|
||||
'4' + '5')
|
||||
|
||||
|
||||
def foo(a, b,<warning descr="Unnecessary backslash in expression."> \</warning>
|
||||
c):
|
||||
pass
|
||||
|
||||
foo(1, 2,<warning descr="Unnecessary backslash in expression."> \</warning>
|
||||
3)
|
||||
@@ -0,0 +1,4 @@
|
||||
var1 = (1,1,<warning descr="Unnecessary backslash in expression."><caret>\</warning>
|
||||
2,<warning descr="Unnecessary backslash in expression.">\</warning>
|
||||
3,
|
||||
4)
|
||||
@@ -0,0 +1,4 @@
|
||||
def foo(a, b,<warning descr="Unnecessary backslash in expression."><caret>\</warning>
|
||||
c,<warning descr="Unnecessary backslash in expression.">\</warning>
|
||||
d):
|
||||
pass
|
||||
@@ -0,0 +1,4 @@
|
||||
def foo(a, b,
|
||||
c,
|
||||
d):
|
||||
pass
|
||||
@@ -0,0 +1,4 @@
|
||||
var1 = (1,1,
|
||||
2,
|
||||
3,
|
||||
4)
|
||||
@@ -220,6 +220,26 @@ public class PyQuickFixTest extends PyLightFixtureTestCase {
|
||||
PyBundle.message("QFIX.list.creation"), true, true);
|
||||
}
|
||||
|
||||
public void testUnnecessaryBackslash() {
|
||||
String[] testFiles = new String[]{"UnnecessaryBackslash.py"};
|
||||
myFixture.enableInspections(PyUnnecessaryBackslashInspection.class);
|
||||
myFixture.configureByFiles(testFiles);
|
||||
myFixture.checkHighlighting(true, false, true);
|
||||
IntentionAction intentionAction = myFixture.getAvailableIntention(PyBundle.message("QFIX.remove.unnecessary.backslash"));
|
||||
myFixture.launchAction(intentionAction);
|
||||
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
|
||||
}
|
||||
|
||||
public void testUnnecessaryBackslashInArgumentList() {
|
||||
String[] testFiles = new String[]{"UnnecessaryBackslashInArguments.py"};
|
||||
myFixture.enableInspections(PyUnnecessaryBackslashInspection.class);
|
||||
myFixture.configureByFiles(testFiles);
|
||||
myFixture.checkHighlighting(true, false, true);
|
||||
IntentionAction intentionAction = myFixture.getAvailableIntention(PyBundle.message("QFIX.remove.unnecessary.backslash"));
|
||||
myFixture.launchAction(intentionAction);
|
||||
myFixture.checkResultByFile(graftBeforeExt(testFiles[0], "_after"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNls
|
||||
protected String getTestDataPath() {
|
||||
|
||||
@@ -304,4 +304,7 @@ public class PythonInspectionsTest extends PyLightFixtureTestCase {
|
||||
doHighlightingTest(PyStringFormatInspection.class);
|
||||
}
|
||||
|
||||
public void testPyUnnecessaryBackslashInspection() { //PY-2952
|
||||
doHighlightingTest(PyUnnecessaryBackslashInspection.class);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user