fixed PY-9654 Make function from method/Make method static: correctly update class calls with first instance argument

This commit is contained in:
Ekaterina Tuzova
2013-05-29 16:35:09 +04:00
parent b2a2abbce5
commit 536d978917
9 changed files with 87 additions and 15 deletions

View File

@@ -4,9 +4,12 @@ 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.PsiReference;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.usageView.UsageInfo;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.refactoring.PyRefactoringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -35,8 +38,9 @@ public class PyMakeMethodStaticQuickFix implements LocalQuickFix {
final PsiElement element = descriptor.getPsiElement();
final PyFunction problemFunction = PsiTreeUtil.getParentOfType(element, PyFunction.class);
if (problemFunction == null) return;
PyUtil.deleteParameter(problemFunction, 0);
final List<UsageInfo> usages = PyRefactoringUtil.findUsages(problemFunction, false);
PyUtil.deleteParameter(problemFunction, 0);
final PyDecoratorList problemDecoratorList = problemFunction.getDecoratorList();
List<String> decoTexts = new ArrayList<String>();
decoTexts.add("@staticmethod");
@@ -56,5 +60,36 @@ public class PyMakeMethodStaticQuickFix implements LocalQuickFix {
else {
problemFunction.addBefore(decoratorList, problemFunction.getFirstChild());
}
for (UsageInfo usage : usages) {
final PsiElement usageElement = usage.getElement();
if (usageElement instanceof PyReferenceExpression) {
updateUsage((PyReferenceExpression)usageElement);
}
}
}
private static void updateUsage(@NotNull final PyReferenceExpression element) {
final PyExpression qualifier = element.getQualifier();
if (qualifier == null) return;
final PsiReference reference = qualifier.getReference();
if (reference == null) return;
final PsiElement resolved = reference.resolve();
if (resolved instanceof PyClass) { //call with first instance argument A.m(A())
updateArgumentList(element);
}
}
private static void updateArgumentList(@NotNull final PyReferenceExpression element) {
final PyCallExpression callExpression = PsiTreeUtil.getParentOfType(element, PyCallExpression.class);
if (callExpression == null) return;
PyArgumentList argumentList = callExpression.getArgumentList();
if (argumentList == null) return;
final PyExpression[] arguments = argumentList.getArguments();
if (arguments.length > 0) {
final PyExpression argument = arguments[0];
PyUtil.eraseWhitespaceAndComma(argument.getParent().getNode(), argument, false);
argument.delete();
}
}
}

View File

@@ -0,0 +1,6 @@
__author__ = 'ktisha'
class A:
def fo<caret>o(self):
print("Hello Pycharm!")

View File

@@ -0,0 +1,6 @@
class A:
def m<caret>(self, x):
return x
print A.m(A(), 1)

View File

@@ -0,0 +1,3 @@
import test
test.A().foo(1)

View File

@@ -0,0 +1,3 @@
import test
test.A().foo(1)

View File

@@ -0,0 +1,7 @@
class A:
@staticmethod
def m(x):
return x
print A.m(1)

View File

@@ -1,6 +1,5 @@
package com.jetbrains.python.quickFixes;
import com.intellij.codeInsight.intention.IntentionAction;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.inspections.PyMethodMayBeStaticInspection;
@@ -46,21 +45,10 @@ public class PyMakeFunctionFromMethodQuickFixTest extends PyQuickFixTestCase {
}
public void testUsageImport() {
doTest();
doMultifilesTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.function"), new String[]{"test.py"});
}
public void testUsageImport1() {
doTest();
}
protected void doTest() {
final String testFileName = getTestName(true);
myFixture.enableInspections(PyMethodMayBeStaticInspection.class);
myFixture.configureByFiles("test.py", testFileName + ".py");
final IntentionAction intentionAction = myFixture.findSingleIntention(PyBundle.message("QFIX.NAME.make.function"));
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(testFileName + ".py", testFileName + "_after.py", true);
doMultifilesTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.function"), new String[]{"test.py"});
}
}

View File

@@ -32,4 +32,12 @@ public class PyMakeMethodStaticQuickFixTest extends PyQuickFixTestCase {
doInspectionTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static"));
}
public void testUsage() {
doInspectionTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static"));
}
public void testUsageImport() {
doMultifilesTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static"), new String[]{"test.py"});
}
}

View File

@@ -4,6 +4,9 @@ import com.intellij.codeInsight.intention.IntentionAction;
import com.jetbrains.python.PythonTestUtil;
import com.jetbrains.python.fixtures.PyTestCase;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
/**
* User: ktisha
@@ -25,4 +28,17 @@ public abstract class PyQuickFixTestCase extends PyTestCase {
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(testFileName + "_after.py", true);
}
protected void doMultifilesTest(@NotNull final Class inspectionClass, @NotNull final String hint, @NotNull final String[] files) {
final String testFileName = getTestName(true);
myFixture.enableInspections(inspectionClass);
String [] filenames = Arrays.copyOf(files, files.length + 1);
filenames[files.length] = testFileName + ".py";
myFixture.configureByFiles(filenames);
final IntentionAction intentionAction = myFixture.findSingleIntention(hint);
assertNotNull(intentionAction);
myFixture.launchAction(intentionAction);
myFixture.checkResultByFile(testFileName + ".py", testFileName + "_after.py", true);
}
}