diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java b/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java index 6f4ebd6ea5c6..88dafd7caf70 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java @@ -91,4 +91,7 @@ public abstract class PyElementGenerator { public abstract PyExpressionStatement createDocstring(String content); public abstract PyPassStatement createPassStatement(); + + @NotNull + public abstract PyDecoratorList createDecoratorList(@NotNull final String... decoratorTexts); } diff --git a/python/src/com/jetbrains/python/inspections/quickfix/PyMakeMethodStaticQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyMakeMethodStaticQuickFix.java index 51ecbf3d8cb3..565fd8aea98e 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/PyMakeMethodStaticQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyMakeMethodStaticQuickFix.java @@ -10,6 +10,9 @@ import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.List; + /** * User: ktisha */ @@ -32,18 +35,26 @@ public class PyMakeMethodStaticQuickFix implements LocalQuickFix { final PsiElement element = descriptor.getPsiElement(); final PyFunction problemFunction = PsiTreeUtil.getParentOfType(element, PyFunction.class); if (problemFunction == null) return; - if (!PyUtil.deleteParameter(problemFunction, 0)) return; + PyUtil.deleteParameter(problemFunction, 0); + + final PyDecoratorList problemDecoratorList = problemFunction.getDecoratorList(); + List decoTexts = new ArrayList(); + decoTexts.add("@staticmethod"); + if (problemDecoratorList != null) { + final PyDecorator[] decorators = problemDecoratorList.getDecorators(); + for (PyDecorator deco : decorators) { + decoTexts.add(deco.getText()); + } + } PyElementGenerator generator = PyElementGenerator.getInstance(project); - final PyFunction function = - generator.createFromText(LanguageLevel.forElement(problemFunction), PyFunction.class, "@staticmethod\ndef foo():\n\tpass"); - final PyDecoratorList decoratorList = function.getDecoratorList(); - assert decoratorList != null; - final PyDecorator[] decorators = decoratorList.getDecorators(); - final PyDecorator decorator = decorators[0]; - problemFunction.addBefore(decorator, problemFunction.getFirstChild()); - - + final PyDecoratorList decoratorList = generator.createDecoratorList(decoTexts.toArray(new String[decoTexts.size()])); + if (problemDecoratorList != null) { + problemDecoratorList.replace(decoratorList); + } + else { + problemFunction.addBefore(decoratorList, problemFunction.getFirstChild()); + } } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java index 1a38ffb26abd..90862eb50165 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java @@ -324,6 +324,22 @@ public class PyElementGeneratorImpl extends PyElementGenerator { return (PyPassStatement)statementList.getStatements()[0]; } + @NotNull + @Override + public PyDecoratorList createDecoratorList(@NotNull final String... decoratorTexts) { + assert decoratorTexts.length > 0; + StringBuilder functionText = new StringBuilder(); + for (String decoText : decoratorTexts) { + functionText.append(decoText).append("\n"); + } + functionText.append("def foo():\n\tpass"); + final PyFunction function = createFromText(LanguageLevel.getDefault(), PyFunction.class, + functionText.toString()); + final PyDecoratorList decoratorList = function.getDecoratorList(); + assert decoratorList != null; + return decoratorList; + } + private PyStatementList createPassStatementList() { final PyFunction function = createFromText(LanguageLevel.getDefault(), PyFunction.class, "def foo():\n\tpass"); return function.getStatementList(); diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams.py new file mode 100644 index 000000000000..7cdd655d6892 --- /dev/null +++ b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams.py @@ -0,0 +1,10 @@ +__author__ = 'ktisha' + +def foo(x): + return x + +class A(): + + @accepts(int, int) + def my_method(self): + print "Smth" \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams_after.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams_after.py new file mode 100644 index 000000000000..21293a929687 --- /dev/null +++ b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/decoWithParams_after.py @@ -0,0 +1,11 @@ +__author__ = 'ktisha' + +def foo(x): + return x + +class A(): + + @staticmethod + @accepts(int, int) + def my_method(): + print "Smth" \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco.py new file mode 100644 index 000000000000..dded2b053894 --- /dev/null +++ b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco.py @@ -0,0 +1,10 @@ +__author__ = 'ktisha' + +def foo(x): + return x + +class A(): + + @my_deco + def my_method(self): + print "Smth" \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco_after.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco_after.py new file mode 100644 index 000000000000..36607a4cca6d --- /dev/null +++ b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/functionWithDeco_after.py @@ -0,0 +1,11 @@ +__author__ = 'ktisha' + +def foo(x): + return x + +class A(): + + @staticmethod + @my_deco + def my_method(): + print "Smth" \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/noSelf.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/noSelf.py new file mode 100644 index 000000000000..9215e8f86577 --- /dev/null +++ b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/noSelf.py @@ -0,0 +1,8 @@ +__author__ = 'ktisha' + +class Child(Base): + def __init__(self): + super(Child, self).__init__() + + def f(): + test = 1 \ No newline at end of file diff --git a/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/noSelf_after.py b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/noSelf_after.py new file mode 100644 index 000000000000..b2fe125ab34f --- /dev/null +++ b/python/testData/quickFixes/PyMakeMethodStaticQuickFixTest/noSelf_after.py @@ -0,0 +1,9 @@ +__author__ = 'ktisha' + +class Child(Base): + def __init__(self): + super(Child, self).__init__() + + @staticmethod + def f(): + test = 1 \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/quickFixes/PyMakeMethodStaticQuickFixTest.java b/python/testSrc/com/jetbrains/python/quickFixes/PyMakeMethodStaticQuickFixTest.java index a13152fac0c3..c2096112ae44 100644 --- a/python/testSrc/com/jetbrains/python/quickFixes/PyMakeMethodStaticQuickFixTest.java +++ b/python/testSrc/com/jetbrains/python/quickFixes/PyMakeMethodStaticQuickFixTest.java @@ -20,4 +20,16 @@ public class PyMakeMethodStaticQuickFixTest extends PyQuickFixTestCase { doInspectionTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static")); } + public void testFunctionWithDeco() { + doInspectionTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static")); + } + + public void testDecoWithParams() { + doInspectionTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static")); + } + + public void testNoSelf() { + doInspectionTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static")); + } + }