Add KClass.sealedSubclasses to get direct subclasses of sealed class
#KT-14657 Fixed
This commit is contained in:
committed by
Ilya Gorbunov
parent
1b1713a849
commit
cbc92bc9a1
@@ -0,0 +1,41 @@
|
||||
// IGNORE_BACKEND: JS, JS_IR, JVM_IR, NATIVE
|
||||
// WITH_REFLECT
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.jvm.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
// --
|
||||
|
||||
sealed class SealedClassWithTopLevelSubclasses {
|
||||
class NotASealedSubclass : TL2()
|
||||
}
|
||||
object TL1 : SealedClassWithTopLevelSubclasses()
|
||||
open class TL2 : SealedClassWithTopLevelSubclasses()
|
||||
|
||||
// --
|
||||
|
||||
sealed class SealedClassWithNestedSubclasses {
|
||||
data class N1(val x: Unit) : SealedClassWithNestedSubclasses()
|
||||
object N2 : SealedClassWithNestedSubclasses()
|
||||
}
|
||||
|
||||
// --
|
||||
|
||||
sealed class SealedClassWithNoSubclasses
|
||||
|
||||
// --
|
||||
|
||||
fun sealedSubclassNames(c: KClass<*>) = c.sealedSubclasses.map { it.simpleName ?: throw AssertionError("Unnamed class: ${it.java}") }.sorted()
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(listOf("TL1", "TL2"), sealedSubclassNames(SealedClassWithTopLevelSubclasses::class))
|
||||
assertEquals(listOf("N1", "N2"), sealedSubclassNames(SealedClassWithNestedSubclasses::class))
|
||||
assertEquals(emptyList(), sealedSubclassNames(SealedClassWithNoSubclasses::class))
|
||||
|
||||
assertEquals(emptyList(), sealedSubclassNames(String::class))
|
||||
assertEquals(emptyList(), sealedSubclassNames(Thread::class))
|
||||
assertEquals(emptyList(), sealedSubclassNames(FloatArray::class))
|
||||
|
||||
return "OK"
|
||||
}
|
||||
+5
@@ -17844,6 +17844,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/qualifiedNameOfStandardClasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sealedSubclasses.kt")
|
||||
public void testSealedSubclasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/sealedSubclasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("starProjectedType.kt")
|
||||
public void testStarProjectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
||||
|
||||
+5
@@ -17844,6 +17844,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/qualifiedNameOfStandardClasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sealedSubclasses.kt")
|
||||
public void testSealedSubclasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/sealedSubclasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("starProjectedType.kt")
|
||||
public void testStarProjectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
||||
|
||||
+5
@@ -17844,6 +17844,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/qualifiedNameOfStandardClasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sealedSubclasses.kt")
|
||||
public void testSealedSubclasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/sealedSubclasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("starProjectedType.kt")
|
||||
public void testStarProjectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
||||
|
||||
@@ -76,6 +76,12 @@ public interface KClass<T : Any> : KDeclarationContainer, KAnnotatedElement, KCl
|
||||
@SinceKotlin("1.1")
|
||||
public val supertypes: List<KType>
|
||||
|
||||
/**
|
||||
* The list of the immediate subclasses if this class is a sealed class, or an empty list otherwise.
|
||||
*/
|
||||
@SinceKotlin("1.3")
|
||||
public val sealedSubclasses: List<KClass<out T>>
|
||||
|
||||
/**
|
||||
* Visibility of this class, or `null` if its visibility cannot be represented in Kotlin.
|
||||
*/
|
||||
|
||||
@@ -147,6 +147,14 @@ internal class KClassImpl<T : Any>(override val jClass: Class<T>) : KDeclaration
|
||||
result.compact()
|
||||
}
|
||||
|
||||
val sealedSubclasses: List<KClass<out T>> by ReflectProperties.lazySoft {
|
||||
descriptor.sealedSubclasses.mapNotNull { subclass ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val jClass = (subclass as ClassDescriptor).toJavaClass() as Class<out T>?
|
||||
jClass?.let { KClassImpl(it) }
|
||||
}
|
||||
}
|
||||
|
||||
val declaredNonStaticMembers: Collection<KCallableImpl<*>>
|
||||
by ReflectProperties.lazySoft { getMembers(memberScope, DECLARED) }
|
||||
private val declaredStaticMembers: Collection<KCallableImpl<*>>
|
||||
@@ -239,6 +247,11 @@ internal class KClassImpl<T : Any>(override val jClass: Class<T>) : KDeclaration
|
||||
|
||||
override val supertypes: List<KType> get() = data().supertypes
|
||||
|
||||
/**
|
||||
* The list of the immediate subclasses if this class is a sealed class, or an empty list otherwise.
|
||||
*/
|
||||
override val sealedSubclasses: List<KClass<out T>> get() = data().sealedSubclasses
|
||||
|
||||
override val visibility: KVisibility?
|
||||
get() = descriptor.visibility.toKVisibility()
|
||||
|
||||
|
||||
+5
@@ -16009,6 +16009,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/qualifiedNameOfStandardClasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sealedSubclasses.kt")
|
||||
public void testSealedSubclasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/sealedSubclasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("starProjectedType.kt")
|
||||
public void testStarProjectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
||||
|
||||
+5
@@ -17069,6 +17069,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/qualifiedNameOfStandardClasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("sealedSubclasses.kt")
|
||||
public void testSealedSubclasses() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/sealedSubclasses.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("starProjectedType.kt")
|
||||
public void testStarProjectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
||||
|
||||
@@ -40,6 +40,8 @@ internal abstract class KClassImpl<T : Any>(
|
||||
get() = TODO()
|
||||
override val typeParameters: List<KTypeParameter>
|
||||
get() = TODO()
|
||||
override val sealedSubclasses: List<KClass<out T>>
|
||||
get() = TODO()
|
||||
override val visibility: KVisibility?
|
||||
get() = TODO()
|
||||
|
||||
|
||||
@@ -40,6 +40,10 @@ public class ClassReference(override val jClass: Class<*>) : KClass<Any>, ClassB
|
||||
override val supertypes: List<KType>
|
||||
get() = error()
|
||||
|
||||
@SinceKotlin("1.3")
|
||||
override val sealedSubclasses: List<KClass<out Any>>
|
||||
get() = error()
|
||||
|
||||
@SinceKotlin("1.1")
|
||||
override val visibility: KVisibility?
|
||||
get() = error()
|
||||
|
||||
@@ -455,6 +455,7 @@ public final class kotlin/jvm/internal/ClassReference : kotlin/jvm/internal/Clas
|
||||
public fun getNestedClasses ()Ljava/util/Collection;
|
||||
public fun getObjectInstance ()Ljava/lang/Object;
|
||||
public fun getQualifiedName ()Ljava/lang/String;
|
||||
public fun getSealedSubclasses ()Ljava/util/List;
|
||||
public fun getSimpleName ()Ljava/lang/String;
|
||||
public fun getSupertypes ()Ljava/util/List;
|
||||
public fun getTypeParameters ()Ljava/util/List;
|
||||
@@ -1173,6 +1174,7 @@ public abstract interface class kotlin/reflect/KClass : kotlin/reflect/KAnnotate
|
||||
public abstract fun getNestedClasses ()Ljava/util/Collection;
|
||||
public abstract fun getObjectInstance ()Ljava/lang/Object;
|
||||
public abstract fun getQualifiedName ()Ljava/lang/String;
|
||||
public abstract fun getSealedSubclasses ()Ljava/util/List;
|
||||
public abstract fun getSimpleName ()Ljava/lang/String;
|
||||
public abstract fun getSupertypes ()Ljava/util/List;
|
||||
public abstract fun getTypeParameters ()Ljava/util/List;
|
||||
|
||||
+2
@@ -3293,6 +3293,7 @@ public final class kotlin/jvm/internal/ClassReference : kotlin/jvm/internal/Clas
|
||||
public fun getNestedClasses ()Ljava/util/Collection;
|
||||
public fun getObjectInstance ()Ljava/lang/Object;
|
||||
public fun getQualifiedName ()Ljava/lang/String;
|
||||
public fun getSealedSubclasses ()Ljava/util/List;
|
||||
public fun getSimpleName ()Ljava/lang/String;
|
||||
public fun getSupertypes ()Ljava/util/List;
|
||||
public fun getTypeParameters ()Ljava/util/List;
|
||||
@@ -4292,6 +4293,7 @@ public abstract interface class kotlin/reflect/KClass : kotlin/reflect/KAnnotate
|
||||
public abstract fun getNestedClasses ()Ljava/util/Collection;
|
||||
public abstract fun getObjectInstance ()Ljava/lang/Object;
|
||||
public abstract fun getQualifiedName ()Ljava/lang/String;
|
||||
public abstract fun getSealedSubclasses ()Ljava/util/List;
|
||||
public abstract fun getSimpleName ()Ljava/lang/String;
|
||||
public abstract fun getSupertypes ()Ljava/util/List;
|
||||
public abstract fun getTypeParameters ()Ljava/util/List;
|
||||
|
||||
Reference in New Issue
Block a user