Extract Superclass: Allow extraction to existing file

#KT-15351 Fixed
This commit is contained in:
Alexey Sedunov
2018-06-09 15:57:44 +03:00
parent 5ef54a2f03
commit b0e0460ee6
15 changed files with 65 additions and 17 deletions
@@ -677,8 +677,8 @@ fun main(args: Array<String>) {
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<AbstractPullUpTest> {
@@ -675,8 +675,8 @@ fun main(args: Array<String>) {
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<AbstractPullUpTest> {
@@ -673,8 +673,8 @@ fun main(args: Array<String>) {
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<AbstractPullUpTest> {
@@ -673,8 +673,8 @@ fun main(args: Array<String>) {
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<AbstractPullUpTest> {
@@ -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()
@@ -0,0 +1 @@
class Foo
@@ -0,0 +1,5 @@
class Foo
interface ISomething {
// INFO: {checked: "true"}
var independent: Int
}
@@ -0,0 +1,6 @@
// NAME: ISomething
// TARGET_FILE_NAME: extractToExistingFile.1.kt
class <caret>Something {
// INFO: {checked: "true"}
var independent = 1
}
@@ -0,0 +1,6 @@
// NAME: ISomething
// TARGET_FILE_NAME: extractToExistingFile.1.kt
class Something : ISomething {
// INFO: {checked: "true"}
override var independent = 1
}
@@ -0,0 +1 @@
class Foo
@@ -0,0 +1,5 @@
class Foo
open class SomethingBase {
// INFO: {checked: "true"}
var independent = 1
}
@@ -0,0 +1,6 @@
// NAME: SomethingBase
// TARGET_FILE_NAME: extractToExistingFile.1.kt
class <caret>Something {
// INFO: {checked: "true"}
var independent = 1
}
@@ -0,0 +1,4 @@
// NAME: SomethingBase
// TARGET_FILE_NAME: extractToExistingFile.1.kt
class Something : SomethingBase() {
}
@@ -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<KtClassOrObject>()!!
val memberInfos = chooseMembers(extractClassMembers(originalClass))
@@ -315,7 +317,7 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase()
originalClass,
memberInfos,
targetParent,
"$className.${KotlinFileType.EXTENSION}",
targetFileName,
className,
isInterface,
DocCommentPolicy<PsiComment>(DocCommentPolicy.ASIS)
@@ -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");