fixed PY-9405 Method can be static: handle existing decorators

This commit is contained in:
Ekaterina Tuzova
2013-04-09 14:41:50 +04:00
parent 913e96ea0e
commit 6eb69aa83a
10 changed files with 111 additions and 10 deletions

View File

@@ -91,4 +91,7 @@ public abstract class PyElementGenerator {
public abstract PyExpressionStatement createDocstring(String content); public abstract PyExpressionStatement createDocstring(String content);
public abstract PyPassStatement createPassStatement(); public abstract PyPassStatement createPassStatement();
@NotNull
public abstract PyDecoratorList createDecoratorList(@NotNull final String... decoratorTexts);
} }

View File

@@ -10,6 +10,9 @@ import com.jetbrains.python.psi.*;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/** /**
* User: ktisha * User: ktisha
*/ */
@@ -32,18 +35,26 @@ public class PyMakeMethodStaticQuickFix implements LocalQuickFix {
final PsiElement element = descriptor.getPsiElement(); final PsiElement element = descriptor.getPsiElement();
final PyFunction problemFunction = PsiTreeUtil.getParentOfType(element, PyFunction.class); final PyFunction problemFunction = PsiTreeUtil.getParentOfType(element, PyFunction.class);
if (problemFunction == null) return; if (problemFunction == null) return;
if (!PyUtil.deleteParameter(problemFunction, 0)) return; PyUtil.deleteParameter(problemFunction, 0);
final PyDecoratorList problemDecoratorList = problemFunction.getDecoratorList();
List<String> decoTexts = new ArrayList<String>();
decoTexts.add("@staticmethod");
if (problemDecoratorList != null) {
final PyDecorator[] decorators = problemDecoratorList.getDecorators();
for (PyDecorator deco : decorators) {
decoTexts.add(deco.getText());
}
}
PyElementGenerator generator = PyElementGenerator.getInstance(project); PyElementGenerator generator = PyElementGenerator.getInstance(project);
final PyFunction function = final PyDecoratorList decoratorList = generator.createDecoratorList(decoTexts.toArray(new String[decoTexts.size()]));
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());
if (problemDecoratorList != null) {
problemDecoratorList.replace(decoratorList);
}
else {
problemFunction.addBefore(decoratorList, problemFunction.getFirstChild());
}
} }
} }

View File

@@ -324,6 +324,22 @@ public class PyElementGeneratorImpl extends PyElementGenerator {
return (PyPassStatement)statementList.getStatements()[0]; 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() { private PyStatementList createPassStatementList() {
final PyFunction function = createFromText(LanguageLevel.getDefault(), PyFunction.class, "def foo():\n\tpass"); final PyFunction function = createFromText(LanguageLevel.getDefault(), PyFunction.class, "def foo():\n\tpass");
return function.getStatementList(); return function.getStatementList();

View File

@@ -0,0 +1,10 @@
__author__ = 'ktisha'
def foo(x):
return x
class A():
@accepts(int, int)
def my_<caret>method(self):
print "Smth"

View File

@@ -0,0 +1,11 @@
__author__ = 'ktisha'
def foo(x):
return x
class A():
@staticmethod
@accepts(int, int)
def my_<caret>method():
print "Smth"

View File

@@ -0,0 +1,10 @@
__author__ = 'ktisha'
def foo(x):
return x
class A():
@my_deco
def my_<caret>method(self):
print "Smth"

View File

@@ -0,0 +1,11 @@
__author__ = 'ktisha'
def foo(x):
return x
class A():
@staticmethod
@my_deco
def my_method():
print "Smth"

View File

@@ -0,0 +1,8 @@
__author__ = 'ktisha'
class Child(Base):
def __init__(self):
super(Child, self).__init__()
def <caret>f():
test = 1

View File

@@ -0,0 +1,9 @@
__author__ = 'ktisha'
class Child(Base):
def __init__(self):
super(Child, self).__init__()
@staticmethod
def f():
test = 1

View File

@@ -20,4 +20,16 @@ public class PyMakeMethodStaticQuickFixTest extends PyQuickFixTestCase {
doInspectionTest(PyMethodMayBeStaticInspection.class, PyBundle.message("QFIX.NAME.make.static")); 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"));
}
} }