Add KClass.sealedSubclasses to get direct subclasses of sealed class

#KT-14657 Fixed
This commit is contained in:
Alexander Udalov
2018-08-03 13:23:53 +02:00
committed by Ilya Gorbunov
parent 1b1713a849
commit cbc92bc9a1
12 changed files with 95 additions and 0 deletions
@@ -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"
}
@@ -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");
@@ -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");
@@ -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()
@@ -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");
@@ -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;
@@ -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;