From 662e8a23527ad33688f4ad81698b95d8d870d85d Mon Sep 17 00:00:00 2001 From: kiryldz Date: Mon, 13 Mar 2023 11:06:39 +0200 Subject: [PATCH 1/3] Add import support for default parameters --- README.md | 10 ++++++---- .../tobrun/datacompat/annotation/Default.kt | 8 +++++++- .../tobrun/data/compat/example/PersonData.kt | 2 +- .../tobrun/datacompat/DataCompatProcessor.kt | 19 +++++++++++++++++-- .../datacompat/DataCompatProcessorTest.kt | 2 +- .../tobrun/datacompat/SimpleTestContent.kt | 1 + .../com/tobrun/datacompat/TestAnnotation.kt | 4 ++-- 7 files changed, 35 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e75e95d..1a004ec 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,8 @@ And you will have to include the required dependencies: ```groovy dependencies { - implementation 'com.github.tobrun.kotlin-data-compat:annotation:0.3.0' - ksp 'com.github.tobrun.kotlin-data-compat:processor:0.3.0' + implementation 'com.github.tobrun.kotlin-data-compat:annotation:0.4.0' + ksp 'com.github.tobrun.kotlin-data-compat:processor:0.4.0' } ``` @@ -41,6 +41,7 @@ Given an exisiting data class: - mark class private - append `Data` to the class name - support default parameters by using `@Default` annotation + - support imports for default parameters - retain existing class annotations (but not parameters for them) - retain existing interfaces @@ -59,7 +60,7 @@ annotation class SampleAnnotation @DataCompat @SampleAnnotation private data class PersonData( - @Default("\"John\"") + @Default("\"John\" + Date(1580897313933L).toString()", importList = ["java.util.Date"]) val name: String, val nickname: String?, @Default("42") @@ -72,6 +73,7 @@ After compilation, the following class will be generated: ```kotlin package com.tobrun.`data`.compat.example +import java.util.Date import java.util.Objects import kotlin.Any import kotlin.Boolean @@ -120,7 +122,7 @@ public class Person private constructor( */ public class Builder { @set:JvmSynthetic - public var name: String? = "John" + public var name: String? = "John" + Date(1580897313933L).toString() @set:JvmSynthetic public var nickname: String? = null diff --git a/annotation/src/main/kotlin/com/tobrun/datacompat/annotation/Default.kt b/annotation/src/main/kotlin/com/tobrun/datacompat/annotation/Default.kt index 10946f3..4691203 100644 --- a/annotation/src/main/kotlin/com/tobrun/datacompat/annotation/Default.kt +++ b/annotation/src/main/kotlin/com/tobrun/datacompat/annotation/Default.kt @@ -10,7 +10,13 @@ package com.tobrun.datacompat.annotation * @param valueAsString exact representation of the default value. E.g. if default [String] is used, * it should be passed here as "\"STRING_VALUE\""; if default [Int] is used, it should be passed * as "INT_VALUE". + * + * @param importList if default parameter requires additional imports, they should be passed here. + * E.g. `listOf("android.graphics.Color")` */ @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.VALUE_PARAMETER) -annotation class Default(val valueAsString: String) +annotation class Default( + val valueAsString: String, + val importList: Array = [] +) diff --git a/example/src/main/kotlin/com/tobrun/data/compat/example/PersonData.kt b/example/src/main/kotlin/com/tobrun/data/compat/example/PersonData.kt index dd852c8..ba2d798 100644 --- a/example/src/main/kotlin/com/tobrun/data/compat/example/PersonData.kt +++ b/example/src/main/kotlin/com/tobrun/data/compat/example/PersonData.kt @@ -15,7 +15,7 @@ annotation class SampleAnnotation @DataCompat @SampleAnnotation private data class PersonData( - @Default("\"John\"") + @Default("\"John\" + Date(1580897313933L).toString()", importList = ["java.util.Date"]) val name: String, val nickname: String?, @Default("42") diff --git a/processor/src/main/kotlin/com/tobrun/datacompat/DataCompatProcessor.kt b/processor/src/main/kotlin/com/tobrun/datacompat/DataCompatProcessor.kt index 818efcd..c331d00 100644 --- a/processor/src/main/kotlin/com/tobrun/datacompat/DataCompatProcessor.kt +++ b/processor/src/main/kotlin/com/tobrun/datacompat/DataCompatProcessor.kt @@ -77,6 +77,7 @@ class DataCompatProcessor( val implementedInterfaces = classDeclaration .superTypes .filter { (it.resolve().declaration as? KSClassDeclaration)?.classKind == ClassKind.INTERFACE } + val imports = ArrayList() // Map KSP properties with KoltinPoet TypeNames val propertyMap = mutableMapOf() @@ -219,9 +220,15 @@ class DataCompatProcessor( val builderBuilder = TypeSpec.classBuilder("Builder") for (property in propertyMap) { val propertyName = property.key.toString() - val defaultValue = property.key.annotations + val defaultAnnotationsParams = property.key.annotations .firstOrNull { it.annotationType.resolve().toString() == Default::class.simpleName } - ?.arguments?.first() + ?.arguments + val defaultValue = defaultAnnotationsParams?.first() + if ((defaultAnnotationsParams?.size ?: 0) > 1) { + defaultAnnotationsParams?.get(1)?.value?.let { importList -> + imports.addAll(importList as ArrayList) + } + } val nullableType = property.value.copy(nullable = true) builderBuilder.addProperty( PropertySpec.builder(propertyName, nullableType) @@ -350,6 +357,14 @@ class DataCompatProcessor( .addType(classBuilder.build()) .addFunction(initializerFunctionBuilder.build()) + imports.forEach { + fileBuilder + .addImport( + it.split(".").dropLast(1).joinToString("."), + it.split(".").last() + ) + } + fileBuilder.build().writeTo(codeGenerator = codeGenerator, aggregating = false) } diff --git a/processor/src/test/kotlin/com/tobrun/datacompat/DataCompatProcessorTest.kt b/processor/src/test/kotlin/com/tobrun/datacompat/DataCompatProcessorTest.kt index 4c13f76..d9f627b 100644 --- a/processor/src/test/kotlin/com/tobrun/datacompat/DataCompatProcessorTest.kt +++ b/processor/src/test/kotlin/com/tobrun/datacompat/DataCompatProcessorTest.kt @@ -28,7 +28,7 @@ interface EmptyInterface2 @Deprecated @DataCompat private data class PersonData( - @Default("\"John\"") + @Default("\"John\"", ["java.util.Date"]) val name: String, @Default("null") val nickname: String?, diff --git a/processor/src/test/kotlin/com/tobrun/datacompat/SimpleTestContent.kt b/processor/src/test/kotlin/com/tobrun/datacompat/SimpleTestContent.kt index 85d500d..757bdd6 100644 --- a/processor/src/test/kotlin/com/tobrun/datacompat/SimpleTestContent.kt +++ b/processor/src/test/kotlin/com/tobrun/datacompat/SimpleTestContent.kt @@ -1,6 +1,7 @@ package com.tobrun.datacompat internal val expectedSimpleTestContent = """ + import java.util.Date import java.util.Objects import kotlin.Any import kotlin.Boolean diff --git a/processor/src/test/kotlin/com/tobrun/datacompat/TestAnnotation.kt b/processor/src/test/kotlin/com/tobrun/datacompat/TestAnnotation.kt index 301f46d..c9141ed 100644 --- a/processor/src/test/kotlin/com/tobrun/datacompat/TestAnnotation.kt +++ b/processor/src/test/kotlin/com/tobrun/datacompat/TestAnnotation.kt @@ -12,7 +12,7 @@ package com.tobrun.datacompat.annotation annotation class DataCompat @Retention(AnnotationRetention.RUNTIME) -@Target(AnnotationTarget.CLASS) -annotation class Default(val valueAsString: String) +@Target(AnnotationTarget.VALUE_PARAMETER) +annotation class Default(val valueAsString: String, val importList: Array = []) """.trimIndent() ) From cd355871a215db7537c68625ffec12b4d32016c3 Mon Sep 17 00:00:00 2001 From: kiryldz Date: Mon, 13 Mar 2023 13:16:09 +0200 Subject: [PATCH 2/3] PR fixes --- .../main/kotlin/com/tobrun/datacompat/annotation/Default.kt | 4 ++-- .../kotlin/com/tobrun/data/compat/example/PersonData.kt | 2 +- .../kotlin/com/tobrun/datacompat/DataCompatProcessor.kt | 6 ++---- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/annotation/src/main/kotlin/com/tobrun/datacompat/annotation/Default.kt b/annotation/src/main/kotlin/com/tobrun/datacompat/annotation/Default.kt index 4691203..964d443 100644 --- a/annotation/src/main/kotlin/com/tobrun/datacompat/annotation/Default.kt +++ b/annotation/src/main/kotlin/com/tobrun/datacompat/annotation/Default.kt @@ -11,12 +11,12 @@ package com.tobrun.datacompat.annotation * it should be passed here as "\"STRING_VALUE\""; if default [Int] is used, it should be passed * as "INT_VALUE". * - * @param importList if default parameter requires additional imports, they should be passed here. + * @param imports if default parameter requires additional imports, they should be passed here. * E.g. `listOf("android.graphics.Color")` */ @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.VALUE_PARAMETER) annotation class Default( val valueAsString: String, - val importList: Array = [] + val imports: Array = [] ) diff --git a/example/src/main/kotlin/com/tobrun/data/compat/example/PersonData.kt b/example/src/main/kotlin/com/tobrun/data/compat/example/PersonData.kt index ba2d798..5136eea 100644 --- a/example/src/main/kotlin/com/tobrun/data/compat/example/PersonData.kt +++ b/example/src/main/kotlin/com/tobrun/data/compat/example/PersonData.kt @@ -15,7 +15,7 @@ annotation class SampleAnnotation @DataCompat @SampleAnnotation private data class PersonData( - @Default("\"John\" + Date(1580897313933L).toString()", importList = ["java.util.Date"]) + @Default("\"John\" + Date(1580897313933L).toString()", imports = ["java.util.Date"]) val name: String, val nickname: String?, @Default("42") diff --git a/processor/src/main/kotlin/com/tobrun/datacompat/DataCompatProcessor.kt b/processor/src/main/kotlin/com/tobrun/datacompat/DataCompatProcessor.kt index c331d00..65ec6d2 100644 --- a/processor/src/main/kotlin/com/tobrun/datacompat/DataCompatProcessor.kt +++ b/processor/src/main/kotlin/com/tobrun/datacompat/DataCompatProcessor.kt @@ -224,10 +224,8 @@ class DataCompatProcessor( .firstOrNull { it.annotationType.resolve().toString() == Default::class.simpleName } ?.arguments val defaultValue = defaultAnnotationsParams?.first() - if ((defaultAnnotationsParams?.size ?: 0) > 1) { - defaultAnnotationsParams?.get(1)?.value?.let { importList -> - imports.addAll(importList as ArrayList) - } + defaultAnnotationsParams?.getOrNull(1)?.value?.let { + imports.addAll(it as ArrayList) } val nullableType = property.value.copy(nullable = true) builderBuilder.addProperty( From a66f2ee154448acf99cbb71cab49bb667f997376 Mon Sep 17 00:00:00 2001 From: kiryldz Date: Mon, 13 Mar 2023 13:24:57 +0200 Subject: [PATCH 3/3] upd readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a004ec..f2696ee 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ annotation class SampleAnnotation @DataCompat @SampleAnnotation private data class PersonData( - @Default("\"John\" + Date(1580897313933L).toString()", importList = ["java.util.Date"]) + @Default("\"John\" + Date(1580897313933L).toString()", imports = ["java.util.Date"]) val name: String, val nickname: String?, @Default("42")