From 2cc672b113de72adff23182eebc3aad473bcf43d Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Mon, 17 Feb 2014 21:15:16 +0400 Subject: [PATCH] PY-12175 Extract superclass: import for existing super class is removed --- .../PyExtractSuperclassHelper.java | 6 ++++-- .../PyMembersRefactoringBaseProcessor.java | 2 ++ .../membersManager/SuperClassesManager.java | 11 +++++++---- .../membersManager/TypeSafeMovingStrategy.java | 2 -- .../extractsuperclass/importNotBroken.after.py | 9 +++++++++ .../extractsuperclass/importNotBroken.before.py | 5 +++++ .../dest_module.after.py | 5 +++++ .../importNotBrokenManyFiles/dest_module.py | 0 .../importNotBrokenManyFiles/shared_module.py | 1 + .../source_module.after.py | 5 +++++ .../importNotBrokenManyFiles/source_module.py | 4 ++++ .../moveExtends/source_module.after.py | 4 ++-- .../dest_module.after.py | 5 +++++ .../moveExtendsCheckReference/dest_module.py | 0 .../moveExtendsCheckReference/shared_module.py | 2 ++ .../source_module.after.py | 5 +++++ .../moveExtendsCheckReference/source_module.py | 4 ++++ .../refactoring/extractsuperclass/shared.py | 1 + .../PyExtractSuperclassTest.java | 16 ++++++++++++++++ 19 files changed, 77 insertions(+), 10 deletions(-) create mode 100644 python/testData/refactoring/extractsuperclass/importNotBroken.after.py create mode 100644 python/testData/refactoring/extractsuperclass/importNotBroken.before.py create mode 100644 python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.after.py create mode 100644 python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.py create mode 100644 python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/shared_module.py create mode 100644 python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.after.py create mode 100644 python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.py create mode 100644 python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.after.py create mode 100644 python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.py create mode 100644 python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/shared_module.py create mode 100644 python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.after.py create mode 100644 python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.py create mode 100644 python/testData/refactoring/extractsuperclass/shared.py diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java index 41d0362f65d9..52657c67d9a8 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java +++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java @@ -60,7 +60,6 @@ public final class PyExtractSuperclassHelper { @NotNull Collection> selectedMemberInfos, final String superBaseName, final String targetFile) { - //We will need to change it probably while param may be read-only //noinspection AssignmentToMethodParameter selectedMemberInfos = new ArrayList>(selectedMemberInfos); @@ -88,9 +87,12 @@ public final class PyExtractSuperclassHelper { PyClass newClass = PyElementGenerator.getInstance(project).createFromText(LanguageLevel.getDefault(), PyClass.class, text); newClass = placeNewClass(project, newClass, clazz, targetFile); - MembersManager.moveAllMembers(selectedMemberInfos, clazz, newClass); + if (! newClass.getContainingFile().equals(clazz.getContainingFile())) { + PyClassRefactoringUtil.optimizeImports(clazz.getContainingFile()); // To remove unneeded imports only if user used different file + } PyClassRefactoringUtil.addSuperclasses(project, clazz, null, newClass); + } private static PyClass placeNewClass(final Project project, PyClass newClass, @NotNull final PyClass clazz, final String targetFile) { diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java index 2744cf0ae9aa..983deb65f601 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java @@ -7,6 +7,7 @@ import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewDescriptor; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; +import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -80,5 +81,6 @@ public abstract class PyMembersRefactoringBaseProcessor extends BaseRefactoringP destinations.add(((PyUsageInfo)usage).getTo()); } MembersManager.moveAllMembers(myMembersToMove, myFrom, destinations.toArray(new PyClass[destinations.size()])); + PyClassRefactoringUtil.optimizeImports(myFrom.getContainingFile()); // To remove unneeded imports } } diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java index 1d2a3d47996a..82ce209931f7 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java @@ -5,9 +5,7 @@ import com.google.common.collect.Lists; import com.intellij.refactoring.RefactoringBundle; import com.jetbrains.NotNullPredicate; import com.jetbrains.python.PyNames; -import com.jetbrains.python.psi.PyClass; -import com.jetbrains.python.psi.PyElement; -import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.psi.*; import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil; import com.jetbrains.python.refactoring.classes.ui.PyClassCellRenderer; import org.jetbrains.annotations.NotNull; @@ -47,8 +45,13 @@ class SuperClassesManager extends MembersManager { } for (final PyExpression expression : from.getSuperClassExpressions()) { + // Remove all superclass expressions that point to class from memberinfo + if (!(expression instanceof PyQualifiedExpression)) { + continue; + } + final PyReferenceExpression reference = (PyReferenceExpression)expression; for (final PyClass element : elements) { - if (expression.getText().equals(element.getName())) { + if (reference.getReference().isReferenceTo(element)) { expression.delete(); } } diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/TypeSafeMovingStrategy.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/TypeSafeMovingStrategy.java index a55a7d215346..2cf9efda6d4a 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/TypeSafeMovingStrategy.java +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/TypeSafeMovingStrategy.java @@ -66,7 +66,5 @@ class TypeSafeMovingStrategy { for (final PyElement element : newElements) { PyClassRefactoringUtil.restoreNamedReferences(element); } - - PyClassRefactoringUtil.optimizeImports(myFrom.getContainingFile()); // To remove unneeded imports from source } } diff --git a/python/testData/refactoring/extractsuperclass/importNotBroken.after.py b/python/testData/refactoring/extractsuperclass/importNotBroken.after.py new file mode 100644 index 000000000000..897c62a71cfc --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/importNotBroken.after.py @@ -0,0 +1,9 @@ +from shared import SharedClass + + +class DestClass(SharedClass): + pass + + +class Source(DestClass): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/importNotBroken.before.py b/python/testData/refactoring/extractsuperclass/importNotBroken.before.py new file mode 100644 index 000000000000..82d6d5c04c20 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/importNotBroken.before.py @@ -0,0 +1,5 @@ +from shared import SharedClass + + +class Source(SharedClass): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.after.py b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.after.py new file mode 100644 index 000000000000..6189ad4fc76b --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.after.py @@ -0,0 +1,5 @@ +from shared_module import SharedClass + + +class NewParent(SharedClass): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.py b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/shared_module.py b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/shared_module.py new file mode 100644 index 000000000000..da81c49673f4 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/shared_module.py @@ -0,0 +1 @@ +class SharedClass(object): pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.after.py b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.after.py new file mode 100644 index 000000000000..b9d711783970 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.after.py @@ -0,0 +1,5 @@ +from dest_module import NewParent + + +class MyClass(NewParent): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.py b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.py new file mode 100644 index 000000000000..1824aec09d61 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.py @@ -0,0 +1,4 @@ +from shared_module import SharedClass + +class MyClass(SharedClass): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/moveExtends/source_module.after.py b/python/testData/refactoring/extractsuperclass/moveExtends/source_module.after.py index b5e6cda02c55..b9d711783970 100644 --- a/python/testData/refactoring/extractsuperclass/moveExtends/source_module.after.py +++ b/python/testData/refactoring/extractsuperclass/moveExtends/source_module.after.py @@ -1,5 +1,5 @@ from dest_module import NewParent -import shared_module -class MyClass(shared_module.TheParentOfItAll, NewParent): + +class MyClass(NewParent): pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.after.py b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.after.py new file mode 100644 index 000000000000..1171abf73b10 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.after.py @@ -0,0 +1,5 @@ +from shared_module import TheParentOfItAll + + +class NewParent(TheParentOfItAll): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.py b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/shared_module.py b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/shared_module.py new file mode 100644 index 000000000000..fd3d3fc7bf88 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/shared_module.py @@ -0,0 +1,2 @@ +class TheParentOfItAll(object): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.after.py b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.after.py new file mode 100644 index 000000000000..b9d711783970 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.after.py @@ -0,0 +1,5 @@ +from dest_module import NewParent + + +class MyClass(NewParent): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.py b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.py new file mode 100644 index 000000000000..c2ca97497a33 --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.py @@ -0,0 +1,4 @@ +from shared_module import TheParentOfItAll + +class MyClass(TheParentOfItAll): + pass \ No newline at end of file diff --git a/python/testData/refactoring/extractsuperclass/shared.py b/python/testData/refactoring/extractsuperclass/shared.py new file mode 100644 index 000000000000..71f03ab781fc --- /dev/null +++ b/python/testData/refactoring/extractsuperclass/shared.py @@ -0,0 +1 @@ +class SharedClass: pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java index 34a1c852311d..13d5b4d4f253 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java @@ -54,6 +54,11 @@ public class PyExtractSuperclassTest extends PyClassRefactoringTest { multiFileTestHelper("TheParentOfItAll", false); } + // Checks that moving methods between files moves superclass expressions regardless import style (q.name or name) + public void testMoveExtendsCheckReference() throws Throwable { + multiFileTestHelper("TheParentOfItAll", false); + } + // Extracts method as abstract public void testMoveAndMakeAbstract() throws Throwable { multiFileTestHelper(".foo_method", true); @@ -105,6 +110,17 @@ public class PyExtractSuperclassTest extends PyClassRefactoringTest { doSimpleTest("A", "Suppa", null, false, ".foo"); } + // PY-12175 + public void testImportNotBroken() throws Exception { + myFixture.copyFileToProject("/refactoring/extractsuperclass/shared.py", "shared.py"); + doSimpleTest("Source", "DestClass", null, true, "SharedClass"); + } + + // PY-12175 but between several files + public void testImportNotBrokenManyFiles() throws Exception { + multiFileTestHelper("SharedClass", false); + } + public void testMoveFields() throws Exception { doSimpleTest("FromClass", "ToClass", null, true, "#instance_field", "#CLASS_FIELD"); }