added PY-8367 Quickfix for removing unused parameter or variable

This commit is contained in:
Ekaterina Tuzova
2014-03-13 18:16:42 +04:00
parent 4aedbcc372
commit 068794c6dc
16 changed files with 222 additions and 7 deletions
@@ -145,6 +145,8 @@ QFIX.NAME.change.signature=Change signature
QFIX.NAME.remove.argument=Remove argument
QFIX.NAME.remove.parameter=Remove parameter
QFIX.NAME.rename.argument=Rename argument
QFIX.NAME.wrap.in.exception=Wrap with Exception call
@@ -34,6 +34,8 @@ import com.jetbrains.python.codeInsight.controlflow.ScopeOwner;
import com.jetbrains.python.codeInsight.dataflow.scope.Scope;
import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil;
import com.jetbrains.python.inspections.quickfix.AddFieldQuickFix;
import com.jetbrains.python.inspections.quickfix.PyRemoveParameterQuickFix;
import com.jetbrains.python.inspections.quickfix.PyRemoveStatementQuickFix;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyAugAssignmentStatementNavigator;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
@@ -246,14 +248,14 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
final PsiElement nameIdentifier = ((PyFunction)element).getNameIdentifier();
registerWarning(nameIdentifier == null ? element : nameIdentifier,
PyBundle.message("INSP.unused.locals.local.function.isnot.used",
((PyFunction)element).getName()));
((PyFunction)element).getName()), new PyRemoveStatementQuickFix());
}
else if (element instanceof PyClass) {
// Local class
final PyClass cls = (PyClass)element;
final PsiElement name = cls.getNameIdentifier();
registerWarning(name != null ? name : element,
PyBundle.message("INSP.unused.locals.local.class.isnot.used", cls.getName()));
PyBundle.message("INSP.unused.locals.local.class.isnot.used", cls.getName()), new PyRemoveStatementQuickFix());
}
else {
// Local variable or parameter
@@ -297,7 +299,7 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
}
final LocalQuickFix[] fixes = mayBeField
? new LocalQuickFix[] { new AddFieldQuickFix(name, name, containingClass.getName()) }
: LocalQuickFix.EMPTY_ARRAY;
: new LocalQuickFix[] { new PyRemoveParameterQuickFix() };
registerWarning(element, PyBundle.message("INSP.unused.locals.parameter.isnot.used", name), fixes);
}
else {
@@ -312,7 +314,7 @@ public class PyUnusedLocalInspectionVisitor extends PyInspectionVisitor {
}
}
else {
registerWarning(element, PyBundle.message("INSP.unused.locals.local.variable.isnot.used", name));
registerWarning(element, PyBundle.message("INSP.unused.locals.local.variable.isnot.used", name), new PyRemoveStatementQuickFix());
}
}
}
@@ -0,0 +1,78 @@
/*
* 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.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
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.documentation.PyDocumentationSettings;
import com.jetbrains.python.editor.PythonDocCommentUtil;
import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class PyRemoveParameterQuickFix implements LocalQuickFix {
@NotNull
public String getName() {
return PyBundle.message("QFIX.NAME.remove.parameter");
}
@NonNls
@NotNull
public String getFamilyName() {
return getName();
}
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
assert element instanceof PyParameter;
final PyFunction pyFunction = PsiTreeUtil.getParentOfType(element, PyFunction.class);
final PsiElement nextSibling = PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace.class);
final PsiElement prevSibling = PsiTreeUtil.skipSiblingsBackward(element, PsiWhiteSpace.class);
element.delete();
if (nextSibling != null && nextSibling.getNode().getElementType().equals(PyTokenTypes.COMMA)) {
nextSibling.delete();
return;
}
if (prevSibling != null && prevSibling.getNode().getElementType().equals(PyTokenTypes.COMMA)) {
prevSibling.delete();
}
if (pyFunction != null) {
final PyStringLiteralExpression expression = pyFunction.getDocStringExpression();
final String paramName = ((PyParameter)element).getName();
if (expression != null && paramName != null) {
final Module module = ModuleUtilCore.findModuleForPsiElement(pyFunction);
assert module != null;
PyDocumentationSettings documentationSettings = PyDocumentationSettings.getInstance(module);
String prefix = documentationSettings.isEpydocFormat(pyFunction.getContainingFile()) ? "@" : ":";
final String replacement = PythonDocCommentUtil.removeParamFromDocstring(expression.getText(), prefix, paramName);
PyExpression str =
PyElementGenerator.getInstance(project).createDocstring(replacement).getExpression();
expression.replace(str);
}
}
}
}
@@ -18,7 +18,6 @@ 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.util.PsiTreeUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyElementGenerator;
@@ -41,8 +40,8 @@ public class PyRemoveStatementQuickFix implements LocalQuickFix {
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement statement = descriptor.getPsiElement();
if (statement instanceof PyStatement) {
final PyStatement statement = PsiTreeUtil.getParentOfType(descriptor.getPsiElement(), PyStatement.class, false);
if (statement != null) {
final PyStatementList statementList = PsiTreeUtil.getParentOfType(statement, PyStatementList.class);
if (statementList != null) {
if (statementList.getStatements().length == 1) {
@@ -0,0 +1,11 @@
def foo(r<caret>):
"""
:param r:
:return:
"""
def a():
pass
x = 1
x = 2
@@ -0,0 +1,10 @@
def foo():
"""
:return:
"""
def a():
pass
x = 1
x = 2
@@ -0,0 +1,6 @@
def foo(r, **<caret>kwargs):
def a():
pass
x = 1
x = 2
@@ -0,0 +1,6 @@
def foo(r):
def a():
pass
x = 1
x = 2
@@ -0,0 +1,6 @@
def foo(r<caret>):
def a():
pass
x = 1
x = 2
@@ -0,0 +1,6 @@
def foo():
def a():
pass
x = 1
x = 2
@@ -0,0 +1,11 @@
def foo(r):
"""
:param r:
:return:
"""
def a<caret>():
pass
x = 1
x = 2
@@ -0,0 +1,10 @@
def foo(r):
"""
:param r:
:return:
"""
x = 1
x = 2
@@ -0,0 +1,11 @@
def foo(r):
"""
:param r:
:return:
"""
def a():
pass
x<caret> = 1
x = 2
@@ -0,0 +1,11 @@
def foo(r):
"""
:param r:
:return:
"""
def a():
pass
x = 2
@@ -0,0 +1,37 @@
/*
* 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.PyUnusedLocalInspection;
@TestDataPath("$CONTENT_ROOT/../testData//quickFixes/PyRemoveParameterQuickFixTest/")
public class PyRemoveParameterQuickFixTest extends PyQuickFixTestCase {
public void testParam() {
doQuickFixTest(PyUnusedLocalInspection.class, PyBundle.message("QFIX.NAME.remove.parameter"));
}
public void testKwParam() {
doQuickFixTest(PyUnusedLocalInspection.class, PyBundle.message("QFIX.NAME.remove.parameter"));
}
public void testDocstring() {
doQuickFixTest(PyUnusedLocalInspection.class, PyBundle.message("QFIX.NAME.remove.parameter"));
}
}
@@ -19,6 +19,7 @@ import com.intellij.testFramework.TestDataPath;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyQuickFixTestCase;
import com.jetbrains.python.inspections.PyReturnFromInitInspection;
import com.jetbrains.python.inspections.PyUnusedLocalInspection;
@TestDataPath("$CONTENT_ROOT/../testData//quickFixes/PyRemoveStatementQuickFixTest/")
public class PyRemoveStatementQuickFixTest extends PyQuickFixTestCase {
@@ -31,4 +32,12 @@ public class PyRemoveStatementQuickFixTest extends PyQuickFixTestCase {
doQuickFixTest(PyReturnFromInitInspection.class, PyBundle.message("QFIX.NAME.remove.statement"));
}
public void testFunction() {
doQuickFixTest(PyUnusedLocalInspection.class, PyBundle.message("QFIX.NAME.remove.statement"));
}
public void testVariable() {
doQuickFixTest(PyUnusedLocalInspection.class, PyBundle.message("QFIX.NAME.remove.statement"));
}
}