Don't suggest to move type to separate file for sealed classes
So #KT-23321 Fixed
This commit is contained in:
committed by
Mikhail Glukhikh
parent
02578bc378
commit
a8d0e8995d
+37
-23
@@ -24,6 +24,10 @@ import com.intellij.openapi.fileEditor.FileEditorManager
|
|||||||
import com.intellij.openapi.util.TextRange
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.refactoring.move.MoveCallback
|
import com.intellij.refactoring.move.MoveCallback
|
||||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
|
||||||
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
|
import org.jetbrains.kotlin.idea.intentions.SelfTargetingRangeIntention
|
||||||
import org.jetbrains.kotlin.idea.core.moveCaret
|
import org.jetbrains.kotlin.idea.core.moveCaret
|
||||||
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
|
import org.jetbrains.kotlin.idea.refactoring.createKotlinFile
|
||||||
@@ -35,16 +39,24 @@ import org.jetbrains.kotlin.psi.KtFile
|
|||||||
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
import org.jetbrains.kotlin.psi.KtObjectDeclaration
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
|
||||||
class MoveDeclarationToSeparateFileIntention :
|
class MoveDeclarationToSeparateFileIntention :
|
||||||
SelfTargetingRangeIntention<KtClassOrObject>(KtClassOrObject::class.java, "Move declaration to separate file"),
|
SelfTargetingRangeIntention<KtClassOrObject>(KtClassOrObject::class.java, "Move declaration to separate file"),
|
||||||
LowPriorityAction {
|
LowPriorityAction {
|
||||||
override fun applicabilityRange(element: KtClassOrObject): TextRange? {
|
override fun applicabilityRange(element: KtClassOrObject): TextRange? {
|
||||||
if (element.name == null) return null
|
if (element.name == null) return null
|
||||||
if (element.parent !is KtFile) return null
|
if (element.parent !is KtFile) return null
|
||||||
if (element.hasModifier(KtTokens.PRIVATE_KEYWORD)) return null
|
if (element.hasModifier(KtTokens.PRIVATE_KEYWORD)) return null
|
||||||
if (element.containingKtFile.declarations.size == 1) return null
|
if (element.containingKtFile.declarations.size == 1) return null
|
||||||
|
|
||||||
|
if (element.resolveToDescriptorIfAny()?.sealedSubclasses?.isNotEmpty() == true) return null
|
||||||
|
if (element.superTypeListEntries.any {
|
||||||
|
val superType = it.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, it.typeReference]
|
||||||
|
(superType?.constructor?.declarationDescriptor as? ClassDescriptor)?.modality == Modality.SEALED
|
||||||
|
}) return null
|
||||||
|
|
||||||
val keyword = when (element) {
|
val keyword = when (element) {
|
||||||
is KtClass -> element.getClassOrInterfaceKeyword()
|
is KtClass -> element.getClassOrInterfaceKeyword()
|
||||||
is KtObjectDeclaration -> element.getObjectKeyword()
|
is KtObjectDeclaration -> element.getObjectKeyword()
|
||||||
@@ -76,15 +88,17 @@ class MoveDeclarationToSeparateFileIntention :
|
|||||||
|
|
||||||
// If automatic move is not possible, fall back to full-fledged Move Declarations refactoring
|
// If automatic move is not possible, fall back to full-fledged Move Declarations refactoring
|
||||||
ApplicationManager.getApplication().invokeLater {
|
ApplicationManager.getApplication().invokeLater {
|
||||||
MoveKotlinTopLevelDeclarationsDialog(project,
|
MoveKotlinTopLevelDeclarationsDialog(
|
||||||
setOf(element),
|
project,
|
||||||
packageName.asString(),
|
setOf(element),
|
||||||
directory,
|
packageName.asString(),
|
||||||
targetFile as? KtFile,
|
directory,
|
||||||
true,
|
targetFile as? KtFile,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
null).show()
|
true,
|
||||||
|
null
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -92,18 +106,18 @@ class MoveDeclarationToSeparateFileIntention :
|
|||||||
createKotlinFile(targetFileName, directory, packageName.asString())
|
createKotlinFile(targetFileName, directory, packageName.asString())
|
||||||
}
|
}
|
||||||
val descriptor = MoveDeclarationsDescriptor(
|
val descriptor = MoveDeclarationsDescriptor(
|
||||||
project = project,
|
project = project,
|
||||||
elementsToMove = listOf(element),
|
elementsToMove = listOf(element),
|
||||||
moveTarget = moveTarget,
|
moveTarget = moveTarget,
|
||||||
delegate = MoveDeclarationsDelegate.TopLevel,
|
delegate = MoveDeclarationsDelegate.TopLevel,
|
||||||
searchInCommentsAndStrings = false,
|
searchInCommentsAndStrings = false,
|
||||||
searchInNonCode = false,
|
searchInNonCode = false,
|
||||||
moveCallback = MoveCallback {
|
moveCallback = MoveCallback {
|
||||||
val newFile = directory.findFile(targetFileName) as KtFile
|
val newFile = directory.findFile(targetFileName) as KtFile
|
||||||
val newDeclaration = newFile.declarations.first()
|
val newDeclaration = newFile.declarations.first()
|
||||||
NavigationUtil.activateFileWithPsiElement(newFile)
|
NavigationUtil.activateFileWithPsiElement(newFile)
|
||||||
FileEditorManager.getInstance(project).selectedTextEditor?.moveCaret(newDeclaration.startOffset + originalOffset)
|
FileEditorManager.getInstance(project).selectedTextEditor?.moveCaret(newDeclaration.startOffset + originalOffset)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
MoveKotlinDeclarationsProcessor(descriptor).run()
|
MoveKotlinDeclarationsProcessor(descriptor).run()
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
org.jetbrains.kotlin.idea.refactoring.move.moveDeclarations.MoveDeclarationToSeparateFileIntention
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
sealed class A
|
||||||
|
class B<caret> : A()
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// IS_APPLICABLE: false
|
||||||
|
sealed class A<caret>
|
||||||
|
class B : A()
|
||||||
@@ -11824,6 +11824,27 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("idea/testData/intentions/moveDeclarationToSeparateFile")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class MoveDeclarationToSeparateFile extends AbstractIntentionTest {
|
||||||
|
public void testAllFilesPresentInMoveDeclarationToSeparateFile() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/moveDeclarationToSeparateFile"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extendSealed.kt")
|
||||||
|
public void testExtendSealed() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/moveDeclarationToSeparateFile/extendSealed.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sealed.kt")
|
||||||
|
public void testSealed() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/moveDeclarationToSeparateFile/sealed.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("idea/testData/intentions/moveLambdaInsideParentheses")
|
@TestMetadata("idea/testData/intentions/moveLambdaInsideParentheses")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user