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

callable-system.mddocs/

Callable System

Function and property reflection with dynamic invocation capabilities, parameter inspection, suspend function support, and extension handling for comprehensive callable manipulation.

Capabilities

Property Reflection

Access and manipulate properties of different receiver types with full type safety.

/**
 * Represents a property without any kind of receiver
 */
interface KProperty0<out V> : KProperty<V>, () -> V {
  /** Returns the current value of the property */
  fun get(): V
}

/**
 * Represents a var-property without any kind of receiver
 */
interface KMutableProperty0<V> : KProperty0<V>, KMutableProperty<V> {
  /** Modifies the value of the property */
  fun set(value: V)
}

/**
 * Represents a property with one receiver
 */
interface KProperty1<T, out V> : KProperty<V>, (T) -> V {
  /** Returns the current value of the property */
  fun get(receiver: T): V
}

/**
 * Represents a var-property with one receiver
 */
interface KMutableProperty1<T, V> : KProperty1<T, V>, KMutableProperty<V> {
  /** Modifies the value of the property */
  fun set(receiver: T, value: V)
}

Usage Examples:

class Person(var name: String, val age: Int)

val person = Person("Alice", 30)

// Access member properties
val nameProperty = Person::name
val ageProperty = Person::age

// Get property values
println(nameProperty.get(person))  // "Alice"
println(ageProperty.get(person))   // 30

// Set mutable property value
if (nameProperty is KMutableProperty1<Person, String>) {
    nameProperty.set(person, "Bob")
    println(person.name)  // "Bob"
}

// Top-level property access
var globalCounter = 0
val counterProperty = ::globalCounter

// Access top-level property
println(counterProperty.get())  // 0
if (counterProperty is KMutableProperty0<Int>) {
    counterProperty.set(42)
    println(globalCounter)  // 42
}

Function Invocation

Dynamic function calling with parameter mapping and suspend function support.

/**
 * Calls this callable with the specified arguments
 */
fun <R> KCallable<R>.call(vararg args: Any?): R

/**
 * Calls this callable with arguments provided in a map
 */
fun <R> KCallable<R>.callBy(args: Map<KParameter, Any?>): R

/**
 * Calls a callable in the current suspend context
 */
suspend fun <R> KCallable<R>.callSuspend(vararg args: Any?): R

/**
 * Calls a callable in the current suspend context with named arguments
 */
suspend fun <R> KCallable<R>.callSuspendBy(args: Map<KParameter, Any?>): R

Usage Examples:

class Calculator {
    fun add(a: Int, b: Int): Int = a + b
    suspend fun asyncAdd(a: Int, b: Int): Int {
        delay(100)
        return a + b
    }
}

val calc = Calculator()
val addFunction = Calculator::add
val asyncAddFunction = Calculator::asyncAdd

// Call function with positional arguments
val result1 = addFunction.call(calc, 5, 3)  // 8

// Call function with named arguments
val params = addFunction.parameters
val argMap = mapOf(
    params[0] to calc,  // receiver
    params[1] to 10,    // first parameter
    params[2] to 20     // second parameter
)
val result2 = addFunction.callBy(argMap)  // 30

// Call suspend function
runBlocking {
    val asyncResult = asyncAddFunction.callSuspend(calc, 7, 13)  // 20
}

Parameter Inspection

Access detailed information about function and property parameters.

/**
 * Represents a parameter of a function or property
 */
interface KParameter {
  /** Name of the parameter, or null if not available */
  val name: String?
  /** Type of the parameter */
  val type: KType
  /** Kind of the parameter */
  val kind: Kind
  /** Whether the parameter is optional (has default value) */
  val isOptional: Boolean
  /** Whether the parameter is vararg */
  val isVararg: Boolean
  
  enum class Kind {
    INSTANCE,           // 'this' instance
    EXTENSION_RECEIVER, // extension receiver
    VALUE,             // regular parameter
    CONTEXT            // context parameter
  }
}

/** Returns a parameter representing the 'this' instance */
val KCallable<*>.instanceParameter: KParameter?

/** Returns a parameter representing the extension receiver */
val KCallable<*>.extensionReceiverParameter: KParameter?

/** Returns parameters excluding 'this' and extension receiver */
val KCallable<*>.valueParameters: List<KParameter>

/** Returns context parameters of this callable */
@ExperimentalContextParameters
val KCallable<*>.contextParameters: List<KParameter>

Usage Examples:

class Example {
    fun method(required: String, optional: Int = 42, vararg extras: String): String {
        return "$required-$optional-${extras.joinToString()}"
    }
}

fun String.extensionFunction(param: Int): String = "$this:$param"

// Inspect regular method parameters
val method = Example::method
val parameters = method.parameters

println("Total parameters: ${parameters.size}")  // 4 (including receiver)

val instanceParam = method.instanceParameter
println("Instance parameter: ${instanceParam?.kind}")  // INSTANCE

val valueParams = method.valueParameters
valueParams.forEach { param ->
    println("${param.name}: ${param.type}, optional: ${param.isOptional}, vararg: ${param.isVararg}")
}
// required: kotlin.String, optional: false, vararg: false
// optional: kotlin.Int, optional: true, vararg: false
// extras: kotlin.Array<out kotlin.String>, optional: false, vararg: true

// Inspect extension function parameters
val extensionFunc = String::extensionFunction
val extReceiver = extensionFunc.extensionReceiverParameter
println("Extension receiver: ${extReceiver?.type}")  // kotlin.String

Parameter Lookup

Find parameters by name and build argument mappings dynamically.

/**
 * Returns the parameter with the given name, or null if not found
 */
fun KCallable<*>.findParameterByName(name: String): KParameter?

Usage Examples:

fun exampleFunction(first: String, second: Int, third: Boolean = true): String {
    return "$first-$second-$third"
}

val function = ::exampleFunction

// Find parameters by name
val firstParam = function.findParameterByName("first")
val secondParam = function.findParameterByName("second")
val thirdParam = function.findParameterByName("third")

// Build argument map dynamically
val args = buildMap<KParameter, Any?> {
    firstParam?.let { put(it, "hello") }
    secondParam?.let { put(it, 42) }
    // third parameter omitted - will use default value
}

val result = function.callBy(args)  // "hello-42-true"

Property Delegation

Access property delegates for delegated properties inspection.

/**
 * Returns the instance of a delegated extension property, or null if not delegated
 */
fun KProperty1<*, *>.getExtensionDelegate(): Any?

/**
 * Returns the instance of a delegated member extension property, or null if not delegated
 */
fun <D> KProperty2<D, *, *>.getExtensionDelegate(receiver: D): Any?

/**
 * Returns the delegate of this property, or null if it is not delegated
 */
fun KProperty0<*>.getDelegate(): Any?
fun <T> KProperty1<T, *>.getDelegate(receiver: T): Any?

Usage Examples:

class MyDelegate {
    operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
        return "delegated value"
    }
    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
        println("Setting $value")
    }
}

class Example {
    var delegatedProperty: String by MyDelegate()
}

val example = Example()
val property = Example::delegatedProperty

// Access the delegate
val delegate = property.getDelegate(example)
println(delegate::class.simpleName)  // "MyDelegate"

// Check if property is delegated
val hasDelegate = property.getDelegate(example) != null
println("Is delegated: $hasDelegate")  // true

Experimental Features

Context parameters are an experimental feature that allows functions to have implicit context receivers.

/**
 * Marks an API related to Kotlin's context parameters experimental feature
 */
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
@Retention(AnnotationRetention.BINARY)
@MustBeDocumented
annotation class ExperimentalContextParameters

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