Skip to content
This repository was archived by the owner on Jan 20, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Project exclude paths
/.gradle/
/build/
/target/
/target/
/out/
2 changes: 2 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
}

group = "com.mapk"
version = "0.8"
version = "0.9"

java {
sourceCompatibility = JavaVersion.VERSION_1_8
Expand Down
67 changes: 0 additions & 67 deletions src/main/java/com/mapk/core/BucketGenerator.java

This file was deleted.

5 changes: 4 additions & 1 deletion src/main/java/com/mapk/core/EnumMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
* Kotlinの型推論バグでクラスからvalueOfが使えないため、ここだけJavaで書いている(型引数もT extends Enumでは書けなかった)
*/
public class EnumMapper {
/**
* Kotlinの型推論バグでクラスからvalueOfが使えないため、ここだけJavaで書いている(型引数もT extends Enumでは書けなかった)
* 文字列 -> Enumのマッピング
* @param clazz Class of Enum
* @param value StringValue
* @param <T> enumClass
Expand Down
18 changes: 7 additions & 11 deletions src/main/kotlin/com/mapk/core/ArgumentBucket.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ class ArgumentBucket internal constructor(
private val keyArray: Array<KParameter?>,
internal val valueArray: Array<Any?>,
private val isRequireNonNull: List<Boolean>,
private var initializationStatus: Int,
private val initializeMask: List<Int>,
private val completionValue: Int
private val initializationStatusManager: InitializationStatusManager
) : Map<KParameter, Any?> {
// インスタンス有りなら1、そうでなければ0スタート
private var count: Int = initializationStatus
private var count: Int = initializationStatusManager.count

val isInitialized: Boolean get() = initializationStatus == completionValue
val isInitialized: Boolean get() = initializationStatusManager.isFullInitialized

class Entry internal constructor(
override val key: KParameter,
Expand All @@ -32,7 +30,7 @@ class ArgumentBucket internal constructor(

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

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

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

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

val temp = initializationStatus or initializeMask[index]

// 先に入ったものを優先するため、初期化済みなら何もしない
if (initializationStatus == temp) return
if (initializationStatusManager.isInitialized(index)) return

count += 1
initializationStatus = temp
initializationStatusManager.put(index)
keyArray[index] = key
valueArray[index] = value

Expand Down
39 changes: 39 additions & 0 deletions src/main/kotlin/com/mapk/core/BucketGenerator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.mapk.core

import com.mapk.annotations.KParameterRequireNonNull
import kotlin.reflect.KParameter

internal class BucketGenerator(parameters: List<KParameter>, instancePair: Pair<KParameter, Any>?) {
private val initializationStatus: Array<Boolean>
private val isRequireNonNull: List<Boolean>
private val keyArray: Array<KParameter?>
private val valueArray: Array<Any?>

init {
val capacity = parameters.size
isRequireNonNull = parameters.map { param ->
param.annotations.stream().anyMatch { it is KParameterRequireNonNull }
}
initializationStatus = Array(capacity) { false }

keyArray = arrayOfNulls(capacity)
valueArray = arrayOfNulls(capacity)

if (instancePair != null) {
keyArray[0] = instancePair.first
valueArray[0] = instancePair.second
initializationStatus[0] = true
} else {
initializationStatus[0] = false
}
}

fun generate(): ArgumentBucket {
return ArgumentBucket(
keyArray.clone(),
valueArray.clone(),
isRequireNonNull,
InitializationStatusManager(initializationStatus.clone())
)
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/com/mapk/core/InitializationStatusManager.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.mapk.core

internal class InitializationStatusManager(private val initializationStatus: Array<Boolean>) {
private val size = initializationStatus.size
val isFullInitialized: Boolean get() = count == size
var count: Int = if (initializationStatus[0]) 1 else 0

fun isInitialized(index: Int): Boolean = initializationStatus[index]

fun put(index: Int) {
initializationStatus[index] = true
count++
}
}
101 changes: 101 additions & 0 deletions src/test/kotlin/com/mapk/core/Over64ArgTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.mapk.core

import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test

@DisplayName("65以上の引数の関数を呼び出すテスト")
class Over64ArgTest {
data class Dst(
val arg0: Int,
val arg1: Int,
val arg2: Int,
val arg3: Int,
val arg4: Int,
val arg5: Int,
val arg6: Int,
val arg7: Int,
val arg8: Int,
val arg9: Int,
val arg10: Int,
val arg11: Int,
val arg12: Int,
val arg13: Int,
val arg14: Int,
val arg15: Int,
val arg16: Int,
val arg17: Int,
val arg18: Int,
val arg19: Int,
val arg20: Int,
val arg21: Int,
val arg22: Int,
val arg23: Int,
val arg24: Int,
val arg25: Int,
val arg26: Int,
val arg27: Int,
val arg28: Int,
val arg29: Int,
val arg30: Int,
val arg31: Int,
val arg32: Int,
val arg33: Int,
val arg34: Int,
val arg35: Int,
val arg36: Int,
val arg37: Int,
val arg38: Int,
val arg39: Int,
val arg40: Int,
val arg41: Int,
val arg42: Int,
val arg43: Int,
val arg44: Int,
val arg45: Int,
val arg46: Int,
val arg47: Int,
val arg48: Int,
val arg49: Int,
val arg50: Int,
val arg51: Int,
val arg52: Int,
val arg53: Int,
val arg54: Int,
val arg55: Int,
val arg56: Int,
val arg57: Int,
val arg58: Int,
val arg59: Int,
val arg60: Int,
val arg61: Int,
val arg62: Int,
val arg63: Int,
val arg64: Int,
val arg65: Int
) {
companion object {
val expected: Dst = Dst(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 62, 63, 64, 65
)
}
}

@Test
fun test() {
val functionForCall = KFunctionForCall(::Dst)
val dst: Dst = functionForCall.getArgumentBucket().apply {
functionForCall.parameters.forEach {
putIfAbsent(it, it.index)
}
}.let { functionForCall.call(it) }

assertEquals(Dst.expected, dst)
}
}