mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-15 20:26:04 +07:00
fixed PY-9654 Make function from method/Make method static: correctly update class calls with first instance argument
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
__author__ = 'ktisha'
|
||||
|
||||
class A:
|
||||
def fo<caret>o(self):
|
||||
print("Hello Pycharm!")
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
class A:
|
||||
def m<caret>(self, x):
|
||||
return x
|
||||
|
||||
|
||||
print A.m(A(), 1)
|
||||
@@ -0,0 +1,3 @@
|
||||
import test
|
||||
|
||||
test.A().foo(1)
|
||||
@@ -0,0 +1,3 @@
|
||||
import test
|
||||
|
||||
test.A().foo(1)
|
||||
@@ -0,0 +1,7 @@
|
||||
class A:
|
||||
@staticmethod
|
||||
def m(x):
|
||||
return x
|
||||
|
||||
|
||||
print A.m(1)
|
||||
@@ -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"});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user