1 package org.jetbrains.dokka 2 3 import kotlin.reflect.* 4 import kotlin.reflect.full.memberFunctions 5 import kotlin.reflect.full.memberProperties 6 import kotlin.reflect.jvm.isAccessible 7 8 object ReflectDsl { 9 10 class CallOrPropAccess(private val receiver: Any?, 11 private val clz: KClass<*>, 12 private val selector: String) { 13 14 @Suppress("UNCHECKED_CAST") invokenull15 operator fun <T : Any?> invoke(vararg a: Any?): T { 16 return func!!.call(receiver, *a) as T 17 } 18 getnull19 operator fun get(s: String): CallOrPropAccess { 20 return v<Any?>()!![s] 21 } 22 <lambda>null23 val func: KFunction<*>? by lazy { clz.memberFunctions.find { it.name == selector } } <lambda>null24 val prop: KProperty<*>? by lazy { clz.memberProperties.find { it.name == selector } } 25 takeIfIsFuncnull26 fun takeIfIsFunc(): CallOrPropAccess? = if (func != null) this else null 27 28 fun takeIfIsProp(): CallOrPropAccess? = if (prop != null) this else null 29 30 @Suppress("UNCHECKED_CAST") 31 fun <T : Any?> v(): T { 32 val prop = prop!! 33 return try { 34 prop.getter.apply { isAccessible = true }.call(receiver) as T 35 } catch (e: KotlinNullPointerException) { 36 // Hack around kotlin-reflect bug KT-18480 37 val jclass = clz.java 38 val customGetterName = prop.getter.name 39 val getterName = if (customGetterName.startsWith("<")) "get" + prop.name.capitalize() else customGetterName 40 val getter = jclass.getDeclaredMethod(getterName) 41 getter.isAccessible = true 42 43 getter.invoke(receiver) as T 44 45 } 46 } 47 48 @Suppress("UNCHECKED_CAST") vnull49 fun v(x: Any?) { 50 (prop as KMutableProperty).setter.apply { isAccessible = true }.call(receiver, x) 51 } 52 53 54 } 55 getnull56 operator fun Any.get(s: String): CallOrPropAccess { 57 val clz = this.javaClass.kotlin 58 return CallOrPropAccess(this, clz, s) 59 } 60 getnull61 operator fun Any.get(s: String, clz: Class<*>): CallOrPropAccess { 62 val kclz = clz.kotlin 63 return CallOrPropAccess(this, kclz, s) 64 } 65 getnull66 operator fun Any.get(s: String, clz: KClass<*>): CallOrPropAccess { 67 return CallOrPropAccess(this, clz, s) 68 } 69 isInstancenull70 inline infix fun Any.isInstance(clz: Class<*>?): Boolean = clz != null && clz.isAssignableFrom(this.javaClass) 71 inline infix fun Any.isNotInstance(clz: Class<*>?): Boolean = !(this isInstance clz) 72 }