From dd6b3a2aa00317ade1b3985009d156279bc9a570 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Wed, 12 Mar 2014 19:50:39 +0400 Subject: [PATCH] added Remove call quick fix to the Trying to call a non-callable object inspection --- .../com/jetbrains/python/PyBundle.properties | 2 + .../PyCallingNonCallableInspection.java | 7 +-- .../quickfix/PyRemoveCallQuickFix.java | 53 +++++++++++++++++++ .../PyRemoveCallQuickFixTest/class.py | 6 +++ .../PyRemoveCallQuickFixTest/class_after.py | 6 +++ .../PyRemoveCallQuickFixTest/decorator.py | 12 +++++ .../decorator_after.py | 11 ++++ .../PyRemoveCallQuickFixTest/expression.py | 4 ++ .../expression_after.py | 4 ++ .../quickFixes/PyRemoveCallQuickFixTest.java | 38 +++++++++++++ 10 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 python/src/com/jetbrains/python/inspections/quickfix/PyRemoveCallQuickFix.java create mode 100644 python/testData/quickFixes/PyRemoveCallQuickFixTest/class.py create mode 100644 python/testData/quickFixes/PyRemoveCallQuickFixTest/class_after.py create mode 100644 python/testData/quickFixes/PyRemoveCallQuickFixTest/decorator.py create mode 100644 python/testData/quickFixes/PyRemoveCallQuickFixTest/decorator_after.py create mode 100644 python/testData/quickFixes/PyRemoveCallQuickFixTest/expression.py create mode 100644 python/testData/quickFixes/PyRemoveCallQuickFixTest/expression_after.py create mode 100644 python/testSrc/com/jetbrains/python/quickFixes/PyRemoveCallQuickFixTest.java diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties index 93dab333a159..6559bc35559c 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.remove.statement=Remove statement +QFIX.NAME.remove.call=Remove call + QFIX.NAME.move.except.up=Move except clause up QFIX.NAME.remove.dict.key=Remove this key diff --git a/python/src/com/jetbrains/python/inspections/PyCallingNonCallableInspection.java b/python/src/com/jetbrains/python/inspections/PyCallingNonCallableInspection.java index 4af6767fbcb2..04477b1be313 100644 --- a/python/src/com/jetbrains/python/inspections/PyCallingNonCallableInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyCallingNonCallableInspection.java @@ -19,6 +19,7 @@ import com.intellij.codeInspection.LocalInspectionToolSession; import com.intellij.codeInspection.ProblemsHolder; import com.intellij.psi.PsiElementVisitor; import com.jetbrains.python.PyNames; +import com.jetbrains.python.inspections.quickfix.PyRemoveCallQuickFix; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.types.PyClassType; import com.jetbrains.python.psi.types.PyType; @@ -78,13 +79,13 @@ public class PyCallingNonCallableInspection extends PyInspection { if (!callable) { final PyType calleeType = callee != null ? myTypeEvalContext.getType(callee) : type; if (calleeType instanceof PyClassType) { - registerProblem(node, String.format("'%s' object is not callable", calleeType.getName())); + registerProblem(node, String.format("'%s' object is not callable", calleeType.getName()), new PyRemoveCallQuickFix()); } else if (callee != null) { - registerProblem(node, String.format("'%s' is not callable", callee.getName())); + registerProblem(node, String.format("'%s' is not callable", callee.getName()), new PyRemoveCallQuickFix()); } else { - registerProblem(node, "Expression is not callable"); + registerProblem(node, "Expression is not callable", new PyRemoveCallQuickFix()); } } } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveCallQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveCallQuickFix.java new file mode 100644 index 000000000000..9753f258fc31 --- /dev/null +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyRemoveCallQuickFix.java @@ -0,0 +1,53 @@ +/* + * 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.jetbrains.python.PyBundle; +import com.jetbrains.python.psi.PyArgumentList; +import com.jetbrains.python.psi.PyCallExpression; +import com.jetbrains.python.psi.PyDecorator; +import org.jetbrains.annotations.NotNull; + +public class PyRemoveCallQuickFix implements LocalQuickFix { + @NotNull + @Override + public String getName() { + return PyBundle.message("QFIX.NAME.remove.call"); + } + + @NotNull + public String getFamilyName() { + return getName(); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiElement call = descriptor.getPsiElement(); + assert call instanceof PyCallExpression; + if (call instanceof PyDecorator) { + call.delete(); + } + else { + final PyArgumentList argumentList = ((PyCallExpression)call).getArgumentList(); + assert argumentList != null; + argumentList.delete(); + } + } +} diff --git a/python/testData/quickFixes/PyRemoveCallQuickFixTest/class.py b/python/testData/quickFixes/PyRemoveCallQuickFixTest/class.py new file mode 100644 index 000000000000..52530e7b14d1 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveCallQuickFixTest/class.py @@ -0,0 +1,6 @@ + +class A(): + x = "" + + +b = A().x() \ No newline at end of file diff --git a/python/testData/quickFixes/PyRemoveCallQuickFixTest/class_after.py b/python/testData/quickFixes/PyRemoveCallQuickFixTest/class_after.py new file mode 100644 index 000000000000..ee10a08744c3 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveCallQuickFixTest/class_after.py @@ -0,0 +1,6 @@ + +class A(): + x = "" + + +b = A().x \ No newline at end of file diff --git a/python/testData/quickFixes/PyRemoveCallQuickFixTest/decorator.py b/python/testData/quickFixes/PyRemoveCallQuickFixTest/decorator.py new file mode 100644 index 000000000000..7f8efe576fa9 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveCallQuickFixTest/decorator.py @@ -0,0 +1,12 @@ + +a = "" + +def b(c): + pass + + +@a +@b +def foo(): + pass + diff --git a/python/testData/quickFixes/PyRemoveCallQuickFixTest/decorator_after.py b/python/testData/quickFixes/PyRemoveCallQuickFixTest/decorator_after.py new file mode 100644 index 000000000000..9bcfe6741bcf --- /dev/null +++ b/python/testData/quickFixes/PyRemoveCallQuickFixTest/decorator_after.py @@ -0,0 +1,11 @@ + +a = "" + +def b(c): + pass + + +@b +def foo(): + pass + diff --git a/python/testData/quickFixes/PyRemoveCallQuickFixTest/expression.py b/python/testData/quickFixes/PyRemoveCallQuickFixTest/expression.py new file mode 100644 index 000000000000..7b9faddb5789 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveCallQuickFixTest/expression.py @@ -0,0 +1,4 @@ + +a = "string" + +b = a() \ No newline at end of file diff --git a/python/testData/quickFixes/PyRemoveCallQuickFixTest/expression_after.py b/python/testData/quickFixes/PyRemoveCallQuickFixTest/expression_after.py new file mode 100644 index 000000000000..f1bae37c79e8 --- /dev/null +++ b/python/testData/quickFixes/PyRemoveCallQuickFixTest/expression_after.py @@ -0,0 +1,4 @@ + +a = "string" + +b = a \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveCallQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveCallQuickFixTest.java new file mode 100644 index 000000000000..4538bf384e8b --- /dev/null +++ b/python/testSrc/com/jetbrains/python/quickFixes/PyRemoveCallQuickFixTest.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.PyCallingNonCallableInspection; + +@TestDataPath("$CONTENT_ROOT/../testData/quickFixes/PyRemoveCallQuickFixTest/") +public class PyRemoveCallQuickFixTest extends PyQuickFixTestCase { + + public void testExpression() { + doQuickFixTest(PyCallingNonCallableInspection.class, PyBundle.message("QFIX.NAME.remove.call")); + } + + public void testDecorator() { + doQuickFixTest(PyCallingNonCallableInspection.class, PyBundle.message("QFIX.NAME.remove.call")); + } + + public void testClass() { + doQuickFixTest(PyCallingNonCallableInspection.class, PyBundle.message("QFIX.NAME.remove.call")); + } + +}