|
1 | 1 | package com.mapk.core
|
2 | 2 |
|
3 | 3 | import com.mapk.annotations.KConstructor
|
| 4 | +import com.mapk.annotations.KParameterFlatten |
| 5 | +import com.mapk.core.internal.ArgumentBinder |
4 | 6 | import com.mapk.core.internal.BucketGenerator
|
5 | 7 | import com.mapk.core.internal.ParameterNameConverter
|
| 8 | +import com.mapk.core.internal.getAliasOrName |
6 | 9 | import com.mapk.core.internal.isUseDefaultArgument
|
7 | 10 | import kotlin.reflect.KClass
|
8 | 11 | import kotlin.reflect.KFunction
|
9 | 12 | import kotlin.reflect.KParameter
|
10 | 13 | import kotlin.reflect.full.companionObjectInstance
|
| 14 | +import kotlin.reflect.full.findAnnotation |
11 | 15 | import kotlin.reflect.full.functions
|
12 | 16 | import kotlin.reflect.full.primaryConstructor
|
13 | 17 | import kotlin.reflect.jvm.isAccessible
|
@@ -41,16 +45,32 @@ class KFunctionForCall<T> internal constructor(
|
41 | 45 | // この関数には確実にアクセスするためアクセシビリティ書き換え
|
42 | 46 | function.isAccessible = true
|
43 | 47 |
|
44 |
| - val filteredParameters = parameters.filter { it.kind == KParameter.Kind.VALUE && !it.isUseDefaultArgument() } |
| 48 | + val binders: List<ArgumentBinder> = parameters |
| 49 | + .filter { it.kind == KParameter.Kind.VALUE && !it.isUseDefaultArgument() } |
| 50 | + .map { it.toArgumentBinder(parameterNameConverter) } |
| 51 | + |
45 | 52 | bucketGenerator = BucketGenerator(
|
46 | 53 | parameters,
|
47 |
| - filteredParameters, |
48 |
| - instance, |
49 |
| - parameterNameConverter |
| 54 | + binders, |
| 55 | + instance |
50 | 56 | )
|
51 | 57 |
|
52 |
| - requiredParameters = bucketGenerator.valueParameters |
53 |
| - requiredParametersMap = requiredParameters.associateBy { it.name } |
| 58 | + requiredParameters = binders.fold(ArrayList()) { acc, elm -> |
| 59 | + when (elm) { |
| 60 | + is ArgumentBinder.Value<*> -> acc.add(elm) |
| 61 | + is ArgumentBinder.Function -> acc.addAll(elm.requiredParameters) |
| 62 | + } |
| 63 | + acc |
| 64 | + } |
| 65 | + |
| 66 | + requiredParametersMap = HashMap<String, ValueParameter<*>>().apply { |
| 67 | + requiredParameters.forEach { |
| 68 | + if (containsKey(it.name)) |
| 69 | + throw IllegalArgumentException("The argument name ${it.name} is duplicated.") |
| 70 | + |
| 71 | + this[it.name] = it |
| 72 | + } |
| 73 | + } |
54 | 74 | }
|
55 | 75 |
|
56 | 76 | fun getArgumentAdaptor(): ArgumentAdaptor = ArgumentAdaptor(requiredParametersMap)
|
@@ -84,3 +104,26 @@ internal fun <T : Any> KClass<T>.toKConstructor(parameterNameConverter: Paramete
|
84 | 104 | @Suppress("UNCHECKED_CAST")
|
85 | 105 | fun <T : Any> KClass<T>.toKConstructor(parameterNameConverter: (String) -> String): KFunctionForCall<T> =
|
86 | 106 | this.toKConstructor(ParameterNameConverter.Simple(parameterNameConverter))
|
| 107 | + |
| 108 | +private fun KParameter.toArgumentBinder(parameterNameConverter: ParameterNameConverter): ArgumentBinder { |
| 109 | + val name = getAliasOrName()!! |
| 110 | + |
| 111 | + return findAnnotation<KParameterFlatten>()?.let { annotation -> |
| 112 | + // 名前の変換処理 |
| 113 | + val converter: ParameterNameConverter = if (annotation.fieldNameToPrefix) { |
| 114 | + // 結合が必要な場合は結合機能のインスタンスを持ってきて対応する |
| 115 | + parameterNameConverter.nest(name, annotation.nameJoiner.objectInstance!!) |
| 116 | + } else { |
| 117 | + // プレフィックスを要求しない場合は全てsimpleでマップするように修正 |
| 118 | + parameterNameConverter.toSimple() |
| 119 | + } |
| 120 | + |
| 121 | + ArgumentBinder.Function((type.classifier as KClass<*>).toKConstructor(converter), index, annotations) |
| 122 | + } ?: ArgumentBinder.Value( |
| 123 | + index, |
| 124 | + annotations, |
| 125 | + isOptional, |
| 126 | + parameterNameConverter.convert(name), |
| 127 | + type.classifier as KClass<*> |
| 128 | + ) |
| 129 | +} |
0 commit comments