Allow sealed inheritors for expect sealed classes in MPP submodules

KT-45842 Fixed
KTIJ-7068
This commit is contained in:
Dmitriy Novozhilov
2021-04-05 12:48:35 +03:00
committed by TeamCityServer
parent 1633190478
commit fe81078366
12 changed files with 78 additions and 3 deletions
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.checkers
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
import org.jetbrains.kotlin.descriptors.isSealed
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtClassOrObject
@@ -22,8 +23,16 @@ object SealedInheritorInSameModuleChecker : DeclarationChecker {
val typeReference = superTypeListEntry.typeReference ?: continue
val superType = typeReference.getAbbreviatedTypeOrType(context.trace.bindingContext)?.unwrap() ?: continue
val superClass = superType.constructor.declarationDescriptor ?: continue
if (superClass.isSealed() && superClass.module != currentModule) {
context.trace.report(Errors.SEALED_INHERITOR_IN_DIFFERENT_MODULE.on(typeReference))
if (superClass.isSealed()) {
/*
* It's allowed to declare inheritors of expect sealed class in any dependent module until actual
* counterpart for this class will be declared. So if super class is resolved to expect sealed
* class then its allowed to declare inheritor
*/
val inheritorAllowed = superClass.isExpect || superClass.module == currentModule
if (!inheritorAllowed) {
context.trace.report(Errors.SEALED_INHERITOR_IN_DIFFERENT_MODULE.on(typeReference))
}
}
}
}
@@ -0,0 +1,4 @@
package foo
expect sealed class <!LINE_MARKER("descr='Is subclassed by SealedWithPlatformActuals [common] SealedWithPlatformActuals [main] SimpleShared'"), LINE_MARKER("descr='Has actuals in JVM'")!>SealedWithSharedActual<!>()
expect sealed class <!LINE_MARKER("descr='Is subclassed by SimpleShared'")!>SealedWithPlatformActuals<!> : SealedWithSharedActual
@@ -0,0 +1,6 @@
MODULE common { platform=[JVM, JS, Native]; root=common }
MODULE intermediate { platform=[JVM]; root=intermediate }
MODULE main { platform=[JVM]; root=main }
intermediate -> common { kind=DEPENDS_ON }
main -> intermediate { kind=DEPENDS_ON }
@@ -0,0 +1,4 @@
package foo
actual sealed class <!LINE_MARKER("descr='Is subclassed by SealedWithPlatformActuals [main] SimpleShared'"), LINE_MARKER("descr='Has declaration in common module'")!>SealedWithSharedActual<!>
class SimpleShared : SealedWithPlatformActuals<!NO_CONSTRUCTOR!>()<!>
@@ -0,0 +1,3 @@
package foo
actual sealed class SealedWithPlatformActuals <!ACTUAL_WITHOUT_EXPECT!>actual constructor()<!>: <!SEALED_INHERITOR_IN_DIFFERENT_MODULE!>SealedWithSharedActual<!>()
@@ -0,0 +1,16 @@
package foo
/*
* - Sealed1 [common], actualized in [main]
* - Sealed2 [common], actualized in [intermediate]
* - Derived11 [common]
* - Derived12 [intermediate]
* - Derived1 [common]
* - Derived2 [intermediate]
* - Derived3 [main]
*/
expect sealed class <!LINE_MARKER("descr='Has subclasses'")!>Sealed1<!>()
expect sealed class <!LINE_MARKER("descr='Is subclassed by Derived11 Derived12 Derived13Error'"), LINE_MARKER("descr='Has actuals in JVM'")!>Sealed2<!>() : Sealed1
class Derived1 : Sealed1()
class Derived11 : Sealed2()
@@ -0,0 +1,8 @@
MODULE common { platform=[JVM, JS, Native]; root=common }
MODULE intermediate { platform=[JVM]; root=intermediate }
MODULE main { platform=[JVM]; root=main }
MODULE real-main { platform=[JVM]; root=real-main }
intermediate -> common { kind=DEPENDS_ON }
main -> intermediate { kind=DEPENDS_ON }
real-main -> main { kind=DEPENDS_ON }
@@ -0,0 +1,6 @@
package foo
actual sealed class <!LINE_MARKER("descr='Is subclassed by Derived12 Derived13Error'"), LINE_MARKER("descr='Has declaration in common module'")!>Sealed2<!> : Sealed1()
class Derived2 : Sealed1()
class Derived12 : Sealed2()
@@ -0,0 +1,6 @@
package foo
actual sealed class <!LINE_MARKER("descr='Is subclassed by Derived2 Derived3Error'")!>Sealed1<!> actual constructor()
class Derived2 : Sealed1()
class Derived13Error : <!SEALED_INHERITOR_IN_DIFFERENT_MODULE!>Sealed2<!>() // should be an error
@@ -0,0 +1,3 @@
package foo
class Derived3Error : <!SEALED_INHERITOR_IN_DIFFERENT_MODULE!>Sealed1<!>() // should be an error
@@ -1 +1 @@
class CommonAImplTestClass: <!SEALED_INHERITOR_IN_DIFFERENT_MODULE!>TestClass<!>()
class CommonAImplTestClass: TestClass()
@@ -229,6 +229,16 @@ public class MultiplatformAnalysisTestGenerated extends AbstractMultiplatformAna
runTest("idea/testData/multiplatform/recursiveTypes/");
}
@TestMetadata("sealedInheritorsInComplexModuleStructure1")
public void testSealedInheritorsInComplexModuleStructure1() throws Exception {
runTest("idea/testData/multiplatform/sealedInheritorsInComplexModuleStructure1/");
}
@TestMetadata("sealedInheritorsInComplexModuleStructure2")
public void testSealedInheritorsInComplexModuleStructure2() throws Exception {
runTest("idea/testData/multiplatform/sealedInheritorsInComplexModuleStructure2/");
}
@TestMetadata("simple")
public void testSimple() throws Exception {
runTest("idea/testData/multiplatform/simple/");