Move: Check if sealed class is moved with its subclasses

#KT-22769 Fixed
This commit is contained in:
Alexey Sedunov
2018-02-13 19:31:13 +03:00
parent 27d4593fc4
commit 4537192e86
22 changed files with 115 additions and 0 deletions
@@ -59,6 +59,7 @@ import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.descriptorUtil.getImportableDescriptor
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.descriptorUtil.isSubclassOf
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
@@ -451,6 +452,38 @@ class MoveConflictChecker(
}
}
private fun checkSealedClassMove(conflicts: MultiMap<PsiElement, String>) {
val visited = HashSet<PsiElement>()
for (elementToMove in elementsToMove) {
if (!visited.add(elementToMove)) continue
if (elementToMove !is KtClassOrObject) continue
val rootClass: KtClass
val rootClassDescriptor: ClassDescriptor
if (elementToMove is KtClass && elementToMove.isSealed()) {
rootClass = elementToMove
rootClassDescriptor = rootClass.resolveToDescriptorIfAny() as? ClassDescriptor ?: return
}
else {
val classDescriptor = elementToMove.resolveToDescriptorIfAny() as? ClassDescriptor ?: return
val superClassDescriptor = classDescriptor.getSuperClassNotAny() ?: return
if (superClassDescriptor.modality != Modality.SEALED) return
rootClassDescriptor = superClassDescriptor
rootClass = rootClassDescriptor.source.getPsi() as? KtClass ?: return
}
val subclasses = rootClassDescriptor.sealedSubclasses.mapNotNull { it.source.getPsi() }
if (subclasses.isEmpty()) continue
visited.add(rootClass)
visited.addAll(subclasses)
if (isToBeMoved(rootClass) && subclasses.all { isToBeMoved(it) }) continue
conflicts.putValue(rootClass, "Sealed class '${rootClass.name}' must be moved with all its subclasses")
}
}
fun checkAllConflicts(
externalUsages: MutableSet<UsageInfo>,
internalUsages: MutableSet<UsageInfo>,
@@ -461,6 +494,7 @@ class MoveConflictChecker(
checkVisibilityInUsages(externalUsages, conflicts)
checkVisibilityInDeclarations(conflicts)
checkInternalMemberUsages(conflicts)
checkSealedClassMove(conflicts)
}
}