Minor: refactoring 'refactoring' package
This commit is contained in:
@@ -25,12 +25,12 @@ abstract class AbstractIntroduceAction : BasePlatformRefactoringAction() {
|
||||
setInjectedContext(true)
|
||||
}
|
||||
|
||||
override final fun setInjectedContext(worksInInjected: Boolean) {
|
||||
final override fun setInjectedContext(worksInInjected: Boolean) {
|
||||
super.setInjectedContext(worksInInjected)
|
||||
}
|
||||
|
||||
override fun isAvailableInEditorOnly(): Boolean = true
|
||||
|
||||
override fun isEnabledOnElements(elements: Array<out PsiElement>): Boolean =
|
||||
elements.all { it is KtElement }
|
||||
elements.all { it is KtElement }
|
||||
}
|
||||
+15
-16
@@ -33,14 +33,14 @@ import org.jetbrains.kotlin.psi.psiUtil.isIdentifier
|
||||
import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded
|
||||
import java.awt.BorderLayout
|
||||
|
||||
abstract class AbstractKotlinInplaceIntroducer<D: KtNamedDeclaration>(
|
||||
localVariable: D?,
|
||||
expression: KtExpression?,
|
||||
occurrences: Array<KtExpression>,
|
||||
title: String,
|
||||
project: Project,
|
||||
editor: Editor
|
||||
): AbstractInplaceIntroducer<D, KtExpression>(project, editor, expression, localVariable, occurrences, title, KotlinFileType.INSTANCE) {
|
||||
abstract class AbstractKotlinInplaceIntroducer<D : KtNamedDeclaration>(
|
||||
localVariable: D?,
|
||||
expression: KtExpression?,
|
||||
occurrences: Array<KtExpression>,
|
||||
title: String,
|
||||
project: Project,
|
||||
editor: Editor
|
||||
) : AbstractInplaceIntroducer<D, KtExpression>(project, editor, expression, localVariable, occurrences, title, KotlinFileType.INSTANCE) {
|
||||
protected fun initFormComponents(init: FormBuilder.() -> Unit) {
|
||||
myWholePanel.layout = BorderLayout()
|
||||
|
||||
@@ -58,8 +58,7 @@ abstract class AbstractKotlinInplaceIntroducer<D: KtNamedDeclaration>(
|
||||
// myExprMarker was invalidated by stopIntroduce()
|
||||
myExprMarker = myExpr?.let { createMarker(it) }
|
||||
startInplaceIntroduceTemplate()
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
myEditor.putUserData(InplaceRefactoring.INTRODUCE_RESTART, false)
|
||||
}
|
||||
}
|
||||
@@ -74,10 +73,10 @@ abstract class AbstractKotlinInplaceIntroducer<D: KtNamedDeclaration>(
|
||||
override fun getActionName(): String? = null
|
||||
|
||||
override fun restoreExpression(
|
||||
containingFile: PsiFile,
|
||||
declaration: D,
|
||||
marker: RangeMarker,
|
||||
exprText: String?
|
||||
containingFile: PsiFile,
|
||||
declaration: D,
|
||||
marker: RangeMarker,
|
||||
exprText: String?
|
||||
): KtExpression? {
|
||||
if (exprText == null || !declaration.isValid) return null
|
||||
|
||||
@@ -89,8 +88,8 @@ abstract class AbstractKotlinInplaceIntroducer<D: KtNamedDeclaration>(
|
||||
|
||||
val occurrenceExprText = (myExpr as? KtProperty)?.name ?: exprText
|
||||
return leaf
|
||||
.getNonStrictParentOfType<KtSimpleNameExpression>()
|
||||
?.replaced(KtPsiFactory(myProject).createExpression(occurrenceExprText))
|
||||
.getNonStrictParentOfType<KtSimpleNameExpression>()
|
||||
?.replaced(KtPsiFactory(myProject).createExpression(occurrenceExprText))
|
||||
}
|
||||
|
||||
override fun updateTitle(declaration: D?) = updateTitle(declaration, null)
|
||||
|
||||
+49
-55
@@ -72,23 +72,23 @@ import org.jetbrains.kotlin.resolve.scopes.utils.findClassifier
|
||||
import java.util.*
|
||||
|
||||
data class ExtractSuperInfo(
|
||||
val originalClass: KtClassOrObject,
|
||||
val memberInfos: Collection<KotlinMemberInfo>,
|
||||
val targetParent: PsiElement,
|
||||
val targetFileName: String,
|
||||
val newClassName: String,
|
||||
val isInterface: Boolean,
|
||||
val docPolicy: DocCommentPolicy<*>
|
||||
val originalClass: KtClassOrObject,
|
||||
val memberInfos: Collection<KotlinMemberInfo>,
|
||||
val targetParent: PsiElement,
|
||||
val targetFileName: String,
|
||||
val newClassName: String,
|
||||
val isInterface: Boolean,
|
||||
val docPolicy: DocCommentPolicy<*>
|
||||
)
|
||||
|
||||
class ExtractSuperRefactoring(
|
||||
private var extractInfo: ExtractSuperInfo
|
||||
private var extractInfo: ExtractSuperInfo
|
||||
) {
|
||||
companion object {
|
||||
private fun getElementsToMove(
|
||||
memberInfos: Collection<KotlinMemberInfo>,
|
||||
originalClass: KtClassOrObject,
|
||||
isExtractInterface: Boolean
|
||||
memberInfos: Collection<KotlinMemberInfo>,
|
||||
originalClass: KtClassOrObject,
|
||||
isExtractInterface: Boolean
|
||||
): Map<KtElement, KotlinMemberInfo?> {
|
||||
val project = originalClass.project
|
||||
val elementsToMove = LinkedHashMap<KtElement, KotlinMemberInfo?>()
|
||||
@@ -98,8 +98,7 @@ class ExtractSuperRefactoring(
|
||||
val member = memberInfo.member ?: continue
|
||||
if (memberInfo.isSuperClass) {
|
||||
superInterfacesToMove += member
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
elementsToMove[member] = memberInfo
|
||||
}
|
||||
}
|
||||
@@ -107,8 +106,9 @@ class ExtractSuperRefactoring(
|
||||
val superTypeList = originalClass.getSuperTypeList()
|
||||
if (superTypeList != null) {
|
||||
for (superTypeListEntry in originalClass.superTypeListEntries) {
|
||||
val superType = superTypeListEntry.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, superTypeListEntry.typeReference]
|
||||
?: continue
|
||||
val superType =
|
||||
superTypeListEntry.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, superTypeListEntry.typeReference]
|
||||
?: continue
|
||||
val superClassDescriptor = superType.constructor.declarationDescriptor ?: continue
|
||||
val superClass = DescriptorToSourceUtilsIde.getAnyDeclaration(project, superClassDescriptor) as? KtClass ?: continue
|
||||
if ((!isExtractInterface && !superClass.isInterface()) || superClass in superInterfacesToMove) {
|
||||
@@ -121,11 +121,11 @@ class ExtractSuperRefactoring(
|
||||
}
|
||||
|
||||
fun collectConflicts(
|
||||
originalClass: KtClassOrObject,
|
||||
memberInfos: List<KotlinMemberInfo>,
|
||||
targetParent: PsiElement,
|
||||
newClassName: String,
|
||||
isExtractInterface: Boolean
|
||||
originalClass: KtClassOrObject,
|
||||
memberInfos: List<KotlinMemberInfo>,
|
||||
targetParent: PsiElement,
|
||||
newClassName: String,
|
||||
isExtractInterface: Boolean
|
||||
): MultiMap<PsiElement, String> {
|
||||
val conflicts = MultiMap<PsiElement, String>()
|
||||
|
||||
@@ -134,9 +134,9 @@ class ExtractSuperRefactoring(
|
||||
if (targetParent is KtElement) {
|
||||
val targetSibling = originalClass.parentsWithSelf.first { it.parent == targetParent } as KtElement
|
||||
targetSibling.getResolutionScope()
|
||||
.findClassifier(Name.identifier(newClassName), NoLookupLocation.FROM_IDE)
|
||||
?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) }
|
||||
?.let { conflicts.putValue(it, "Class $newClassName already exists in the target scope") }
|
||||
.findClassifier(Name.identifier(newClassName), NoLookupLocation.FROM_IDE)
|
||||
?.let { DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) }
|
||||
?.let { conflicts.putValue(it, "Class $newClassName already exists in the target scope") }
|
||||
}
|
||||
|
||||
val elementsToMove = getElementsToMove(memberInfos, originalClass, isExtractInterface).keys
|
||||
@@ -144,16 +144,15 @@ class ExtractSuperRefactoring(
|
||||
val moveTarget = if (targetParent is PsiDirectory) {
|
||||
val targetPackage = targetParent.getPackage() ?: return conflicts
|
||||
KotlinMoveTargetForDeferredFile(FqName(targetPackage.qualifiedName), targetParent) { null }
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
KotlinMoveTargetForExistingElement(targetParent as KtElement)
|
||||
}
|
||||
val conflictChecker = MoveConflictChecker(
|
||||
project,
|
||||
elementsToMove,
|
||||
moveTarget,
|
||||
originalClass,
|
||||
memberInfos.asSequence().filter { it.isToAbstract }.mapNotNull { it.member }.toList()
|
||||
project,
|
||||
elementsToMove,
|
||||
moveTarget,
|
||||
originalClass,
|
||||
memberInfos.asSequence().filter { it.isToAbstract }.mapNotNull { it.member }.toList()
|
||||
)
|
||||
|
||||
project.runSynchronouslyWithProgress(RefactoringBundle.message("detecting.possible.conflicts"), true) {
|
||||
@@ -163,11 +162,11 @@ class ExtractSuperRefactoring(
|
||||
ReferencesSearch.search(element).mapTo(usages) { MoveRenameUsageInfo(it, element) }
|
||||
if (element is KtCallableDeclaration) {
|
||||
element.toLightMethods().flatMapTo(usages) {
|
||||
MethodReferencesSearch.search(it).map { MoveRenameUsageInfo(it, element) }
|
||||
MethodReferencesSearch.search(it).map { reference -> MoveRenameUsageInfo(reference, element) }
|
||||
}
|
||||
}
|
||||
}
|
||||
conflictChecker.checkAllConflicts(usages, LinkedHashSet<UsageInfo>(), conflicts)
|
||||
conflictChecker.checkAllConflicts(usages, LinkedHashSet(), conflicts)
|
||||
if (targetParent is PsiDirectory) {
|
||||
ExtractSuperClassUtil.checkSuperAccessible(targetParent, conflicts, originalClass.toLightClass())
|
||||
}
|
||||
@@ -190,11 +189,11 @@ class ExtractSuperRefactoring(
|
||||
if (refTarget is KtTypeParameter && refTarget.getStrictParentOfType<KtTypeParameterListOwner>() == extractInfo.originalClass) {
|
||||
typeParameters += refTarget
|
||||
refTarget.accept(
|
||||
object : KtTreeVisitorVoid() {
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||
(expression.mainReference.resolve() as? KtTypeParameter)?.let { typeParameters += it }
|
||||
}
|
||||
object : KtTreeVisitorVoid() {
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression) {
|
||||
(expression.mainReference.resolve() as? KtTypeParameter)?.let { typeParameters += it }
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -207,12 +206,12 @@ class ExtractSuperRefactoring(
|
||||
}
|
||||
}
|
||||
getElementsToMove(extractInfo.memberInfos, extractInfo.originalClass, extractInfo.isInterface)
|
||||
.asSequence()
|
||||
.flatMap {
|
||||
val (element, info) = it
|
||||
info?.getChildrenToAnalyze()?.asSequence() ?: sequenceOf(element)
|
||||
}
|
||||
.forEach { it.accept(visitor) }
|
||||
.asSequence()
|
||||
.flatMap {
|
||||
val (element, info) = it
|
||||
info?.getChildrenToAnalyze()?.asSequence() ?: sequenceOf(element)
|
||||
}
|
||||
.forEach { it.accept(visitor) }
|
||||
}
|
||||
|
||||
private fun createClass(superClassEntry: KtSuperTypeListEntry?): KtClass? {
|
||||
@@ -228,8 +227,7 @@ class ExtractSuperRefactoring(
|
||||
NewKotlinFileAction.createFileFromTemplate(extractInfo.targetFileName, template, targetParent) ?: return null
|
||||
}
|
||||
file.add(prototype) as KtClass
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
val targetSibling = originalClass.parentsWithSelf.first { it.parent == targetParent }
|
||||
insertDeclaration(prototype, targetSibling)
|
||||
}
|
||||
@@ -256,13 +254,12 @@ class ExtractSuperRefactoring(
|
||||
}
|
||||
}
|
||||
val needSuperCall = !extractInfo.isInterface
|
||||
&& (superClassEntry is KtSuperTypeCallEntry
|
||||
|| originalClass.hasPrimaryConstructor()
|
||||
|| originalClass.secondaryConstructors.isEmpty())
|
||||
&& (superClassEntry is KtSuperTypeCallEntry
|
||||
|| originalClass.hasPrimaryConstructor()
|
||||
|| originalClass.secondaryConstructors.isEmpty())
|
||||
val newSuperTypeListEntry = if (needSuperCall) {
|
||||
psiFactory.createSuperTypeCallEntry("$superTypeText()")
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
psiFactory.createSuperTypeEntry(superTypeText)
|
||||
}
|
||||
if (superClassEntry != null) {
|
||||
@@ -271,12 +268,10 @@ class ExtractSuperRefactoring(
|
||||
}
|
||||
val superClassEntryToAdd = if (qualifiedTypeRefText != null) {
|
||||
superClassEntry.copied().apply { typeReference?.replace(psiFactory.createType(qualifiedTypeRefText)) }
|
||||
}
|
||||
else superClassEntry
|
||||
} else superClassEntry
|
||||
newClass.addSuperTypeListEntry(superClassEntryToAdd)
|
||||
ShortenReferences.DEFAULT.process(superClassEntry.replaced(newSuperTypeListEntry))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ShortenReferences.DEFAULT.process(originalClass.addSuperTypeListEntry(newSuperTypeListEntry))
|
||||
}
|
||||
|
||||
@@ -297,8 +292,7 @@ class ExtractSuperRefactoring(
|
||||
originalClass.superTypeListEntries.firstOrNull {
|
||||
bindingContext[BindingContext.TYPE, it.typeReference]?.constructor?.declarationDescriptor == superClassDescriptor
|
||||
}
|
||||
}
|
||||
else null
|
||||
} else null
|
||||
|
||||
project.runSynchronouslyWithProgress(RefactoringBundle.message("progress.text"), true) { runReadAction { analyzeContext() } }
|
||||
|
||||
|
||||
+5
-5
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
|
||||
object KotlinExtractInterfaceHandler : KotlinExtractSuperHandlerBase(true) {
|
||||
val REFACTORING_NAME = "Extract Interface"
|
||||
const val REFACTORING_NAME = "Extract Interface"
|
||||
|
||||
override fun getErrorMessage(klass: KtClassOrObject): String? {
|
||||
val superMessage = super.getErrorMessage(klass)
|
||||
@@ -33,9 +33,9 @@ object KotlinExtractInterfaceHandler : KotlinExtractSuperHandlerBase(true) {
|
||||
|
||||
override fun createDialog(klass: KtClassOrObject, targetParent: PsiElement) =
|
||||
KotlinExtractInterfaceDialog(
|
||||
originalClass = klass,
|
||||
targetParent = targetParent,
|
||||
conflictChecker = { checkConflicts(klass, it) },
|
||||
refactoring = { ExtractSuperRefactoring(it).performRefactoring() }
|
||||
originalClass = klass,
|
||||
targetParent = targetParent,
|
||||
conflictChecker = { checkConflicts(klass, it) },
|
||||
refactoring = { ExtractSuperRefactoring(it).performRefactoring() }
|
||||
)
|
||||
}
|
||||
+16
-16
@@ -68,11 +68,11 @@ abstract class KotlinExtractSuperHandlerBase(private val isExtractInterface: Boo
|
||||
|
||||
getErrorMessage(klass)?.let {
|
||||
CommonRefactoringUtil.showErrorHint(
|
||||
project,
|
||||
editor,
|
||||
RefactoringBundle.getCannotRefactorMessage(it),
|
||||
KotlinExtractSuperclassHandler.REFACTORING_NAME,
|
||||
HelpID.EXTRACT_SUPERCLASS
|
||||
project,
|
||||
editor,
|
||||
RefactoringBundle.getCannotRefactorMessage(it),
|
||||
KotlinExtractSuperclassHandler.REFACTORING_NAME,
|
||||
HelpID.EXTRACT_SUPERCLASS
|
||||
)
|
||||
return false
|
||||
}
|
||||
@@ -90,22 +90,22 @@ abstract class KotlinExtractSuperHandlerBase(private val isExtractInterface: Boo
|
||||
if (editor == null) return doInvoke(klass, containers.first())
|
||||
|
||||
chooseContainerElementIfNecessary(
|
||||
containers,
|
||||
editor,
|
||||
if (containers.first() is KtFile) "Select target file" else "Select target code block / file",
|
||||
true,
|
||||
{ it },
|
||||
{ doInvoke(klass, if (it is SeparateFileWrapper) klass.containingFile.parent!! else it) }
|
||||
containers,
|
||||
editor,
|
||||
if (containers.first() is KtFile) "Select target file" else "Select target code block / file",
|
||||
true,
|
||||
{ it },
|
||||
{ doInvoke(klass, if (it is SeparateFileWrapper) klass.containingFile.parent!! else it) }
|
||||
)
|
||||
}
|
||||
|
||||
protected fun checkConflicts(originalClass: KtClassOrObject, dialog: KotlinExtractSuperDialogBase): Boolean {
|
||||
val conflicts = ExtractSuperRefactoring.collectConflicts(
|
||||
originalClass,
|
||||
dialog.selectedMembers,
|
||||
dialog.selectedTargetParent,
|
||||
dialog.extractedSuperName,
|
||||
isExtractInterface
|
||||
originalClass,
|
||||
dialog.selectedMembers,
|
||||
dialog.selectedTargetParent,
|
||||
dialog.extractedSuperName,
|
||||
isExtractInterface
|
||||
)
|
||||
return ExtractSuperClassUtil.showConflicts(dialog, conflicts, originalClass.project)
|
||||
}
|
||||
|
||||
+5
-5
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.psi.KtClass
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject
|
||||
|
||||
object KotlinExtractSuperclassHandler : KotlinExtractSuperHandlerBase(false) {
|
||||
val REFACTORING_NAME = "Extract Superclass"
|
||||
const val REFACTORING_NAME = "Extract Superclass"
|
||||
|
||||
override fun getErrorMessage(klass: KtClassOrObject): String? {
|
||||
val superMessage = super.getErrorMessage(klass)
|
||||
@@ -38,9 +38,9 @@ object KotlinExtractSuperclassHandler : KotlinExtractSuperHandlerBase(false) {
|
||||
|
||||
override fun createDialog(klass: KtClassOrObject, targetParent: PsiElement) =
|
||||
KotlinExtractSuperclassDialog(
|
||||
originalClass = klass,
|
||||
targetParent = targetParent,
|
||||
conflictChecker = { checkConflicts(klass, it) },
|
||||
refactoring = { ExtractSuperRefactoring(it).performRefactoring() }
|
||||
originalClass = klass,
|
||||
targetParent = targetParent,
|
||||
conflictChecker = { checkConflicts(klass, it) },
|
||||
refactoring = { ExtractSuperRefactoring(it).performRefactoring() }
|
||||
)
|
||||
}
|
||||
+13
-6
@@ -36,13 +36,20 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
|
||||
class KotlinExtractInterfaceDialog(
|
||||
originalClass: KtClassOrObject,
|
||||
targetParent: PsiElement,
|
||||
conflictChecker: (KotlinExtractSuperDialogBase) -> Boolean,
|
||||
refactoring: (ExtractSuperInfo) -> Unit
|
||||
) : KotlinExtractSuperDialogBase(originalClass, targetParent, conflictChecker, true, KotlinExtractInterfaceHandler.REFACTORING_NAME, refactoring) {
|
||||
originalClass: KtClassOrObject,
|
||||
targetParent: PsiElement,
|
||||
conflictChecker: (KotlinExtractSuperDialogBase) -> Boolean,
|
||||
refactoring: (ExtractSuperInfo) -> Unit
|
||||
) : KotlinExtractSuperDialogBase(
|
||||
originalClass,
|
||||
targetParent,
|
||||
conflictChecker,
|
||||
true,
|
||||
KotlinExtractInterfaceHandler.REFACTORING_NAME,
|
||||
refactoring
|
||||
) {
|
||||
companion object {
|
||||
private val DESTINATION_PACKAGE_RECENT_KEY = "KotlinExtractInterfaceDialog.RECENT_KEYS"
|
||||
private const val DESTINATION_PACKAGE_RECENT_KEY = "KotlinExtractInterfaceDialog.RECENT_KEYS"
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
+27
-22
@@ -44,12 +44,12 @@ import java.awt.BorderLayout
|
||||
import javax.swing.*
|
||||
|
||||
abstract class KotlinExtractSuperDialogBase(
|
||||
protected val originalClass: KtClassOrObject,
|
||||
protected val targetParent: PsiElement,
|
||||
private val conflictChecker: (KotlinExtractSuperDialogBase) -> Boolean,
|
||||
private val isExtractInterface: Boolean,
|
||||
refactoringName: String,
|
||||
private val refactoring: (ExtractSuperInfo) -> Unit
|
||||
protected val originalClass: KtClassOrObject,
|
||||
protected val targetParent: PsiElement,
|
||||
private val conflictChecker: (KotlinExtractSuperDialogBase) -> Boolean,
|
||||
private val isExtractInterface: Boolean,
|
||||
refactoringName: String,
|
||||
private val refactoring: (ExtractSuperInfo) -> Unit
|
||||
) : JavaExtractSuperBaseDialog(originalClass.project, originalClass.toLightClass()!!, emptyList(), refactoringName) {
|
||||
private var initComplete: Boolean = false
|
||||
|
||||
@@ -61,10 +61,15 @@ abstract class KotlinExtractSuperDialogBase(
|
||||
private val fileNameField = JTextField()
|
||||
|
||||
open class MemberInfoModelBase(
|
||||
originalClass: KtClassOrObject,
|
||||
val memberInfos: List<KotlinMemberInfo>,
|
||||
interfaceContainmentVerifier: (KtNamedDeclaration) -> Boolean
|
||||
) : KotlinUsesAndInterfacesDependencyMemberInfoModel<KtNamedDeclaration, KotlinMemberInfo>(originalClass, null, false, interfaceContainmentVerifier) {
|
||||
originalClass: KtClassOrObject,
|
||||
val memberInfos: List<KotlinMemberInfo>,
|
||||
interfaceContainmentVerifier: (KtNamedDeclaration) -> Boolean
|
||||
) : KotlinUsesAndInterfacesDependencyMemberInfoModel<KtNamedDeclaration, KotlinMemberInfo>(
|
||||
originalClass,
|
||||
null,
|
||||
false,
|
||||
interfaceContainmentVerifier
|
||||
) {
|
||||
override fun isMemberEnabled(member: KotlinMemberInfo): Boolean {
|
||||
val declaration = member.member ?: return false
|
||||
return !declaration.hasModifier(KtTokens.CONST_KEYWORD)
|
||||
@@ -73,8 +78,8 @@ abstract class KotlinExtractSuperDialogBase(
|
||||
override fun isAbstractEnabled(memberInfo: KotlinMemberInfo): Boolean {
|
||||
val member = memberInfo.member
|
||||
return !(member.hasModifier(KtTokens.INLINE_KEYWORD) ||
|
||||
member.hasModifier(KtTokens.EXTERNAL_KEYWORD) ||
|
||||
member.hasModifier(KtTokens.LATEINIT_KEYWORD))
|
||||
member.hasModifier(KtTokens.EXTERNAL_KEYWORD) ||
|
||||
member.hasModifier(KtTokens.LATEINIT_KEYWORD))
|
||||
}
|
||||
|
||||
override fun isFixedAbstract(memberInfo: KotlinMemberInfo?) = true
|
||||
@@ -140,9 +145,9 @@ abstract class KotlinExtractSuperDialogBase(
|
||||
|
||||
return JPanel(BorderLayout()).apply {
|
||||
val memberSelectionPanel = KotlinMemberSelectionPanel(
|
||||
RefactoringBundle.message(if (isExtractInterface) "members.to.form.interface" else "members.to.form.superclass"),
|
||||
memberInfoModel.memberInfos,
|
||||
RefactoringBundle.message("make.abstract")
|
||||
RefactoringBundle.message(if (isExtractInterface) "members.to.form.interface" else "members.to.form.superclass"),
|
||||
memberInfoModel.memberInfos,
|
||||
RefactoringBundle.message("make.abstract")
|
||||
)
|
||||
memberSelectionPanel.table.memberInfoModel = memberInfoModel
|
||||
memberSelectionPanel.table.addMemberInfoChangeListener(memberInfoModel)
|
||||
@@ -178,13 +183,13 @@ abstract class KotlinExtractSuperDialogBase(
|
||||
|
||||
override fun executeRefactoring() {
|
||||
val extractInfo = ExtractSuperInfo(
|
||||
mySourceClass.unwrapped as KtClassOrObject,
|
||||
selectedMembers,
|
||||
if (targetParent is PsiDirectory) targetDirectory else targetParent,
|
||||
targetFileName,
|
||||
extractedSuperName.quoteIfNeeded(),
|
||||
isExtractInterface,
|
||||
DocCommentPolicy<PsiComment>(docCommentPolicy)
|
||||
mySourceClass.unwrapped as KtClassOrObject,
|
||||
selectedMembers,
|
||||
if (targetParent is PsiDirectory) targetDirectory else targetParent,
|
||||
targetFileName,
|
||||
extractedSuperName.quoteIfNeeded(),
|
||||
isExtractInterface,
|
||||
DocCommentPolicy<PsiComment>(docCommentPolicy)
|
||||
)
|
||||
refactoring(extractInfo)
|
||||
}
|
||||
|
||||
+16
-9
@@ -31,13 +31,20 @@ import org.jetbrains.kotlin.psi.KtParameter
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
|
||||
class KotlinExtractSuperclassDialog(
|
||||
originalClass: KtClassOrObject,
|
||||
targetParent: PsiElement,
|
||||
conflictChecker: (KotlinExtractSuperDialogBase) -> Boolean,
|
||||
refactoring: (ExtractSuperInfo) -> Unit
|
||||
) : KotlinExtractSuperDialogBase(originalClass, targetParent, conflictChecker, false, KotlinExtractSuperclassHandler.REFACTORING_NAME, refactoring) {
|
||||
originalClass: KtClassOrObject,
|
||||
targetParent: PsiElement,
|
||||
conflictChecker: (KotlinExtractSuperDialogBase) -> Boolean,
|
||||
refactoring: (ExtractSuperInfo) -> Unit
|
||||
) : KotlinExtractSuperDialogBase(
|
||||
originalClass,
|
||||
targetParent,
|
||||
conflictChecker,
|
||||
false,
|
||||
KotlinExtractSuperclassHandler.REFACTORING_NAME,
|
||||
refactoring
|
||||
) {
|
||||
companion object {
|
||||
private val DESTINATION_PACKAGE_RECENT_KEY = "KotlinExtractSuperclassDialog.RECENT_KEYS"
|
||||
private const val DESTINATION_PACKAGE_RECENT_KEY = "KotlinExtractSuperclassDialog.RECENT_KEYS"
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -46,9 +53,9 @@ class KotlinExtractSuperclassDialog(
|
||||
|
||||
override fun createMemberInfoModel(): MemberInfoModelBase {
|
||||
return object : MemberInfoModelBase(
|
||||
originalClass,
|
||||
extractClassMembers(originalClass),
|
||||
getInterfaceContainmentVerifier { selectedMembers }
|
||||
originalClass,
|
||||
extractClassMembers(originalClass),
|
||||
getInterfaceContainmentVerifier { selectedMembers }
|
||||
) {
|
||||
override fun isAbstractEnabled(memberInfo: KotlinMemberInfo): Boolean {
|
||||
if (!super.isAbstractEnabled(memberInfo)) return false
|
||||
|
||||
@@ -42,19 +42,19 @@ fun showErrorHintByKey(project: Project, editor: Editor, messageKey: String, tit
|
||||
}
|
||||
|
||||
fun selectElementsWithTargetSibling(
|
||||
operationName: String,
|
||||
editor: Editor,
|
||||
file: KtFile,
|
||||
title: String,
|
||||
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
||||
elementValidator: (List<PsiElement>) -> String?,
|
||||
getContainers: (elements: List<PsiElement>, commonParent: PsiElement) -> List<PsiElement>,
|
||||
continuation: (elements: List<PsiElement>, targetSibling: PsiElement) -> Unit
|
||||
operationName: String,
|
||||
editor: Editor,
|
||||
file: KtFile,
|
||||
title: String,
|
||||
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
||||
elementValidator: (List<PsiElement>) -> String?,
|
||||
getContainers: (elements: List<PsiElement>, commonParent: PsiElement) -> List<PsiElement>,
|
||||
continuation: (elements: List<PsiElement>, targetSibling: PsiElement) -> Unit
|
||||
) {
|
||||
fun onSelectionComplete(elements: List<PsiElement>, targetContainer: PsiElement) {
|
||||
val physicalElements = elements.map { it.substringContextOrThis }
|
||||
val parent = PsiTreeUtil.findCommonParent(physicalElements)
|
||||
?: throw AssertionError("Should have at least one parent: ${physicalElements.joinToString("\n")}")
|
||||
?: throw AssertionError("Should have at least one parent: ${physicalElements.joinToString("\n")}")
|
||||
|
||||
if (parent == targetContainer) {
|
||||
continuation(elements, physicalElements.first())
|
||||
@@ -74,14 +74,14 @@ fun selectElementsWithTargetSibling(
|
||||
}
|
||||
|
||||
fun selectElementsWithTargetParent(
|
||||
operationName: String,
|
||||
editor: Editor,
|
||||
file: KtFile,
|
||||
title: String,
|
||||
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
||||
elementValidator: (List<PsiElement>) -> String?,
|
||||
getContainers: (elements: List<PsiElement>, commonParent: PsiElement) -> List<PsiElement>,
|
||||
continuation: (elements: List<PsiElement>, targetParent: PsiElement) -> Unit
|
||||
operationName: String,
|
||||
editor: Editor,
|
||||
file: KtFile,
|
||||
title: String,
|
||||
elementKinds: Collection<CodeInsightUtils.ElementKind>,
|
||||
elementValidator: (List<PsiElement>) -> String?,
|
||||
getContainers: (elements: List<PsiElement>, commonParent: PsiElement) -> List<PsiElement>,
|
||||
continuation: (elements: List<PsiElement>, targetParent: PsiElement) -> Unit
|
||||
) {
|
||||
fun showErrorHintByKey(key: String) {
|
||||
showErrorHintByKey(file.project, editor, key, operationName)
|
||||
@@ -95,7 +95,7 @@ fun selectElementsWithTargetParent(
|
||||
|
||||
val physicalElements = elements.map { it.substringContextOrThis }
|
||||
val parent = PsiTreeUtil.findCommonParent(physicalElements)
|
||||
?: throw AssertionError("Should have at least one parent: ${physicalElements.joinToString("\n")}")
|
||||
?: throw AssertionError("Should have at least one parent: ${physicalElements.joinToString("\n")}")
|
||||
|
||||
val containers = getContainers(physicalElements, parent)
|
||||
if (containers.isEmpty()) {
|
||||
@@ -104,12 +104,12 @@ fun selectElementsWithTargetParent(
|
||||
}
|
||||
|
||||
chooseContainerElementIfNecessary(
|
||||
containers,
|
||||
editor,
|
||||
title,
|
||||
true,
|
||||
{ it },
|
||||
{ continuation(elements, it) }
|
||||
containers,
|
||||
editor,
|
||||
title,
|
||||
true,
|
||||
{ it },
|
||||
{ continuation(elements, it) }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -133,8 +133,7 @@ fun selectElementsWithTargetParent(
|
||||
selectElement(editor, file, false, elementKinds) { expr ->
|
||||
if (expr != null) {
|
||||
selectTargetContainer(listOf(expr))
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
if (!editor.selectionModel.hasSelection()) {
|
||||
if (elementKinds.singleOrNull() == CodeInsightUtils.ElementKind.EXPRESSION) {
|
||||
val elementAtCaret = file.findElementAt(editor.caretModel.offset)
|
||||
@@ -221,7 +220,7 @@ fun ExtractableSubstringInfo.replaceWith(replacement: KtExpression): KtExpressio
|
||||
fun KtExpression.mustBeParenthesizedInInitializerPosition(): Boolean {
|
||||
if (this !is KtBinaryExpression) return false
|
||||
|
||||
if (left?.mustBeParenthesizedInInitializerPosition() ?: false) return true
|
||||
if (left?.mustBeParenthesizedInInitializerPosition() == true) return true
|
||||
return PsiChildRange(left, operationReference).any { (it is PsiWhiteSpace) && it.textContains('\n') }
|
||||
}
|
||||
|
||||
|
||||
+23
-24
@@ -36,9 +36,9 @@ import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||
import java.util.*
|
||||
|
||||
class KotlinMemberInfoStorage(
|
||||
classOrObject: KtClassOrObject,
|
||||
filter: (KtNamedDeclaration) -> Boolean = { true }
|
||||
): AbstractMemberInfoStorage<KtNamedDeclaration, PsiNamedElement, KotlinMemberInfo>(classOrObject, filter) {
|
||||
classOrObject: KtClassOrObject,
|
||||
filter: (KtNamedDeclaration) -> Boolean = { true }
|
||||
) : AbstractMemberInfoStorage<KtNamedDeclaration, PsiNamedElement, KotlinMemberInfo>(classOrObject, filter) {
|
||||
override fun memberConflict(member1: KtNamedDeclaration, member: KtNamedDeclaration): Boolean {
|
||||
val descriptor1 = member1.resolveToDescriptorWrapperAware()
|
||||
val descriptor = member.resolveToDescriptorWrapperAware()
|
||||
@@ -50,7 +50,7 @@ class KotlinMemberInfoStorage(
|
||||
!overloadUtil.isOverloadable(descriptor1, descriptor)
|
||||
}
|
||||
descriptor1 is PropertyDescriptor && descriptor is PropertyDescriptor ||
|
||||
descriptor1 is ClassDescriptor && descriptor is ClassDescriptor -> true
|
||||
descriptor1 is ClassDescriptor && descriptor is ClassDescriptor -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
@@ -81,14 +81,14 @@ class KotlinMemberInfoStorage(
|
||||
}
|
||||
|
||||
fun extractClassMembers(
|
||||
aClass: KtClassOrObject,
|
||||
collectSuperTypeEntries: Boolean = true,
|
||||
filter: ((KtNamedDeclaration) -> Boolean)? = null
|
||||
aClass: KtClassOrObject,
|
||||
collectSuperTypeEntries: Boolean = true,
|
||||
filter: ((KtNamedDeclaration) -> Boolean)? = null
|
||||
): List<KotlinMemberInfo> {
|
||||
fun KtClassOrObject.extractFromClassBody(
|
||||
filter: ((KtNamedDeclaration) -> Boolean)?,
|
||||
isCompanion: Boolean,
|
||||
result: MutableCollection<KotlinMemberInfo>
|
||||
filter: ((KtNamedDeclaration) -> Boolean)?,
|
||||
isCompanion: Boolean,
|
||||
result: MutableCollection<KotlinMemberInfo>
|
||||
) {
|
||||
declarations
|
||||
.asSequence()
|
||||
@@ -98,7 +98,7 @@ fun extractClassMembers(
|
||||
&& !(it is KtObjectDeclaration && it.isCompanion())
|
||||
&& (filter == null || filter(it))
|
||||
}
|
||||
.mapTo(result) { KotlinMemberInfo(it as KtNamedDeclaration, isCompanionMember = isCompanion) }
|
||||
.mapTo(result) { KotlinMemberInfo(it as KtNamedDeclaration, isCompanionMember = isCompanion) }
|
||||
}
|
||||
|
||||
val result = ArrayList<KotlinMemberInfo>()
|
||||
@@ -107,26 +107,25 @@ fun extractClassMembers(
|
||||
aClass.superTypeListEntries
|
||||
.asSequence()
|
||||
.filterIsInstance<KtSuperTypeEntry>()
|
||||
.mapNotNull {
|
||||
val typeReference = it.typeReference ?: return@mapNotNull null
|
||||
val type = typeReference.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, typeReference]
|
||||
val classDescriptor = type?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||
val classPsi = classDescriptor?.source?.getPsi()
|
||||
when (classPsi) {
|
||||
is KtClass -> classPsi
|
||||
is PsiClass -> KtPsiClassWrapper(classPsi)
|
||||
else -> null
|
||||
}
|
||||
.mapNotNull {
|
||||
val typeReference = it.typeReference ?: return@mapNotNull null
|
||||
val type = typeReference.analyze(BodyResolveMode.PARTIAL)[BindingContext.TYPE, typeReference]
|
||||
val classDescriptor = type?.constructor?.declarationDescriptor as? ClassDescriptor
|
||||
when (val classPsi = classDescriptor?.source?.getPsi()) {
|
||||
is KtClass -> classPsi
|
||||
is PsiClass -> KtPsiClassWrapper(classPsi)
|
||||
else -> null
|
||||
}
|
||||
.filter { it.isInterfaceClass() }
|
||||
.mapTo(result) { KotlinMemberInfo(it, true) }
|
||||
}
|
||||
.filter { it.isInterfaceClass() }
|
||||
.mapTo(result) { KotlinMemberInfo(it, true) }
|
||||
}
|
||||
|
||||
aClass.primaryConstructor
|
||||
?.valueParameters
|
||||
?.asSequence()
|
||||
?.filter { it.hasValOrVar() }
|
||||
?.mapTo(result) { KotlinMemberInfo(it) }
|
||||
?.mapTo(result) { KotlinMemberInfo(it) }
|
||||
|
||||
aClass.extractFromClassBody(filter, false, result)
|
||||
(aClass as? KtClass)?.companionObjects?.firstOrNull()?.extractFromClassBody(filter, true, result)
|
||||
|
||||
Reference in New Issue
Block a user