diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index 2f5374f6a08..6b0c838b4d7 100755 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -677,8 +677,8 @@ fun main(args: Array) { model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest") model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest") model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest") - model("refactoring/extractSuperclass", pattern = KT_OR_KTS, testMethod = "doExtractSuperclassTest") - model("refactoring/extractInterface", pattern = KT_OR_KTS, testMethod = "doExtractInterfaceTest") + model("refactoring/extractSuperclass", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractSuperclassTest") + model("refactoring/extractInterface", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractInterfaceTest") } testClass { diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.172 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.172 index 98bb2c6b5e8..43fbebaae4c 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.172 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.172 @@ -675,8 +675,8 @@ fun main(args: Array) { model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest") model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest") model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest") - model("refactoring/extractSuperclass", pattern = KT_OR_KTS, testMethod = "doExtractSuperclassTest") - model("refactoring/extractInterface", pattern = KT_OR_KTS, testMethod = "doExtractInterfaceTest") + model("refactoring/extractSuperclass", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractSuperclassTest") + model("refactoring/extractInterface", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractInterfaceTest") } testClass { diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as31 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as31 index 5bbbac961fa..3eaaa7d0da9 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as31 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as31 @@ -673,8 +673,8 @@ fun main(args: Array) { model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest") model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest") model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest") - model("refactoring/extractSuperclass", pattern = KT_OR_KTS, testMethod = "doExtractSuperclassTest") - model("refactoring/extractInterface", pattern = KT_OR_KTS, testMethod = "doExtractInterfaceTest") + model("refactoring/extractSuperclass", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractSuperclassTest") + model("refactoring/extractInterface", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractInterfaceTest") } testClass { diff --git a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as32 b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as32 index 5bbbac961fa..3eaaa7d0da9 100644 --- a/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as32 +++ b/generators/tests/org/jetbrains/kotlin/generators/tests/GenerateTests.kt.as32 @@ -673,8 +673,8 @@ fun main(args: Array) { model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest") model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest") model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest") - model("refactoring/extractSuperclass", pattern = KT_OR_KTS, testMethod = "doExtractSuperclassTest") - model("refactoring/extractInterface", pattern = KT_OR_KTS, testMethod = "doExtractInterfaceTest") + model("refactoring/extractSuperclass", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractSuperclassTest") + model("refactoring/extractInterface", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractInterfaceTest") } testClass { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractClass/ExtractSuperRefactoring.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractClass/ExtractSuperRefactoring.kt index e650506f876..fb4a52ef27c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractClass/ExtractSuperRefactoring.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractClass/ExtractSuperRefactoring.kt @@ -226,7 +226,7 @@ class ExtractSuperRefactoring( .forEach { it.accept(visitor) } } - private fun createClass(superClassEntry: KtSuperTypeListEntry?): KtClass { + private fun createClass(superClassEntry: KtSuperTypeListEntry?): KtClass? { val targetParent = extractInfo.targetParent val newClassName = extractInfo.newClassName.quoteIfNeeded() val originalClass = extractInfo.originalClass @@ -234,9 +234,11 @@ class ExtractSuperRefactoring( val kind = if (extractInfo.isInterface) "interface" else "class" val prototype = psiFactory.createClass("$kind $newClassName") val newClass = if (targetParent is PsiDirectory) { - val template = FileTemplateManager.getInstance(project).getInternalTemplate("Kotlin File") - val newFile = NewKotlinFileAction.createFileFromTemplate(extractInfo.targetFileName, template, targetParent) as KtFile - newFile.add(prototype) as KtClass + val file = targetParent.findFile(extractInfo.targetFileName) ?: run { + val template = FileTemplateManager.getInstance(project).getInternalTemplate("Kotlin File") + NewKotlinFileAction.createFileFromTemplate(extractInfo.targetFileName, template, targetParent) ?: return null + } + file.add(prototype) as KtClass } else { val targetSibling = originalClass.parentsWithSelf.first { it.parent == targetParent } @@ -312,7 +314,7 @@ class ExtractSuperRefactoring( project.runSynchronouslyWithProgress(RefactoringBundle.message("progress.text"), true) { runReadAction { analyzeContext() } } project.executeWriteCommand(KotlinExtractSuperclassHandler.REFACTORING_NAME) { - val newClass = createClass(superClassEntry) + val newClass = createClass(superClassEntry) ?: return@executeWriteCommand val subClass = extractInfo.originalClass.toLightClass() val superClass = newClass.toLightClass() diff --git a/idea/testData/refactoring/extractInterface/extractToExistingFile.1.kt b/idea/testData/refactoring/extractInterface/extractToExistingFile.1.kt new file mode 100644 index 00000000000..43c42f1453b --- /dev/null +++ b/idea/testData/refactoring/extractInterface/extractToExistingFile.1.kt @@ -0,0 +1 @@ +class Foo \ No newline at end of file diff --git a/idea/testData/refactoring/extractInterface/extractToExistingFile.1.kt.after b/idea/testData/refactoring/extractInterface/extractToExistingFile.1.kt.after new file mode 100644 index 00000000000..aa41f3c2bf9 --- /dev/null +++ b/idea/testData/refactoring/extractInterface/extractToExistingFile.1.kt.after @@ -0,0 +1,5 @@ +class Foo +interface ISomething { + // INFO: {checked: "true"} + var independent: Int +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractInterface/extractToExistingFile.kt b/idea/testData/refactoring/extractInterface/extractToExistingFile.kt new file mode 100644 index 00000000000..984af185946 --- /dev/null +++ b/idea/testData/refactoring/extractInterface/extractToExistingFile.kt @@ -0,0 +1,6 @@ +// NAME: ISomething +// TARGET_FILE_NAME: extractToExistingFile.1.kt +class Something { + // INFO: {checked: "true"} + var independent = 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractInterface/extractToExistingFile.kt.after b/idea/testData/refactoring/extractInterface/extractToExistingFile.kt.after new file mode 100644 index 00000000000..9d92ef4b6bc --- /dev/null +++ b/idea/testData/refactoring/extractInterface/extractToExistingFile.kt.after @@ -0,0 +1,6 @@ +// NAME: ISomething +// TARGET_FILE_NAME: extractToExistingFile.1.kt +class Something : ISomething { + // INFO: {checked: "true"} + override var independent = 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractSuperclass/extractToExistingFile.1.kt b/idea/testData/refactoring/extractSuperclass/extractToExistingFile.1.kt new file mode 100644 index 00000000000..43c42f1453b --- /dev/null +++ b/idea/testData/refactoring/extractSuperclass/extractToExistingFile.1.kt @@ -0,0 +1 @@ +class Foo \ No newline at end of file diff --git a/idea/testData/refactoring/extractSuperclass/extractToExistingFile.1.kt.after b/idea/testData/refactoring/extractSuperclass/extractToExistingFile.1.kt.after new file mode 100644 index 00000000000..1c1fa3d8bad --- /dev/null +++ b/idea/testData/refactoring/extractSuperclass/extractToExistingFile.1.kt.after @@ -0,0 +1,5 @@ +class Foo +open class SomethingBase { + // INFO: {checked: "true"} + var independent = 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractSuperclass/extractToExistingFile.kt b/idea/testData/refactoring/extractSuperclass/extractToExistingFile.kt new file mode 100644 index 00000000000..7d2a6c6e19e --- /dev/null +++ b/idea/testData/refactoring/extractSuperclass/extractToExistingFile.kt @@ -0,0 +1,6 @@ +// NAME: SomethingBase +// TARGET_FILE_NAME: extractToExistingFile.1.kt +class Something { + // INFO: {checked: "true"} + var independent = 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractSuperclass/extractToExistingFile.kt.after b/idea/testData/refactoring/extractSuperclass/extractToExistingFile.kt.after new file mode 100644 index 00000000000..3a93cbd0ac3 --- /dev/null +++ b/idea/testData/refactoring/extractSuperclass/extractToExistingFile.kt.after @@ -0,0 +1,4 @@ +// NAME: SomethingBase +// TARGET_FILE_NAME: extractToExistingFile.1.kt +class Something : SomethingBase() { +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt index 3f38a8c1aa5..812232b3e47 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt @@ -298,7 +298,7 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase() } protected fun doExtractSuperTest(path: String, isInterface: Boolean) { - doTest(path) { file -> + doTest(path, true) { file -> file as KtFile markMembersInfo(file) @@ -306,6 +306,8 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase() val targetParent = file.findElementByCommentPrefix("// SIBLING:")?.parent ?: file.parent!! val fileText = file.text val className = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// NAME:")!! + val targetFileName = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// TARGET_FILE_NAME:") + ?: "$className.${KotlinFileType.EXTENSION}" val editor = fixture.editor val originalClass = file.findElementAt(editor.caretModel.offset)?.getStrictParentOfType()!! val memberInfos = chooseMembers(extractClassMembers(originalClass)) @@ -315,7 +317,7 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase() originalClass, memberInfos, targetParent, - "$className.${KotlinFileType.EXTENSION}", + targetFileName, className, isInterface, DocCommentPolicy(DocCommentPolicy.ASIS) diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java index 8a8c916d190..1b67de3561e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java @@ -3957,7 +3957,7 @@ public class ExtractionTestGenerated extends AbstractExtractionTest { } public void testAllFilesPresentInExtractSuperclass() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/extractSuperclass"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/extractSuperclass"), Pattern.compile("^([^.]+)\\.(kt|kts)$"), TargetBackend.ANY, true); } @TestMetadata("annotation.kt") @@ -3975,6 +3975,11 @@ public class ExtractionTestGenerated extends AbstractExtractionTest { runTest("idea/testData/refactoring/extractSuperclass/enum.kt"); } + @TestMetadata("extractToExistingFile.kt") + public void testExtractToExistingFile() throws Exception { + runTest("idea/testData/refactoring/extractSuperclass/extractToExistingFile.kt"); + } + @TestMetadata("interface.kt") public void testInterface() throws Exception { runTest("idea/testData/refactoring/extractSuperclass/interface.kt"); @@ -4045,7 +4050,7 @@ public class ExtractionTestGenerated extends AbstractExtractionTest { } public void testAllFilesPresentInExtractInterface() throws Exception { - KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/extractInterface"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true); + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/extractInterface"), Pattern.compile("^([^.]+)\\.(kt|kts)$"), TargetBackend.ANY, true); } @TestMetadata("annotation.kt") @@ -4058,6 +4063,11 @@ public class ExtractionTestGenerated extends AbstractExtractionTest { runTest("idea/testData/refactoring/extractInterface/dropFinal.kt"); } + @TestMetadata("extractToExistingFile.kt") + public void testExtractToExistingFile() throws Exception { + runTest("idea/testData/refactoring/extractInterface/extractToExistingFile.kt"); + } + @TestMetadata("noWarningOnVisibilityInsideAbstractedMember.kt") public void testNoWarningOnVisibilityInsideAbstractedMember() throws Exception { runTest("idea/testData/refactoring/extractInterface/noWarningOnVisibilityInsideAbstractedMember.kt");