Skip to content
This repository was archived by the owner on Jan 20, 2023. It is now read-only.

Commit 1914dc0

Browse files
committed
単一引数からの高速呼び出し関数を追加
1 parent 7a1ae61 commit 1914dc0

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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(instance: Any?) = also {
58+
if (isEmpty() || (instance != null && size == 1))
59+
throw IllegalArgumentException("This function is not require arguments.")
60+
61+
if (!(this.size == 1 || (this.size == 2 && instance != null)))
62+
throw IllegalArgumentException("This function is require multiple arguments.")
63+
}
64+
65+
private fun <T> topLevelFunctionOf(
66+
function: KFunction<T>,
67+
instance: Any?,
68+
parameters: List<KParameter>,
69+
method: Method
70+
): SingleArgFastKFunction<T> = when {
71+
// KParameter.Kind.EXTENSION_RECEIVERの要求が有れば確定で拡張関数
72+
parameters[0].kind == KParameter.Kind.EXTENSION_RECEIVER -> {
73+
// 対象が拡張関数ならinstanceはreceiver、指定が無ければエラー
74+
instance ?: throw IllegalArgumentException(
75+
"Function requires EXTENSION_RECEIVER instance, but is not present."
76+
)
77+
78+
TopLevelExtensionFunction(parameters[1], method, instance)
79+
}
80+
// javaMethodのパラメータサイズとKFunctionのパラメータサイズが違う場合も拡張関数
81+
// インスタンスが設定されていれば高速呼び出し、そうじゃなければ通常の関数呼び出し
82+
method.parameters.size != parameters.size -> instance
83+
?.let { TopLevelExtensionFunction(parameters[0], method, instance) }
84+
?: Function(parameters[0], function)
85+
// トップレベル関数
86+
else -> TopLevelFunction(parameters[0], method)
87+
}
88+
89+
private fun <T> instanceFunctionOf(
90+
function: KFunction<T>,
91+
inputtedInstance: Any?,
92+
parameters: List<KParameter>,
93+
method: Method
94+
): SingleArgFastKFunction<T> {
95+
val instance = inputtedInstance ?: method.declaringObject
96+
97+
return if (parameters[0].kind == KParameter.Kind.INSTANCE || instance != null) {
98+
instance ?: throw IllegalArgumentException("Function requires INSTANCE parameter, but is not present.")
99+
100+
InstanceFunction(parameters[1], method, instance)
101+
} else {
102+
Function(parameters[0], function)
103+
}
104+
}
105+
106+
fun <T> of(function: KFunction<T>, instance: Any? = null): SingleArgFastKFunction<T> {
107+
// 引数を要求しないか、複数のインスタンスを求める場合エラーとする
108+
val parameters: List<KParameter> = function.parameters.checkParameters(instance)
109+
110+
// この関数には確実にアクセスするためアクセシビリティ書き換え
111+
function.isAccessible = true
112+
113+
val constructor = function.javaConstructor
114+
115+
return if (constructor != null) {
116+
Constructor(parameters[0], constructor)
117+
} else {
118+
val method = function.javaMethod!!
119+
120+
// Methodがstatic関数ならfunctionはトップレベル関数
121+
if (Modifier.isStatic(method.modifiers)) {
122+
topLevelFunctionOf(function, instance, parameters, method)
123+
} else {
124+
instanceFunctionOf(function, instance, parameters, method)
125+
}
126+
}
127+
}
128+
}
129+
}

0 commit comments

Comments
 (0)