1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
package at.hannibal2.skyhanni.utils
import net.minecraftforge.fml.common.Loader
import net.minecraftforge.fml.common.ModContainer
import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.lang.reflect.Modifier
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty0
import kotlin.reflect.KProperty1
import kotlin.reflect.full.isSubtypeOf
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.starProjectedType
import kotlin.reflect.jvm.isAccessible
object ReflectionUtils {
// TODO nea?
// fun <T> dynamic(block: () -> KMutableProperty0<T>?): ReadWriteProperty<Any?, T?> {
// return object : ReadWriteProperty<Any?, T?> {
// override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
// return block()?.get()
// }
//
// override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
// if (value != null)
// block()?.set(value)
// }
// }
// }
fun <T, R> dynamic(root: KProperty0<R?>, child: KMutableProperty1<R, T>) =
object : ReadWriteProperty<Any?, T?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
val rootObj = root.get() ?: return null
return child.get(rootObj)
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
if (value == null) return
val rootObj = root.get() ?: return
child.set(rootObj, value)
}
}
inline fun <reified T : Any> Any.getPropertiesWithType() =
this::class.memberProperties
.filter { it.returnType.isSubtypeOf(T::class.starProjectedType) }
.map {
it.isAccessible = true
(it as KProperty1<Any, T>).get(this)
}
fun Field.makeAccessible() = also { isAccessible = true }
fun <T> Constructor<T>.makeAccessible() = also { isAccessible = true }
fun Field.removeFinal(): Field {
javaClass.getDeclaredField("modifiers").makeAccessible().set(this, modifiers and (Modifier.FINAL.inv()))
return this
}
fun StackTraceElement.getClassInstance(): Class<*> {
return Class.forName(this.className)
}
private val packageLookup by lazy {
Loader.instance().modList
.flatMap { mod -> mod.ownedPackages.map { it to mod } }
.toMap()
}
val Class<*>.shPackageName
get() =
canonicalName?.substringBeforeLast('.')
fun Class<*>.getModContainer(): ModContainer? {
return packageLookup[shPackageName]
}
fun Class<*>.getDeclaredFieldOrNull(name: String): Field? = declaredFields.firstOrNull { it.name == name }
}
|