From 7e317f7a7c0c77cbc6e96b7314c0f6f9f4c5f2a7 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Tue, 12 Jul 2016 19:06:00 +0300 Subject: [PATCH] Reflection: add API for declaration modifiers #KT-10447 Fixed --- .../reflection/modifiers/callableModality.kt | 51 +++++++++++++ .../box/reflection/modifiers/classModality.kt | 56 +++++++++++++++ .../box/reflection/modifiers/classes.kt | 43 +++++++++++ .../box/reflection/modifiers/functions.kt | 71 +++++++++++++++++++ .../box/reflection/modifiers/parameters.kt | 36 ++++++++++ .../box/reflection/modifiers/properties.kt | 22 ++++++ .../reflection/modifiers/typeParameters.kt | 15 ++++ .../codegen/BlackBoxCodegenTestGenerated.java | 51 +++++++++++++ core/builtins/src/kotlin/reflect/KCallable.kt | 15 ++++ core/builtins/src/kotlin/reflect/KClass.kt | 43 +++++++++++ core/builtins/src/kotlin/reflect/KFunction.kt | 42 ++++++++++- .../builtins/src/kotlin/reflect/KParameter.kt | 26 +++++++ core/builtins/src/kotlin/reflect/KProperty.kt | 14 ++++ .../src/kotlin/reflect/KTypeParameter.kt | 7 ++ .../reflect/jvm/internal/KCallableImpl.kt | 10 +++ .../kotlin/reflect/jvm/internal/KClassImpl.kt | 21 ++++++ .../reflect/jvm/internal/KFunctionImpl.kt | 18 +++++ .../reflect/jvm/internal/KParameterImpl.kt | 12 ++++ .../reflect/jvm/internal/KPropertyImpl.kt | 30 ++++++++ .../jvm/internal/KTypeParameterImpl.kt | 3 + .../jvm/internal/CallableReference.java | 15 ++++ .../src/kotlin/jvm/internal/ClassReference.kt | 21 ++++++ .../jvm/internal/FunctionReference.java | 45 ++++++++++++ .../jvm/internal/PropertyReference.java | 15 ++++ 24 files changed, 681 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/box/reflection/modifiers/callableModality.kt create mode 100644 compiler/testData/codegen/box/reflection/modifiers/classModality.kt create mode 100644 compiler/testData/codegen/box/reflection/modifiers/classes.kt create mode 100644 compiler/testData/codegen/box/reflection/modifiers/functions.kt create mode 100644 compiler/testData/codegen/box/reflection/modifiers/parameters.kt create mode 100644 compiler/testData/codegen/box/reflection/modifiers/properties.kt create mode 100644 compiler/testData/codegen/box/reflection/modifiers/typeParameters.kt diff --git a/compiler/testData/codegen/box/reflection/modifiers/callableModality.kt b/compiler/testData/codegen/box/reflection/modifiers/callableModality.kt new file mode 100644 index 00000000000..1658898e409 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/modifiers/callableModality.kt @@ -0,0 +1,51 @@ +// WITH_REFLECT + +import kotlin.test.assertTrue +import kotlin.test.assertFalse + +interface Interface { + open fun openFun() {} + abstract fun abstractFun() +} + +abstract class AbstractClass { + final val finalVal = Unit + open val openVal = Unit + abstract var abstractVar: Unit +} + +fun box(): String { + assertFalse(Interface::openFun.isFinal) + assertTrue(Interface::openFun.isOpen) + assertFalse(Interface::openFun.isAbstract) + + assertFalse(Interface::abstractFun.isFinal) + assertFalse(Interface::abstractFun.isOpen) + assertTrue(Interface::abstractFun.isAbstract) + + assertTrue(AbstractClass::finalVal.isFinal) + assertFalse(AbstractClass::finalVal.isOpen) + assertFalse(AbstractClass::finalVal.isAbstract) + assertTrue(AbstractClass::finalVal.getter.isFinal) + assertFalse(AbstractClass::finalVal.getter.isOpen) + assertFalse(AbstractClass::finalVal.getter.isAbstract) + + assertFalse(AbstractClass::openVal.isFinal) + assertTrue(AbstractClass::openVal.isOpen) + assertFalse(AbstractClass::openVal.isAbstract) + assertFalse(AbstractClass::openVal.getter.isFinal) + assertTrue(AbstractClass::openVal.getter.isOpen) + assertFalse(AbstractClass::openVal.getter.isAbstract) + + assertFalse(AbstractClass::abstractVar.isFinal) + assertFalse(AbstractClass::abstractVar.isOpen) + assertTrue(AbstractClass::abstractVar.isAbstract) + assertFalse(AbstractClass::abstractVar.getter.isFinal) + assertFalse(AbstractClass::abstractVar.getter.isOpen) + assertTrue(AbstractClass::abstractVar.getter.isAbstract) + assertFalse(AbstractClass::abstractVar.setter.isFinal) + assertFalse(AbstractClass::abstractVar.setter.isOpen) + assertTrue(AbstractClass::abstractVar.setter.isAbstract) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/modifiers/classModality.kt b/compiler/testData/codegen/box/reflection/modifiers/classModality.kt new file mode 100644 index 00000000000..9c0286fdd67 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/modifiers/classModality.kt @@ -0,0 +1,56 @@ +// WITH_REFLECT + +import kotlin.test.assertTrue +import kotlin.test.assertFalse + +class FinalClass { + companion object Companion +} +open class OpenClass +abstract class AbstractClass +interface Interface +enum class EnumClass +enum class EnumClassWithAbstractMember { ; abstract fun foo() } +annotation class AnnotationClass +object Object + +fun box(): String { + assertTrue(FinalClass::class.isFinal) + assertFalse(FinalClass::class.isOpen) + assertFalse(FinalClass::class.isAbstract) + + assertTrue(FinalClass.Companion::class.isFinal) + assertFalse(FinalClass.Companion::class.isOpen) + assertFalse(FinalClass.Companion::class.isAbstract) + + assertFalse(OpenClass::class.isFinal) + assertTrue(OpenClass::class.isOpen) + assertFalse(OpenClass::class.isAbstract) + + assertFalse(AbstractClass::class.isFinal) + assertFalse(AbstractClass::class.isOpen) + assertTrue(AbstractClass::class.isAbstract) + + assertFalse(Interface::class.isFinal) + assertFalse(Interface::class.isOpen) + assertTrue(Interface::class.isAbstract) + + assertTrue(EnumClass::class.isFinal) + assertFalse(EnumClass::class.isOpen) + assertFalse(EnumClass::class.isAbstract) + + assertTrue(EnumClassWithAbstractMember::class.isFinal) + assertFalse(EnumClassWithAbstractMember::class.isOpen) + assertFalse(EnumClassWithAbstractMember::class.isAbstract) + + // Note that unlike in JVM, annotation classes are final in Kotlin + assertTrue(AnnotationClass::class.isFinal) + assertFalse(AnnotationClass::class.isOpen) + assertFalse(AnnotationClass::class.isAbstract) + + assertTrue(Object::class.isFinal) + assertFalse(Object::class.isOpen) + assertFalse(Object::class.isAbstract) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/modifiers/classes.kt b/compiler/testData/codegen/box/reflection/modifiers/classes.kt new file mode 100644 index 00000000000..05d7f3c9be4 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/modifiers/classes.kt @@ -0,0 +1,43 @@ +// WITH_REFLECT + +import kotlin.test.assertTrue +import kotlin.test.assertFalse + +sealed class S { + data class DataClass(val x: Int) : S() + inner class InnerClass + companion object + object NonCompanionObject +} + +fun box(): String { + assertTrue(S::class.isSealed) + assertFalse(S::class.isFinal) + assertFalse(S::class.isOpen) + assertFalse(S::class.isAbstract) + assertFalse(S::class.isData) + assertFalse(S::class.isInner) + assertFalse(S::class.isCompanion) + + assertFalse(S.DataClass::class.isSealed) + assertTrue(S.DataClass::class.isData) + assertFalse(S.DataClass::class.isInner) + assertFalse(S.DataClass::class.isCompanion) + + assertFalse(S.InnerClass::class.isSealed) + assertFalse(S.InnerClass::class.isData) + assertTrue(S.InnerClass::class.isInner) + assertFalse(S.InnerClass::class.isCompanion) + + assertFalse(S.Companion::class.isSealed) + assertFalse(S.Companion::class.isData) + assertFalse(S.Companion::class.isInner) + assertTrue(S.Companion::class.isCompanion) + + assertFalse(S.NonCompanionObject::class.isSealed) + assertFalse(S.NonCompanionObject::class.isData) + assertFalse(S.NonCompanionObject::class.isInner) + assertFalse(S.NonCompanionObject::class.isCompanion) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/modifiers/functions.kt b/compiler/testData/codegen/box/reflection/modifiers/functions.kt new file mode 100644 index 00000000000..e4e22ac420d --- /dev/null +++ b/compiler/testData/codegen/box/reflection/modifiers/functions.kt @@ -0,0 +1,71 @@ +// WITH_REFLECT + +import kotlin.test.assertTrue +import kotlin.test.assertFalse + +inline fun inline() {} +class External { external fun external() } +operator fun Unit.invoke() {} +infix fun Unit.infix(unit: Unit) {} +tailrec fun tailrec() { tailrec() } +class Suspend { suspend fun suspend(c: Continuation) {} } + +val externalGetter = Unit + external get + +inline var inlineProperty: Unit + get() = Unit + set(value) {} + +fun box(): String { + assertTrue(::inline.isInline) + assertFalse(::inline.isExternal) + assertFalse(::inline.isOperator) + assertFalse(::inline.isInfix) + assertFalse(::inline.isTailrec) + assertFalse(::inline.isSuspend) + + assertFalse(External::external.isInline) + assertTrue(External::external.isExternal) + assertFalse(External::external.isOperator) + assertFalse(External::external.isInfix) + assertFalse(External::external.isTailrec) + assertFalse(External::external.isSuspend) + + assertFalse(Unit::invoke.isInline) + assertFalse(Unit::invoke.isExternal) + assertTrue(Unit::invoke.isOperator) + assertFalse(Unit::invoke.isInfix) + assertFalse(Unit::invoke.isTailrec) + assertFalse(Unit::invoke.isSuspend) + + assertFalse(Unit::infix.isInline) + assertFalse(Unit::infix.isExternal) + assertFalse(Unit::infix.isOperator) + assertTrue(Unit::infix.isInfix) + assertFalse(Unit::infix.isTailrec) + assertFalse(Unit::infix.isSuspend) + + assertFalse(::tailrec.isInline) + assertFalse(::tailrec.isExternal) + assertFalse(::tailrec.isOperator) + assertFalse(::tailrec.isInfix) + assertTrue(::tailrec.isTailrec) + assertFalse(::tailrec.isSuspend) + + assertFalse(Suspend::suspend.isInline) + assertFalse(Suspend::suspend.isExternal) + assertFalse(Suspend::suspend.isOperator) + assertFalse(Suspend::suspend.isInfix) + assertFalse(Suspend::suspend.isTailrec) + assertTrue(Suspend::suspend.isSuspend) + + assertTrue(::externalGetter.getter.isExternal) + assertFalse(::externalGetter.getter.isInline) + + assertFalse(::inlineProperty.getter.isExternal) + assertTrue(::inlineProperty.getter.isInline) + assertTrue(::inlineProperty.setter.isInline) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/modifiers/parameters.kt b/compiler/testData/codegen/box/reflection/modifiers/parameters.kt new file mode 100644 index 00000000000..f66ec3ded3a --- /dev/null +++ b/compiler/testData/codegen/box/reflection/modifiers/parameters.kt @@ -0,0 +1,36 @@ +// WITH_REFLECT + +import kotlin.test.assertTrue +import kotlin.test.assertFalse + +inline fun Unit.foo( + crossinline crossinline: () -> Unit, + noinline coroutine x: Unit.() -> Continuation, + vararg vararg: Unit +) {} + +fun box(): String { + val p = Unit::foo.parameters + + assertFalse(p[0].isNoinline) + assertFalse(p[0].isCrossinline) + assertFalse(p[0].isVararg) + assertFalse(p[0].isCoroutine) + + assertFalse(p[1].isNoinline) + assertTrue(p[1].isCrossinline) + assertFalse(p[1].isVararg) + assertFalse(p[1].isCoroutine) + + assertTrue(p[2].isNoinline) + assertFalse(p[2].isCrossinline) + assertFalse(p[2].isVararg) + assertTrue(p[2].isCoroutine) + + assertFalse(p[3].isNoinline) + assertFalse(p[3].isCrossinline) + assertTrue(p[3].isVararg) + assertFalse(p[3].isCoroutine) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/modifiers/properties.kt b/compiler/testData/codegen/box/reflection/modifiers/properties.kt new file mode 100644 index 00000000000..3e46b2b6e01 --- /dev/null +++ b/compiler/testData/codegen/box/reflection/modifiers/properties.kt @@ -0,0 +1,22 @@ +// WITH_REFLECT + +import kotlin.test.assertTrue +import kotlin.test.assertFalse + +const val const = "const" +val nonConst = "nonConst" + +class A { + lateinit var lateinit: Unit + var nonLateinit = Unit +} + +fun box(): String { + assertTrue(::const.isConst) + assertFalse(::nonConst.isConst) + + assertTrue(A::lateinit.isLateinit) + assertFalse(A::nonLateinit.isLateinit) + + return "OK" +} diff --git a/compiler/testData/codegen/box/reflection/modifiers/typeParameters.kt b/compiler/testData/codegen/box/reflection/modifiers/typeParameters.kt new file mode 100644 index 00000000000..49dda6c67ae --- /dev/null +++ b/compiler/testData/codegen/box/reflection/modifiers/typeParameters.kt @@ -0,0 +1,15 @@ +// WITH_REFLECT + +import kotlin.test.assertTrue +import kotlin.test.assertFalse + +class A { + fun nonReified(): T = null!! + inline fun reified(): U = null!! +} + +fun box(): String { + assertFalse(A::class.members.single { it.name == "nonReified" }.typeParameters.single().isReified) + assertTrue(A::class.members.single { it.name == "reified" }.typeParameters.single().isReified) + return "OK" +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index f75a5d3c633..23863912886 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -12619,6 +12619,57 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } } + @TestMetadata("compiler/testData/codegen/box/reflection/modifiers") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class Modifiers extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInModifiers() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/reflection/modifiers"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("callableModality.kt") + public void testCallableModality() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/modifiers/callableModality.kt"); + doTest(fileName); + } + + @TestMetadata("classModality.kt") + public void testClassModality() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/modifiers/classModality.kt"); + doTest(fileName); + } + + @TestMetadata("classes.kt") + public void testClasses() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/modifiers/classes.kt"); + doTest(fileName); + } + + @TestMetadata("functions.kt") + public void testFunctions() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/modifiers/functions.kt"); + doTest(fileName); + } + + @TestMetadata("parameters.kt") + public void testParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/modifiers/parameters.kt"); + doTest(fileName); + } + + @TestMetadata("properties.kt") + public void testProperties() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/modifiers/properties.kt"); + doTest(fileName); + } + + @TestMetadata("typeParameters.kt") + public void testTypeParameters() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/reflection/modifiers/typeParameters.kt"); + doTest(fileName); + } + } + @TestMetadata("compiler/testData/codegen/box/reflection/multifileClasses") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/core/builtins/src/kotlin/reflect/KCallable.kt b/core/builtins/src/kotlin/reflect/KCallable.kt index d78b04b5b4d..a22d9386a11 100644 --- a/core/builtins/src/kotlin/reflect/KCallable.kt +++ b/core/builtins/src/kotlin/reflect/KCallable.kt @@ -62,4 +62,19 @@ public interface KCallable : KAnnotatedElement { * or its type does not match the type of the provided value, an exception is thrown. */ public fun callBy(args: Map): R + + /** + * `true` if this callable is `final`. + */ + public val isFinal: Boolean + + /** + * `true` if this callable is `open`. + */ + public val isOpen: Boolean + + /** + * `true` if this callable is `abstract`. + */ + public val isAbstract: Boolean } diff --git a/core/builtins/src/kotlin/reflect/KClass.kt b/core/builtins/src/kotlin/reflect/KClass.kt index 72ca333fb57..9cba0def335 100644 --- a/core/builtins/src/kotlin/reflect/KClass.kt +++ b/core/builtins/src/kotlin/reflect/KClass.kt @@ -73,6 +73,49 @@ public interface KClass : KDeclarationContainer, KAnnotatedElement, KCl */ public val supertypes: List + /** + * `true` if this class is `final`. + */ + public val isFinal: Boolean + + /** + * `true` if this class is `open`. + */ + public val isOpen: Boolean + + /** + * `true` if this class is `abstract`. + */ + public val isAbstract: Boolean + + /** + * `true` if this class is `sealed`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/classes.html#sealed-classes) + * for more information. + */ + public val isSealed: Boolean + + /** + * `true` if this class is a data class. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/data-classes.html) + * for more information. + */ + public val isData: Boolean + + /** + * `true` if this class is an inner class. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/nested-classes.html#inner-classes) + * for more information. + */ + public val isInner: Boolean + + /** + * `true` if this class is a companion object. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects) + * for more information. + */ + public val isCompanion: Boolean + /** * Returns `true` if [other] is a [KClass] instance representing the same class on a given platform. * diff --git a/core/builtins/src/kotlin/reflect/KFunction.kt b/core/builtins/src/kotlin/reflect/KFunction.kt index a6c21632060..bdc14d5d31e 100644 --- a/core/builtins/src/kotlin/reflect/KFunction.kt +++ b/core/builtins/src/kotlin/reflect/KFunction.kt @@ -19,4 +19,44 @@ package kotlin.reflect /** * Represents a function with introspection capabilities. */ -public interface KFunction : KCallable, Function +public interface KFunction : KCallable, Function { + /** + * `true` if this function is `inline`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html) + * for more information. + */ + public val isInline: Boolean + + /** + * `true` if this function is `external`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/java-interop.html#using-jni-with-kotlin) + * for more information. + */ + public val isExternal: Boolean + + /** + * `true` if this function is `operator`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/operator-overloading.html) + * for more information. + */ + public val isOperator: Boolean + + /** + * `true` if this function is `infix`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/functions.html#infix-notation) + * for more information. + */ + public val isInfix: Boolean + + /** + * `true` if this function is `tailrec`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/functions.html#tail-recursive-functions) + * for more information. + */ + public val isTailrec: Boolean + + /** + * `true` if this is a suspending function. + */ + public val isSuspend: Boolean +} diff --git a/core/builtins/src/kotlin/reflect/KParameter.kt b/core/builtins/src/kotlin/reflect/KParameter.kt index 7c05dfa0ce3..b44bf8721b7 100644 --- a/core/builtins/src/kotlin/reflect/KParameter.kt +++ b/core/builtins/src/kotlin/reflect/KParameter.kt @@ -69,4 +69,30 @@ public interface KParameter : KAnnotatedElement { * 2. The parameter is declared in a member function and one of the corresponding parameters in the super functions is optional. */ public val isOptional: Boolean + + /** + * `true` if this parameter is `vararg`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/functions.html#variable-number-of-arguments-varargs) + * for more information. + */ + public val isVararg: Boolean + + /** + * `true` if this parameter is `noinline`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html#noinline) + * for more information. + */ + public val isNoinline: Boolean + + /** + * `true` if this parameter is `crossinline`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html#non-local-returns) + * for more information. + */ + public val isCrossinline: Boolean + + /** + * `true` if this parameter is `coroutine`. + */ + public val isCoroutine: Boolean } diff --git a/core/builtins/src/kotlin/reflect/KProperty.kt b/core/builtins/src/kotlin/reflect/KProperty.kt index a3c39e6a8bd..d53d10d8433 100644 --- a/core/builtins/src/kotlin/reflect/KProperty.kt +++ b/core/builtins/src/kotlin/reflect/KProperty.kt @@ -25,6 +25,20 @@ package kotlin.reflect * @param R the type of the property. */ public interface KProperty : KCallable { + /** + * `true` if this property is `lateinit`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties) + * for more information. + */ + public val isLateinit: Boolean + + /** + * `true` if this property is `const`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/properties.html#compile-time-constants) + * for more information. + */ + public val isConst: Boolean + /** The getter of this property, used to obtain the value of the property. */ public val getter: Getter diff --git a/core/builtins/src/kotlin/reflect/KTypeParameter.kt b/core/builtins/src/kotlin/reflect/KTypeParameter.kt index 971192ec94f..f6e610fadb4 100644 --- a/core/builtins/src/kotlin/reflect/KTypeParameter.kt +++ b/core/builtins/src/kotlin/reflect/KTypeParameter.kt @@ -40,4 +40,11 @@ public interface KTypeParameter : KClassifier { * for more information. */ public val variance: KVariance + + /** + * `true` if this type parameter is `reified`. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters) + * for more information. + */ + public val isReified: Boolean } diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt index 730da030488..d06d940943f 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt @@ -17,6 +17,7 @@ package kotlin.reflect.jvm.internal import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.annotations.Annotated import java.lang.reflect.Type import java.util.* @@ -62,6 +63,15 @@ internal interface KCallableImpl : KCallable, KAnnotatedElementImpl { override val typeParameters: List get() = descriptor.typeParameters.map(::KTypeParameterImpl) + override val isFinal: Boolean + get() = descriptor.modality == Modality.FINAL + + override val isOpen: Boolean + get() = descriptor.modality == Modality.OPEN + + override val isAbstract: Boolean + get() = descriptor.modality == Modality.ABSTRACT + @Suppress("UNCHECKED_CAST") override fun call(vararg args: Any?): R = reflectionCall { return caller.call(args) as R diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt index 5c3f5d8983c..7e3ca8646b4 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KClassImpl.kt @@ -170,6 +170,27 @@ internal class KClassImpl(override val jClass: Class) : } } + override val isFinal: Boolean + get() = descriptor.modality == Modality.FINAL + + override val isOpen: Boolean + get() = descriptor.modality == Modality.OPEN + + override val isAbstract: Boolean + get() = descriptor.modality == Modality.ABSTRACT + + override val isSealed: Boolean + get() = descriptor.modality == Modality.SEALED + + override val isData: Boolean + get() = descriptor.isData + + override val isInner: Boolean + get() = descriptor.isInner + + override val isCompanion: Boolean + get() = descriptor.isCompanionObject + override fun equals(other: Any?): Boolean = other is KClassImpl<*> && jClass == other.jClass diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt index ba4a4557cb7..3d431ef15d9 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt @@ -109,6 +109,24 @@ internal open class KFunctionImpl protected constructor( (if (descriptor.extensionReceiverParameter != null) 1 else 0) } + override val isInline: Boolean + get() = descriptor.isInline + + override val isExternal: Boolean + get() = descriptor.isExternal + + override val isOperator: Boolean + get() = descriptor.isOperator + + override val isInfix: Boolean + get() = descriptor.isInfix + + override val isTailrec: Boolean + get() = descriptor.isTailrec + + override val isSuspend: Boolean + get() = descriptor.isSuspend + override fun equals(other: Any?): Boolean { val that = other.asKFunctionImpl() ?: return false return container == that.container && name == that.name && signature == that.signature diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt index cae8344ef27..73b411b2a96 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt @@ -46,6 +46,18 @@ internal class KParameterImpl( override val isOptional: Boolean get() = (descriptor as? ValueParameterDescriptor)?.hasDefaultValue() ?: false + override val isVararg: Boolean + get() = descriptor.let { it is ValueParameterDescriptor && it.varargElementType != null } + + override val isNoinline: Boolean + get() = descriptor.let { it is ValueParameterDescriptor && it.isNoinline } + + override val isCrossinline: Boolean + get() = descriptor.let { it is ValueParameterDescriptor && it.isCrossinline } + + override val isCoroutine: Boolean + get() = descriptor.let { it is ValueParameterDescriptor && it.isCoroutine } + override fun equals(other: Any?) = other is KParameterImpl && callable == other.callable && descriptor == other.descriptor diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt index f15b53a6194..143a405059e 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt @@ -42,10 +42,40 @@ internal interface KPropertyImpl : KProperty, KCallableImpl { override val defaultCaller: FunctionCaller<*>? get() = getter.defaultCaller + override val isLateinit: Boolean + get() = descriptor.isLateInit + + override val isConst: Boolean + get() = descriptor.isConst + abstract class Accessor : KProperty.Accessor { abstract override val property: KPropertyImpl internal abstract val descriptor: PropertyAccessorDescriptor + + @Suppress("unused") // Used as an implementation of KFunction#isInline in subclasses + val isInline: Boolean + get() = descriptor.isInline + + @Suppress("unused") + val isExternal: Boolean + get() = descriptor.isExternal + + @Suppress("unused") + val isOperator: Boolean + get() = descriptor.isOperator + + @Suppress("unused") + val isInfix: Boolean + get() = descriptor.isInfix + + @Suppress("unused") + val isTailrec: Boolean + get() = descriptor.isTailrec + + @Suppress("unused") + val isSuspend: Boolean + get() = descriptor.isSuspend } abstract class Getter : Accessor(), KProperty.Getter, KCallableImpl { diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeParameterImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeParameterImpl.kt index 6e38d16f86d..691f6563853 100644 --- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeParameterImpl.kt +++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KTypeParameterImpl.kt @@ -40,6 +40,9 @@ internal class KTypeParameterImpl(override val descriptor: TypeParameterDescript Variance.OUT_VARIANCE -> KVariance.OUT } + override val isReified: Boolean + get() = descriptor.isReified + override fun equals(other: Any?) = other is KTypeParameterImpl && descriptor == other.descriptor diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java index d13dd72c6e0..d4914f31145 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/CallableReference.java @@ -99,6 +99,21 @@ public abstract class CallableReference implements KCallable { return getReflected().callBy(args); } + @Override + public boolean isFinal() { + return getReflected().isFinal(); + } + + @Override + public boolean isOpen() { + return getReflected().isOpen(); + } + + @Override + public boolean isAbstract() { + return getReflected().isAbstract(); + } + public KCallable compute() { if (reflected == null) { reflected = computeReflected(); diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/ClassReference.kt b/core/runtime.jvm/src/kotlin/jvm/internal/ClassReference.kt index 79296e3ed38..fd4e3de987a 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/ClassReference.kt +++ b/core/runtime.jvm/src/kotlin/jvm/internal/ClassReference.kt @@ -48,6 +48,27 @@ class ClassReference(override val jClass: Class<*>) : KClass, ClassBasedDec override val supertypes: List get() = error() + override val isFinal: Boolean + get() = error() + + override val isOpen: Boolean + get() = error() + + override val isAbstract: Boolean + get() = error() + + override val isSealed: Boolean + get() = error() + + override val isData: Boolean + get() = error() + + override val isInner: Boolean + get() = error() + + override val isCompanion: Boolean + get() = error() + private fun error(): Nothing = throw KotlinReflectionNotSupportedError() override fun equals(other: Any?) = diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java index 66e9db329f4..19c0dab1471 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/FunctionReference.java @@ -84,6 +84,51 @@ public class FunctionReference extends FunctionImpl implements KFunction { return getReflected().callBy(args); } + @Override + public boolean isFinal() { + return getReflected().isFinal(); + } + + @Override + public boolean isOpen() { + return getReflected().isOpen(); + } + + @Override + public boolean isAbstract() { + return getReflected().isAbstract(); + } + + @Override + public boolean isInline() { + return getReflected().isInline(); + } + + @Override + public boolean isExternal() { + return getReflected().isExternal(); + } + + @Override + public boolean isOperator() { + return getReflected().isOperator(); + } + + @Override + public boolean isInfix() { + return getReflected().isInfix(); + } + + @Override + public boolean isTailrec() { + return getReflected().isTailrec(); + } + + @Override + public boolean isSuspend() { + return getReflected().isSuspend(); + } + @Override public boolean equals(Object obj) { if (obj == this) return true; diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java index 0b597180d29..09454de0e69 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/PropertyReference.java @@ -19,6 +19,21 @@ package kotlin.jvm.internal; import kotlin.reflect.KProperty; public abstract class PropertyReference extends CallableReference implements KProperty { + @Override + protected KProperty getReflected() { + return (KProperty) super.getReflected(); + } + + @Override + public boolean isLateinit() { + return getReflected().isLateinit(); + } + + @Override + public boolean isConst() { + return getReflected().isConst(); + } + @Override public boolean equals(Object obj) { if (obj == this) return true;