commonMain.co.touchlab.skie.compilerinject.reflection.Reflector.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kotlin-compiler-linker-plugin-kgp_1.9.20 Show documentation
Show all versions of kotlin-compiler-linker-plugin-kgp_1.9.20 Show documentation
Kotlin compiler plugin that improves Swift interface of a Kotlin Multiplatform framework.
package co.touchlab.skie.compilerinject.reflection
import kotlin.properties.PropertyDelegateProvider
import kotlin.properties.ReadOnlyProperty
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
abstract class Reflector {
private val reflectedClass: Class<*>
protected abstract val instance: Any
constructor(reflectedClass: Class<*>) {
this.reflectedClass = reflectedClass
}
constructor(reflectedClass: KClass<*>) : this(reflectedClass.java)
constructor(fqName: String) {
reflectedClass = this::class.java.classLoader.loadClass(fqName)
}
protected inline fun declaredMethod0() =
Provider { DeclaredMethod0(it, R::class.java) }
protected inline fun declaredMethod1() =
Provider {
DeclaredMethod1(it, P1::class.java, R::class.java)
}
protected inline fun declaredMethod2() =
Provider {
DeclaredMethod2(it, P1::class.java, P2::class.java, R::class.java)
}
protected inline fun declaredMethod3() =
Provider {
DeclaredMethod3(it, P1::class.java, P2::class.java, P3::class.java, R::class.java)
}
protected inline fun reflectedDeclaredMethod1() =
Provider {
ReflectedMethod<(P1) -> Any, (P1) -> R>(DeclaredMethod1(it, P1::class.java, Any::class.java)) { invoke ->
{ param ->
invoke(param).reflectedBy()
}
}
}
protected inline fun declaredProperty() =
Provider { DeclaredProperty(it, T::class.java) }
protected inline fun declaredField(nameOverride: String? = null) =
Provider { DeclaredField(nameOverride ?: it, T::class.java) }
protected inline fun extensionFunction0(extensionClassFqName: String) =
Provider { ExtensionFunction0(it, extensionClassFqName, R::class.java) }
protected inline fun extensionFunction1(extensionClassFqName: String) =
Provider { ExtensionFunction1(it, extensionClassFqName, P1::class.java, R::class.java) }
protected inline fun extensionFunction1(extensionClassFqName: String, functionName: String) =
Provider { ExtensionFunction1(functionName, extensionClassFqName, P1::class.java, R::class.java) }
protected inline fun extensionProperty(extensionClassFqName: String) =
Provider { ExtensionProperty(it, extensionClassFqName, T::class.java) }
protected class Provider(private val factory: (String) -> T) : PropertyDelegateProvider {
override fun provideDelegate(thisRef: Reflector, property: KProperty<*>): T = factory(property.name)
}
protected abstract inner class DeclaredMethod(
name: String,
private val returnType: Class,
parameterTypes: Array>,
) : ReadOnlyProperty {
private val method by lazy {
reflectedClass.getDeclaredMethod(name, *parameterTypes).also { it.isAccessible = true }
}
protected fun invoke(arguments: Array): R =
method.invoke(instance, *arguments).let { returnType.cast(it) }
}
protected inner class DeclaredMethod0(
name: String,
returnType: Class,
) : DeclaredMethod<() -> R, R>(name, returnType, emptyArray()) {
override fun getValue(thisRef: Reflector, property: KProperty<*>): () -> R = {
invoke(emptyArray())
}
}
protected inner class DeclaredMethod1(
name: String,
param1: Class,
returnType: Class,
) : DeclaredMethod<(P1) -> R, R>(name, returnType, arrayOf(param1)) {
override fun getValue(thisRef: Reflector, property: KProperty<*>): (P1) -> R = {
invoke(arrayOf(it))
}
}
protected inner class DeclaredMethod2(
name: String,
param1: Class,
param2: Class,
returnType: Class,
) : DeclaredMethod<(P1, P2) -> R, R>(name, returnType, arrayOf(param1, param2)) {
override fun getValue(thisRef: Reflector, property: KProperty<*>): (P1, P2) -> R = { p1, p2 ->
invoke(arrayOf(p1, p2))
}
}
protected inner class DeclaredMethod3(
name: String,
param1: Class,
param2: Class,
param3: Class,
returnType: Class,
) : DeclaredMethod<(P1, P2, P3) -> R, R>(name, returnType, arrayOf(param1, param2, param3)) {
override fun getValue(thisRef: Reflector, property: KProperty<*>): (P1, P2, P3) -> R = { p1, p2, p3 ->
invoke(arrayOf(p1, p2, p3))
}
}
protected inner class ReflectedMethod(
private val method: DeclaredMethod,
private val reflectorFactory: (invoke: WRAPPED) -> T,
) : ReadOnlyProperty {
override fun getValue(thisRef: Reflector, property: KProperty<*>): T {
return method.getValue(thisRef, property).let(reflectorFactory)
}
}
protected inner class DeclaredProperty(name: String, type: Class) : ReadWriteProperty {
private val getter by lazy {
DeclaredMethod0("get" + name.replaceFirstChar { it.uppercase() }, type)
}
private val setter by lazy {
DeclaredMethod1("set" + name.replaceFirstChar { it.uppercase() }, type, Unit::class.java)
}
override fun getValue(thisRef: Reflector, property: KProperty<*>): T =
getter.getValue(thisRef, property).invoke()
override fun setValue(thisRef: Reflector, property: KProperty<*>, value: T) {
setter.getValue(thisRef, property).invoke(value)
}
}
protected inner class DeclaredField(name: String, private val type: Class) : ReadWriteProperty {
private val field by lazy {
reflectedClass.getDeclaredField(name).also { it.isAccessible = true }
}
override fun getValue(thisRef: Reflector, property: KProperty<*>): T =
field.get(instance).let { type.cast(it) }
override fun setValue(thisRef: Reflector, property: KProperty<*>, value: T) {
field.set(instance, value)
}
}
protected abstract inner class ExtensionFunction(
name: String,
extensionClassFqName: String,
private val returnType: Class,
parameterTypes: Array>,
) : ReadOnlyProperty {
private val method by lazy {
val extensionClass = this::class.java.classLoader.loadClass(extensionClassFqName)
extensionClass.getDeclaredMethod(name, reflectedClass, *parameterTypes).also { it.isAccessible = true }
}
protected operator fun invoke(arguments: Array): R =
method.invoke(null, *arguments).let { returnType.cast(it) }
}
protected inner class ExtensionFunction0(
name: String,
extensionClassFqName: String,
returnType: Class,
) : ExtensionFunction<() -> R, R>(name, extensionClassFqName, returnType, emptyArray()) {
override fun getValue(thisRef: Reflector, property: KProperty<*>): () -> R = {
invoke(arrayOf(instance))
}
}
protected inner class ExtensionFunction1(
name: String,
extensionClassFqName: String,
param1: Class,
returnType: Class,
) : ExtensionFunction<(P1) -> R, R>(name, extensionClassFqName, returnType, arrayOf(param1)) {
override fun getValue(thisRef: Reflector, property: KProperty<*>): (P1) -> R = {
invoke(arrayOf(instance, it))
}
}
protected inner class ExtensionProperty(
name: String,
extensionClassFqName: String,
type: Class,
) : ReadWriteProperty {
private val getter by lazy {
ExtensionFunction0("get" + name.replaceFirstChar { it.uppercase() }, extensionClassFqName, type)
}
private val setter by lazy {
ExtensionFunction1("set" + name.replaceFirstChar { it.uppercase() }, extensionClassFqName, type, Unit::class.java)
}
override fun getValue(thisRef: Reflector, property: KProperty<*>): T =
getter.getValue(thisRef, property).invoke()
override fun setValue(thisRef: Reflector, property: KProperty<*>, value: T) {
setter.getValue(thisRef, property).invoke(value)
}
}
}