• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }