Suggest dialog if all members without actual modifier

Relates to #KT-31476
This commit is contained in:
Dmitry Gridin
2019-05-23 11:26:48 +07:00
parent 8dd1389979
commit 61a740457d
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory
import org.jetbrains.kotlin.idea.util.allowedValOrVar
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.idea.util.isEffectivelyActual
import org.jetbrains.kotlin.idea.util.liftToExpected
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.psi.*
@@ -111,19 +110,21 @@ class CreateExpectedClassFix(
outerExpectedClass: KtClassOrObject?,
commonModule: Module
) : CreateExpectedFix<KtClassOrObject>(klass, outerExpectedClass, commonModule, block@{ project, element ->
val originalCollection = element.collectDeclarations(false).filter(KtDeclaration::canAddActualModifier).toList()
val collection = originalCollection.filterNot(KtDeclaration::isAlwaysActual)
val originalElements = element.collectDeclarations(false).filter(KtDeclaration::canAddActualModifier).toList()
val members = originalElements.filterNot(KtDeclaration::isAlwaysActual)
val selectedElements = when {
ApplicationManager.getApplication().isUnitTestMode -> collection.filter { it.isEffectivelyActual(false) }
collection.any(KtDeclaration::hasActualModifier) && collection.any { !it.hasActualModifier() } -> {
members.all(KtDeclaration::hasActualModifier) -> originalElements
ApplicationManager.getApplication().isUnitTestMode -> members.filter(KtDeclaration::hasActualModifier)
else -> {
val prefix = klass.fqName?.asString()?.plus(".") ?: ""
chooseMembers(project, collection, prefix) ?: return@block null
chooseMembers(project, members, prefix) ?: return@block null
}
else -> null
}
project.executeWriteCommand("Repair actual members") {
repairActualModifiers(originalCollection, selectedElements)
if (originalElements.isNotEmpty()) {
project.executeWriteCommand("Repair actual members") {
repairActualModifiers(originalElements, selectedElements)
}
}
generateClassOrObject(project, true, element, listOfNotNull(outerExpectedClass))
@@ -140,6 +141,11 @@ private fun KtDeclaration.canAddActualModifier() = when (this) {
*/
private fun chooseMembers(project: Project, collection: Collection<KtDeclaration>, prefixToRemove: String): List<KtDeclaration>? {
val classMembers = collection.map { Member(prefixToRemove, it, it.resolveToDescriptorIfAny()!!) }
val filter = if (collection.any(KtDeclaration::hasActualModifier)) {
{ declaration: KtDeclaration -> declaration.hasActualModifier() }
} else {
{ true }
}
return MemberChooser(
classMembers.toTypedArray(),
true,
@@ -148,7 +154,7 @@ private fun chooseMembers(project: Project, collection: Collection<KtDeclaration
).run {
title = "Choose actual members"
setCopyJavadocVisible(false)
selectElements(classMembers.filter { (it.element as KtDeclaration).hasActualModifier() }.toTypedArray())
selectElements(classMembers.filter { filter((it.element as KtDeclaration)) }.toTypedArray())
show()
if (!isOK) null else selectedElements?.map { it.element as KtDeclaration }.orEmpty()
}
@@ -175,25 +181,24 @@ private fun KtClassOrObject.collectDeclarations(withSelf: Boolean = true): Seque
private fun repairActualModifiers(
originalElements: Collection<KtDeclaration>,
// If null, all class declarations are actual
selectedElements: Collection<KtDeclaration>?
selectedElements: Collection<KtDeclaration>
) {
if (selectedElements == null)
if (originalElements.size == selectedElements.size)
for (original in originalElements) {
original.recursivelyMakeActual()
original.makeActualWithParents()
}
else
for (original in originalElements) {
if (original.isAlwaysActual() || original in selectedElements)
original.recursivelyMakeActual()
original.makeActualWithParents()
else
original.makeNotActual()
}
}
private tailrec fun KtDeclaration.recursivelyMakeActual() {
private tailrec fun KtDeclaration.makeActualWithParents() {
makeActual()
containingClassOrObject?.takeUnless(KtDeclaration::hasActualModifier)?.recursivelyMakeActual()
containingClassOrObject?.takeUnless(KtDeclaration::hasActualModifier)?.makeActualWithParents()
}
private fun KtDeclaration.isAlwaysActual(): Boolean = when (this) {