|
| 1 | +package com.mapk.fastkfunction |
| 2 | + |
| 3 | +import java.lang.reflect.Method |
| 4 | +import java.lang.reflect.Modifier |
| 5 | +import kotlin.reflect.KFunction |
| 6 | +import kotlin.reflect.KParameter |
| 7 | +import kotlin.reflect.jvm.isAccessible |
| 8 | +import kotlin.reflect.jvm.javaConstructor |
| 9 | +import kotlin.reflect.jvm.javaMethod |
| 10 | +import java.lang.reflect.Constructor as JavaConstructor |
| 11 | + |
| 12 | +sealed class SingleArgFastKFunction<T> { |
| 13 | + abstract val valueParameter: KParameter |
| 14 | + abstract fun call(arg: Any?): T |
| 15 | + |
| 16 | + internal class Constructor<T>( |
| 17 | + override val valueParameter: KParameter, |
| 18 | + private val constructor: JavaConstructor<T> |
| 19 | + ) : SingleArgFastKFunction<T>() { |
| 20 | + override fun call(arg: Any?): T = constructor.newInstance(arg) |
| 21 | + } |
| 22 | + |
| 23 | + internal class Function<T>( |
| 24 | + override val valueParameter: KParameter, |
| 25 | + private val function: KFunction<T> |
| 26 | + ) : SingleArgFastKFunction<T>() { |
| 27 | + override fun call(arg: Any?): T = function.call(arg) |
| 28 | + } |
| 29 | + |
| 30 | + internal class TopLevelFunction<T>( |
| 31 | + override val valueParameter: KParameter, |
| 32 | + private val method: Method |
| 33 | + ) : SingleArgFastKFunction<T>() { |
| 34 | + @Suppress("UNCHECKED_CAST") |
| 35 | + override fun call(arg: Any?): T = method.invoke(null, arg) as T |
| 36 | + } |
| 37 | + |
| 38 | + internal class TopLevelExtensionFunction<T>( |
| 39 | + override val valueParameter: KParameter, |
| 40 | + private val method: Method, |
| 41 | + private val extensionReceiver: Any |
| 42 | + ) : SingleArgFastKFunction<T>() { |
| 43 | + @Suppress("UNCHECKED_CAST") |
| 44 | + override fun call(arg: Any?): T = method.invoke(null, extensionReceiver, arg) as T |
| 45 | + } |
| 46 | + |
| 47 | + internal class InstanceFunction<T>( |
| 48 | + override val valueParameter: KParameter, |
| 49 | + private val method: Method, |
| 50 | + private val instance: Any |
| 51 | + ) : SingleArgFastKFunction<T>() { |
| 52 | + @Suppress("UNCHECKED_CAST") |
| 53 | + override fun call(arg: Any?): T = method.invoke(instance, arg) as T |
| 54 | + } |
| 55 | + |
| 56 | + companion object { |
| 57 | + private fun List<KParameter>.checkParameters() = also { |
| 58 | + val requireInstanceParameter = this[0].kind != KParameter.Kind.VALUE |
| 59 | + |
| 60 | + if (isEmpty() || (requireInstanceParameter && size == 1)) |
| 61 | + throw IllegalArgumentException("This function is not require arguments.") |
| 62 | + |
| 63 | + if (!(this.size == 1 || (this.size == 2 && requireInstanceParameter))) |
| 64 | + throw IllegalArgumentException("This function is require multiple arguments.") |
| 65 | + } |
| 66 | + |
| 67 | + private fun <T> topLevelFunctionOf( |
| 68 | + function: KFunction<T>, |
| 69 | + instance: Any?, |
| 70 | + parameters: List<KParameter>, |
| 71 | + method: Method |
| 72 | + ): SingleArgFastKFunction<T> = when { |
| 73 | + // KParameter.Kind.EXTENSION_RECEIVERの要求が有れば確定で拡張関数 |
| 74 | + parameters[0].kind == KParameter.Kind.EXTENSION_RECEIVER -> { |
| 75 | + // 対象が拡張関数ならinstanceはreceiver、指定が無ければエラー |
| 76 | + instance ?: throw IllegalArgumentException( |
| 77 | + "Function requires EXTENSION_RECEIVER instance, but is not present." |
| 78 | + ) |
| 79 | + |
| 80 | + TopLevelExtensionFunction(parameters[1], method, instance) |
| 81 | + } |
| 82 | + // javaMethodのパラメータサイズとKFunctionのパラメータサイズが違う場合も拡張関数 |
| 83 | + // インスタンスが設定されていれば高速呼び出し、そうじゃなければ通常の関数呼び出し |
| 84 | + method.parameters.size != parameters.size -> |
| 85 | + instance |
| 86 | + ?.let { TopLevelExtensionFunction(parameters[0], method, instance) } |
| 87 | + ?: Function(parameters[0], function) |
| 88 | + // トップレベル関数 |
| 89 | + else -> TopLevelFunction(parameters[0], method) |
| 90 | + } |
| 91 | + |
| 92 | + private fun <T> instanceFunctionOf( |
| 93 | + function: KFunction<T>, |
| 94 | + inputtedInstance: Any?, |
| 95 | + parameters: List<KParameter>, |
| 96 | + method: Method |
| 97 | + ): SingleArgFastKFunction<T> { |
| 98 | + val instance = inputtedInstance ?: method.declaringObject |
| 99 | + |
| 100 | + return when { |
| 101 | + parameters[0].kind == KParameter.Kind.INSTANCE -> |
| 102 | + instance |
| 103 | + ?.let { InstanceFunction(parameters[1], method, it) } |
| 104 | + ?: throw IllegalArgumentException("Function requires INSTANCE parameter, but is not present.") |
| 105 | + instance != null -> InstanceFunction(parameters[0], method, instance) |
| 106 | + else -> Function(parameters[0], function) |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + fun <T> of(function: KFunction<T>, instance: Any? = null): SingleArgFastKFunction<T> { |
| 111 | + // 引数を要求しないか、複数のインスタンスを求める場合エラーとする |
| 112 | + val parameters: List<KParameter> = function.parameters.checkParameters() |
| 113 | + |
| 114 | + // この関数には確実にアクセスするためアクセシビリティ書き換え |
| 115 | + function.isAccessible = true |
| 116 | + |
| 117 | + val constructor = function.javaConstructor |
| 118 | + |
| 119 | + return if (constructor != null) { |
| 120 | + Constructor(parameters[0], constructor) |
| 121 | + } else { |
| 122 | + val method = function.javaMethod!! |
| 123 | + |
| 124 | + // Methodがstatic関数ならfunctionはトップレベル関数 |
| 125 | + if (Modifier.isStatic(method.modifiers)) { |
| 126 | + topLevelFunctionOf(function, instance, parameters, method) |
| 127 | + } else { |
| 128 | + instanceFunctionOf(function, instance, parameters, method) |
| 129 | + } |
| 130 | + } |
| 131 | + } |
| 132 | + } |
| 133 | +} |
0 commit comments