@@ -2,124 +2,203 @@ package com.mapk.fastkfunction
22
33import com.mapk.fastkfunction.argumentbucket.ArgumentBucket
44import com.mapk.fastkfunction.argumentbucket.BucketGenerator
5- import java.lang.Exception
6- import java.lang.UnsupportedOperationException
75import java.lang.reflect.Method
86import java.lang.reflect.Modifier
7+ import java.lang.reflect.Constructor as JavaConstructor
98import kotlin.reflect.KFunction
109import kotlin.reflect.KParameter
1110import kotlin.reflect.jvm.isAccessible
1211import kotlin.reflect.jvm.javaConstructor
1312import kotlin.reflect.jvm.javaMethod
1413
15- class FastKFunction <T >( private val function : KFunction < T >, instance : Any? = null ) {
16- val valueParameters: List <KParameter > // 公開するのはバインドに使うパラメータのみ
17- private val fullInitializedFunction : ( Array < out Any ?>) -> T
18- private val bucketGenerator : BucketGenerator
14+ sealed class FastKFunction <T > {
15+ abstract val valueParameters: List <KParameter >
16+ internal abstract val bucketGenerator : BucketGenerator
17+ fun generateBucket (): ArgumentBucket = bucketGenerator.generateBucket()
1918
20- companion object {
21- private fun List<KParameter>.checkParameters (instance : Any? ) = apply {
22- if (isEmpty() || (instance != null && size == 1 ))
23- throw IllegalArgumentException (" This function is not require arguments." )
19+ abstract fun callBy (bucket : ArgumentBucket ): T
20+ abstract fun callByCollection (args : Collection <Any ?>): T
21+ abstract fun call (vararg args : Any? ): T
2422
25- if (3 <= size && get(0 ).kind != KParameter .Kind .VALUE && get(1 ).kind != KParameter .Kind .VALUE )
26- throw IllegalArgumentException (" This function is require multiple instances." )
23+ internal class Constructor <T >(
24+ private val function : KFunction <T >,
25+ private val constructor : JavaConstructor <T >,
26+ override val valueParameters : List <KParameter >
27+ ) : FastKFunction<T>() {
28+ override val bucketGenerator = BucketGenerator (valueParameters, null )
29+
30+ override fun callBy (bucket : ArgumentBucket ): T = if (bucket.isFullInitialized()) {
31+ constructor .newInstance(* bucket.getValueArray())
32+ } else {
33+ function.callBy(bucket)
34+ }
35+
36+ override fun callByCollection (args : Collection <Any ?>): T = constructor .newInstance(* args.toTypedArray())
37+
38+ override fun call (vararg args : Any? ): T = constructor .newInstance(* args)
39+ }
40+
41+ internal class Function <T >(
42+ private val function : KFunction <T >,
43+ override val valueParameters : List <KParameter >
44+ ) : FastKFunction<T>() {
45+ override val bucketGenerator = BucketGenerator (valueParameters, null )
46+
47+ override fun callBy (bucket : ArgumentBucket ): T = if (bucket.isFullInitialized()) {
48+ function.call(* bucket.getValueArray())
49+ } else {
50+ function.callBy(bucket)
2751 }
2852
29- private fun <T > getFunctionCall (function : KFunction <T >): (Array <out Any ?>) -> T = { function.call(* it) }
53+ override fun callByCollection (args : Collection <Any ?>): T = function.call(* args.toTypedArray())
54+
55+ override fun call (vararg args : Any? ): T = function.call(* args)
56+ }
57+
58+ internal class TopLevelFunction <T >(
59+ private val function : KFunction <T >,
60+ private val method : Method ,
61+ override val valueParameters : List <KParameter >
62+ ) : FastKFunction<T>() {
63+ override val bucketGenerator = BucketGenerator (valueParameters, null )
64+
65+ @Suppress(" UNCHECKED_CAST" )
66+ override fun callBy (bucket : ArgumentBucket ): T = if (bucket.isFullInitialized()) {
67+ method.invoke(null , * bucket.getValueArray()) as T
68+ } else {
69+ function.callBy(bucket)
70+ }
3071
31- // methodはTを返せないため強制キャスト
3272 @Suppress(" UNCHECKED_CAST" )
33- private fun <T > getStaticMethodCall (method : Method , instance : Any ): (Array <out Any ?>) -> T =
34- { method.invoke(null , instance, * it) as T }
73+ override fun callByCollection (args : Collection <Any ?>): T = method.invoke(null , * args.toTypedArray()) as T
3574
3675 @Suppress(" UNCHECKED_CAST" )
37- private fun <T > getInstanceMethodCall (method : Method , instance : Any ): (Array <out Any ?>) -> T =
38- { method.invoke(instance, * it) as T }
76+ override fun call (vararg args : Any? ): T = method.invoke(null , * args) as T
3977 }
4078
41- init {
42- // 引数を要求しないか、複数のインスタンスを求める場合エラーとする
43- val parameters: List <KParameter > = function.parameters.checkParameters(instance)
79+ internal class TopLevelExtensionFunction <T >(
80+ private val function : KFunction <T >,
81+ private val method : Method ,
82+ private val extensionReceiver : Any? ,
83+ override val bucketGenerator : BucketGenerator ,
84+ override val valueParameters : List <KParameter >
85+ ) : FastKFunction<T>() {
86+ @Suppress(" UNCHECKED_CAST" )
87+ override fun callBy (bucket : ArgumentBucket ): T = if (bucket.isFullInitialized()) {
88+ method.invoke(null , extensionReceiver, * bucket.getValueArray()) as T
89+ } else {
90+ function.callBy(bucket)
91+ }
4492
45- // この関数には確実にアクセスするためアクセシビリティ書き換え
46- function.isAccessible = true
93+ @Suppress(" UNCHECKED_CAST" )
94+ override fun callByCollection (args : Collection <Any ?>): T =
95+ method.invoke(null , extensionReceiver, * args.toTypedArray()) as T
4796
48- val constructor = function.javaConstructor
97+ @Suppress(" UNCHECKED_CAST" )
98+ override fun call (vararg args : Any? ): T = method.invoke(null , extensionReceiver, * args) as T
99+ }
49100
50- if (constructor != null ) {
51- valueParameters = parameters
52- bucketGenerator = BucketGenerator (parameters, null )
53- fullInitializedFunction = { constructor .newInstance(* it) }
101+ internal class InstanceFunction <T >(
102+ private val function : KFunction <T >,
103+ private val method : Method ,
104+ private val instance : Any ,
105+ override val bucketGenerator : BucketGenerator ,
106+ override val valueParameters : List <KParameter >
107+ ) : FastKFunction<T>() {
108+ @Suppress(" UNCHECKED_CAST" )
109+ override fun callBy (bucket : ArgumentBucket ): T = if (bucket.isFullInitialized()) {
110+ method.invoke(instance, * bucket.getValueArray()) as T
54111 } else {
55- val method = function.javaMethod!!
56-
57- when (parameters[0 ].kind) {
58- KParameter .Kind .EXTENSION_RECEIVER -> {
59- // 対象が拡張関数ならinstanceはreceiver、指定が無ければエラー
60- instance ? : throw IllegalArgumentException (
61- " Function requires EXTENSION_RECEIVER instance, but is not present."
62- )
63-
64- valueParameters = parameters.subList(1 , parameters.size)
65- bucketGenerator = BucketGenerator (parameters, instance)
66- fullInitializedFunction = getStaticMethodCall(method, instance)
67- }
68- KParameter .Kind .INSTANCE -> {
69- valueParameters = parameters.subList(1 , parameters.size)
70-
71- // 対象がインスタンスを要求する関数ならinstanceはobject、与えられたインスタンスがnullでもobjectからの取得を試みる
72- val nonNullInstance = instance ? : try {
73- method.declaringObject!!
74- } catch (e: Exception ) {
75- throw IllegalArgumentException (" Function requires INSTANCE parameter, but is not present." , e)
76- }
77-
78- bucketGenerator = BucketGenerator (parameters, nonNullInstance)
79- fullInitializedFunction = getInstanceMethodCall(method, nonNullInstance)
80- }
81- KParameter .Kind .VALUE -> {
82- valueParameters = parameters
83- bucketGenerator = BucketGenerator (parameters, null )
84-
85- fullInitializedFunction = if (instance != null ) {
86- // staticメソッドならば渡されたのが拡張関数でinstanceはレシーバと見做す
87- if (Modifier .isStatic(method.modifiers)) {
88- getStaticMethodCall(method, instance)
89- } else {
90- getInstanceMethodCall(method, instance)
91- }
92- } else {
93- // staticメソッドかつ引数の数がKFunctionの引数の数と変わらない場合はトップレベル関数(= 実体はstatic関数)
94- if (Modifier .isStatic(method.modifiers) && parameters.size == method.parameters.size) {
95- @Suppress(" UNCHECKED_CAST" )
96- { method.invoke(null , * it) as T }
97- } else {
98- try {
99- // 定義先がobjectであればインスタンスを利用した呼び出しを行い、そうでなければ普通に呼び出す
100- method.declaringObject
101- ?.let { instanceFromClass -> getInstanceMethodCall(method, instanceFromClass) }
102- ? : getFunctionCall(function)
103- } catch (e: UnsupportedOperationException ) {
104- // トップレベル関数でobjectInstanceを取得しようとするとUnsupportedOperationExceptionになるためtryする
105- getFunctionCall(function)
106- }
107- }
108- }
109- }
110- }
112+ function.callBy(bucket)
111113 }
114+
115+ @Suppress(" UNCHECKED_CAST" )
116+ override fun callByCollection (args : Collection <Any ?>): T = method.invoke(instance, * args.toTypedArray()) as T
117+
118+ @Suppress(" UNCHECKED_CAST" )
119+ override fun call (vararg args : Any? ): T = method.invoke(instance, * args) as T
112120 }
113121
114- fun generateBucket (): ArgumentBucket = bucketGenerator.generateBucket()
122+ companion object {
123+ private fun List<KParameter>.checkParameters (instance : Any? ) = also {
124+ if (isEmpty() || (instance != null && size == 1 ))
125+ throw IllegalArgumentException (" This function is not require arguments." )
126+
127+ if (3 <= size && get(0 ).kind != KParameter .Kind .VALUE && get(1 ).kind != KParameter .Kind .VALUE )
128+ throw IllegalArgumentException (" This function is require multiple instances." )
129+ }
115130
116- fun callBy (bucket : ArgumentBucket ): T = if (bucket.isFullInitialized())
117- fullInitializedFunction(bucket.getValueArray())
118- else
119- function.callBy(bucket)
131+ private fun <T > topLevelFunctionOf (
132+ function : KFunction <T >, instance : Any? , parameters : List <KParameter >, method : Method
133+ ): FastKFunction <T > {
134+ return if (parameters[0 ].kind == KParameter .Kind .EXTENSION_RECEIVER ) {
135+ // KParameter.Kind.EXTENSION_RECEIVERの要求が有れば確定で拡張関数
136+ // 対象が拡張関数ならinstanceはreceiver、指定が無ければエラー
137+ instance ? : throw IllegalArgumentException (
138+ " Function requires EXTENSION_RECEIVER instance, but is not present."
139+ )
140+
141+ val generator = BucketGenerator (parameters, instance)
142+ val valueParameters = parameters.subList(1 , parameters.size)
143+
144+ TopLevelExtensionFunction (function, method, instance, generator, valueParameters)
145+ } else if (method.parameters.size != parameters.size) {
146+ // javaMethodのパラメータサイズとKFunctionのパラメータサイズが違う場合も拡張関数
147+ // インスタンスが設定されていれば高速呼び出し、そうじゃなければ通常の関数呼び出し
148+ instance
149+ ?.let {
150+ val generator = BucketGenerator (parameters, instance)
151+ val valueParameters = parameters.subList(1 , parameters.size)
152+
153+ TopLevelExtensionFunction (function, method, instance, generator, valueParameters)
154+ } ? : Function (function, parameters)
155+ } else {
156+ // トップレベル関数
157+ TopLevelFunction (function, method, parameters)
158+ }
159+ }
160+
161+ private fun <T > instanceFunctionOf (
162+ function : KFunction <T >, inputtedInstance : Any? , parameters : List <KParameter >, method : Method
163+ ): FastKFunction <T > {
164+ val instance = inputtedInstance ? : method.declaringObject
165+
166+ return if (parameters[0 ].kind == KParameter .Kind .INSTANCE ) {
167+ instance ? : throw IllegalArgumentException (" Function requires INSTANCE parameter, but is not present." )
168+
169+ val generator = BucketGenerator (parameters, instance)
170+ val valueParameters = parameters.subList(1 , parameters.size)
171+
172+ InstanceFunction (function, method, instance, generator, valueParameters)
173+ } else {
174+ instance
175+ ?.let {
176+ InstanceFunction (function, method, instance, BucketGenerator (parameters, null ), parameters)
177+ } ? : Function (function, parameters)
178+ }
179+ }
120180
121- fun callByCollection (args : Collection <Any ?>): T = fullInitializedFunction(args.toTypedArray())
181+ fun <T > of (function : KFunction <T >, instance : Any? = null): FastKFunction <T > {
182+ // 引数を要求しないか、複数のインスタンスを求める場合エラーとする
183+ val parameters: List <KParameter > = function.parameters.checkParameters(instance)
122184
123- @Suppress(" UNCHECKED_CAST" )
124- fun call (vararg args : Any? ): T = fullInitializedFunction(args)
185+ // この関数には確実にアクセスするためアクセシビリティ書き換え
186+ function.isAccessible = true
187+
188+ val constructor = function.javaConstructor
189+
190+ return if (constructor != null ) {
191+ Constructor (function, constructor , parameters)
192+ } else {
193+ val method = function.javaMethod!!
194+
195+ // Methodがstatic関数ならfunctionはトップレベル関数
196+ if (Modifier .isStatic(method.modifiers)) {
197+ topLevelFunctionOf(function, instance, parameters, method)
198+ } else {
199+ instanceFunctionOf(function, instance, parameters, method)
200+ }
201+ }
202+ }
203+ }
125204}
0 commit comments