From 8dd9cc4f491a4b042ca854c20e1e282a070ec175 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 11 Mar 2014 15:19:31 +0400 Subject: [PATCH] added remove dictionary key quick fix for the Dictionary contains duplicate keys inspection --- .../com/jetbrains/python/PyBundle.properties | 2 + .../PyDictDuplicateKeysInspection.java | 5 +- .../quickfix/PyRemoveDictKeyQuickFix.java | 58 +++++++++++++++++++ .../PyRemoveDictKeyQuickFixTest/first.py | 2 + .../first_after.py | 2 + .../inTheMiddle.py | 2 + .../inTheMiddle_after.py | 2 + .../PyRemoveDictKeyQuickFixTest/last.py | 2 + .../PyRemoveDictKeyQuickFixTest/last_after.py | 2 + .../PyRemoveDictKeyQuickFixTest.java | 38 ++++++++++++ 10 files changed, 113 insertions(+), 2 deletions(-) create mode 100644 python/src/com/jetbrains/python/inspections/quickfix/PyRemoveDictKeyQuickFix.java create mode 100644 python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/first.py create mode 100644 python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/first_after.py create mode 100644 python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/inTheMiddle.py create mode 100644 python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/inTheMiddle_after.py create mode 100644 python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/last.py create mode 100644 python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/last_after.py create mode 100644 python/testSrc/com/jetbrains/python/quickFixes/PyRemoveDictKeyQuickFixTest.java diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties index f3fc223ce57a..982af0bf6709 100644 --- a/python/src/com/jetbrains/python/PyBundle.properties +++ b/python/src/com/jetbrains/python/PyBundle.properties @@ -125,6 +125,8 @@ QFIX.NAME.remove.assignment=Remove assignment QFIX.NAME.move.except.up=Move except clause up +QFIX.NAME.remove.dict.key=Remove this key + # 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' diff --git a/python/src/com/jetbrains/python/inspections/PyDictDuplicateKeysInspection.java b/python/src/com/jetbrains/python/inspections/PyDictDuplicateKeysInspection.java index 8bcf14fa3b29..51784a57bd41 100644 --- a/python/src/com/jetbrains/python/inspections/PyDictDuplicateKeysInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyDictDuplicateKeysInspection.java @@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.util.containers.HashMap; import com.jetbrains.python.PyBundle; +import com.jetbrains.python.inspections.quickfix.PyRemoveDictKeyQuickFix; import com.jetbrains.python.psi.*; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -64,8 +65,8 @@ public class PyDictDuplicateKeysInspection extends PyInspection { if (key instanceof PyNumericLiteralExpression || key instanceof PyStringLiteralExpression || key instanceof PyReferenceExpression) { if (map.keySet().contains(key.getText())) { - registerProblem(key, "Dictionary contains duplicate keys " + key.getText()); - registerProblem(map.get(key.getText()), "Dictionary contains duplicate keys " + key.getText()); + registerProblem(key, "Dictionary contains duplicate keys " + key.getText(), new PyRemoveDictKeyQuickFix()); + registerProblem(map.get(key.getText()), "Dictionary contains duplicate keys " + key.getText(), new PyRemoveDictKeyQuickFix()); } map.put(key.getText(), key); } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveDictKeyQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveDictKeyQuickFix.java new file mode 100644 index 000000000000..759ebaa2842e --- /dev/null +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveDictKeyQuickFix.java @@ -0,0 +1,58 @@ +/* + * Copyright 2000-2013 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.quickfix; + +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.jetbrains.python.PyBundle; +import com.jetbrains.python.PyTokenTypes; +import com.jetbrains.python.psi.PyKeyValueExpression; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class PyRemoveDictKeyQuickFix implements LocalQuickFix { + + @NotNull + public String getName() { + return PyBundle.message("QFIX.NAME.remove.dict.key"); + } + + @NonNls + @NotNull + public String getFamilyName() { + return getName(); + } + + public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) { + final PsiElement element = descriptor.getPsiElement(); + final PyKeyValueExpression expression = PsiTreeUtil.getParentOfType(element, PyKeyValueExpression.class); + if (expression == null) return; + final PsiElement nextSibling = PsiTreeUtil.skipSiblingsForward(expression, PsiWhiteSpace.class); + final PsiElement prevSibling = PsiTreeUtil.skipSiblingsBackward(expression, PsiWhiteSpace.class); + expression.delete(); + if (nextSibling != null && nextSibling.getNode().getElementType().equals(PyTokenTypes.COMMA)) { + nextSibling.delete(); + return; + } + if (prevSibling != null && prevSibling.getNode().getElementType().equals(PyTokenTypes.COMMA)) { + prevSibling.delete(); + } + } +} diff --git a/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/first.py b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/first.py new file mode 100644 index 000000000000..88c3864f3813 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/first.py @@ -0,0 +1,2 @@ + +a = {'x':1, "y":2, 'x':1} \ No newline at end of file diff --git a/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/first_after.py b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/first_after.py new file mode 100644 index 000000000000..28111fd19a50 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/first_after.py @@ -0,0 +1,2 @@ + +a = {"y":2, 'x':1} \ No newline at end of file diff --git a/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/inTheMiddle.py b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/inTheMiddle.py new file mode 100644 index 000000000000..1ed5736f864f --- /dev/null +++ b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/inTheMiddle.py @@ -0,0 +1,2 @@ + +a = {'x':1, "y":2, 'x':1,"c":2} \ No newline at end of file diff --git a/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/inTheMiddle_after.py b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/inTheMiddle_after.py new file mode 100644 index 000000000000..dd04c14abd02 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/inTheMiddle_after.py @@ -0,0 +1,2 @@ + +a = {'x':1, "y":2, "c":2} \ No newline at end of file diff --git a/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/last.py b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/last.py new file mode 100644 index 000000000000..0e75add702e3 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/last.py @@ -0,0 +1,2 @@ + +a = {'x':1, "y":2, 'x':1} \ No newline at end of file diff --git a/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/last_after.py b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/last_after.py new file mode 100644 index 000000000000..9d3bcaf373b4 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveDictKeyQuickFixTest/last_after.py @@ -0,0 +1,2 @@ + +a = {'x':1, "y":2} \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveDictKeyQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveDictKeyQuickFixTest.java new file mode 100644 index 000000000000..4f9ce87a8bb2 --- /dev/null +++ b/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveDictKeyQuickFixTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2013 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.quickFixes; + +import com.intellij.testFramework.TestDataPath; +import com.jetbrains.python.PyBundle; +import com.jetbrains.python.PyQuickFixTestCase; +import com.jetbrains.python.inspections.PyDictDuplicateKeysInspection; + +@TestDataPath("$CONTENT_ROOT/../testData//quickFixes/PyRemoveDictKeyQuickFixTest/") +public class PyRemoveDictKeyQuickFixTest extends PyQuickFixTestCase { + + public void testFirst() { + doQuickFixTest(PyDictDuplicateKeysInspection.class, PyBundle.message("QFIX.NAME.remove.dict.key")); + } + + public void testLast() { + doQuickFixTest(PyDictDuplicateKeysInspection.class, PyBundle.message("QFIX.NAME.remove.dict.key")); + } + + public void testInTheMiddle() { + doQuickFixTest(PyDictDuplicateKeysInspection.class, PyBundle.message("QFIX.NAME.remove.dict.key")); + } + +}