diff --git a/compiler/psi/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt b/compiler/psi/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt index 6a1b3f005aa..3b06b5d9896 100644 --- a/compiler/psi/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt +++ b/compiler/psi/src/org/jetbrains/kotlin/psi/psiUtil/ktPsiUtil.kt @@ -578,4 +578,13 @@ fun KtNamedDeclaration.safeFqNameForLazyResolve(): FqName? { //NOTE: should only create special names for package level declarations, so we can safely rely on real fq name for parent val parentFqName = KtNamedDeclarationUtil.getParentFqName(this) return parentFqName?.child(safeNameForLazyResolve()) +} + +fun isTopLevelInFileOrScript(element: PsiElement): Boolean { + val parent = element.parent + return when (parent) { + is KtFile -> true + is KtBlockExpression -> parent.parent is KtScript + else -> false + } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt index aaa95db02a7..44ddb8c052f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt @@ -43,12 +43,13 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext +import org.jetbrains.kotlin.psi.psiUtil.isTopLevelInFileOrScript import java.util.* class MoveKotlinDeclarationsHandler : MoveHandlerDelegate() { private fun getUniqueContainer(elements: Array): PsiElement? { val getContainer: (PsiElement) -> PsiElement? = - if (elements.any { it.parent !is KtFile }) { e -> + if (elements.any { !isTopLevelInFileOrScript(it) }) { e -> when (e) { is KtNamedDeclaration -> e.containingClassOrObject ?: e.parent is KtFile -> e.parent diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt.172 b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt.172 index f551b851c8e..032ec4b8414 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt.172 +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsHandler.kt.172 @@ -43,12 +43,13 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext +import org.jetbrains.kotlin.psi.psiUtil.isTopLevelInFileOrScript import java.util.* class MoveKotlinDeclarationsHandler : MoveHandlerDelegate() { private fun getUniqueContainer(elements: Array): PsiElement? { val getContainer: (PsiElement) -> PsiElement? = - if (elements.any { it.parent !is KtFile }) { e -> + if (elements.any { !isTopLevelInFileOrScript(it) }) { e -> when (e) { is KtNamedDeclaration -> e.containingClassOrObject ?: e.parent is KtFile -> e.parent diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt index 60b456958f7..d4d3bc11ef9 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/MoveKotlinDeclarationsProcessor.kt @@ -71,7 +71,11 @@ interface Mover : (KtNamedDeclaration, KtElement) -> KtNamedDeclaration { object Default : Mover { override fun invoke(originalElement: KtNamedDeclaration, targetContainer: KtElement): KtNamedDeclaration { return when (targetContainer) { - is KtFile -> targetContainer.add(originalElement) as KtNamedDeclaration + is KtFile -> { + val declarationContainer: KtElement = + if (targetContainer.isScript()) targetContainer.script!!.blockExpression else targetContainer + declarationContainer.add(originalElement) as KtNamedDeclaration + } is KtClassOrObject -> targetContainer.addDeclaration(originalElement) else -> error("Unexpected element: ${targetContainer.getElementTextWithContext()}") }.apply { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java index e269b2edc46..c3baa034597 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java @@ -66,6 +66,7 @@ import org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.*; import org.jetbrains.kotlin.idea.refactoring.ui.KotlinFileChooserDialog; import org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt; import org.jetbrains.kotlin.name.FqName; +import org.jetbrains.kotlin.psi.KtDeclarationContainer; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtNamedDeclaration; @@ -77,6 +78,8 @@ import java.io.File; import java.util.*; import java.util.List; +import static java.util.Collections.emptyList; + public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog { private static final String RECENTS_KEY = "MoveKotlinTopLevelDeclarationsDialog.RECENTS_KEY"; private final MoveCallback moveCallback; @@ -169,7 +172,8 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog { new Function1>() { @Override public Iterable invoke(KtFile jetFile) { - return jetFile.getDeclarations(); + KtDeclarationContainer container = jetFile.isScript() ? jetFile.getScript() : jetFile; + return container != null ? container.getDeclarations() : emptyList(); } } ), @@ -190,7 +194,7 @@ public class MoveKotlinTopLevelDeclarationsDialog extends RefactoringDialog { @Nullable String targetFileName, @Nullable final PsiDirectory targetDirectory ) { - if (targetDirectory == null) return Collections.emptyList(); + if (targetDirectory == null) return emptyList(); List fileNames = targetFileName != null diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/after/source/test.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/after/source/test.kt new file mode 100644 index 00000000000..b3fec8e09dd --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/after/source/test.kt @@ -0,0 +1,2 @@ +class Foo + diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/after/source/testNew.kts b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/after/source/testNew.kts new file mode 100644 index 00000000000..4a643c4dde8 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/after/source/testNew.kts @@ -0,0 +1 @@ +class Bar \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/before/source/test.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/before/source/test.kt new file mode 100644 index 00000000000..efe2f76f96b --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/before/source/test.kt @@ -0,0 +1,3 @@ +class Foo + +class Bar \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/before/source/testNew.kts b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/before/source/testNew.kts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/classFromKtToKts.test b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/classFromKtToKts.test new file mode 100644 index 00000000000..e2494798785 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/classFromKtToKts.test @@ -0,0 +1,5 @@ +{ + "mainFile": "source/test.kt", + "type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS", + "targetFile": "source/testNew.kts" +} diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/after/source/test.kts b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/after/source/test.kts new file mode 100644 index 00000000000..b3fec8e09dd --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/after/source/test.kts @@ -0,0 +1,2 @@ +class Foo + diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/after/source/testNew.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/after/source/testNew.kt new file mode 100644 index 00000000000..4a643c4dde8 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/after/source/testNew.kt @@ -0,0 +1 @@ +class Bar \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/before/source/test.kts b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/before/source/test.kts new file mode 100644 index 00000000000..efe2f76f96b --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/before/source/test.kts @@ -0,0 +1,3 @@ +class Foo + +class Bar \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/before/source/testNew.kt b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/before/source/testNew.kt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/classFromKtsToKt.test b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/classFromKtsToKt.test new file mode 100644 index 00000000000..ec8eeb5339b --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/classFromKtsToKt.test @@ -0,0 +1,5 @@ +{ + "mainFile": "source/test.kts", + "type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS", + "targetFile": "source/testNew.kt" +} diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/after/source/test.kts b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/after/source/test.kts new file mode 100644 index 00000000000..b3fec8e09dd --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/after/source/test.kts @@ -0,0 +1,2 @@ +class Foo + diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/after/source/testNew.kts b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/after/source/testNew.kts new file mode 100644 index 00000000000..4a643c4dde8 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/after/source/testNew.kts @@ -0,0 +1 @@ +class Bar \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/before/source/test.kts b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/before/source/test.kts new file mode 100644 index 00000000000..efe2f76f96b --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/before/source/test.kts @@ -0,0 +1,3 @@ +class Foo + +class Bar \ No newline at end of file diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/before/source/testNew.kts b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/before/source/testNew.kts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/classFromKtsToKts.test b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/classFromKtsToKts.test new file mode 100644 index 00000000000..3e68d42ba63 --- /dev/null +++ b/idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/classFromKtsToKts.test @@ -0,0 +1,5 @@ +{ + "mainFile": "source/test.kts", + "type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS", + "targetFile": "source/testNew.kts" +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java index 39d57cfd983..83849be8b5b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/MoveTestGenerated.java @@ -479,6 +479,21 @@ public class MoveTestGenerated extends AbstractMoveTest { runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/implicitInvokeCalls/differentTarget/differentTarget.test"); } + @TestMetadata("kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/classFromKtsToKt.test") + public void testKotlin_moveTopLevelDeclarations_misc_classFromKtsToKt_ClassFromKtsToKt() throws Exception { + runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKt/classFromKtsToKt.test"); + } + + @TestMetadata("kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/classFromKtsToKts.test") + public void testKotlin_moveTopLevelDeclarations_misc_classFromKtsToKts_ClassFromKtsToKts() throws Exception { + runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtsToKts/classFromKtsToKts.test"); + } + + @TestMetadata("kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/classFromKtToKts.test") + public void testKotlin_moveTopLevelDeclarations_misc_classFromKtToKts_ClassFromKtToKts() throws Exception { + runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classFromKtToKts/classFromKtToKts.test"); + } + @TestMetadata("kotlin/moveTopLevelDeclarations/misc/classWithInitializer/delegateInObject.test") public void testKotlin_moveTopLevelDeclarations_misc_classWithInitializer_DelegateInObject() throws Exception { runTest("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/classWithInitializer/delegateInObject.test");