diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDelegate.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDelegate.java index c1c84717490a..c9d6ce6db003 100644 --- a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDelegate.java +++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDelegate.java @@ -36,7 +36,6 @@ import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyBundle; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.psi.PyFile; -import com.jetbrains.python.psi.PyUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -116,8 +115,8 @@ public class PyMoveModuleMembersDelegate extends MoveHandlerDelegate { // Fallback to the old way to select single element to move final PsiNamedElement e = PyMoveModuleMembersHelper.extractNamedElement(element); - if (e != null && PyMoveModuleMembersHelper.isMovableElement(e)) { - if (PyUtil.isTopLevel(e)) { + if (e != null && PyMoveModuleMembersHelper.hasMovableElementType(e)) { + if (PyMoveModuleMembersHelper.isMovableModuleMember(e)) { doMove(project, new PsiElement[]{e}, targetContainer, null); } else { diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersHelper.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersHelper.java index f13b59bf5f92..dd631eb0719e 100644 --- a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersHelper.java +++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersHelper.java @@ -2,6 +2,7 @@ package com.jetbrains.python.refactoring.move; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; +import com.jetbrains.python.PyNames; import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,11 +28,17 @@ public class PyMoveModuleMembersHelper { * @return whether this element is acceptable for "Move ..." refactoring */ public static boolean isMovableModuleMember(@NotNull PsiElement element) { - return isMovableElement(element) && PyUtil.isTopLevel(element); + if (!(hasMovableElementType(element) && PyUtil.isTopLevel(element))) { + return false; + } + if (element instanceof PyTargetExpression) { + return !(PyNames.ALL.equals(((PyTargetExpression)element).getName())) && isTargetOfSimpleAssignment(element); + } + return true; } - public static boolean isMovableElement(@NotNull PsiElement element) { - return element instanceof PyClass || element instanceof PyFunction || isTargetOfSimpleAssignment(element); + public static boolean hasMovableElementType(@NotNull PsiElement element) { + return element instanceof PyClass || element instanceof PyFunction || element instanceof PyTargetExpression; } /** @@ -60,7 +67,7 @@ public class PyMoveModuleMembersHelper { public static List getTopLevelModuleMembers(@NotNull PyFile pyFile) { final List result = new ArrayList(); for (PyTargetExpression attr : pyFile.getTopLevelAttributes()) { - if (isTargetOfSimpleAssignment(attr)) { + if (isMovableModuleMember(attr)) { result.add(attr); } } diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersProcessor.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersProcessor.java index c444f9d66f68..eb020bb9d902 100644 --- a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersProcessor.java @@ -35,6 +35,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; +import com.jetbrains.python.codeInsight.PyDunderAllReference; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.QualifiedNameFinder; @@ -220,8 +221,13 @@ public class PyMoveModuleMembersProcessor extends BaseRefactoringProcessor { } if (usage instanceof PyStringLiteralExpression) { for (PsiReference ref : usage.getReferences()) { - if (ref.isReferenceTo(oldElement)) { - ref.bindToElement(newElement); + if ((ref instanceof PyDunderAllReference)) { + usage.delete(); + } + else { + if (ref.isReferenceTo(oldElement)) { + ref.bindToElement(newElement); + } } } } diff --git a/python/testData/refactoring/move/dunderAll/after/src/a.py b/python/testData/refactoring/move/dunderAll/after/src/a.py new file mode 100644 index 000000000000..2baf29a799ba --- /dev/null +++ b/python/testData/refactoring/move/dunderAll/after/src/a.py @@ -0,0 +1,8 @@ +__all__ = ['C'] + + + + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAll/after/src/b.py b/python/testData/refactoring/move/dunderAll/after/src/b.py new file mode 100644 index 000000000000..06075aebd98e --- /dev/null +++ b/python/testData/refactoring/move/dunderAll/after/src/b.py @@ -0,0 +1,2 @@ +def func(): + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAll/before/src/a.py b/python/testData/refactoring/move/dunderAll/before/src/a.py new file mode 100644 index 000000000000..44885d7e59c3 --- /dev/null +++ b/python/testData/refactoring/move/dunderAll/before/src/a.py @@ -0,0 +1,9 @@ +__all__ = ['func', 'C'] + + +def func(): + pass + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAll/before/src/b.py b/python/testData/refactoring/move/dunderAll/before/src/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/a.py b/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/a.py new file mode 100644 index 000000000000..1fe7dabf9398 --- /dev/null +++ b/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/a.py @@ -0,0 +1,5 @@ +__all__ = () + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/b.py b/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/b.py new file mode 100644 index 000000000000..06075aebd98e --- /dev/null +++ b/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/b.py @@ -0,0 +1,2 @@ +def func(): + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/a.py b/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/a.py new file mode 100644 index 000000000000..5cbf71790ced --- /dev/null +++ b/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/a.py @@ -0,0 +1,9 @@ +__all__ = 'func', + + +def func(): + pass + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/b.py b/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/a.py b/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/a.py new file mode 100644 index 000000000000..94cfac702a68 --- /dev/null +++ b/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/a.py @@ -0,0 +1,8 @@ +__all__ = ('C',) + + + + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/b.py b/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/b.py new file mode 100644 index 000000000000..06075aebd98e --- /dev/null +++ b/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/b.py @@ -0,0 +1,2 @@ +def func(): + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/a.py b/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/a.py new file mode 100644 index 000000000000..d51579fb56a1 --- /dev/null +++ b/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/a.py @@ -0,0 +1,9 @@ +__all__ = ('func', 'C') + + +def func(): + pass + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/b.py b/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java index cbb5c10669a4..37c3d40f2c07 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java @@ -319,7 +319,22 @@ public class PyMoveTest extends PyTestCase { doMoveSymbolsTest("b.py", "f", "A"); } - private void doMoveFileTest(String fileName, String toDirName) { + // PY-15343 + public void testDunderAll() { + doMoveSymbolTest("func", "b.py"); + } + + // PY-15343 + public void testDunderAllSingleElementTuple() { + doMoveSymbolTest("func", "b.py"); + } + + // PY-15343 + public void testDunderAllTwoElementsTuple() { + doMoveSymbolTest("func", "b.py"); + } + + private void doMoveFileTest(String fileName, String toDirName) { Project project = myFixture.getProject(); PsiManager manager = PsiManager.getInstance(project); @@ -340,7 +355,7 @@ public class PyMoveTest extends PyTestCase { VirtualFile toVirtualDir = dir1.findFileByRelativePath(toDirName); assertNotNull(toVirtualDir); PsiDirectory toDir = manager.findDirectory(toVirtualDir); - new MoveFilesOrDirectoriesProcessor(project, new PsiElement[] {file}, toDir, false, false, null, null).run(); + new MoveFilesOrDirectoriesProcessor(project, new PsiElement[]{file}, toDir, false, false, null, null).run(); VirtualFile dir2 = getVirtualFileByName(PythonTestUtil.getTestDataPath() + rootAfter); try {