From 95555f01035f643d6270161d32a17d143a75c5cc Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 10:53:23 +0900 Subject: [PATCH 01/10] =?UTF-8?q?=E3=82=A2=E3=82=AF=E3=82=BB=E3=82=B7?= =?UTF-8?q?=E3=83=93=E3=83=AA=E3=83=86=E3=82=A3=E6=9B=B8=E3=81=8D=E6=8F=9B?= =?UTF-8?q?=E3=81=88=E3=81=AE=E5=A0=B4=E6=89=80=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/wrongwrong/mapk/core/CompanionKFunction.kt | 6 ++++++ src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt | 6 +----- src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt | 2 -- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/com/wrongwrong/mapk/core/CompanionKFunction.kt b/src/main/kotlin/com/wrongwrong/mapk/core/CompanionKFunction.kt index 564c8b3..195284c 100644 --- a/src/main/kotlin/com/wrongwrong/mapk/core/CompanionKFunction.kt +++ b/src/main/kotlin/com/wrongwrong/mapk/core/CompanionKFunction.kt @@ -3,11 +3,17 @@ package com.wrongwrong.mapk.core import kotlin.reflect.KFunction import kotlin.reflect.KParameter import kotlin.reflect.full.instanceParameter +import kotlin.reflect.jvm.isAccessible internal class CompanionKFunction( private val function: KFunction, private val instance: Any ) : KFunction by function { + init { + // このインスタンスを生成している時点でfunctionにアクセスしたい状況なので、アクセシビリティはここでセットする + function.isAccessible = true + } + private val instanceParam by lazy { mapOf(function.instanceParameter!! to instance) } override val parameters: List by lazy { diff --git a/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt b/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt index e526d2b..c66ccdc 100644 --- a/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt +++ b/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt @@ -117,11 +117,7 @@ internal fun getTarget(clazz: KClass): KFunction { clazz.companionObjectInstance?.let { companionObject -> companionObject::class.functions .filter { it.annotations.any { annotation -> annotation is KConstructor } } - .map { - // isAccessibleの書き換えはKotlinの都合で先に行う必要が有る - it.isAccessible = true - CompanionKFunction(it, companionObject) as KFunction - } + .map { CompanionKFunction(it, companionObject) as KFunction } } ?: emptyList() val constructors: List> = factoryConstructor + clazz.constructors diff --git a/src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt b/src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt index a6e5bc0..fa374e2 100644 --- a/src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt +++ b/src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt @@ -66,8 +66,6 @@ private fun creatorsFromCompanionObject(clazz: KClass): Set annotation is KConverter } } .map { function -> - // isAccessibleの書き換えはKotlinの都合で先に行う必要が有る - function.isAccessible = true val func: KFunction = CompanionKFunction(function, companionObject) as KFunction (func.parameters.single().type.classifier as KClass<*>) to func From 936e6cbb537e539a2c11a92065f5d9612561b746 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 10:54:32 +0900 Subject: [PATCH 02/10] =?UTF-8?q?=E6=94=B9=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/{CompanionKFunction.kt => KFunctionWithInstance.kt} | 2 +- src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt | 2 +- src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/main/kotlin/com/wrongwrong/mapk/core/{CompanionKFunction.kt => KFunctionWithInstance.kt} (95%) diff --git a/src/main/kotlin/com/wrongwrong/mapk/core/CompanionKFunction.kt b/src/main/kotlin/com/wrongwrong/mapk/core/KFunctionWithInstance.kt similarity index 95% rename from src/main/kotlin/com/wrongwrong/mapk/core/CompanionKFunction.kt rename to src/main/kotlin/com/wrongwrong/mapk/core/KFunctionWithInstance.kt index 195284c..d3fa059 100644 --- a/src/main/kotlin/com/wrongwrong/mapk/core/CompanionKFunction.kt +++ b/src/main/kotlin/com/wrongwrong/mapk/core/KFunctionWithInstance.kt @@ -5,7 +5,7 @@ import kotlin.reflect.KParameter import kotlin.reflect.full.instanceParameter import kotlin.reflect.jvm.isAccessible -internal class CompanionKFunction( +internal class KFunctionWithInstance( private val function: KFunction, private val instance: Any ) : KFunction by function { diff --git a/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt b/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt index c66ccdc..b2353b3 100644 --- a/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt +++ b/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt @@ -117,7 +117,7 @@ internal fun getTarget(clazz: KClass): KFunction { clazz.companionObjectInstance?.let { companionObject -> companionObject::class.functions .filter { it.annotations.any { annotation -> annotation is KConstructor } } - .map { CompanionKFunction(it, companionObject) as KFunction } + .map { KFunctionWithInstance(it, companionObject) as KFunction } } ?: emptyList() val constructors: List> = factoryConstructor + clazz.constructors diff --git a/src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt b/src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt index fa374e2..8df3d96 100644 --- a/src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt +++ b/src/main/kotlin/com/wrongwrong/mapk/core/ParameterForMap.kt @@ -66,7 +66,7 @@ private fun creatorsFromCompanionObject(clazz: KClass): Set annotation is KConverter } } .map { function -> - val func: KFunction = CompanionKFunction(function, companionObject) as KFunction + val func: KFunction = KFunctionWithInstance(function, companionObject) as KFunction (func.parameters.single().type.classifier as KClass<*>) to func }.toSet() From cef2aa63c809afa67d82625517402c54c61a93df Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 11:07:18 +0900 Subject: [PATCH 03/10] =?UTF-8?q?=E3=83=97=E3=83=AD=E3=83=91=E3=83=86?= =?UTF-8?q?=E3=82=A3=E5=90=8D=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E7=94=A8?= =?UTF-8?q?=E3=81=ABguava=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 8a465a5..d6b2a65 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,6 +33,9 @@ dependencies { testImplementation(group = "org.junit.jupiter", name = "junit-jupiter", version = "5.6.0") { exclude(group = "org.junit.vintage", module = "junit-vintage-engine") } + // 現状プロパティ名の変換はテストでしか使っていないのでtestImplementation + // https://mvnrepository.com/artifact/com.google.guava/guava + testImplementation(group = "com.google.guava", name = "guava", version = "28.2-jre") } tasks.compileKotlin { From 8005c125b226578bd48a96867efe5d8a7b503b6d Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 11:07:37 +0900 Subject: [PATCH 04/10] =?UTF-8?q?=E3=83=97=E3=83=AD=E3=83=91=E3=83=86?= =?UTF-8?q?=E3=82=A3=E5=90=8D=E5=A4=89=E6=8F=9B=E3=81=AE=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mapk/core/PropertyNameConverterTest.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/kotlin/mapk/core/PropertyNameConverterTest.kt diff --git a/src/test/kotlin/mapk/core/PropertyNameConverterTest.kt b/src/test/kotlin/mapk/core/PropertyNameConverterTest.kt new file mode 100644 index 0000000..9f48670 --- /dev/null +++ b/src/test/kotlin/mapk/core/PropertyNameConverterTest.kt @@ -0,0 +1,24 @@ +package mapk.core + +import com.google.common.base.CaseFormat +import com.wrongwrong.mapk.core.KMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test + +private class CamelCaseDst(val camelCase: String) + +@DisplayName("プロパティ名変換のテスト") +class PropertyNameConverterTest { + @Test + @DisplayName("スネークケースsrc -> キャメルケースdst") + fun test() { + val expected = "snakeCase" + val src = mapOf("camel_case" to expected) + + val mapper = KMapper(CamelCaseDst::class) { CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, it) } + val result = mapper.map(src) + + assertEquals(expected, result.camelCase) + } +} From 4816193d6cf3666d5b74b99893a631def504ef0b Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 11:10:40 +0900 Subject: [PATCH 05/10] =?UTF-8?q?=E8=A8=98=E8=BF=B0=E3=82=92=E7=B0=A1?= =?UTF-8?q?=E7=95=A5=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt b/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt index b2353b3..c7b09ed 100644 --- a/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt +++ b/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt @@ -5,7 +5,6 @@ import com.wrongwrong.mapk.annotations.KPropertyAlias import com.wrongwrong.mapk.annotations.KPropertyIgnore import kotlin.reflect.KClass import kotlin.reflect.KFunction -import kotlin.reflect.KParameter import kotlin.reflect.KProperty1 import kotlin.reflect.KVisibility import kotlin.reflect.full.companionObjectInstance @@ -20,16 +19,12 @@ class KMapper(private val function: KFunction, propertyNameConverter getTarget(clazz), propertyNameConverter ) - private val parameters: Set> + private val parameters: Set> = function.parameters + .map { ParameterForMap.newInstance(it, propertyNameConverter) } + .toSet() init { - val params: List = function.parameters - - if (params.isEmpty()) throw IllegalArgumentException("This function is not require arguments.") - - parameters = params - .map { ParameterForMap.newInstance(it, propertyNameConverter) } - .toSet() + if (parameters.isEmpty()) throw IllegalArgumentException("This function is not require arguments.") // private関数に対してもマッピングできなければ何かと不都合があるため、accessibleは書き換える function.isAccessible = true From 462e0d3f0b716cbf77fc45c80437a60ed05aae9a Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 11:34:04 +0900 Subject: [PATCH 06/10] =?UTF-8?q?Pair=E3=82=92src=E3=81=AB=E3=81=A7?= =?UTF-8?q?=E3=81=8D=E3=81=AA=E3=81=8B=E3=81=A3=E3=81=9F=E5=95=8F=E9=A1=8C?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Any要求のmapが別に居ることが原因 そっちを消しても良かったが、vararg要求の方を経由させると非効率なので、新設する形で対応 --- src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt b/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt index c7b09ed..1083db6 100644 --- a/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt +++ b/src/main/kotlin/com/wrongwrong/mapk/core/KMapper.kt @@ -39,6 +39,12 @@ class KMapper(private val function: KFunction, propertyNameConverter }.let { function.callBy(it) } } + fun map(srcPair: Pair): T = parameters + .single { it.name == srcPair.first } + .let { + function.callBy(mapOf(it.param to srcPair.second?.let { value -> mapObject(it, value) })) + } + fun map(src: Any): T { val srcMap: Map> = src::class.memberProperties.filterTargets().associate { property -> From a35db64fd85bfc91178d70bce6589134dfc4429a Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 11:37:06 +0900 Subject: [PATCH 07/10] =?UTF-8?q?Enum=E3=81=AE=E3=83=9E=E3=83=83=E3=83=94?= =?UTF-8?q?=E3=83=B3=E3=82=B0=E3=83=86=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/mapk/core/EnumMappingTest.kt | 26 ++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/test/kotlin/mapk/core/EnumMappingTest.kt diff --git a/src/test/kotlin/mapk/core/EnumMappingTest.kt b/src/test/kotlin/mapk/core/EnumMappingTest.kt new file mode 100644 index 0000000..9d64775 --- /dev/null +++ b/src/test/kotlin/mapk/core/EnumMappingTest.kt @@ -0,0 +1,26 @@ +package mapk.core + +import com.wrongwrong.mapk.core.KMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.EnumSource + +enum class JvmLanguage { + Java, Scala, Groovy, Kotlin +} + +private class EnumMappingDst(val language: JvmLanguage?) + +@DisplayName("文字列 -> Enumのマッピングテスト") +class EnumMappingTest { + private val mapper = KMapper(EnumMappingDst::class) + + @ParameterizedTest(name = "Non-Null要求") + @EnumSource(value = JvmLanguage::class) + fun test(language: JvmLanguage) { + val result = mapper.map("language" to language.name) + + assertEquals(language, result.language) + } +} From f31a64dd537217bd3351266aef477f3f78182ebd Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 11:48:31 +0900 Subject: [PATCH 08/10] =?UTF-8?q?=E6=96=87=E5=AD=97=E5=88=97=E3=81=AB?= =?UTF-8?q?=E5=AF=BE=E3=81=97=E3=81=A6toString=E3=81=97=E3=81=9F=E3=82=82?= =?UTF-8?q?=E3=81=AE=E3=82=92=E6=B8=A1=E3=81=99=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/mapk/core/StringMappingTest.kt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/test/kotlin/mapk/core/StringMappingTest.kt diff --git a/src/test/kotlin/mapk/core/StringMappingTest.kt b/src/test/kotlin/mapk/core/StringMappingTest.kt new file mode 100644 index 0000000..cb3b2a7 --- /dev/null +++ b/src/test/kotlin/mapk/core/StringMappingTest.kt @@ -0,0 +1,17 @@ +package mapk.core + +import com.wrongwrong.mapk.core.KMapper +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test + +private data class StringMappingDst(val value: String) + +@DisplayName("文字列に対してtoStringしたものを渡すテスト") +class StringMappingTest { + @Test + fun test() { + val result: StringMappingDst = KMapper(StringMappingDst::class).map("value" to 1) + assertEquals("1", result.value) + } +} From 8b9a3e07557d94388344ba8ef4a54c2a21305e7d Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 11:53:54 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=E8=AD=A6=E5=91=8A=E3=81=AE=E6=8A=91?= =?UTF-8?q?=E5=88=B6=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/mapk/core/EnumMappingTest.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/kotlin/mapk/core/EnumMappingTest.kt b/src/test/kotlin/mapk/core/EnumMappingTest.kt index 9d64775..8edd826 100644 --- a/src/test/kotlin/mapk/core/EnumMappingTest.kt +++ b/src/test/kotlin/mapk/core/EnumMappingTest.kt @@ -1,3 +1,5 @@ +@file:Suppress("unused") + package mapk.core import com.wrongwrong.mapk.core.KMapper From 0a35ce4ad43db664f6b6a31d76c35b0b5e4e0a3c Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sat, 22 Feb 2020 11:54:16 +0900 Subject: [PATCH 10/10] =?UTF-8?q?=E8=AD=A6=E5=91=8A=E3=81=AF=E3=82=A8?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=81=A8=E3=81=97=E3=81=A6=E6=89=B1=E3=81=86?= =?UTF-8?q?=E3=82=88=E3=81=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle.kts b/build.gradle.kts index d6b2a65..3087eb3 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -42,6 +42,7 @@ tasks.compileKotlin { dependsOn("ktlintFormat") kotlinOptions { jvmTarget = "1.8" + allWarningsAsErrors = true } }