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

Commit d10cb4c

Browse files
authored
Merge pull request #11 from k163377/feature
Fixed a bug when calling with a large number of arguments.
2 parents c1c8469 + d25e48c commit d10cb4c

File tree

9 files changed

+170
-81
lines changed

9 files changed

+170
-81
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Project exclude paths
22
/.gradle/
33
/build/
4-
/target/
4+
/target/
5+
/out/

.idea/gradle.xml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66
}
77

88
group = "com.mapk"
9-
version = "0.8"
9+
version = "0.9"
1010

1111
java {
1212
sourceCompatibility = JavaVersion.VERSION_1_8

src/main/java/com/mapk/core/BucketGenerator.java

Lines changed: 0 additions & 67 deletions
This file was deleted.

src/main/java/com/mapk/core/EnumMapper.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
import org.jetbrains.annotations.NotNull;
44
import org.jetbrains.annotations.Nullable;
55

6+
/**
7+
* Kotlinの型推論バグでクラスからvalueOfが使えないため、ここだけJavaで書いている(型引数もT extends Enumでは書けなかった)
8+
*/
69
public class EnumMapper {
710
/**
8-
* Kotlinの型推論バグでクラスからvalueOfが使えないため、ここだけJavaで書いている(型引数もT extends Enumでは書けなかった)
11+
* 文字列 -> Enumのマッピング
912
* @param clazz Class of Enum
1013
* @param value StringValue
1114
* @param <T> enumClass

src/main/kotlin/com/mapk/core/ArgumentBucket.kt

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,12 @@ class ArgumentBucket internal constructor(
77
private val keyArray: Array<KParameter?>,
88
internal val valueArray: Array<Any?>,
99
private val isRequireNonNull: List<Boolean>,
10-
private var initializationStatus: Int,
11-
private val initializeMask: List<Int>,
12-
private val completionValue: Int
10+
private val initializationStatusManager: InitializationStatusManager
1311
) : Map<KParameter, Any?> {
1412
// インスタンス有りなら1、そうでなければ0スタート
15-
private var count: Int = initializationStatus
13+
private var count: Int = initializationStatusManager.count
1614

17-
val isInitialized: Boolean get() = initializationStatus == completionValue
15+
val isInitialized: Boolean get() = initializationStatusManager.isFullInitialized
1816

1917
class Entry internal constructor(
2018
override val key: KParameter,
@@ -32,7 +30,7 @@ class ArgumentBucket internal constructor(
3230

3331
override fun get(key: KParameter): Any? = valueArray[key.index]
3432
fun getByIndex(key: Int): Any? =
35-
if (initializationStatus and initializeMask[key] != 0) valueArray[key]
33+
if (initializationStatusManager.isInitialized(key)) valueArray[key]
3634
else throw IllegalStateException("This argument is not initialized.")
3735

3836
override fun isEmpty(): Boolean = count == 0
@@ -42,21 +40,19 @@ class ArgumentBucket internal constructor(
4240
override val keys: MutableSet<KParameter>
4341
get() = keyArray.filterNotNull().toMutableSet()
4442
override val values: MutableCollection<Any?>
45-
get() = valueArray.filterIndexed { i, _ -> initializationStatus and initializeMask[i] != 0 }.toMutableList()
43+
get() = valueArray.filterIndexed { i, _ -> initializationStatusManager.isInitialized(i) }.toMutableList()
4644

4745
fun putIfAbsent(key: KParameter, value: Any?) {
4846
val index = key.index
4947

5048
// null入力禁止かつnullなら無視する
5149
if (isRequireNonNull[index] && value == null) return
5250

53-
val temp = initializationStatus or initializeMask[index]
54-
5551
// 先に入ったものを優先するため、初期化済みなら何もしない
56-
if (initializationStatus == temp) return
52+
if (initializationStatusManager.isInitialized(index)) return
5753

5854
count += 1
59-
initializationStatus = temp
55+
initializationStatusManager.put(index)
6056
keyArray[index] = key
6157
valueArray[index] = value
6258

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.mapk.core
2+
3+
import com.mapk.annotations.KParameterRequireNonNull
4+
import kotlin.reflect.KParameter
5+
6+
internal class BucketGenerator(parameters: List<KParameter>, instancePair: Pair<KParameter, Any>?) {
7+
private val initializationStatus: Array<Boolean>
8+
private val isRequireNonNull: List<Boolean>
9+
private val keyArray: Array<KParameter?>
10+
private val valueArray: Array<Any?>
11+
12+
init {
13+
val capacity = parameters.size
14+
isRequireNonNull = parameters.map { param ->
15+
param.annotations.stream().anyMatch { it is KParameterRequireNonNull }
16+
}
17+
initializationStatus = Array(capacity) { false }
18+
19+
keyArray = arrayOfNulls(capacity)
20+
valueArray = arrayOfNulls(capacity)
21+
22+
if (instancePair != null) {
23+
keyArray[0] = instancePair.first
24+
valueArray[0] = instancePair.second
25+
initializationStatus[0] = true
26+
} else {
27+
initializationStatus[0] = false
28+
}
29+
}
30+
31+
fun generate(): ArgumentBucket {
32+
return ArgumentBucket(
33+
keyArray.clone(),
34+
valueArray.clone(),
35+
isRequireNonNull,
36+
InitializationStatusManager(initializationStatus.clone())
37+
)
38+
}
39+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.mapk.core
2+
3+
internal class InitializationStatusManager(private val initializationStatus: Array<Boolean>) {
4+
private val size = initializationStatus.size
5+
val isFullInitialized: Boolean get() = count == size
6+
var count: Int = if (initializationStatus[0]) 1 else 0
7+
8+
fun isInitialized(index: Int): Boolean = initializationStatus[index]
9+
10+
fun put(index: Int) {
11+
initializationStatus[index] = true
12+
count++
13+
}
14+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
package com.mapk.core
2+
3+
import org.junit.jupiter.api.Assertions.assertEquals
4+
import org.junit.jupiter.api.DisplayName
5+
import org.junit.jupiter.api.Test
6+
7+
@DisplayName("65以上の引数の関数を呼び出すテスト")
8+
class Over64ArgTest {
9+
data class Dst(
10+
val arg0: Int,
11+
val arg1: Int,
12+
val arg2: Int,
13+
val arg3: Int,
14+
val arg4: Int,
15+
val arg5: Int,
16+
val arg6: Int,
17+
val arg7: Int,
18+
val arg8: Int,
19+
val arg9: Int,
20+
val arg10: Int,
21+
val arg11: Int,
22+
val arg12: Int,
23+
val arg13: Int,
24+
val arg14: Int,
25+
val arg15: Int,
26+
val arg16: Int,
27+
val arg17: Int,
28+
val arg18: Int,
29+
val arg19: Int,
30+
val arg20: Int,
31+
val arg21: Int,
32+
val arg22: Int,
33+
val arg23: Int,
34+
val arg24: Int,
35+
val arg25: Int,
36+
val arg26: Int,
37+
val arg27: Int,
38+
val arg28: Int,
39+
val arg29: Int,
40+
val arg30: Int,
41+
val arg31: Int,
42+
val arg32: Int,
43+
val arg33: Int,
44+
val arg34: Int,
45+
val arg35: Int,
46+
val arg36: Int,
47+
val arg37: Int,
48+
val arg38: Int,
49+
val arg39: Int,
50+
val arg40: Int,
51+
val arg41: Int,
52+
val arg42: Int,
53+
val arg43: Int,
54+
val arg44: Int,
55+
val arg45: Int,
56+
val arg46: Int,
57+
val arg47: Int,
58+
val arg48: Int,
59+
val arg49: Int,
60+
val arg50: Int,
61+
val arg51: Int,
62+
val arg52: Int,
63+
val arg53: Int,
64+
val arg54: Int,
65+
val arg55: Int,
66+
val arg56: Int,
67+
val arg57: Int,
68+
val arg58: Int,
69+
val arg59: Int,
70+
val arg60: Int,
71+
val arg61: Int,
72+
val arg62: Int,
73+
val arg63: Int,
74+
val arg64: Int,
75+
val arg65: Int
76+
) {
77+
companion object {
78+
val expected: Dst = Dst(
79+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
80+
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
81+
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
82+
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
83+
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
84+
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
85+
60, 61, 62, 63, 64, 65
86+
)
87+
}
88+
}
89+
90+
@Test
91+
fun test() {
92+
val functionForCall = KFunctionForCall(::Dst)
93+
val dst: Dst = functionForCall.getArgumentBucket().apply {
94+
functionForCall.parameters.forEach {
95+
putIfAbsent(it, it.index)
96+
}
97+
}.let { functionForCall.call(it) }
98+
99+
assertEquals(Dst.expected, dst)
100+
}
101+
}

0 commit comments

Comments
 (0)