From 23788a4a64273dec413a6b8f3e2224f026795d1e Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 17 Aug 2010 19:35:52 +0400 Subject: [PATCH] Introduce Field honors name of method argument (PY-1580) --- .../introduce/IntroduceHandler.java | 24 +++++++++++++++++-- .../field/FieldIntroduceHandler.java | 16 +++++++++++-- .../variable/VariableIntroduceHandler.java | 24 +------------------ .../introduceField/metaClass.after.py | 4 ++++ .../refactoring/introduceField/metaClass.py | 3 +++ .../jetbrains/python/PythonAllTestsSuite.java | 1 + .../refactoring/PyIntroduceFieldTest.java | 20 ++++++++++++++++ 7 files changed, 65 insertions(+), 27 deletions(-) create mode 100644 python/testData/refactoring/introduceField/metaClass.after.py create mode 100644 python/testData/refactoring/introduceField/metaClass.py create mode 100644 python/testSrc/com/jetbrains/python/refactoring/PyIntroduceFieldTest.java diff --git a/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java b/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java index 9ff5f6b5f5e6..3a3a84d51aa2 100644 --- a/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java +++ b/python/src/com/jetbrains/python/refactoring/introduce/IntroduceHandler.java @@ -36,6 +36,25 @@ import java.util.*; * @author Alexey.Ivanov */ abstract public class IntroduceHandler implements RefactoringActionHandler { + protected static PsiElement findAnchor(List occurrences) { + PsiElement anchor = occurrences.get(0); + next: + do { + PyStatement statement = PsiTreeUtil.getParentOfType(anchor, PyStatement.class); + + final PsiElement parent = statement.getParent(); + for (PsiElement element : occurrences) { + if (!PsiTreeUtil.isAncestor(parent, element, true)) { + anchor = statement; + continue next; + } + } + + return statement; + } + while (true); + } + public enum InitPlace { SAME_METHOD, CONSTRUCTOR, @@ -234,7 +253,8 @@ abstract public class IntroduceHandler implements RefactoringActionHandler { initInConstructor = dialog.getInitPlace(); } String assignmentText = name + " = " + expression.getText(); - PyAssignmentStatement declaration = createDeclaration(project, assignmentText); + PsiElement anchor = replaceAll ? findAnchor(occurrences) : PsiTreeUtil.getParentOfType(expression, PyStatement.class); + PyAssignmentStatement declaration = createDeclaration(project, assignmentText, anchor); assert name != null; declaration = performReplace(project, declaration, expression, occurrences, name, replaceAll, initInConstructor); @@ -245,7 +265,7 @@ abstract public class IntroduceHandler implements RefactoringActionHandler { protected abstract String getHelpId(); - protected PyAssignmentStatement createDeclaration(Project project, String assignmentText) { + protected PyAssignmentStatement createDeclaration(Project project, String assignmentText, PsiElement anchor) { return PyElementGenerator.getInstance(project).createFromText(PyAssignmentStatement.class, assignmentText); } diff --git a/python/src/com/jetbrains/python/refactoring/introduce/field/FieldIntroduceHandler.java b/python/src/com/jetbrains/python/refactoring/introduce/field/FieldIntroduceHandler.java index a7ca72f7b10a..e352715792a4 100644 --- a/python/src/com/jetbrains/python/refactoring/introduce/field/FieldIntroduceHandler.java +++ b/python/src/com/jetbrains/python/refactoring/introduce/field/FieldIntroduceHandler.java @@ -8,6 +8,7 @@ import com.intellij.openapi.editor.SelectionModel; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.util.Function; @@ -107,8 +108,19 @@ public class FieldIntroduceHandler extends IntroduceHandler { } @Override - protected PyAssignmentStatement createDeclaration(Project project, String assignmentText) { - return PyElementGenerator.getInstance(project).createFromText(PyAssignmentStatement.class, PyNames.CANONICAL_SELF + "." + assignmentText); + protected PyAssignmentStatement createDeclaration(Project project, String assignmentText, PsiElement anchor) { + String selfName = PyNames.CANONICAL_SELF; + final PyFunction container = PsiTreeUtil.getParentOfType(anchor, PyFunction.class); + if (container != null) { + final PyParameter[] params = container.getParameterList().getParameters(); + if (params.length > 0) { + final PyNamedParameter named = params[0].getAsNamed(); + if (named != null) { + selfName = named.getName(); + } + } + } + return PyElementGenerator.getInstance(project).createFromText(PyAssignmentStatement.class, selfName + "." + assignmentText); } @Override diff --git a/python/src/com/jetbrains/python/refactoring/introduce/variable/VariableIntroduceHandler.java b/python/src/com/jetbrains/python/refactoring/introduce/variable/VariableIntroduceHandler.java index b365a0c0e0d8..9085ca011808 100644 --- a/python/src/com/jetbrains/python/refactoring/introduce/variable/VariableIntroduceHandler.java +++ b/python/src/com/jetbrains/python/refactoring/introduce/variable/VariableIntroduceHandler.java @@ -10,10 +10,7 @@ import org.jetbrains.annotations.NotNull; import java.util.List; /** - * Created by IntelliJ IDEA. - * User: Alexey.Ivanov - * Date: Aug 19, 2009 - * Time: 5:22:02 PM + * @author Alexey.Ivanov */ public class VariableIntroduceHandler extends IntroduceHandler { public VariableIntroduceHandler() { @@ -39,25 +36,6 @@ public class VariableIntroduceHandler extends IntroduceHandler { return parent.addBefore(declaration, anchor); } - private static PsiElement findAnchor(List occurrences) { - PsiElement anchor = occurrences.get(0); - next: - do { - PyStatement statement = PsiTreeUtil.getParentOfType(anchor, PyStatement.class); - - final PsiElement parent = statement.getParent(); - for (PsiElement element : occurrences) { - if (!PsiTreeUtil.isAncestor(parent, element, true)) { - anchor = statement; - continue next; - } - } - - return statement; - } - while (true); - } - @Override protected String getHelpId() { return "refactoring.introduceVariable"; diff --git a/python/testData/refactoring/introduceField/metaClass.after.py b/python/testData/refactoring/introduceField/metaClass.after.py new file mode 100644 index 000000000000..6c22281c4cf0 --- /dev/null +++ b/python/testData/refactoring/introduceField/metaClass.after.py @@ -0,0 +1,4 @@ +class DirectMeta(type): + def __init__(cls, arg1, arg2): + cls.a = arg1 + print cls.a diff --git a/python/testData/refactoring/introduceField/metaClass.py b/python/testData/refactoring/introduceField/metaClass.py new file mode 100644 index 000000000000..0315e44b687d --- /dev/null +++ b/python/testData/refactoring/introduceField/metaClass.py @@ -0,0 +1,3 @@ +class DirectMeta(type): + def __init__(cls, arg1, arg2): + print arg1 diff --git a/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java b/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java index e05623eb7580..e11aa2b425d4 100644 --- a/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java +++ b/python/testSrc/com/jetbrains/python/PythonAllTestsSuite.java @@ -57,6 +57,7 @@ public class PythonAllTestsSuite { PySmartEnterTest.class, PyStatementMoverTest.class, PyIntroduceVariableTest.class, + PyIntroduceFieldTest.class, PyClassNameCompletionTest.class, PySuppressInspectionsTest.class, PyPropertyTestSuite.PyClassicPropertyTest.class, diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceFieldTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceFieldTest.java new file mode 100644 index 000000000000..da28f498e42d --- /dev/null +++ b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceFieldTest.java @@ -0,0 +1,20 @@ +package com.jetbrains.python.refactoring; + +import com.jetbrains.python.fixtures.PyLightFixtureTestCase; +import com.jetbrains.python.refactoring.introduce.field.FieldIntroduceHandler; + +/** + * @author yole + */ +public class PyIntroduceFieldTest extends PyLightFixtureTestCase { + public void testMetaClass() { // PY-1580 + doTest(); + } + + private void doTest() { + myFixture.configureByFile("/refactoring/introduceField/" + getTestName(true) + ".py"); + FieldIntroduceHandler handler = new FieldIntroduceHandler(); + handler.performAction(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile(), "a", true, false, false); + myFixture.checkResultByFile("/refactoring/introduceField/" + getTestName(true) + ".after.py"); + } +}