package at.hannibal2.skyhanni.utils 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 dynamic(block: () -> KMutableProperty0?): ReadWriteProperty { // return object : ReadWriteProperty { // 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 dynamic(root: KProperty0, child: KMutableProperty1) = object : ReadWriteProperty { 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 Any.getPropertiesWithType() = this::class.memberProperties .filter { it.returnType.isSubtypeOf(T::class.starProjectedType) } .map { it.isAccessible = true (it as KProperty1).get(this) } fun Field.makeAccessible() = also { isAccessible = true } fun Constructor.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) } fun Class<*>.getDeclaredFieldOrNull(name: String): Field? = declaredFields.firstOrNull { it.name == name } }