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
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.11"
version = "0.12"

java {
sourceCompatibility = JavaVersion.VERSION_1_8
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/com/mapk/core/ArgumentAdaptor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ArgumentAdaptor(private val requiredParameters: Map<String, ValueParameter
}

fun putIfAbsent(key: String, value: Any?) {
if (!isInitialized(key) && !(requiredParameters.getValue(key).isNullable && value == null)) {
if (!isInitialized(key) && !(!requiredParameters.getValue(key).isNullable && value == null)) {
argumentMap[key] = value
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/main/kotlin/com/mapk/core/internal/ArgumentBinder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ internal sealed class ArgumentBinder(val annotations: List<Annotation>) {
override val isOptional: Boolean,
override val name: String,
override val requiredClazz: KClass<T>
) : ArgumentBinder(annotations),
ValueParameter<T> {
) : ArgumentBinder(annotations), ValueParameter<T> {
override fun bindArgument(adaptor: ArgumentAdaptor, valueArray: Array<Any?>): Boolean {
return if (adaptor.isInitialized(name)) {
valueArray[index] = adaptor.readout(name)
Expand Down
7 changes: 2 additions & 5 deletions src/main/kotlin/com/mapk/core/internal/ArgumentBucket.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ internal class ArgumentBucket(
override var value: Any?
) : Map.Entry<KParameter, Any?>

private val initializationStatusManager =
InitializationStatusManager(initializationStatus)
private val initializationStatusManager = InitializationStatusManager(initializationStatus)
val isInitialized: Boolean
override val size: Int

Expand All @@ -32,9 +31,7 @@ internal class ArgumentBucket(
size = initializationStatusManager.count
}

override fun containsKey(key: KParameter): Boolean {
return initializationStatusManager.isInitialized(key.index)
}
override fun containsKey(key: KParameter): Boolean = initializationStatusManager.isInitialized(key.index)

override fun containsValue(value: Any?): Boolean = valueArray.any { Objects.equals(value, it) }

Expand Down
10 changes: 5 additions & 5 deletions src/main/kotlin/com/mapk/core/internal/BucketGenerator.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,20 @@ internal class BucketGenerator(
}

fun generate(adaptor: ArgumentAdaptor): ArgumentBucket =
ArgumentBucket(
parameters, originalValueArray.clone(), originalInitializationStatus.clone(), binders, adaptor
)
ArgumentBucket(parameters, originalValueArray.clone(), originalInitializationStatus.clone(), binders, adaptor)
}

private fun KParameter.toArgumentBinder(parameterNameConverter: ParameterNameConverter): ArgumentBinder {
val name = getAliasOrName()!!

return findAnnotation<KParameterFlatten>()?.let { annotation ->
// 名前の変換処理、結合が必要な場合はインスタンスを持ってきて対応する
// 名前の変換処理
val converter: ParameterNameConverter = if (annotation.fieldNameToPrefix) {
// 結合が必要な場合は結合機能のインスタンスを持ってきて対応する
parameterNameConverter.nest(name, annotation.nameJoiner.objectInstance!!)
} else {
parameterNameConverter
// プレフィックスを要求しない場合は全てsimpleでマップするように修正
parameterNameConverter.toSimple()
}

ArgumentBinder.Function((type.classifier as KClass<*>).toKConstructor(converter), index, annotations)
Expand Down
7 changes: 4 additions & 3 deletions src/main/kotlin/com/mapk/core/internal/Functions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.mapk.annotations.KUseDefaultArgument
import java.lang.IllegalArgumentException
import kotlin.reflect.KParameter
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.jvm.jvmName

/**
* パラメータからエイリアスもしくはプロパティ名を取得する関数
Expand All @@ -16,9 +17,9 @@ internal fun KParameter.getAliasOrName(): String? = findAnnotation<KParameterAli
*/
internal fun KParameter.isUseDefaultArgument(): Boolean {
if (annotations.any { it is KUseDefaultArgument }) {
if (!isOptional) {
throw IllegalArgumentException("Find KUseDefaultArgument, but it's not has default argument.")
}
if (!isOptional) throw IllegalArgumentException(
"Find ${KUseDefaultArgument::class.jvmName}, but it's not has default argument."
)
return true
}
return false
Expand Down
13 changes: 5 additions & 8 deletions src/main/kotlin/com/mapk/core/internal/ParameterNameConverter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ internal sealed class ParameterNameConverter {
protected abstract val converter: (String) -> String
abstract fun convert(name: String): String
abstract fun nest(infix: String, nameJoiner: NameJoiner): WithPrefix
abstract fun toSimple(): Simple

class Simple(override val converter: (String) -> String) : ParameterNameConverter() {
override fun convert(name: String) = converter(name)
override fun nest(infix: String, nameJoiner: NameJoiner) =
WithPrefix(infix, nameJoiner, converter)
override fun nest(infix: String, nameJoiner: NameJoiner) = WithPrefix(infix, nameJoiner, converter)
override fun toSimple(): Simple = this
}

class WithPrefix(
Expand All @@ -22,11 +23,7 @@ internal sealed class ParameterNameConverter {

// 結合を伴う変換では、「双方変換 -> 結合」の順で処理を行う
override fun convert(name: String) = converter(name).let { nameJoiner.join(prefix, it) }
override fun nest(infix: String, nameJoiner: NameJoiner) =
WithPrefix(
convert(infix),
nameJoiner,
converter
)
override fun nest(infix: String, nameJoiner: NameJoiner) = WithPrefix(convert(infix), nameJoiner, converter)
override fun toSimple(): Simple = Simple(converter)
}
}
96 changes: 96 additions & 0 deletions src/test/kotlin/com/mapk/core/ArgumentAdaptorTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.mapk.core

import io.mockk.every
import io.mockk.mockk
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows

@DisplayName("ArgumentAdaptorのテスト")
class ArgumentAdaptorTest {
private val keys = listOf("foo", "bar", "baz")
private val adaptor: ArgumentAdaptor = keys.mapIndexed { i, argName ->
mockk<ValueParameter<*>> {
every { name } returns argName
every { isNullable } returns (i % 2 == 0)
}
}.associateBy {
it.name
}.let { ArgumentAdaptor(it) }

@Nested
@DisplayName("値をバインドするテスト")
inner class PutIfAbsentTest {
@Nested
@DisplayName("Null入力")
inner class NullabilityTest {
@Test
@DisplayName("nullableかつnull入力")
fun isNullableAndNull() {
adaptor.putIfAbsent(keys[0], null)
assertTrue(adaptor.isInitialized(keys[0]))
}

@Test
@DisplayName("non-nullかつnull入力")
fun isNonNullAndNull() {
adaptor.putIfAbsent(keys[1], null)
assertFalse(adaptor.isInitialized(keys[0]))
}

@Test
@DisplayName("2重バインドテスト")
fun isDuplicateKey() {
adaptor.putIfAbsent(keys[0], keys[0])
adaptor.putIfAbsent(keys[0], keys[1])
assertEquals(keys[0], adaptor.readout(keys[0]))
}
}
}

@Nested
@DisplayName("完全初期化チェックのテスト")
inner class IsFullInitializedTest {
@Test
@DisplayName("完全初期化していない場合")
fun isNotFullInitialized() {
adaptor.putIfAbsent(keys[0], keys[0])
adaptor.putIfAbsent(keys[1], keys[1])
assertFalse(adaptor.isFullInitialized())
}

@Test
@DisplayName("完全初期化した場合")
fun isFullInitialized() {
keys.forEach { adaptor.putIfAbsent(it, it) }
assertTrue(adaptor.isFullInitialized())
}
}

@Nested
@DisplayName("存在しないkeyの読み出しテスト")
inner class NotContainsKeyTest {
@Test
@DisplayName("isInitializedのテスト")
fun isInitialized() {
assertThrows<IllegalArgumentException> { adaptor.isInitialized("hoge") }
}

@Test
@DisplayName("putIfAbsentのテスト")
fun putIfAbsent() {
assertThrows<IllegalArgumentException> { adaptor.putIfAbsent("hoge", "hoge") }
}
}

@Test
@DisplayName("読み出しテスト")
fun readoutTest() {
keys.forEach { adaptor.putIfAbsent(it, it) }
keys.forEach { assertEquals(it, adaptor.readout(it)) }
}
}
13 changes: 10 additions & 3 deletions src/test/kotlin/com/mapk/core/KParameterFlattenTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import org.junit.jupiter.api.Test

@DisplayName("パラメータのフラット化テスト")
class KParameterFlattenTest {
data class InnerDst1(val quxQux: Int)
data class InnerDst1(val quxQux: Int, @KParameterFlatten(fieldNameToPrefix = false) val fredFred: InnerInnerDst)
data class InnerInnerDst(val waldoWaldo: Int)
data class InnerDst2(val quuxQuux: Int)
data class InnerDst3(val graultGrault: String) {
@KConstructor
Expand All @@ -31,8 +32,14 @@ class KParameterFlattenTest {

companion object {
val expectedParams: Set<String> =
linkedSetOf("fooFoo", "barBar", "bazBazQuxQux", "quuxQuux", "garplyGarply-graultGrault")
val expected: Dst = Dst(0, 1, InnerDst1(2), InnerDst2(3), InnerDst3("4"))
linkedSetOf("fooFoo", "barBar", "bazBazQuxQux", "waldoWaldo", "quuxQuux", "garplyGarply-graultGrault")
val expected: Dst = Dst(
0,
1,
InnerDst1(2, InnerInnerDst(3)),
InnerDst2(4),
InnerDst3("5")
)
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.mapk.core.internal

import com.mapk.core.NameJoiner
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test

@DisplayName("パラメータ名変換関連のテスト")
class ParameterNameConverterTest {
@Nested
@DisplayName("シンプルな変換機能のテスト")
inner class SimpleTest {
private val simple = ParameterNameConverter.Simple { it.toLowerCase() }

@Test
@DisplayName("単純な変換テスト")
fun convertTest() {
val expected = "abcdef"
val actual = simple.convert("AbCdEf")
assertEquals(expected, actual)
}

@Test
@DisplayName("ネストしたインスタンスを作るテスト")
fun nestTest() {
val nested1 = simple.nest("AbCdEf", NameJoiner.Kebab)
run {
val expected = "abcdef-ghijkl"
val actual = nested1.convert("gHiJkL")
assertEquals(expected, actual)
}

val nested2 = nested1.nest("gHiJkL", NameJoiner.Snake)
run {
val expected = "abcdef-ghijkl_mnopqr"
val actual = nested2.convert("MNopQR")
assertEquals(expected, actual)
}
}

@Test
@DisplayName("Simpleにした場合のテスト")
fun simple() {
val simple2 = simple.toSimple()
assertEquals(simple, simple2)
}
}

@Nested
@DisplayName("プレフィックス付き変換機能のテスト")
inner class WithPrefixTest {
private val withPrefix =
ParameterNameConverter.WithPrefix("abcdef", NameJoiner.Snake) { it.toUpperCase() }

@Test
@DisplayName("単純な変換テスト")
fun convertTest() {
val expected = "ABCDEF_GHIJKL"
val actual = withPrefix.convert("GhIJkL")
assertEquals(expected, actual)
}

@Test
@DisplayName("ネストしたインスタンスを作るテスト")
fun nestTest() {
val nested = withPrefix.nest("GhIJkL", NameJoiner.Kebab)
run {
val expected = "ABCDEF_GHIJKL-MNOPQR"
val actual = nested.convert("mnOpQr")
assertEquals(expected, actual)
}
}

@Test
@DisplayName("Simpleにした場合のテスト")
fun simple() {
val simple = withPrefix.toSimple()
val expected = "ABCDEF"
val actual = simple.convert(expected)
assertEquals(expected, actual)
}
}
}