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");
|
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")
|
@TestMetadata("starProjectedType.kt")
|
||||||
public void testStarProjectedType() throws Exception {
|
public void testStarProjectedType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
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");
|
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")
|
@TestMetadata("starProjectedType.kt")
|
||||||
public void testStarProjectedType() throws Exception {
|
public void testStarProjectedType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
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");
|
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")
|
@TestMetadata("starProjectedType.kt")
|
||||||
public void testStarProjectedType() throws Exception {
|
public void testStarProjectedType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
||||||
|
|||||||
@@ -76,6 +76,12 @@ public interface KClass<T : Any> : KDeclarationContainer, KAnnotatedElement, KCl
|
|||||||
@SinceKotlin("1.1")
|
@SinceKotlin("1.1")
|
||||||
public val supertypes: List<KType>
|
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.
|
* 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()
|
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<*>>
|
val declaredNonStaticMembers: Collection<KCallableImpl<*>>
|
||||||
by ReflectProperties.lazySoft { getMembers(memberScope, DECLARED) }
|
by ReflectProperties.lazySoft { getMembers(memberScope, DECLARED) }
|
||||||
private val declaredStaticMembers: Collection<KCallableImpl<*>>
|
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
|
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?
|
override val visibility: KVisibility?
|
||||||
get() = descriptor.visibility.toKVisibility()
|
get() = descriptor.visibility.toKVisibility()
|
||||||
|
|
||||||
|
|||||||
+5
@@ -16009,6 +16009,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/reflection/classes/qualifiedNameOfStandardClasses.kt");
|
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")
|
@TestMetadata("starProjectedType.kt")
|
||||||
public void testStarProjectedType() throws Exception {
|
public void testStarProjectedType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
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");
|
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")
|
@TestMetadata("starProjectedType.kt")
|
||||||
public void testStarProjectedType() throws Exception {
|
public void testStarProjectedType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
runTest("compiler/testData/codegen/box/reflection/classes/starProjectedType.kt");
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ internal abstract class KClassImpl<T : Any>(
|
|||||||
get() = TODO()
|
get() = TODO()
|
||||||
override val typeParameters: List<KTypeParameter>
|
override val typeParameters: List<KTypeParameter>
|
||||||
get() = TODO()
|
get() = TODO()
|
||||||
|
override val sealedSubclasses: List<KClass<out T>>
|
||||||
|
get() = TODO()
|
||||||
override val visibility: KVisibility?
|
override val visibility: KVisibility?
|
||||||
get() = TODO()
|
get() = TODO()
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ public class ClassReference(override val jClass: Class<*>) : KClass<Any>, ClassB
|
|||||||
override val supertypes: List<KType>
|
override val supertypes: List<KType>
|
||||||
get() = error()
|
get() = error()
|
||||||
|
|
||||||
|
@SinceKotlin("1.3")
|
||||||
|
override val sealedSubclasses: List<KClass<out Any>>
|
||||||
|
get() = error()
|
||||||
|
|
||||||
@SinceKotlin("1.1")
|
@SinceKotlin("1.1")
|
||||||
override val visibility: KVisibility?
|
override val visibility: KVisibility?
|
||||||
get() = error()
|
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 getNestedClasses ()Ljava/util/Collection;
|
||||||
public fun getObjectInstance ()Ljava/lang/Object;
|
public fun getObjectInstance ()Ljava/lang/Object;
|
||||||
public fun getQualifiedName ()Ljava/lang/String;
|
public fun getQualifiedName ()Ljava/lang/String;
|
||||||
|
public fun getSealedSubclasses ()Ljava/util/List;
|
||||||
public fun getSimpleName ()Ljava/lang/String;
|
public fun getSimpleName ()Ljava/lang/String;
|
||||||
public fun getSupertypes ()Ljava/util/List;
|
public fun getSupertypes ()Ljava/util/List;
|
||||||
public fun getTypeParameters ()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 getNestedClasses ()Ljava/util/Collection;
|
||||||
public abstract fun getObjectInstance ()Ljava/lang/Object;
|
public abstract fun getObjectInstance ()Ljava/lang/Object;
|
||||||
public abstract fun getQualifiedName ()Ljava/lang/String;
|
public abstract fun getQualifiedName ()Ljava/lang/String;
|
||||||
|
public abstract fun getSealedSubclasses ()Ljava/util/List;
|
||||||
public abstract fun getSimpleName ()Ljava/lang/String;
|
public abstract fun getSimpleName ()Ljava/lang/String;
|
||||||
public abstract fun getSupertypes ()Ljava/util/List;
|
public abstract fun getSupertypes ()Ljava/util/List;
|
||||||
public abstract fun getTypeParameters ()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 getNestedClasses ()Ljava/util/Collection;
|
||||||
public fun getObjectInstance ()Ljava/lang/Object;
|
public fun getObjectInstance ()Ljava/lang/Object;
|
||||||
public fun getQualifiedName ()Ljava/lang/String;
|
public fun getQualifiedName ()Ljava/lang/String;
|
||||||
|
public fun getSealedSubclasses ()Ljava/util/List;
|
||||||
public fun getSimpleName ()Ljava/lang/String;
|
public fun getSimpleName ()Ljava/lang/String;
|
||||||
public fun getSupertypes ()Ljava/util/List;
|
public fun getSupertypes ()Ljava/util/List;
|
||||||
public fun getTypeParameters ()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 getNestedClasses ()Ljava/util/Collection;
|
||||||
public abstract fun getObjectInstance ()Ljava/lang/Object;
|
public abstract fun getObjectInstance ()Ljava/lang/Object;
|
||||||
public abstract fun getQualifiedName ()Ljava/lang/String;
|
public abstract fun getQualifiedName ()Ljava/lang/String;
|
||||||
|
public abstract fun getSealedSubclasses ()Ljava/util/List;
|
||||||
public abstract fun getSimpleName ()Ljava/lang/String;
|
public abstract fun getSimpleName ()Ljava/lang/String;
|
||||||
public abstract fun getSupertypes ()Ljava/util/List;
|
public abstract fun getSupertypes ()Ljava/util/List;
|
||||||
public abstract fun getTypeParameters ()Ljava/util/List;
|
public abstract fun getTypeParameters ()Ljava/util/List;
|
||||||
|
|||||||
Reference in New Issue
Block a user