CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlin--kotlin-reflect

Runtime component for full Kotlin reflection support, enabling inspection and manipulation of Kotlin classes, functions, properties, and types at runtime

Pending
Overview
Eval results
Files

jvm-interoperability.mddocs/

JVM Interoperability

Seamless bridge between Kotlin and Java reflection APIs, providing bidirectional conversion and access to JVM-specific features like accessibility control and type erasure.

Capabilities

Kotlin to Java Mapping

Convert Kotlin reflection objects to their Java reflection equivalents.

/** Returns Java Field instance for property backing field, or null */
val KProperty<*>.javaField: Field?

/** Returns Java Method instance for property getter, or null */
val KProperty<*>.javaGetter: Method?

/** Returns Java Method instance for mutable property setter, or null */
val KMutableProperty<*>.javaSetter: Method?

/** Returns Java Method instance for function, or null if constructor */
val KFunction<*>.javaMethod: Method?

/** Returns Java Constructor instance for function, or null if not constructor */
val <T> KFunction<T>.javaConstructor: Constructor<T>?

/** Returns Java Type instance corresponding to this KType */
val KType.javaType: Type

/** Returns JVM name of the class represented by this KClass */
val KClass<*>.jvmName: String

Usage Examples:

class Person(val name: String) {
    var age: Int = 0
    
    fun greet(): String = "Hello, $name"
    
    constructor(name: String, age: Int) : this(name) {
        this.age = age
    }
}

val personClass = Person::class

// Property to Java Field/Method mapping
val nameProperty = Person::name
val ageProperty = Person::age

val nameField = nameProperty.javaField
val nameGetter = nameProperty.javaGetter
val ageSetter = (ageProperty as? KMutableProperty<*>)?.javaSetter

println("Name field: ${nameField?.name}")      // "name"
println("Name getter: ${nameGetter?.name}")    // "getName" 
println("Age setter: ${ageSetter?.name}")      // "setAge"

// Function to Java Method mapping
val greetFunction = Person::greet
val javaMethod = greetFunction.javaMethod
println("Java method: ${javaMethod?.name}")    // "greet"

// Constructor to Java Constructor mapping
val constructor = personClass.constructors.find { it.parameters.size == 3 }
val javaConstructor = constructor?.javaConstructor
println("Java constructor params: ${javaConstructor?.parameterCount}")  // 2

// Type to Java Type mapping
val stringType = typeOf<String>()
val javaType = stringType.javaType
println("Java type: $javaType")  // class java.lang.String

// Class JVM name
println("JVM name: ${personClass.jvmName}")  // "Person"

Java to Kotlin Mapping

Convert Java reflection objects to their Kotlin reflection equivalents.

/** Returns KProperty instance for Java field, or null if not representable */
val Field.kotlinProperty: KProperty<*>?

/** Returns KFunction instance for Java method, or null if not representable */
val Method.kotlinFunction: KFunction<*>?

/** Returns KFunction instance for Java constructor, or null if not representable */
val <T : Any> Constructor<T>.kotlinFunction: KFunction<T>?

Usage Examples:

class Sample {
    val readOnlyProperty: String = "value"
    var mutableProperty: Int = 42
    
    fun sampleMethod(param: String): Int = param.length
}

val sampleClass = Sample::class.java

// Java Field to Kotlin Property
val javaFields = sampleClass.declaredFields
javaFields.forEach { field ->
    val kotlinProperty = field.kotlinProperty
    println("Field ${field.name} -> Kotlin property: ${kotlinProperty?.name}")
}

// Java Method to Kotlin Function
val javaMethods = sampleClass.declaredMethods
javaMethods.forEach { method ->
    val kotlinFunction = method.kotlinFunction
    if (kotlinFunction != null) {
        println("Method ${method.name} -> Kotlin function: ${kotlinFunction.name}")
    }
}

// Java Constructor to Kotlin Function
val javaConstructors = sampleClass.declaredConstructors
javaConstructors.forEach { constructor ->
    val kotlinFunction = constructor.kotlinFunction
    println("Constructor -> Kotlin function: ${kotlinFunction != null}")
}

JVM Type Operations

Access JVM-specific type information including type erasure.

/** Returns the KClass representing the runtime class this type is erased to on JVM */
val KType.jvmErasure: KClass<*>

Usage Examples:

// Type erasure examples
val stringType = typeOf<String>()
val listType = typeOf<List<String>>()
val mapType = typeOf<Map<String, Int>>()

println("String erasure: ${stringType.jvmErasure}")     // class kotlin.String
println("List erasure: ${listType.jvmErasure}")         // interface kotlin.collections.List
println("Map erasure: ${mapType.jvmErasure}")           // interface kotlin.collections.Map

// Complex generic type erasure
val complexType = typeOf<List<Map<String, List<Int>>>>()
println("Complex type erasure: ${complexType.jvmErasure}")  // interface kotlin.collections.List

// Nullable type erasure
val nullableType = typeOf<String?>()
println("Nullable erasure: ${nullableType.jvmErasure}")     // class kotlin.String

Accessibility Control

Control JVM access checks for reflective operations.

/**
 * Provides a way to suppress JVM access checks for a callable
 * For properties, affects all accessors (getter, setter, backing field)
 */
var KCallable<*>.isAccessible: Boolean

Usage Examples:

class PrivateExample {
    private val privateProperty: String = "secret"
    private fun privateMethod(): String = "private result"
}

val example = PrivateExample()
val clazz = PrivateExample::class

// Access private property
val privateProperty = clazz.memberProperties.find { it.name == "privateProperty" }
if (privateProperty != null) {
    try {
        // This would normally throw IllegalCallableAccessException
        val value = privateProperty.get(example)
    } catch (e: Exception) {
        println("Access denied: ${e.message}")
    }
    
    // Make accessible and try again
    privateProperty.isAccessible = true
    val value = privateProperty.get(example)
    println("Private property value: $value")  // "secret"
}

// Access private function
val privateFunction = clazz.memberFunctions.find { it.name == "privateMethod" }
if (privateFunction != null) {
    privateFunction.isAccessible = true
    val result = privateFunction.call(example)
    println("Private method result: $result")  // "private result"
}

Annotation Access

Access annotations through both Kotlin and Java reflection APIs.

/**
 * Returns an annotation of the given type on this element
 */
inline fun <reified T : Annotation> KAnnotatedElement.findAnnotation(): T?

/**
 * Returns true if this element is annotated with the given type
 */
inline fun <reified T : Annotation> KAnnotatedElement.hasAnnotation(): Boolean

/**
 * Returns all annotations of the given type including repeated annotations
 */
inline fun <reified T : Annotation> KAnnotatedElement.findAnnotations(): List<T>

Usage Examples:

@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
annotation class MyAnnotation(val value: String)

@Target(AnnotationTarget.FUNCTION)
annotation class Deprecated(val message: String)

@MyAnnotation("class-level")
class AnnotatedClass {
    
    @MyAnnotation("property-level")
    val annotatedProperty: String = "value"
    
    @MyAnnotation("function-level")
    @Deprecated("This method is deprecated")
    fun annotatedMethod(): String = "result"
}

val clazz = AnnotatedClass::class

// Check class annotations
val classAnnotation = clazz.findAnnotation<MyAnnotation>()
println("Class annotation: ${classAnnotation?.value}")  // "class-level"

val hasAnnotation = clazz.hasAnnotation<MyAnnotation>()
println("Class has annotation: $hasAnnotation")  // true

// Check property annotations
val property = clazz.memberProperties.find { it.name == "annotatedProperty" }
val propertyAnnotation = property?.findAnnotation<MyAnnotation>()
println("Property annotation: ${propertyAnnotation?.value}")  // "property-level"

// Check function annotations
val function = clazz.memberFunctions.find { it.name == "annotatedMethod" }
val functionAnnotations = function?.findAnnotations<MyAnnotation>()
println("Function annotations: ${functionAnnotations?.size}")  // 1

val deprecatedAnnotation = function?.findAnnotation<Deprecated>()
println("Deprecated message: ${deprecatedAnnotation?.message}")  // "This method is deprecated"

Exception Types

Handle JVM reflection specific exceptions.

/**
 * Thrown when call is invoked on a callable that is not accessible
 */
class IllegalCallableAccessException(cause: IllegalAccessException) : Exception

/**
 * Thrown when getDelegate is invoked on a non-accessible property
 */
class IllegalPropertyDelegateAccessException(cause: IllegalAccessException) : Exception

/**
 * Thrown when introspecting a property that no longer exists
 */
class NoSuchPropertyException(cause: Exception? = null) : Exception

Usage Examples:

class ExampleClass {
    private val privateProperty: String = "private"
}

val clazz = ExampleClass::class
val instance = ExampleClass()

// Attempt to access private property without making it accessible
val privateProperty = clazz.memberProperties.find { it.name == "privateProperty" }

try {
    val value = privateProperty?.get(instance)
} catch (e: IllegalCallableAccessException) {
    println("Access exception: ${e.message}")
    println("Caused by: ${e.cause}")
    
    // Make accessible and retry
    privateProperty?.isAccessible = true
    val value = privateProperty.get(instance)
    println("Successfully accessed: $value")
}

### Lambda Reflection

Experimental API for reflecting on lambda expressions and function instances.

```kotlin { .api }
/**
 * Experimental API to get KFunction instance for compiled lambda or function expression
 * Note: call() and callBy() are not currently supported
 */
@ExperimentalReflectionOnLambdas
fun <R> Function<R>.reflect(): KFunction<R>?

/**
 * Annotation marking experimental lambda reflection API
 */
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalReflectionOnLambdas

Usage Examples:

@OptIn(ExperimentalReflectionOnLambdas::class)
fun demonstrateLambdaReflection() {
    val lambda: (String) -> Int = { it.length }
    
    // Reflect on lambda
    val reflected = lambda.reflect()
    
    if (reflected != null) {
        println("Lambda name: ${reflected.name}")
        println("Parameters: ${reflected.parameters.size}")
        println("Return type: ${reflected.returnType}")
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-reflect

docs

callable-system.md

class-introspection.md

core-reflection.md

index.md

jvm-interoperability.md

type-system.md

tile.json