Extract Superclass: Allow extraction to existing file
#KT-15351 Fixed
This commit is contained in:
@@ -677,8 +677,8 @@ fun main(args: Array<String>) {
|
|||||||
model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest")
|
model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest")
|
||||||
model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest")
|
model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest")
|
||||||
model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest")
|
model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest")
|
||||||
model("refactoring/extractSuperclass", pattern = KT_OR_KTS, testMethod = "doExtractSuperclassTest")
|
model("refactoring/extractSuperclass", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractSuperclassTest")
|
||||||
model("refactoring/extractInterface", pattern = KT_OR_KTS, testMethod = "doExtractInterfaceTest")
|
model("refactoring/extractInterface", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractInterfaceTest")
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractPullUpTest> {
|
testClass<AbstractPullUpTest> {
|
||||||
|
|||||||
@@ -675,8 +675,8 @@ fun main(args: Array<String>) {
|
|||||||
model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest")
|
model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest")
|
||||||
model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest")
|
model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest")
|
||||||
model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest")
|
model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest")
|
||||||
model("refactoring/extractSuperclass", pattern = KT_OR_KTS, testMethod = "doExtractSuperclassTest")
|
model("refactoring/extractSuperclass", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractSuperclassTest")
|
||||||
model("refactoring/extractInterface", pattern = KT_OR_KTS, testMethod = "doExtractInterfaceTest")
|
model("refactoring/extractInterface", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractInterfaceTest")
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractPullUpTest> {
|
testClass<AbstractPullUpTest> {
|
||||||
|
|||||||
@@ -673,8 +673,8 @@ fun main(args: Array<String>) {
|
|||||||
model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest")
|
model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest")
|
||||||
model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest")
|
model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest")
|
||||||
model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest")
|
model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest")
|
||||||
model("refactoring/extractSuperclass", pattern = KT_OR_KTS, testMethod = "doExtractSuperclassTest")
|
model("refactoring/extractSuperclass", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractSuperclassTest")
|
||||||
model("refactoring/extractInterface", pattern = KT_OR_KTS, testMethod = "doExtractInterfaceTest")
|
model("refactoring/extractInterface", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractInterfaceTest")
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractPullUpTest> {
|
testClass<AbstractPullUpTest> {
|
||||||
|
|||||||
@@ -673,8 +673,8 @@ fun main(args: Array<String>) {
|
|||||||
model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest")
|
model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest")
|
||||||
model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest")
|
model("refactoring/introduceTypeParameter", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeParameterTest")
|
||||||
model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest")
|
model("refactoring/introduceTypeAlias", pattern = KT_OR_KTS, testMethod = "doIntroduceTypeAliasTest")
|
||||||
model("refactoring/extractSuperclass", pattern = KT_OR_KTS, testMethod = "doExtractSuperclassTest")
|
model("refactoring/extractSuperclass", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractSuperclassTest")
|
||||||
model("refactoring/extractInterface", pattern = KT_OR_KTS, testMethod = "doExtractInterfaceTest")
|
model("refactoring/extractInterface", pattern = KT_OR_KTS_WITHOUT_DOTS_IN_NAME, testMethod = "doExtractInterfaceTest")
|
||||||
}
|
}
|
||||||
|
|
||||||
testClass<AbstractPullUpTest> {
|
testClass<AbstractPullUpTest> {
|
||||||
|
|||||||
+7
-5
@@ -226,7 +226,7 @@ class ExtractSuperRefactoring(
|
|||||||
.forEach { it.accept(visitor) }
|
.forEach { it.accept(visitor) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createClass(superClassEntry: KtSuperTypeListEntry?): KtClass {
|
private fun createClass(superClassEntry: KtSuperTypeListEntry?): KtClass? {
|
||||||
val targetParent = extractInfo.targetParent
|
val targetParent = extractInfo.targetParent
|
||||||
val newClassName = extractInfo.newClassName.quoteIfNeeded()
|
val newClassName = extractInfo.newClassName.quoteIfNeeded()
|
||||||
val originalClass = extractInfo.originalClass
|
val originalClass = extractInfo.originalClass
|
||||||
@@ -234,9 +234,11 @@ class ExtractSuperRefactoring(
|
|||||||
val kind = if (extractInfo.isInterface) "interface" else "class"
|
val kind = if (extractInfo.isInterface) "interface" else "class"
|
||||||
val prototype = psiFactory.createClass("$kind $newClassName")
|
val prototype = psiFactory.createClass("$kind $newClassName")
|
||||||
val newClass = if (targetParent is PsiDirectory) {
|
val newClass = if (targetParent is PsiDirectory) {
|
||||||
val template = FileTemplateManager.getInstance(project).getInternalTemplate("Kotlin File")
|
val file = targetParent.findFile(extractInfo.targetFileName) ?: run {
|
||||||
val newFile = NewKotlinFileAction.createFileFromTemplate(extractInfo.targetFileName, template, targetParent) as KtFile
|
val template = FileTemplateManager.getInstance(project).getInternalTemplate("Kotlin File")
|
||||||
newFile.add(prototype) as KtClass
|
NewKotlinFileAction.createFileFromTemplate(extractInfo.targetFileName, template, targetParent) ?: return null
|
||||||
|
}
|
||||||
|
file.add(prototype) as KtClass
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val targetSibling = originalClass.parentsWithSelf.first { it.parent == targetParent }
|
val targetSibling = originalClass.parentsWithSelf.first { it.parent == targetParent }
|
||||||
@@ -312,7 +314,7 @@ class ExtractSuperRefactoring(
|
|||||||
project.runSynchronouslyWithProgress(RefactoringBundle.message("progress.text"), true) { runReadAction { analyzeContext() } }
|
project.runSynchronouslyWithProgress(RefactoringBundle.message("progress.text"), true) { runReadAction { analyzeContext() } }
|
||||||
|
|
||||||
project.executeWriteCommand(KotlinExtractSuperclassHandler.REFACTORING_NAME) {
|
project.executeWriteCommand(KotlinExtractSuperclassHandler.REFACTORING_NAME) {
|
||||||
val newClass = createClass(superClassEntry)
|
val newClass = createClass(superClassEntry) ?: return@executeWriteCommand
|
||||||
|
|
||||||
val subClass = extractInfo.originalClass.toLightClass()
|
val subClass = extractInfo.originalClass.toLightClass()
|
||||||
val superClass = newClass.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() {
|
||||||
|
}
|
||||||
+4
-2
@@ -298,7 +298,7 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase()
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun doExtractSuperTest(path: String, isInterface: Boolean) {
|
protected fun doExtractSuperTest(path: String, isInterface: Boolean) {
|
||||||
doTest(path) { file ->
|
doTest(path, true) { file ->
|
||||||
file as KtFile
|
file as KtFile
|
||||||
|
|
||||||
markMembersInfo(file)
|
markMembersInfo(file)
|
||||||
@@ -306,6 +306,8 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase()
|
|||||||
val targetParent = file.findElementByCommentPrefix("// SIBLING:")?.parent ?: file.parent!!
|
val targetParent = file.findElementByCommentPrefix("// SIBLING:")?.parent ?: file.parent!!
|
||||||
val fileText = file.text
|
val fileText = file.text
|
||||||
val className = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// NAME:")!!
|
val className = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// NAME:")!!
|
||||||
|
val targetFileName = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// TARGET_FILE_NAME:")
|
||||||
|
?: "$className.${KotlinFileType.EXTENSION}"
|
||||||
val editor = fixture.editor
|
val editor = fixture.editor
|
||||||
val originalClass = file.findElementAt(editor.caretModel.offset)?.getStrictParentOfType<KtClassOrObject>()!!
|
val originalClass = file.findElementAt(editor.caretModel.offset)?.getStrictParentOfType<KtClassOrObject>()!!
|
||||||
val memberInfos = chooseMembers(extractClassMembers(originalClass))
|
val memberInfos = chooseMembers(extractClassMembers(originalClass))
|
||||||
@@ -315,7 +317,7 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase()
|
|||||||
originalClass,
|
originalClass,
|
||||||
memberInfos,
|
memberInfos,
|
||||||
targetParent,
|
targetParent,
|
||||||
"$className.${KotlinFileType.EXTENSION}",
|
targetFileName,
|
||||||
className,
|
className,
|
||||||
isInterface,
|
isInterface,
|
||||||
DocCommentPolicy<PsiComment>(DocCommentPolicy.ASIS)
|
DocCommentPolicy<PsiComment>(DocCommentPolicy.ASIS)
|
||||||
|
|||||||
+12
-2
@@ -3957,7 +3957,7 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInExtractSuperclass() throws Exception {
|
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")
|
@TestMetadata("annotation.kt")
|
||||||
@@ -3975,6 +3975,11 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
|
|||||||
runTest("idea/testData/refactoring/extractSuperclass/enum.kt");
|
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")
|
@TestMetadata("interface.kt")
|
||||||
public void testInterface() throws Exception {
|
public void testInterface() throws Exception {
|
||||||
runTest("idea/testData/refactoring/extractSuperclass/interface.kt");
|
runTest("idea/testData/refactoring/extractSuperclass/interface.kt");
|
||||||
@@ -4045,7 +4050,7 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testAllFilesPresentInExtractInterface() throws Exception {
|
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")
|
@TestMetadata("annotation.kt")
|
||||||
@@ -4058,6 +4063,11 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
|
|||||||
runTest("idea/testData/refactoring/extractInterface/dropFinal.kt");
|
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")
|
@TestMetadata("noWarningOnVisibilityInsideAbstractedMember.kt")
|
||||||
public void testNoWarningOnVisibilityInsideAbstractedMember() throws Exception {
|
public void testNoWarningOnVisibilityInsideAbstractedMember() throws Exception {
|
||||||
runTest("idea/testData/refactoring/extractInterface/noWarningOnVisibilityInsideAbstractedMember.kt");
|
runTest("idea/testData/refactoring/extractInterface/noWarningOnVisibilityInsideAbstractedMember.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user