From f04dda8ea2aa22ea70bd9a51f29c8758800a2a5d Mon Sep 17 00:00:00 2001 From: Jan Galinski Date: Sun, 1 Sep 2024 14:48:07 +0200 Subject: [PATCH 1/7] Update for next development version --- _build/parent/pom.xml | 2 +- _build/report-generator/pom.xml | 2 +- _itest/builder-itest/pom.xml | 2 +- _itest/pom.xml | 2 +- _itest/spi-itest/pom.xml | 2 +- kotlin-code-generation-bom/pom.xml | 2 +- kotlin-code-generation-test/pom.xml | 2 +- kotlin-code-generation/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/_build/parent/pom.xml b/_build/parent/pom.xml index 62b3724..2d56614 100644 --- a/_build/parent/pom.xml +++ b/_build/parent/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-root - 0.0.6 + 0.0.7-SNAPSHOT ../../pom.xml diff --git a/_build/report-generator/pom.xml b/_build/report-generator/pom.xml index 954b49b..2dd79bd 100644 --- a/_build/report-generator/pom.xml +++ b/_build/report-generator/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-parent - 0.0.6 + 0.0.7-SNAPSHOT ../parent/pom.xml diff --git a/_itest/builder-itest/pom.xml b/_itest/builder-itest/pom.xml index b63421b..65bcb0f 100644 --- a/_itest/builder-itest/pom.xml +++ b/_itest/builder-itest/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-itest-root - 0.0.6 + 0.0.7-SNAPSHOT io.toolisticon.kotlin.generation.itest diff --git a/_itest/pom.xml b/_itest/pom.xml index 2e6fb35..2b0cafd 100644 --- a/_itest/pom.xml +++ b/_itest/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-parent - 0.0.6 + 0.0.7-SNAPSHOT ../_build/parent/pom.xml diff --git a/_itest/spi-itest/pom.xml b/_itest/spi-itest/pom.xml index 9d0871c..4fac7d0 100644 --- a/_itest/spi-itest/pom.xml +++ b/_itest/spi-itest/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-itest-root - 0.0.6 + 0.0.7-SNAPSHOT io.toolisticon.kotlin.generation.itest diff --git a/kotlin-code-generation-bom/pom.xml b/kotlin-code-generation-bom/pom.xml index 6b720a8..caa48e4 100644 --- a/kotlin-code-generation-bom/pom.xml +++ b/kotlin-code-generation-bom/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-root - 0.0.6 + 0.0.7-SNAPSHOT io.toolisticon.kotlin.generation diff --git a/kotlin-code-generation-test/pom.xml b/kotlin-code-generation-test/pom.xml index 765c8d0..8183db5 100644 --- a/kotlin-code-generation-test/pom.xml +++ b/kotlin-code-generation-test/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-parent - 0.0.6 + 0.0.7-SNAPSHOT ../_build/parent/pom.xml diff --git a/kotlin-code-generation/pom.xml b/kotlin-code-generation/pom.xml index cea195d..5ac4a78 100644 --- a/kotlin-code-generation/pom.xml +++ b/kotlin-code-generation/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-parent - 0.0.6 + 0.0.7-SNAPSHOT ../_build/parent/pom.xml diff --git a/pom.xml b/pom.xml index ae75050..cd5a88a 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-root - 0.0.6 + 0.0.7-SNAPSHOT pom: ${project.artifactId} Root of kotlin-code-generation From 606a8aaa238f250a8a30366ee5b1b267b71b3bfc Mon Sep 17 00:00:00 2001 From: Jan Galinski Date: Mon, 9 Sep 2024 17:35:34 +0200 Subject: [PATCH 2/7] chore: prepare multi file strategy --- .../kotlin/model/KotlinCompilationCommand.kt | 5 +-- .../src/main/kotlin/spec/KotlinFileSpec.kt | 16 ++++++++++ .../spi/strategy/KotlinFileSpecsStrategy.kt | 31 +++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 kotlin-code-generation/src/main/kotlin/spi/strategy/KotlinFileSpecsStrategy.kt diff --git a/kotlin-code-generation-test/src/main/kotlin/model/KotlinCompilationCommand.kt b/kotlin-code-generation-test/src/main/kotlin/model/KotlinCompilationCommand.kt index 5c3d9c5..235d8c8 100644 --- a/kotlin-code-generation-test/src/main/kotlin/model/KotlinCompilationCommand.kt +++ b/kotlin-code-generation-test/src/main/kotlin/model/KotlinCompilationCommand.kt @@ -3,6 +3,7 @@ package io.toolisticon.kotlin.generation.test.model import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.tschuchort.compiletesting.SourceFile import io.toolisticon.kotlin.generation.spec.KotlinFileSpec +import io.toolisticon.kotlin.generation.spec.KotlinFileSpecs import io.toolisticon.kotlin.generation.test.KotlinCodeGenerationTest.sourceFile import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi @@ -12,10 +13,10 @@ import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi @ExperimentalKotlinPoetApi @ExperimentalCompilerApi data class KotlinCompilationCommand( - val fileSpecs: List + val fileSpecs: KotlinFileSpecs ) { - constructor(fileSpec: KotlinFileSpec) : this(listOf(fileSpec)) + constructor(fileSpec: KotlinFileSpec) : this(KotlinFileSpecs(fileSpec)) operator fun plus(fileSpec: KotlinFileSpec) = copy(fileSpecs = fileSpecs + fileSpec) diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinFileSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinFileSpec.kt index d57c989..1ec4ea8 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinFileSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinFileSpec.kt @@ -22,3 +22,19 @@ data class KotlinFileSpec( interface KotlinFileSpecSupplier : KotlinGeneratorSpecSupplier, FileSpecSupplier, WithClassName { override fun get(): FileSpec = spec().get() } + +/** + * List that contains multiple [KotlinFileSpec]s. + */ +@JvmInline +value class KotlinFileSpecs(private val fileSpecs: List) : List by fileSpecs { + companion object { + val EMPTY = KotlinFileSpecs(emptyList()) + + fun collect(vararg fns: () -> KotlinFileSpec) = fns.fold(EMPTY) { acc, cur -> acc + cur() } + } + + constructor(fileSpec : KotlinFileSpec) : this(listOf(fileSpec)) + + operator fun plus(fileSpec : KotlinFileSpec): KotlinFileSpecs = KotlinFileSpecs(fileSpecs + fileSpec) +} diff --git a/kotlin-code-generation/src/main/kotlin/spi/strategy/KotlinFileSpecsStrategy.kt b/kotlin-code-generation/src/main/kotlin/spi/strategy/KotlinFileSpecsStrategy.kt new file mode 100644 index 0000000..96747a2 --- /dev/null +++ b/kotlin-code-generation/src/main/kotlin/spi/strategy/KotlinFileSpecsStrategy.kt @@ -0,0 +1,31 @@ +package io.toolisticon.kotlin.generation.spi.strategy + +import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi +import io.toolisticon.kotlin.generation.spec.KotlinFileSpecs +import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationContext +import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationSpi +import kotlin.reflect.KClass + +/** + * Used to implement a [io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationStrategy] + * that will generate multiple [io.toolisticon.kotlin.generation.spec.KotlinFileSpec]s wrapped in [KotlinFileSpecs]. + * + * Implementations should override the `invoke` function to call multiple [KotlinFileSpecStrategy]s and collect the + * results. + */ +@ExperimentalKotlinPoetApi +abstract class KotlinFileSpecsStrategy, INPUT : Any>( + contextType: KClass, + override val inputType: KClass, + order: Int = KotlinCodeGenerationSpi.DEFAULT_ORDER, +) : KotlinCodeGenerationStrategyBase( + contextType = contextType, + inputType = inputType, + specType = KotlinFileSpecs::class, + order = order +) { + + abstract override fun invoke(context: CONTEXT, input: INPUT): KotlinFileSpecs + + override fun test(context: CONTEXT, input: Any): Boolean = super.test(context, input) +} From 17bb36b48f11a4180d876ea05d156cdd0233c3e0 Mon Sep 17 00:00:00 2001 From: Jan Galinski Date: Tue, 10 Sep 2024 14:35:52 +0200 Subject: [PATCH 3/7] collect annotation members in single block, fixes #50 --- .../support/GeneratedAnnotationITest.kt | 2 +- .../builder/KotlinAnnotationSpecBuilder.kt | 37 ++++++++++++------- .../src/main/kotlin/support/CodeBlockArray.kt | 19 +++++++--- .../kotlin/support/GeneratedAnnotation.kt | 15 +++----- .../test/kotlin/support/CodeBlockArrayTest.kt | 2 +- .../kotlin/support/GeneratedAnnotationTest.kt | 26 ++++++++++++- 6 files changed, 69 insertions(+), 32 deletions(-) diff --git a/_itest/builder-itest/src/test/kotlin/support/GeneratedAnnotationITest.kt b/_itest/builder-itest/src/test/kotlin/support/GeneratedAnnotationITest.kt index d0d9219..ac9929f 100644 --- a/_itest/builder-itest/src/test/kotlin/support/GeneratedAnnotationITest.kt +++ b/_itest/builder-itest/src/test/kotlin/support/GeneratedAnnotationITest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) package io.toolisticon.kotlin.generation.itest.support @@ -12,6 +11,7 @@ import io.toolisticon.kotlin.generation.test.model.KotlinCompilationResult import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) internal class GeneratedAnnotationITest { @Test diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt index 5ec851a..6b00ef6 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt @@ -2,6 +2,7 @@ package io.toolisticon.kotlin.generation.builder import com.squareup.kotlinpoet.* import io.toolisticon.kotlin.generation.BuilderSupplier +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildCodeBlock import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_KCLASS import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_LITERAL import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_MEMBER @@ -11,7 +12,6 @@ import io.toolisticon.kotlin.generation.poet.AnnotationSpecBuilder import io.toolisticon.kotlin.generation.poet.AnnotationSpecBuilder.Companion.wrap import io.toolisticon.kotlin.generation.poet.AnnotationSpecBuilderReceiver import io.toolisticon.kotlin.generation.poet.CodeBlockBuilder.Companion.codeBlock -import io.toolisticon.kotlin.generation.spec.KotlinAnnotationClassSpec import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpec import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpecSupplier import io.toolisticon.kotlin.generation.support.CodeBlockArray @@ -20,14 +20,13 @@ import io.toolisticon.kotlin.generation.support.CodeBlockArray.Companion.kclassA import io.toolisticon.kotlin.generation.support.CodeBlockArray.Companion.numberArray import io.toolisticon.kotlin.generation.support.CodeBlockArray.Companion.stringArray import io.toolisticon.kotlin.generation.support.SUPPRESS_CLASS_NAME -import io.toolisticon.kotlin.generation.support.SUPPRESS_UNUSED import kotlin.reflect.KClass /** * Builder for [KotlinAnnotationSpec]. */ @ExperimentalKotlinPoetApi -@Suppress(SUPPRESS_UNUSED) +//@Suppress(SUPPRESS_UNUSED) class KotlinAnnotationSpecBuilder internal constructor( private val delegate: AnnotationSpecBuilder ) : BuilderSupplier, @@ -63,13 +62,19 @@ class KotlinAnnotationSpecBuilder internal constructor( fun enum(name: String, value: Enum<*>) = codeBlock("$name = $FORMAT_MEMBER", value.asMemberName()) fun enums(name: String, vararg values: Enum<*>) = codeBlock("$name = $FORMAT_LITERAL", enumArray(*values).build()) } + } - fun addMember(format: String, vararg args: Any): KotlinAnnotationSpecBuilder = apply { delegate.addMember(format, *args) } - fun addMember(codeBlock: CodeBlock): KotlinAnnotationSpecBuilder = apply { delegate.addMember(codeBlock) } + private var multiLine = false + private val members: MutableList = mutableListOf() + + fun multiLine() = apply { multiLine = true } + + fun addMember(codeBlock: CodeBlock): KotlinAnnotationSpecBuilder = apply { members.add(codeBlock) } + + fun addMember(format: String, vararg args: Any): KotlinAnnotationSpecBuilder = addMember(buildCodeBlock(format, *args)) - fun addMember(memberName: MemberName): KotlinAnnotationSpecBuilder = addMember("%M", memberName) - private fun addArrayMember(name: String, array: CodeBlockArray<*>): KotlinAnnotationSpecBuilder = addMember("$name = $FORMAT_LITERAL", array.build()) + fun addNameMember(memberName: MemberName): KotlinAnnotationSpecBuilder = addMember("%M", memberName) fun addKClassMember(name: String, value: KClass<*>) = addMember(member.kclass(name, value)) fun addKClassMembers(name: String, vararg values: KClass<*>) = addMember(member.kclasses(name, *values)) @@ -83,15 +88,21 @@ class KotlinAnnotationSpecBuilder internal constructor( fun addNumberMember(name: String, value: Number): KotlinAnnotationSpecBuilder = addMember(member.number(name, value)) fun addNumberMembers(name: String, vararg values: Number): KotlinAnnotationSpecBuilder = addMember(member.numbers(name, *values)) - fun clearMembers() = apply { - delegate.clearMembers(); - } + fun clearMembers() = apply { members.clear() } + + override fun builder(block: AnnotationSpecBuilderReceiver) = apply { delegate.builder.block() } - override fun builder(block: AnnotationSpecBuilderReceiver) = apply { - delegate.builder.block() + override fun build(): KotlinAnnotationSpec { + if (members.isNotEmpty()) { + if (multiLine) { + members.forEach(delegate::addMember) + } else { + delegate.addMember(CodeBlockArray.codeBlockArray(items = members.toTypedArray()).build()) + } + } + return KotlinAnnotationSpec(spec = delegate.build()) } - override fun build(): KotlinAnnotationSpec = KotlinAnnotationSpec(spec = delegate.build()) override fun spec(): KotlinAnnotationSpec = build() override fun get(): AnnotationSpec = build().get() } diff --git a/kotlin-code-generation/src/main/kotlin/support/CodeBlockArray.kt b/kotlin-code-generation/src/main/kotlin/support/CodeBlockArray.kt index 2516f88..dd49c62 100644 --- a/kotlin-code-generation/src/main/kotlin/support/CodeBlockArray.kt +++ b/kotlin-code-generation/src/main/kotlin/support/CodeBlockArray.kt @@ -1,10 +1,6 @@ package io.toolisticon.kotlin.generation.support -import com.squareup.kotlinpoet.CodeBlock -import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi -import com.squareup.kotlinpoet.MemberName -import com.squareup.kotlinpoet.TypeName -import com.squareup.kotlinpoet.joinToCode +import com.squareup.kotlinpoet.* import io.toolisticon.kotlin.generation.Builder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildCodeBlock import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_KCLASS @@ -14,6 +10,9 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_STRIN import io.toolisticon.kotlin.generation.KotlinCodeGeneration.name.asMemberName import kotlin.reflect.KClass +/** + * Allows concatenating and wrapping of multiple codeBlocks or format/value pairs. + */ @ExperimentalKotlinPoetApi data class CodeBlockArray( val format: Format, @@ -21,9 +20,17 @@ data class CodeBlockArray( ) : Builder { companion object { + /** + * Holds formatting values as kotlin poet format, pre- and suffix, separator. + */ data class Format(val format: String, val separator: CharSequence = ", ", val prefix: CharSequence = "[", val suffix: CharSequence = "]") - fun codeBlockArray(format: Format, vararg items: CodeBlock) = CodeBlockArray(format, items.toList()) + /** + * Special format for concatenating codeBlocks. + */ + val CODE_BLOCK_FORMAT = CodeBlockArray.Companion.Format(format = "", prefix = "", suffix = "") + + fun codeBlockArray(format: Format = CODE_BLOCK_FORMAT, vararg items: CodeBlock) = CodeBlockArray(format, items.toList()) fun stringArray(vararg items: String) = CodeBlockArray(FORMAT_STRING, items.toList()) diff --git a/kotlin-code-generation/src/main/kotlin/support/GeneratedAnnotation.kt b/kotlin-code-generation/src/main/kotlin/support/GeneratedAnnotation.kt index 0ec7f2c..148a3b0 100644 --- a/kotlin-code-generation/src/main/kotlin/support/GeneratedAnnotation.kt +++ b/kotlin-code-generation/src/main/kotlin/support/GeneratedAnnotation.kt @@ -1,12 +1,9 @@ package io.toolisticon.kotlin.generation.support -import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.asTypeName -import com.squareup.kotlinpoet.joinToCode import io.toolisticon.kotlin.generation.KotlinCodeGeneration import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildAnnotation -import io.toolisticon.kotlin.generation.builder.KotlinAnnotationSpecBuilder.Companion.member import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpec import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpecSupplier import jakarta.annotation.Generated @@ -26,12 +23,10 @@ data class GeneratedAnnotation( fun comment(comment: Pair) = copy(comments = this.comments + "${comment.first} = ${comment.second}") override fun spec(): KotlinAnnotationSpec = buildAnnotation(Generated::class) { - addMember(buildList { - add(member.strings("value", value)) - add(member.string("date", date.toString())) - if (comments.isNotEmpty()) { - add(member.string("comments", comments.joinToString(separator = "; "))) - } - }.joinToCode()) + addStringMembers("value", value) + addStringMember("date", date.toString()) + if (comments.isNotEmpty()) { + addStringMember("comments", comments.joinToString(separator = "; ")) + } } } diff --git a/kotlin-code-generation/src/test/kotlin/support/CodeBlockArrayTest.kt b/kotlin-code-generation/src/test/kotlin/support/CodeBlockArrayTest.kt index b043bb5..0e37e9f 100644 --- a/kotlin-code-generation/src/test/kotlin/support/CodeBlockArrayTest.kt +++ b/kotlin-code-generation/src/test/kotlin/support/CodeBlockArrayTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.support @@ -11,6 +10,7 @@ import io.toolisticon.kotlin.generation.support.CodeBlockArray.Companion.stringA import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class CodeBlockArrayTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/support/GeneratedAnnotationTest.kt b/kotlin-code-generation/src/test/kotlin/support/GeneratedAnnotationTest.kt index 35e0fe7..ae8bc9b 100644 --- a/kotlin-code-generation/src/test/kotlin/support/GeneratedAnnotationTest.kt +++ b/kotlin-code-generation/src/test/kotlin/support/GeneratedAnnotationTest.kt @@ -1,12 +1,14 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.support import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi +import io.toolisticon.kotlin.generation.KotlinCodeGeneration import io.toolisticon.kotlin.generation.TestFixtures +import io.toolisticon.kotlin.generation.spec.toFileSpec import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class GeneratedAnnotationTest { @Test @@ -17,4 +19,26 @@ internal class GeneratedAnnotationTest { assertThat(annotation.code).isEqualTo("""@jakarta.`annotation`.Generated(value = ["io.toolisticon.kotlin.generation.KotlinCodeGeneration"], date = "2024-07-02T10:01:33.205357100Z", comments = "version = 1.0")""") } + + @Test + fun `apply generated to class`() { + val file = KotlinCodeGeneration.buildDataClass("foo","Bar") { + addAnnotation(GeneratedAnnotation(date = TestFixtures.NOW)) + addConstructorProperty("x", String::class) + }.toFileSpec() + + assertThat(file.code).isEqualTo(""" + package foo + + import jakarta.`annotation`.Generated + import kotlin.String + + @Generated(value = ["io.toolisticon.kotlin.generation.KotlinCodeGeneration"], date = + "2024-07-02T10:01:33.205357100Z") + public data class Bar( + public val x: String, + ) + + """.trimIndent()) + } } From 1d66083545109eefa3a682eae1f0ea8c37c8d0d9 Mon Sep 17 00:00:00 2001 From: Jan Galinski Date: Tue, 10 Sep 2024 14:36:09 +0200 Subject: [PATCH 4/7] chore: move optin to class level --- .../src/main/kotlin/MyCustomAnnotationSpec.kt | 2 +- .../src/test/kotlin/HelloWorldExampleITest.kt | 2 +- .../src/test/kotlin/KotlinFileSpecITest.kt | 2 +- .../kotlin/MyCustomAnnotationSpecITest.kt | 2 +- _itest/spi-itest/src/test/kotlin/SpiITest.kt | 3 +- .../main/kotlin/KotlinCodeGenerationTest.kt | 3 +- .../test/kotlin/KotlinCodeGenerationTest.kt | 2 +- .../src/test/kotlin/TestFixtures.kt | 2 +- .../test/kotlin/_test/MutableSpiRegistry.kt | 2 +- .../src/test/kotlin/_test/TestContext.kt | 2 +- .../_test/TestDeclarationFileStrategy.kt | 2 +- .../src/test/kotlin/poet/KDocTest.kt | 2 +- .../test/kotlin/poet/TypeSpecBuilderTest.kt | 2 +- .../kotlin/spec/KotlinAnnotationClassTest.kt | 2 +- .../test/kotlin/spec/KotlinAnnotationTest.kt | 29 ++++++++++++++++--- .../kotlin/spec/KotlinAnonymousClassTest.kt | 2 +- .../kotlin/spec/KotlinCompanionObjectTest.kt | 2 +- .../spec/KotlinConstructorPropertyTest.kt | 2 +- .../test/kotlin/spec/KotlinDataClassTest.kt | 3 +- .../test/kotlin/spec/KotlinEnumClassTest.kt | 2 +- .../src/test/kotlin/spec/KotlinFileTest.kt | 2 +- .../src/test/kotlin/spec/KotlinFunTest.kt | 2 +- .../test/kotlin/spec/KotlinInterfaceTest.kt | 2 +- .../src/test/kotlin/spec/KotlinObjectTest.kt | 2 +- .../test/kotlin/spec/KotlinParameterTest.kt | 2 +- .../test/kotlin/spec/KotlinPropertyTest.kt | 2 +- .../test/kotlin/spec/KotlinTypeAliasTest.kt | 2 +- .../test/kotlin/spec/KotlinValueClassTest.kt | 3 +- ...tlinCodeGenerationServiceRepositoryTest.kt | 5 ++-- .../KotlinCodeGenerationStrategyListTest.kt | 2 +- .../spi/ServiceLoaderTestClassLoaderTest.kt | 2 +- .../KotlinAnnotationClassSpecProcessorTest.kt | 2 +- .../kotlin/support/SuppressAnnotationTest.kt | 2 +- 33 files changed, 58 insertions(+), 42 deletions(-) diff --git a/_itest/builder-itest/src/main/kotlin/MyCustomAnnotationSpec.kt b/_itest/builder-itest/src/main/kotlin/MyCustomAnnotationSpec.kt index 6bc1138..016a654 100644 --- a/_itest/builder-itest/src/main/kotlin/MyCustomAnnotationSpec.kt +++ b/_itest/builder-itest/src/main/kotlin/MyCustomAnnotationSpec.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.itest @@ -9,6 +8,7 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildFile import io.toolisticon.kotlin.generation.itest.KotlinCodeGenerationITestConfig.ROOT_PACKAGE +@OptIn(ExperimentalKotlinPoetApi::class) object MyCustomAnnotationSpec { val name = ClassName(ROOT_PACKAGE, "MyCustomAnnotation") diff --git a/_itest/builder-itest/src/test/kotlin/HelloWorldExampleITest.kt b/_itest/builder-itest/src/test/kotlin/HelloWorldExampleITest.kt index 17abacf..9f7511c 100644 --- a/_itest/builder-itest/src/test/kotlin/HelloWorldExampleITest.kt +++ b/_itest/builder-itest/src/test/kotlin/HelloWorldExampleITest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) package io.toolisticon.kotlin.generation.itest @@ -14,6 +13,7 @@ import org.assertj.core.api.Assertions.assertThat import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) internal class HelloWorldExampleITest { @Test diff --git a/_itest/builder-itest/src/test/kotlin/KotlinFileSpecITest.kt b/_itest/builder-itest/src/test/kotlin/KotlinFileSpecITest.kt index 6348c15..c6cea9b 100644 --- a/_itest/builder-itest/src/test/kotlin/KotlinFileSpecITest.kt +++ b/_itest/builder-itest/src/test/kotlin/KotlinFileSpecITest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) package io.toolisticon.kotlin.generation.itest import com.squareup.kotlinpoet.ClassName @@ -8,6 +7,7 @@ import io.toolisticon.kotlin.generation.builder.KotlinFileSpecBuilder import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) internal class KotlinFileSpecITest { @Target(AnnotationTarget.FILE) diff --git a/_itest/builder-itest/src/test/kotlin/MyCustomAnnotationSpecITest.kt b/_itest/builder-itest/src/test/kotlin/MyCustomAnnotationSpecITest.kt index 8da29c9..2364625 100644 --- a/_itest/builder-itest/src/test/kotlin/MyCustomAnnotationSpecITest.kt +++ b/_itest/builder-itest/src/test/kotlin/MyCustomAnnotationSpecITest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) package io.toolisticon.kotlin.generation.itest @@ -17,6 +16,7 @@ import org.junit.jupiter.api.Test import kotlin.reflect.KClass import io.toolisticon.kotlin.generation.test.KotlinCodeGenerationTest.assertThat as assertThatCompilation +@OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) internal class MyCustomAnnotationSpecITest { @Test diff --git a/_itest/spi-itest/src/test/kotlin/SpiITest.kt b/_itest/spi-itest/src/test/kotlin/SpiITest.kt index 9ff6868..c371675 100644 --- a/_itest/spi-itest/src/test/kotlin/SpiITest.kt +++ b/_itest/spi-itest/src/test/kotlin/SpiITest.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) - package io.toolisticon.kotlin.generation.itest.spi import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi @@ -15,6 +13,7 @@ import org.assertj.core.api.Assertions.assertThatThrownBy import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) internal class SpiITest { @Test diff --git a/kotlin-code-generation-test/src/main/kotlin/KotlinCodeGenerationTest.kt b/kotlin-code-generation-test/src/main/kotlin/KotlinCodeGenerationTest.kt index 2417b79..63f4c60 100644 --- a/kotlin-code-generation-test/src/main/kotlin/KotlinCodeGenerationTest.kt +++ b/kotlin-code-generation-test/src/main/kotlin/KotlinCodeGenerationTest.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) - package io.toolisticon.kotlin.generation.test import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi @@ -34,6 +32,7 @@ import java.io.ByteArrayOutputStream * ``` */ @ExperimentalCompilerApi +@ExperimentalKotlinPoetApi object KotlinCodeGenerationTest { fun assertThat(actual: KotlinCompilationResult): KotlinCompilationAssert = KotlinCompilationAssert(actual) diff --git a/kotlin-code-generation/src/test/kotlin/KotlinCodeGenerationTest.kt b/kotlin-code-generation/src/test/kotlin/KotlinCodeGenerationTest.kt index 0708f3f..1f3f2ae 100644 --- a/kotlin-code-generation/src/test/kotlin/KotlinCodeGenerationTest.kt +++ b/kotlin-code-generation/src/test/kotlin/KotlinCodeGenerationTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation @@ -18,6 +17,7 @@ import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.jupiter.api.Nested import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinCodeGenerationTest { @Nested diff --git a/kotlin-code-generation/src/test/kotlin/TestFixtures.kt b/kotlin-code-generation/src/test/kotlin/TestFixtures.kt index 3a3358a..e78c2b4 100644 --- a/kotlin-code-generation/src/test/kotlin/TestFixtures.kt +++ b/kotlin-code-generation/src/test/kotlin/TestFixtures.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation @@ -21,6 +20,7 @@ import java.time.Instant import java.util.* import kotlin.reflect.KClass +@OptIn(ExperimentalKotlinPoetApi::class) object TestFixtures { // a fixed instant to be used in test with diff --git a/kotlin-code-generation/src/test/kotlin/_test/MutableSpiRegistry.kt b/kotlin-code-generation/src/test/kotlin/_test/MutableSpiRegistry.kt index d9ff9ca..8b6a79e 100644 --- a/kotlin-code-generation/src/test/kotlin/_test/MutableSpiRegistry.kt +++ b/kotlin-code-generation/src/test/kotlin/_test/MutableSpiRegistry.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation._test @@ -10,6 +9,7 @@ import io.toolisticon.kotlin.generation.spi.processor.KotlinCodeGenerationProces import io.toolisticon.kotlin.generation.spi.strategy.KotlinCodeGenerationStrategyList import kotlin.reflect.KClass +@OptIn(ExperimentalKotlinPoetApi::class) class MutableSpiRegistry( val strategyList: MutableList = mutableListOf(), val processorList: MutableList = mutableListOf(), diff --git a/kotlin-code-generation/src/test/kotlin/_test/TestContext.kt b/kotlin-code-generation/src/test/kotlin/_test/TestContext.kt index 39c76e3..4011999 100644 --- a/kotlin-code-generation/src/test/kotlin/_test/TestContext.kt +++ b/kotlin-code-generation/src/test/kotlin/_test/TestContext.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation._test @@ -6,6 +5,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationContext +@OptIn(ExperimentalKotlinPoetApi::class) class TestContext( val rootClassName: ClassName, override val registry: MutableSpiRegistry diff --git a/kotlin-code-generation/src/test/kotlin/_test/TestDeclarationFileStrategy.kt b/kotlin-code-generation/src/test/kotlin/_test/TestDeclarationFileStrategy.kt index afd8147..69499f3 100644 --- a/kotlin-code-generation/src/test/kotlin/_test/TestDeclarationFileStrategy.kt +++ b/kotlin-code-generation/src/test/kotlin/_test/TestDeclarationFileStrategy.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation._test @@ -8,6 +7,7 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildFile import io.toolisticon.kotlin.generation.spec.KotlinFileSpec import io.toolisticon.kotlin.generation.spi.strategy.KotlinFileSpecStrategy +@OptIn(ExperimentalKotlinPoetApi::class) class TestDeclarationFileStrategy : KotlinFileSpecStrategy( contextType = TestContext::class, TestDeclaration::class ) { diff --git a/kotlin-code-generation/src/test/kotlin/poet/KDocTest.kt b/kotlin-code-generation/src/test/kotlin/poet/KDocTest.kt index 0ef7657..229a6e7 100644 --- a/kotlin-code-generation/src/test/kotlin/poet/KDocTest.kt +++ b/kotlin-code-generation/src/test/kotlin/poet/KDocTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.poet @@ -7,6 +6,7 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class KDocTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/poet/TypeSpecBuilderTest.kt b/kotlin-code-generation/src/test/kotlin/poet/TypeSpecBuilderTest.kt index 4641670..07d7e7c 100644 --- a/kotlin-code-generation/src/test/kotlin/poet/TypeSpecBuilderTest.kt +++ b/kotlin-code-generation/src/test/kotlin/poet/TypeSpecBuilderTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.poet @@ -10,6 +9,7 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class TypeSpecBuilderTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationClassTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationClassTest.kt index c3f8896..f003408 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationClassTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationClassTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -8,6 +7,7 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildAnnotationClas import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinAnnotationClassTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationTest.kt index 7c8b882..954585f 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationTest.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) - package io.toolisticon.kotlin.generation.spec import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi @@ -11,6 +9,7 @@ import org.junit.jupiter.api.Test import kotlin.reflect.KClass +@OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinAnnotationTest { annotation class Foo( @@ -29,13 +28,13 @@ internal class KotlinAnnotationTest { assertThat(annotation.code).isEqualTo("""@io.toolisticon.kotlin.generation.TestFixtures.MyAnnotation(name = "foo", type = kotlin.String::class)"""); } - @Test - fun `create Foo annotation`() { + fun `create Foo annotation - multiline`() { val spec = KotlinAnnotationSpecBuilder.builder(Foo::class) .addMember("bar = %S", "hello world") .addStringMember("x", "foo") .addKClassMember("type", Long::class) + .multiLine() .build() assertThat(spec.code).isEqualTo("""@io.toolisticon.kotlin.generation.spec.KotlinAnnotationTest.Foo(bar = "hello world", x = "foo", type = kotlin.Long::class)""") @@ -52,6 +51,28 @@ internal class KotlinAnnotationTest { ) } + @Test + fun `create Foo annotation - singleline`() { + val spec = KotlinAnnotationSpecBuilder.builder(Foo::class) + .addMember("bar = %S", "hello world") + .addStringMember("x", "foo") + .addKClassMember("type", Long::class) + .build() + + assertThat(spec.code).isEqualTo("""@io.toolisticon.kotlin.generation.spec.KotlinAnnotationTest.Foo(bar = "hello world", x = "foo", type = kotlin.Long::class)""") + assertThat(spec.members).hasSize(1) + + assertThat(spec).hasToString( + "KotlinAnnotationSpec(" + + "typeName=io.toolisticon.kotlin.generation.spec.KotlinAnnotationTest.Foo, " + + "members=[" + + "bar = \"hello world\", " + + "x = \"foo\", " + + "type = kotlin.Long::class]" + + ")" + ) + } + @Test fun `use toBuilder to add members`() { var spec = KotlinAnnotationSpecBuilder.builder(Foo::class) diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinAnonymousClassTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinAnonymousClassTest.kt index 046b7a2..ae0649d 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinAnonymousClassTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinAnonymousClassTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -8,6 +7,7 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildFun import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinAnonymousClassTest { @Test fun build() { diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinCompanionObjectTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinCompanionObjectTest.kt index 89a3b40..cdb5ef1 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinCompanionObjectTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinCompanionObjectTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -10,6 +9,7 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_STRIN import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinCompanionObjectTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinConstructorPropertyTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinConstructorPropertyTest.kt index f0a1441..f86f111 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinConstructorPropertyTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinConstructorPropertyTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -8,6 +7,7 @@ import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.Assumptions.assumeTrue import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) @Deprecated("not implemented yet") internal class KotlinConstructorPropertyTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinDataClassTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinDataClassTest.kt index e744c4f..8c3d686 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinDataClassTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinDataClassTest.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) - package io.toolisticon.kotlin.generation.spec import com.squareup.kotlinpoet.ClassName @@ -11,6 +9,7 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinDataClassTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinEnumClassTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinEnumClassTest.kt index de6b36b..556314e 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinEnumClassTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinEnumClassTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -7,6 +6,7 @@ import io.toolisticon.kotlin.generation.TestFixtures.notDeprecated import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) @Deprecated("not implemented yet") internal class KotlinEnumClassTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinFileTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinFileTest.kt index 63dc18f..1a50c31 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinFileTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinFileTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -7,6 +6,7 @@ import io.toolisticon.kotlin.generation.TestFixtures.notDeprecated import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) @Deprecated("not implemented yet") internal class KotlinFileTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinFunTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinFunTest.kt index 7b90a3c..d0d8db6 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinFunTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinFunTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -7,6 +6,7 @@ import io.toolisticon.kotlin.generation.TestFixtures.notDeprecated import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) @Deprecated("not implemented yet") internal class KotlinFunTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinInterfaceTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinInterfaceTest.kt index 546c57c..3f474ed 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinInterfaceTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinInterfaceTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -7,6 +6,7 @@ import io.toolisticon.kotlin.generation.TestFixtures.notDeprecated import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) @Deprecated("not implemented yet") internal class KotlinInterfaceTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinObjectTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinObjectTest.kt index 0487b81..0862dd8 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinObjectTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinObjectTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -7,6 +6,7 @@ import io.toolisticon.kotlin.generation.TestFixtures.notDeprecated import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) @Deprecated("not implemented yet") internal class KotlinObjectTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinParameterTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinParameterTest.kt index f694b45..672bfa5 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinParameterTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinParameterTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -7,6 +6,7 @@ import io.toolisticon.kotlin.generation.TestFixtures.notDeprecated import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) @Deprecated("not implemented yet") internal class KotlinParameterTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinPropertyTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinPropertyTest.kt index 9ca283b..f93c58f 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinPropertyTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinPropertyTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -7,6 +6,7 @@ import io.toolisticon.kotlin.generation.TestFixtures.notDeprecated import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) @Deprecated("not implemented yet") internal class KotlinPropertyTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinTypeAliasTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinTypeAliasTest.kt index c23b0f2..b428222 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinTypeAliasTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinTypeAliasTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spec @@ -7,6 +6,7 @@ import io.toolisticon.kotlin.generation.TestFixtures.notDeprecated import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) @Deprecated("not implemented yet") internal class KotlinTypeAliasTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinValueClassTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinValueClassTest.kt index e77ff0a..65e1f9a 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinValueClassTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinValueClassTest.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) - package io.toolisticon.kotlin.generation.spec import com.squareup.kotlinpoet.ClassName @@ -9,6 +7,7 @@ import io.toolisticon.kotlin.generation.TestFixtures import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinValueClassTest { @Test diff --git a/kotlin-code-generation/src/test/kotlin/spi/KotlinCodeGenerationServiceRepositoryTest.kt b/kotlin-code-generation/src/test/kotlin/spi/KotlinCodeGenerationServiceRepositoryTest.kt index 56fc63b..c72b324 100644 --- a/kotlin-code-generation/src/test/kotlin/spi/KotlinCodeGenerationServiceRepositoryTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spi/KotlinCodeGenerationServiceRepositoryTest.kt @@ -1,5 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) - package io.toolisticon.kotlin.generation.spi import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi @@ -7,12 +5,13 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration import io.toolisticon.kotlin.generation.spec.KotlinDataClassSpec import io.toolisticon.kotlin.generation.spi.context.KotlinCodeGenerationContextBase import io.toolisticon.kotlin.generation.spi.registry.KotlinCodeGenerationServiceRepository -import io.toolisticon.kotlin.generation.spi.strategy.KotlinDataClassSpecStrategy import io.toolisticon.kotlin.generation.spi.strategy.KotlinCodeGenerationStrategyList +import io.toolisticon.kotlin.generation.spi.strategy.KotlinDataClassSpecStrategy import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import kotlin.reflect.KClass +@OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinCodeGenerationServiceRepositoryTest { class TestContext(registry: KotlinCodeGenerationSpiRegistry) : KotlinCodeGenerationContextBase(registry) { diff --git a/kotlin-code-generation/src/test/kotlin/spi/KotlinCodeGenerationStrategyListTest.kt b/kotlin-code-generation/src/test/kotlin/spi/KotlinCodeGenerationStrategyListTest.kt index 28f6ae4..58bcdde 100644 --- a/kotlin-code-generation/src/test/kotlin/spi/KotlinCodeGenerationStrategyListTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spi/KotlinCodeGenerationStrategyListTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spi @@ -18,6 +17,7 @@ import io.toolisticon.kotlin.generation.spi.strategy.executeSingle import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) class KotlinCodeGenerationStrategyListTest { class AStrategy : DataClassAStrategy() { diff --git a/kotlin-code-generation/src/test/kotlin/spi/ServiceLoaderTestClassLoaderTest.kt b/kotlin-code-generation/src/test/kotlin/spi/ServiceLoaderTestClassLoaderTest.kt index f5d5e65..64d3e82 100644 --- a/kotlin-code-generation/src/test/kotlin/spi/ServiceLoaderTestClassLoaderTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spi/ServiceLoaderTestClassLoaderTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spi @@ -8,6 +7,7 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import java.util.ServiceLoader +@OptIn(ExperimentalKotlinPoetApi::class) class ServiceLoaderTestClassLoaderTest { interface MyInterface { diff --git a/kotlin-code-generation/src/test/kotlin/spi/processor/KotlinAnnotationClassSpecProcessorTest.kt b/kotlin-code-generation/src/test/kotlin/spi/processor/KotlinAnnotationClassSpecProcessorTest.kt index 6b9081b..61e1f75 100644 --- a/kotlin-code-generation/src/test/kotlin/spi/processor/KotlinAnnotationClassSpecProcessorTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spi/processor/KotlinAnnotationClassSpecProcessorTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.spi.processor @@ -12,6 +11,7 @@ import io.toolisticon.kotlin.generation.spec.toFileSpec import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinAnnotationClassSpecProcessorTest { class AddRetentionProcessor : KotlinAnnotationClassSpecProcessor( diff --git a/kotlin-code-generation/src/test/kotlin/support/SuppressAnnotationTest.kt b/kotlin-code-generation/src/test/kotlin/support/SuppressAnnotationTest.kt index 867f182..d53fc54 100644 --- a/kotlin-code-generation/src/test/kotlin/support/SuppressAnnotationTest.kt +++ b/kotlin-code-generation/src/test/kotlin/support/SuppressAnnotationTest.kt @@ -1,4 +1,3 @@ -@file:OptIn(ExperimentalKotlinPoetApi::class) package io.toolisticon.kotlin.generation.support @@ -9,6 +8,7 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.fileBuilder import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +@OptIn(ExperimentalKotlinPoetApi::class) internal class SuppressAnnotationTest { private val className = ClassName("foo", "Bar") private val typeBuilder = classBuilder(className) From 6d71610c31610c9332176c01b5bde4040490fcb4 Mon Sep 17 00:00:00 2001 From: Jan Galinski Date: Tue, 10 Sep 2024 23:48:38 +0200 Subject: [PATCH 5/7] introduce builder for exception type (#52) * wip * implment tagging builders * read tag from spec * implement extra/RuntimeExceptionSpecBuilder, fixes #46 --- .../src/main/kotlin/KotlinCodeGeneration.kt | 20 ++- .../KotlinAnnotationClassSpecBuilder.kt | 16 +-- .../builder/KotlinAnnotationSpecBuilder.kt | 3 + .../KotlinAnonymousClassSpecBuilder.kt | 15 ++- .../kotlin/builder/KotlinClassSpecBuilder.kt | 23 ++-- .../KotlinCompanionObjectSpecBuilder.kt | 15 ++- .../KotlinConstructorPropertySpecBuilder.kt | 15 +-- .../builder/KotlinDataClassSpecBuilder.kt | 17 ++- .../builder/KotlinEnumClassSpecBuilder.kt | 19 ++- .../kotlin/builder/KotlinFileSpecBuilder.kt | 7 +- .../kotlin/builder/KotlinFunSpecBuilder.kt | 9 +- .../builder/KotlinInterfaceSpecBuilder.kt | 15 ++- .../kotlin/builder/KotlinObjectSpecBuilder.kt | 15 ++- .../builder/KotlinParameterSpecBuilder.kt | 9 +- .../builder/KotlinPropertySpecBuilder.kt | 7 +- .../builder/KotlinTypeAliasSpecBuilder.kt | 10 +- .../builder/KotlinValueClassSpecBuilder.kt | 22 ++-- .../src/main/kotlin/builder/_types.kt | 49 ++++++-- .../extra/RuntimeExceptionSpecBuilder.kt | 114 ++++++++++++++++++ .../main/kotlin/poet/AnnotationSpecBuilder.kt | 4 +- .../src/main/kotlin/poet/FileSpecBuilder.kt | 3 + .../src/main/kotlin/poet/FunSpecBuilder.kt | 3 + .../main/kotlin/poet/ParameterSpecBuilder.kt | 3 + .../main/kotlin/poet/PropertySpecBuilder.kt | 2 + .../main/kotlin/poet/TypeAliasSpecBuilder.kt | 3 + .../src/main/kotlin/poet/TypeSpecBuilder.kt | 5 +- .../src/main/kotlin/poet/_types.kt | 4 + .../kotlin/spec/KotlinAnnotationClassSpec.kt | 4 +- .../main/kotlin/spec/KotlinAnnotationSpec.kt | 1 - .../kotlin/spec/KotlinAnonymousClassSpec.kt | 3 + .../src/main/kotlin/spec/KotlinClassSpec.kt | 8 +- .../kotlin/spec/KotlinCompanionObjectSpec.kt | 2 + .../spec/KotlinConstructorPropertySpec.kt | 2 + .../main/kotlin/spec/KotlinDataClassSpec.kt | 2 + .../main/kotlin/spec/KotlinEnumClassSpec.kt | 2 + .../src/main/kotlin/spec/KotlinFileSpec.kt | 4 +- .../src/main/kotlin/spec/KotlinFunSpec.kt | 2 + .../main/kotlin/spec/KotlinInterfaceSpec.kt | 3 + .../src/main/kotlin/spec/KotlinObjectSpec.kt | 3 + .../main/kotlin/spec/KotlinParameterSpec.kt | 2 + .../main/kotlin/spec/KotlinPropertySpec.kt | 2 + .../main/kotlin/spec/KotlinTypeAliasSpec.kt | 2 + .../main/kotlin/spec/KotlinValueClassSpec.kt | 2 + .../src/main/kotlin/spec/_types.kt | 33 ++++- .../src/main/kotlin/support/CodeBlockArray.kt | 2 +- .../test/kotlin/poet/TypeSpecBuilderTest.kt | 3 +- .../test/kotlin/spec/KotlinAnnotationTest.kt | 4 +- .../kotlin/spec/KotlinClassExceptionTest.kt | 32 ----- .../spec/KotlinConstructorPropertyTest.kt | 1 - .../kotlin/spec/KotlinExceptionClassTest.kt | 42 +++++++ 50 files changed, 409 insertions(+), 179 deletions(-) create mode 100644 kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt delete mode 100644 kotlin-code-generation/src/test/kotlin/spec/KotlinClassExceptionTest.kt create mode 100644 kotlin-code-generation/src/test/kotlin/spec/KotlinExceptionClassTest.kt diff --git a/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt b/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt index 0628943..59cb7ac 100644 --- a/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt +++ b/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt @@ -16,9 +16,12 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.interfaceBu import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.objectBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.parameterBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.propertyBuilder +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.runtimeExceptionClassBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.typeAliasBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.valueClassBuilder import io.toolisticon.kotlin.generation.builder.* +import io.toolisticon.kotlin.generation.builder.extra.RuntimeExceptionSpecBuilder +import io.toolisticon.kotlin.generation.builder.extra.RuntimeExceptionSpecBuilderReceiver import io.toolisticon.kotlin.generation.poet.FormatSpecifier.asCodeBlock import io.toolisticon.kotlin.generation.spec.* import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationContext @@ -80,6 +83,16 @@ object KotlinCodeGeneration : KLogging() { */ inline fun buildClass(packageName: PackageName, simpleName: SimpleName, block: KotlinClassSpecBuilderReceiver = {}) = buildClass(className(packageName, simpleName), block) + /** + * @see RuntimeExceptionSpecBuilder + */ + inline fun buildRuntimeExceptionClass(packageName: PackageName, simpleName: SimpleName, block: RuntimeExceptionSpecBuilderReceiver = {}) = buildRuntimeExceptionClass(className(packageName, simpleName), block) + + /** + * @see RuntimeExceptionSpecBuilder + */ + inline fun buildRuntimeExceptionClass(className: ClassName, block: RuntimeExceptionSpecBuilderReceiver = {}) = runtimeExceptionClassBuilder(className).also(block).build() + /** * @see [CodeBlock.of] */ @@ -137,7 +150,7 @@ object KotlinCodeGeneration : KLogging() { * Build [KotlinFileSpec]. * @see [KotlinFileSpecBuilder.builder] */ - inline fun buildFile(className: ClassName, block: KotlinFileSpecBuilderReceiver = {}): KotlinFileSpec = fileBuilder(className).also(block).build() + inline fun buildFile(className: ClassName, block: KotlinFileSpecBuilderReceiver = {}) = fileBuilder(className).also(block).build() /** * Build [KotlinFileSpec]. @@ -305,6 +318,11 @@ object KotlinCodeGeneration : KLogging() { */ fun enumClassBuilder(className: ClassName) = KotlinEnumClassSpecBuilder.builder(className) + /** + * @see KotlinExceptionClassSpecBuilder + */ + fun runtimeExceptionClassBuilder(className: ClassName) = RuntimeExceptionSpecBuilder.builder(className) + /** * @see KotlinFileSpecBuilder */ diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt index 9f5e1f9..6df0adf 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt @@ -10,6 +10,7 @@ import io.toolisticon.kotlin.generation.builder.KotlinConstructorPropertySpecBui import io.toolisticon.kotlin.generation.poet.* import io.toolisticon.kotlin.generation.spec.* import javax.lang.model.element.Element +import kotlin.reflect.KClass /** * Builder for [KotlinAnnotationClassSpec]. @@ -19,12 +20,10 @@ class KotlinAnnotationClassSpecBuilder internal constructor( val className: ClassName, private val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, - KotlinAnnotatableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinConstructorPropertySupport, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, KotlinMemberSpecHolderBuilder, - KotlinModifiableBuilder, KotlinTypeSpecHolderBuilder { companion object { @@ -51,14 +50,15 @@ class KotlinAnnotationClassSpecBuilder internal constructor( this._retention = retention } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinAnnotationClassSpecBuilder = apply { delegate.addAnnotation(spec.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { constructorProperties[spec.name] = spec } - override fun contextReceivers(vararg receiverTypes: TypeName): KotlinAnnotationClassSpecBuilder = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinAnnotationClassSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinAnnotationClassSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinAnnotationClassSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt index 6b00ef6..6468976 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt @@ -30,6 +30,7 @@ import kotlin.reflect.KClass class KotlinAnnotationSpecBuilder internal constructor( private val delegate: AnnotationSpecBuilder ) : BuilderSupplier, + KotlinTaggableBuilder, KotlinAnnotationSpecSupplier, DelegatingBuilder { @@ -68,6 +69,8 @@ class KotlinAnnotationSpecBuilder internal constructor( private var multiLine = false private val members: MutableList = mutableListOf() + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + fun multiLine() = apply { multiLine = true } fun addMember(codeBlock: CodeBlock): KotlinAnnotationSpecBuilder = apply { members.add(codeBlock) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt index 77caa39..88fb3e3 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt @@ -19,11 +19,9 @@ import kotlin.reflect.KClass class KotlinAnonymousClassSpecBuilder internal constructor( private val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, - KotlinAnnotatableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, KotlinMemberSpecHolderBuilder, - KotlinModifiableBuilder, KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder, DelegatingBuilder { @@ -34,13 +32,14 @@ class KotlinAnonymousClassSpecBuilder internal constructor( internal constructor() : this(delegate = TypeSpecBuilder.anonymousClassBuilder()) - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinAnonymousClassSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName): KotlinAnonymousClassSpecBuilder = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinAnonymousClassSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinAnonymousClassSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinAnonymousClassSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinClassSpecBuilder.kt index c1778e0..5c5bd77 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinClassSpecBuilder.kt @@ -16,15 +16,13 @@ import kotlin.reflect.KClass */ @ExperimentalKotlinPoetApi class KotlinClassSpecBuilder internal constructor( - private val className: ClassName, + internal val className: ClassName, private val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, - KotlinAnnotatableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinConstructorPropertySupport, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, KotlinMemberSpecHolderBuilder, - KotlinModifiableBuilder, KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder { @@ -38,17 +36,20 @@ class KotlinClassSpecBuilder internal constructor( private val constructorProperties: LinkedHashMap = LinkedHashMap() private var isSetPrimaryConstructor: Boolean = false - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinClassSpecBuilder = apply { delegate.addAnnotation(spec.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { constructorProperties[spec.name] = spec } - override fun contextReceivers(vararg receiverTypes: TypeName): KotlinClassSpecBuilder = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinClassSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinClassSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinClassSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } + override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } + override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } + fun primaryConstructor(primaryConstructor: FunSpecSupplier?) = apply { if (primaryConstructor != null) { delegate.primaryConstructor(primaryConstructor.get()) @@ -62,8 +63,6 @@ class KotlinClassSpecBuilder internal constructor( fun addSuperclassConstructorParameter(format: String, vararg args: Any) = builder { this.addSuperclassConstructorParameter(format, *args) } fun addSuperclassConstructorParameter(codeBlock: CodeBlock) = builder { this.addSuperclassConstructorParameter(codeBlock) } - override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } - override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt index 59afdee..50fbd0a 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt @@ -21,11 +21,9 @@ import kotlin.reflect.KClass class KotlinCompanionObjectSpecBuilder internal constructor( private val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, - KotlinAnnotatableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, KotlinMemberSpecHolderBuilder, - KotlinModifiableBuilder, KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder { @@ -35,13 +33,14 @@ class KotlinCompanionObjectSpecBuilder internal constructor( internal constructor(name: String? = null) : this(TypeSpecBuilder.Companion.companionObjectBuilder(name)) - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinCompanionObjectSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName): KotlinCompanionObjectSpecBuilder = builder { delegate.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinCompanionObjectSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinCompanionObjectSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { delegate.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { delegate.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinCompanionObjectSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addType(typeSpec: TypeSpecSupplier) = builder { delegate.addType(typeSpec.get()) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { delegate.addOriginatingElement( diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinConstructorPropertySpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinConstructorPropertySpecBuilder.kt index 7a0789c..b2045ee 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinConstructorPropertySpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinConstructorPropertySpecBuilder.kt @@ -10,6 +10,7 @@ import io.toolisticon.kotlin.generation.poet.TypeSpecBuilder import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpecSupplier import io.toolisticon.kotlin.generation.spec.KotlinConstructorPropertySpec import io.toolisticon.kotlin.generation.spec.KotlinConstructorPropertySpecSupplier +import kotlin.reflect.KClass /** * Builder for [KotlinConstructorPropertySpec]. @@ -21,10 +22,8 @@ class KotlinConstructorPropertySpecBuilder internal constructor( private val propertyBuilder: KotlinPropertySpecBuilder, private val parameterBuilder: KotlinParameterSpecBuilder ) : Builder, - KotlinAnnotatableBuilder, - KotlinConstructorPropertySpecSupplier, - KotlinDocumentableBuilder, - KotlinModifiableBuilder { + KotlinAnnotatableDocumentableModifiableBuilder, + KotlinConstructorPropertySpecSupplier { companion object { fun builder(name: String, type: TypeName): KotlinConstructorPropertySpecBuilder = KotlinConstructorPropertySpecBuilder( @@ -45,9 +44,10 @@ class KotlinConstructorPropertySpecBuilder internal constructor( } } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinConstructorPropertySpecBuilder = apply { parameterBuilder.addAnnotation(spec) } - override fun addKdoc(kdoc: KDoc): KotlinConstructorPropertySpecBuilder = apply { parameterBuilder.addKdoc(kdoc) } - override fun addModifiers(vararg modifiers: KModifier): KotlinConstructorPropertySpecBuilder = apply{ propertyBuilder.addModifiers(*modifiers) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { parameterBuilder.addAnnotation(spec) } + override fun addKdoc(kdoc: KDoc) = apply { parameterBuilder.addKdoc(kdoc) } + override fun addModifiers(vararg modifiers: KModifier) = apply { propertyBuilder.addModifiers(*modifiers) } + override fun tag(type: KClass<*>, tag: Any?) = apply { propertyBuilder.tag(type, tag) } override fun build(): KotlinConstructorPropertySpec { val parameter = parameterBuilder.build() @@ -59,6 +59,7 @@ class KotlinConstructorPropertySpecBuilder internal constructor( return KotlinConstructorPropertySpec(parameter = parameter, property = property) } + override fun spec(): KotlinConstructorPropertySpec = build() } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt index e88243c..09db23e 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt @@ -10,6 +10,7 @@ import io.toolisticon.kotlin.generation.spec.* import io.toolisticon.kotlin.generation.support.SUPPRESS_UNUSED import mu.KLogging import javax.lang.model.element.Element +import kotlin.reflect.KClass /** * Builder for [KotlinDataClassSpec]. @@ -19,12 +20,10 @@ class KotlinDataClassSpecBuilder internal constructor( private val className: ClassName, private val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinConstructorPropertySupport, - KotlinAnnotatableBuilder, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, KotlinMemberSpecHolderBuilder, - KotlinModifiableBuilder, KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder { companion object : KLogging() { @@ -43,15 +42,15 @@ class KotlinDataClassSpecBuilder internal constructor( private val constructorProperties = LinkedHashMap() - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinDataClassSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier): KotlinDataClassSpecBuilder = apply { this.constructorProperties[spec.name] = spec } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { this.constructorProperties[spec.name] = spec } override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinDataClassSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinDataClassSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinDataClassSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt index f3cb347..8193eaa 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt @@ -21,11 +21,9 @@ class KotlinEnumClassSpecBuilder internal constructor( private val className: ClassName, private val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, - KotlinAnnotatableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, KotlinMemberSpecHolderBuilder, - KotlinModifiableBuilder, KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder { @@ -38,13 +36,14 @@ class KotlinEnumClassSpecBuilder internal constructor( delegate.addModifiers(KModifier.ENUM) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinEnumClassSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName): KotlinEnumClassSpecBuilder = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinEnumClassSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinEnumClassSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier): KotlinEnumClassSpecBuilder = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinEnumClassSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } - override fun addType(typeSpec: TypeSpecSupplier): KotlinEnumClassSpecBuilder = builder { this.addType(typeSpec.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } + override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addEnumConstant(name: String): KotlinEnumClassSpecBuilder = apply { delegate.addEnumConstant(name) } fun addEnumConstant(name: String, typeSpec: TypeSpec = TypeSpec.anonymousClassBuilder().build()): KotlinEnumClassSpecBuilder = builder { this.addEnumConstant(name, typeSpec) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinFileSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinFileSpecBuilder.kt index a8d3c85..dcce5df 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinFileSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinFileSpecBuilder.kt @@ -43,10 +43,11 @@ class KotlinFileSpecBuilder internal constructor( fun builder(spec: FileSpec) = KotlinFileSpecBuilder(delegate = spec.toBuilder().wrap()) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinFileSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinFileSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinFileSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addAliasedImport(kclass: KClass<*>, alias: String) = builder { this.addAliasedImport(kclass, alias) } fun addAliasedImport(className: ClassName, alias: String) = builder { this.addAliasedImport(className, alias) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt index a36e618..b8ab8eb 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt @@ -22,10 +22,8 @@ class KotlinFunSpecBuilder internal constructor( private val delegate: FunSpecBuilder ) : BuilderSupplier, DelegatingBuilder, - KotlinAnnotatableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, - KotlinModifiableBuilder, KotlinFunSpecSupplier { companion object { @@ -56,10 +54,11 @@ class KotlinFunSpecBuilder internal constructor( fun addParameter(parameter: KotlinParameterSpecSupplier) = builder { this.addParameter(parameter.get()) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinFunSpecBuilder = apply { delegate.addAnnotation(spec.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addKdoc(kdoc: KDoc): KotlinFunSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun jvmModifiers(modifiers: Iterable) = builder { this.jvmModifiers(modifiers) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt index 2f353ae..47c8236 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt @@ -21,11 +21,9 @@ class KotlinInterfaceSpecBuilder internal constructor( private val className: ClassName, private val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, - KotlinAnnotatableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, KotlinMemberSpecHolderBuilder, - KotlinModifiableBuilder, KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder { companion object { @@ -39,13 +37,14 @@ class KotlinInterfaceSpecBuilder internal constructor( delegate = if (funInterface) TypeSpecBuilder.funInterfaceBuilder(className) else TypeSpecBuilder.interfaceBuilder(className) ) - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinInterfaceSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName): KotlinInterfaceSpecBuilder = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinInterfaceSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinInterfaceSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinInterfaceSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt index f0ddd64..f8d6d74 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt @@ -21,11 +21,9 @@ class KotlinObjectSpecBuilder internal constructor( private val className: ClassName, private val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, - KotlinAnnotatableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, KotlinMemberSpecHolderBuilder, - KotlinModifiableBuilder, KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder { companion object { @@ -35,13 +33,14 @@ class KotlinObjectSpecBuilder internal constructor( internal constructor(className: ClassName) : this(className, TypeSpecBuilder.objectBuilder(className)) - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinObjectSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName): KotlinObjectSpecBuilder = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinObjectSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinObjectSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinObjectSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt index 220af54..52e0513 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt @@ -20,9 +20,7 @@ class KotlinParameterSpecBuilder internal constructor( private val delegate: ParameterSpecBuilder ) : BuilderSupplier, DelegatingBuilder, - KotlinAnnotatableBuilder, - KotlinDocumentableBuilder, - KotlinModifiableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinParameterSpecSupplier { companion object { @@ -54,9 +52,10 @@ class KotlinParameterSpecBuilder internal constructor( fun builder(spec: ParameterSpec) = KotlinParameterSpecBuilder(delegate = spec.toBuilder().wrap()) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinParameterSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinParameterSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun defaultValue(format: String, vararg args: Any?) = builder { this.defaultValue(format, *args) } fun defaultValue(codeBlock: CodeBlock?) = builder { this.defaultValue(codeBlock) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt index 084cc32..2688086 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt @@ -20,10 +20,8 @@ class KotlinPropertySpecBuilder internal constructor( private val delegate: PropertySpecBuilder ) : BuilderSupplier, DelegatingBuilder, - KotlinAnnotatableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, - KotlinModifiableBuilder, KotlinPropertySpecSupplier { companion object { @@ -53,10 +51,11 @@ class KotlinPropertySpecBuilder internal constructor( fun builder(spec: PropertySpec) = KotlinPropertySpecBuilder(delegate = spec.toBuilder().wrap()) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinPropertySpecBuilder = apply { delegate.addAnnotation(spec.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } override fun addKdoc(kdoc: KDoc): KotlinPropertySpecBuilder = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt index bd79119..db32893 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt @@ -18,9 +18,7 @@ class KotlinTypeAliasSpecBuilder internal constructor( private val delegate: TypeAliasSpecBuilder ) : BuilderSupplier, DelegatingBuilder, - KotlinAnnotatableBuilder, - KotlinDocumentableBuilder, - KotlinModifiableBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinTypeAliasSpecSupplier { companion object { @@ -30,12 +28,12 @@ class KotlinTypeAliasSpecBuilder internal constructor( internal constructor(name: String, type: TypeName) : this(delegate = TypeAliasSpecBuilder.builder(name, type)) - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinTypeAliasSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinTypeAliasSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - fun addTypeVariables(typeVariables: Iterable) = builder { this.addTypeVariables(typeVariables) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } override fun builder(block: TypeAliasSpecBuilderReceiver) = apply { delegate.builder.block() } override fun build() = KotlinTypeAliasSpec(spec = delegate.build()) diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt index 6af6ef7..1bdab00 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt @@ -9,6 +9,7 @@ import io.toolisticon.kotlin.generation.poet.* import io.toolisticon.kotlin.generation.spec.* import io.toolisticon.kotlin.generation.support.SUPPRESS_UNUSED import javax.lang.model.element.Element +import kotlin.reflect.KClass /** * Builder for [KotlinValueClassSpec]. @@ -18,12 +19,10 @@ class KotlinValueClassSpecBuilder internal constructor( val className: ClassName, private val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, KotlinConstructorPropertySupport, - KotlinAnnotatableBuilder, KotlinContextReceivableBuilder, - KotlinDocumentableBuilder, KotlinMemberSpecHolderBuilder, - KotlinModifiableBuilder, KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder { @@ -39,14 +38,15 @@ class KotlinValueClassSpecBuilder internal constructor( delegate.builder.jvmInline() } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier): KotlinValueClassSpecBuilder = apply { delegate.addAnnotation(spec.get()) } - override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier): KotlinValueClassSpecBuilder = apply { this.constructorProperty = spec } - override fun contextReceivers(vararg receiverTypes: TypeName): KotlinValueClassSpecBuilder = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier): KotlinValueClassSpecBuilder = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc): KotlinValueClassSpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { this.constructorProperty = spec } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier): KotlinValueClassSpecBuilder = apply { delegate.addProperty(propertySpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } @@ -56,9 +56,7 @@ class KotlinValueClassSpecBuilder internal constructor( fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } - override fun builder(block: TypeSpecBuilderReceiver) = apply { - delegate.builder.block() - } + override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } override fun build(): KotlinValueClassSpec { check(::constructorProperty.isInitialized) { "Value class must have exactly one property." } diff --git a/kotlin-code-generation/src/main/kotlin/builder/_types.kt b/kotlin-code-generation/src/main/kotlin/builder/_types.kt index 0330b2c..be17722 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/_types.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/_types.kt @@ -35,9 +35,8 @@ sealed interface DelegatingBuilder { /** * Common interface for typeSpec builders. */ -sealed interface KotlinGeneratorTypeSpecBuilder> : BuilderSupplier, - DelegatingBuilder, - TypeSpecSupplier, +interface KotlinGeneratorTypeSpecBuilder> : BuilderSupplier, + DelegatingBuilder, TypeSpecSupplier, KotlinGeneratorSpecSupplier { override fun spec(): SPEC = build() @@ -48,7 +47,7 @@ sealed interface KotlinGeneratorTypeSpecBuilder { +sealed interface KotlinConstructorPropertySupport : KotlinTaggableBuilder { /** * Implementing builder needs to store the spec provided and apply it to the build. @@ -74,7 +73,7 @@ sealed interface KotlinConstructorPropertySupport { * Typesafe wrapper for [Annotatable.Builder]. */ @OptIn(ExperimentalKotlinPoetApi::class) -sealed interface KotlinAnnotatableBuilder { +interface KotlinAnnotatableBuilder : KotlinTaggableBuilder { /** * Implementing builder needs to store the spec provided and apply it to the build. @@ -106,14 +105,13 @@ sealed interface KotlinAnnotatableBuilder { fun addAnnotation(annotationSpec: AnnotationSpecSupplier): SELF = addAnnotation(annotationSpec.get()) } - /** * Typesafe wrapper for [com.squareup.kotlinpoet.Documentable.Builder]. Marks anything that can have `kdoc` documentation. * * * `addKdoc` */ @ExperimentalKotlinPoetApi -sealed interface KotlinDocumentableBuilder { +interface KotlinDocumentableBuilder : KotlinTaggableBuilder { /** * Implementing builders have to add this to their build. */ @@ -145,7 +143,7 @@ sealed interface KotlinDocumentableBuilder { * * `addProperty` */ @ExperimentalKotlinPoetApi -sealed interface KotlinMemberSpecHolderBuilder { +sealed interface KotlinMemberSpecHolderBuilder : KotlinTaggableBuilder { fun addFunction(funSpec: KotlinFunSpecSupplier): SELF fun addFunction(name: FunctionName, block: KotlinFunSpecBuilderReceiver): SELF = addFunction(funSpec = buildFun(name, block)) @@ -157,7 +155,7 @@ sealed interface KotlinMemberSpecHolderBuilder { /** * Shared wrapper fo all builders that support `addModifiers` */ -sealed interface KotlinModifiableBuilder { +interface KotlinModifiableBuilder : KotlinTaggableBuilder { /** * Add modifiers. @@ -185,7 +183,7 @@ sealed interface KotlinModifiableBuilder { /** * ContextReceivable for type-safe builders. */ -sealed interface KotlinContextReceivableBuilder { +sealed interface KotlinContextReceivableBuilder : KotlinTaggableBuilder { /** * @see KotlinContextReceivableBuilder#contextReceivers @@ -198,7 +196,7 @@ sealed interface KotlinContextReceivableBuilder { fun contextReceivers(vararg receiverTypes: TypeName): SELF } -sealed interface KotlinSuperInterfaceSupport { +interface KotlinSuperInterfaceSupport : KotlinTaggableBuilder { fun addSuperinterface(superinterface: TypeName, constructorParameter: String): SELF fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock = CodeBlockBuilder.EMPTY_CODE_BLOCK): SELF @@ -215,7 +213,7 @@ sealed interface KotlinSuperInterfaceSupport { * * `addType` */ @ExperimentalKotlinPoetApi -sealed interface KotlinTypeSpecHolderBuilder { +sealed interface KotlinTypeSpecHolderBuilder : KotlinTaggableBuilder { /** * @see KotlinTypeSpecHolderBuilder.addType(TypeSpecSupplier) */ @@ -256,3 +254,30 @@ sealed interface KotlinTypeSpecHolderBuilder { */ fun addType(typeSpec: TypeSpecSupplier): SELF } + +/** + * Support tagging. + * @see com.squareup.kotlinpoet.Taggable#Builder + */ +sealed interface KotlinTaggableBuilder { + /** + * @see com.squareup.kotlinpoet.Taggable#Builder#tag + */ + fun tag(type: KClass<*>, tag: Any?): SELF + + /** + * Store tag under key of ::class. + */ + fun tag(tag: T): SELF = tag(tag::class, tag) + + fun removeTag(type: KClass<*>): SELF = tag(type, null) +} + +/** + * Groups the features of [KotlinAnnotatableBuilder], [KotlinDocumentableBuilder] and [KotlinModifiableBuilder]. + */ +@ExperimentalKotlinPoetApi +interface KotlinAnnotatableDocumentableModifiableBuilder : + KotlinAnnotatableBuilder, + KotlinDocumentableBuilder, + KotlinModifiableBuilder diff --git a/kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt new file mode 100644 index 0000000..0e78fe0 --- /dev/null +++ b/kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt @@ -0,0 +1,114 @@ +package io.toolisticon.kotlin.generation.builder.extra + +import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi +import com.squareup.kotlinpoet.KModifier +import com.squareup.kotlinpoet.TypeName +import com.squareup.kotlinpoet.TypeSpec +import com.squareup.kotlinpoet.asTypeName +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildParameter +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.constructorBuilder +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_NAME +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_STRING_TEMPLATE +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.name.nullable +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.simpleClassName +import io.toolisticon.kotlin.generation.builder.KotlinAnnotatableDocumentableModifiableBuilder +import io.toolisticon.kotlin.generation.builder.KotlinClassSpecBuilder +import io.toolisticon.kotlin.generation.builder.KotlinFunSpecBuilder +import io.toolisticon.kotlin.generation.builder.KotlinGeneratorTypeSpecBuilder +import io.toolisticon.kotlin.generation.builder.KotlinSuperInterfaceSupport +import io.toolisticon.kotlin.generation.poet.KDoc +import io.toolisticon.kotlin.generation.spec.ClassSpecType +import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpecSupplier +import io.toolisticon.kotlin.generation.spec.KotlinClassSpec +import kotlin.reflect.KClass + +/** + * Builder for a special [io.toolisticon.kotlin.generation.spec.KotlinClassSpec] that represents + * an [RuntimeException] with String-Message-Template. + */ +@ExperimentalKotlinPoetApi +class RuntimeExceptionSpecBuilder internal constructor( + private val delegate: KotlinClassSpecBuilder, +) : KotlinGeneratorTypeSpecBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, + KotlinSuperInterfaceSupport { + companion object { + private val NULLABLE_THROWABLE = Throwable::class.asTypeName().nullable() + private val FIND_TEMPLATE_PARAMS = Regex("\\$(\\w+)") + + fun builder(name: String): RuntimeExceptionSpecBuilder = builder(simpleClassName(name)) + fun builder(className: ClassName): RuntimeExceptionSpecBuilder = RuntimeExceptionSpecBuilder(className = className) + + /** + * Gets template parameters as names. + */ + private fun findTemplateParams(template: String) = FIND_TEMPLATE_PARAMS.findAll(template).map { it.value } + .map { it.removePrefix("$") } + } + + private lateinit var _messageTemplate: String + private var _cause: Pair = false to "cause" + private val _messageTemplateParameters = LinkedHashMap() + + internal constructor(className: ClassName) : this(delegate = KotlinClassSpecBuilder(className = className)) { + tag(ClassSpecType.EXCEPTION) + delegate.superclass(RuntimeException::class) + } + + fun messageTemplate(messageTemplate: String) = apply { + _messageTemplate = messageTemplate + + findTemplateParams(_messageTemplate).forEach { + _messageTemplateParameters.putIfAbsent(it, Any::class.asTypeName()) + } + } + + fun addParameter(name: String, type: KClass<*>) = addParameter(name, type.asTypeName()) + + fun addParameter(name: String, type: TypeName) = apply { + _messageTemplateParameters[name] = type + } + + fun includeCause(name: String? = null) = apply { + _cause = true to (name ?: _cause.second) + } + + override fun build(): KotlinClassSpec { + require(::_messageTemplate.isInitialized) { "Message template must be initialized." } + delegate.addSuperclassConstructorParameter(FORMAT_STRING_TEMPLATE, _messageTemplate) + + val constructorBuilder: KotlinFunSpecBuilder = _messageTemplateParameters.entries.fold(constructorBuilder()) { acc, cur -> + acc.addParameter(cur.key, cur.value) + } + + if (_cause.first) { + delegate.addSuperclassConstructorParameter(FORMAT_NAME, _cause.second) + val nullableCauseParameter = buildParameter(_cause.second, NULLABLE_THROWABLE) { + defaultValue("null") + } + + constructorBuilder.addParameter(nullableCauseParameter) + } + + return delegate.primaryConstructor(constructorBuilder).build() + } + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc) } + override fun addModifiers(vararg modifiers: KModifier) = apply { delegate.addModifiers(*modifiers) } + override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = apply { delegate.addSuperinterface(superinterface, constructorParameter) } + override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock): RuntimeExceptionSpecBuilder { + TODO("Not yet implemented") + } + + //override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) : RuntimeExceptionSpecBuilder= apply { delegate.addS } + override fun tag(type: KClass<*>, tag: Any?) = apply { delegate.tag(type, tag) } + override fun builder(block: TypeSpec.Builder.() -> Unit): RuntimeExceptionSpecBuilder = apply { delegate.builder(block) } + // +} + +@ExperimentalKotlinPoetApi +typealias RuntimeExceptionSpecBuilderReceiver = RuntimeExceptionSpecBuilder.() -> Unit diff --git a/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt index 4d10ded..d9deb80 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt @@ -9,7 +9,7 @@ import kotlin.reflect.KClass */ class AnnotationSpecBuilder( override val builder: AnnotationSpec.Builder -) : PoetSpecBuilder { +) : PoetSpecBuilder, PoetTaggableBuilder { companion object { fun AnnotationSpec.Builder.wrap() = AnnotationSpecBuilder(this) @@ -21,7 +21,7 @@ class AnnotationSpecBuilder( } // Taggable - fun tag(type: KClass<*>, tag: Any?) = apply { builder.tag(type, tag) } + override fun tag(type: KClass<*>, tag: Any?) = apply { builder.tag(type, tag) } // Annotatable fun addMember(format: String, vararg args: Any) = apply { builder.addMember(CodeBlock.of(format, *args)) } diff --git a/kotlin-code-generation/src/main/kotlin/poet/FileSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/FileSpecBuilder.kt index 0e5e428..abcfa74 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/FileSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/FileSpecBuilder.kt @@ -15,6 +15,7 @@ class FileSpecBuilder( PoetAnnotatableBuilder, PoetMemberSpecHolderBuilder, PoetTypeSpecHolderBuilder, + PoetTaggableBuilder, WithClassName { companion object { internal fun FileSpec.Builder.wrap() = FileSpecBuilder(this) @@ -69,6 +70,8 @@ class FileSpecBuilder( fun addStatement(format: String, vararg args: Any): FileSpecBuilder = apply { builder.addStatement(format, *args) } fun clearBody(): FileSpecBuilder = apply { builder.clearBody() } + override fun tag(type: KClass<*>, tag: Any?): FileSpecBuilder = apply { builder.tag(type, tag) } + override fun build(): FileSpec = builder.build() override val className: ClassName = className(builder.packageName, builder.name) } diff --git a/kotlin-code-generation/src/main/kotlin/poet/FunSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/FunSpecBuilder.kt index 3877967..9569ae3 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/FunSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/FunSpecBuilder.kt @@ -15,6 +15,7 @@ class FunSpecBuilder( PoetAnnotatableBuilder, PoetContextReceivableBuilder, PoetDocumentableBuilder, + PoetTaggableBuilder, PoetOriginatingElementsHolderBuilder { companion object { fun FunSpec.Builder.wrap() = FunSpecBuilder(this) @@ -100,6 +101,8 @@ class FunSpecBuilder( fun clearBody(): FunSpecBuilder = apply { builder.clearBody() } + override fun tag(type: KClass<*>, tag: Any?): FunSpecBuilder = apply { builder.tag(type, tag) } + override fun build(): FunSpec = builder.build() } diff --git a/kotlin-code-generation/src/main/kotlin/poet/ParameterSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/ParameterSpecBuilder.kt index 4f7519c..88dd123 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/ParameterSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/ParameterSpecBuilder.kt @@ -11,6 +11,7 @@ class ParameterSpecBuilder( override val builder: ParameterSpec.Builder ) : PoetSpecBuilder, PoetAnnotatableBuilder, + PoetTaggableBuilder, PoetDocumentableBuilder { companion object { fun ParameterSpec.Builder.wrap() = ParameterSpecBuilder(this) @@ -48,6 +49,8 @@ class ParameterSpecBuilder( fun defaultValue(format: String, vararg args: Any?): ParameterSpecBuilder = apply { builder.defaultValue(format, *args) } fun defaultValue(codeBlock: CodeBlock?): ParameterSpecBuilder = apply { builder.defaultValue(codeBlock) } + override fun tag(type: KClass<*>, tag: Any?): ParameterSpecBuilder = apply { builder.tag(type, tag) } + override fun build(): ParameterSpec = builder.build() } diff --git a/kotlin-code-generation/src/main/kotlin/poet/PropertySpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/PropertySpecBuilder.kt index 585c928..4c86cca 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/PropertySpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/PropertySpecBuilder.kt @@ -14,6 +14,7 @@ class PropertySpecBuilder( ) : PoetSpecBuilder, PoetAnnotatableBuilder, PoetContextReceivableBuilder, + PoetTaggableBuilder, PoetDocumentableBuilder, PoetOriginatingElementsHolderBuilder { companion object { @@ -65,6 +66,7 @@ class PropertySpecBuilder( fun receiver(receiverType: TypeName?): PropertySpecBuilder = apply { builder.receiver(receiverType) } fun receiver(receiverType: KClass<*>): PropertySpecBuilder = apply { builder.receiver(receiverType) } + override fun tag(type: KClass<*>, tag: Any?): PropertySpecBuilder = apply { builder.tag(type, tag) } override fun build(): PropertySpec = builder.build() } diff --git a/kotlin-code-generation/src/main/kotlin/poet/TypeAliasSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/TypeAliasSpecBuilder.kt index d8b6344..755ef4e 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/TypeAliasSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/TypeAliasSpecBuilder.kt @@ -10,6 +10,7 @@ class TypeAliasSpecBuilder( override val builder: TypeAliasSpec.Builder ) : PoetSpecBuilder, PoetAnnotatableBuilder, + PoetTaggableBuilder, PoetDocumentableBuilder { companion object { fun TypeAliasSpec.Builder.wrap() = TypeAliasSpecBuilder(builder = this) @@ -33,6 +34,8 @@ class TypeAliasSpecBuilder( fun addTypeVariables(typeVariables: Iterable): TypeAliasSpecBuilder = apply { builder.addTypeVariables(typeVariables) } fun addTypeVariable(typeVariable: TypeVariableName): TypeAliasSpecBuilder = apply { builder.addTypeVariable(typeVariable) } + override fun tag(type: KClass<*>, tag: Any?): TypeAliasSpecBuilder = apply { builder.tag(type, tag) } + override fun build(): TypeAliasSpec = builder.build() } diff --git a/kotlin-code-generation/src/main/kotlin/poet/TypeSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/TypeSpecBuilder.kt index 772e022..9264495 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/TypeSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/TypeSpecBuilder.kt @@ -27,6 +27,7 @@ class TypeSpecBuilder( PoetAnnotatableBuilder, PoetContextReceivableBuilder, PoetDocumentableBuilder, + PoetTaggableBuilder, PoetMemberSpecHolderBuilder, PoetOriginatingElementsHolderBuilder, PoetTypeSpecHolderBuilder { @@ -63,7 +64,6 @@ class TypeSpecBuilder( fun anonymousClassBuilder(): TypeSpecBuilder = TypeSpec.anonymousClassBuilder().wrap() } - // AnnotatableBuilder override fun addAnnotation(annotationSpec: AnnotationSpec) = apply { builder.addAnnotation(annotationSpec) } override fun addAnnotations(annotationSpecs: Iterable) = apply { builder.addAnnotations(annotationSpecs) } @@ -89,7 +89,6 @@ class TypeSpecBuilder( override fun addType(typeSpec: TypeSpec) = apply { builder.addType(typeSpec) } override fun addTypes(typeSpecs: Iterable) = apply { builder.addTypes(typeSpecs) } - fun addModifiers(vararg modifiers: KModifier): TypeSpecBuilder = apply { builder.addModifiers(*modifiers) } fun addModifiers(modifiers: Iterable): TypeSpecBuilder = apply { builder.addModifiers(modifiers) } fun addTypeVariables(typeVariables: Iterable): TypeSpecBuilder = apply { builder.addTypeVariables(typeVariables) } @@ -112,6 +111,8 @@ class TypeSpecBuilder( fun addEnumConstant(name: String, typeSpec: TypeSpec = TypeSpec.anonymousClassBuilder().build()): TypeSpecBuilder = apply { builder.addEnumConstant(name, typeSpec) } fun addInitializerBlock(block: CodeBlock): TypeSpecBuilder = apply { builder.addInitializerBlock(block) } + override fun tag(type: KClass<*>, tag: Any?): TypeSpecBuilder = apply { builder.tag(type, tag) } + override fun build(): TypeSpec = builder.build() } diff --git a/kotlin-code-generation/src/main/kotlin/poet/_types.kt b/kotlin-code-generation/src/main/kotlin/poet/_types.kt index 0db1c97..9c78e1f 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/_types.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/_types.kt @@ -90,3 +90,7 @@ sealed interface PoetDocumentableBuilder { fun addKdoc(block: CodeBlock): SELF fun addKdoc(format: String, vararg args: Any): SELF } + +sealed interface PoetTaggableBuilder { + fun tag(type: KClass<*>, tag: Any?): SELF +} diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinAnnotationClassSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinAnnotationClassSpec.kt index 4594564..f14e7df 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinAnnotationClassSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinAnnotationClassSpec.kt @@ -5,14 +5,16 @@ import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeSpec import io.toolisticon.kotlin.generation.poet.KDoc import io.toolisticon.kotlin.generation.poet.TypeSpecSupplier +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinAnnotationClassSpec( override val className: ClassName, - private val spec: TypeSpec, + private val spec: TypeSpec ) : KotlinGeneratorTypeSpec, TypeSpecSupplier, KotlinAnnotationClassSpecSupplier, KotlinDocumentableSpec { + override fun tag(type: KClass): T? = get().tag(type) override fun spec(): KotlinAnnotationClassSpec = this override fun get(): TypeSpec = spec override val kdoc: KDoc get() = KDoc(spec.kdoc) diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinAnnotationSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinAnnotationSpec.kt index 874381f..3981824 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinAnnotationSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinAnnotationSpec.kt @@ -24,7 +24,6 @@ data class KotlinAnnotationSpec( override fun toString(): String { return "KotlinAnnotationSpec(typeName=$typeName, members=$members)" } - } interface KotlinAnnotationSpecSupplier : KotlinGeneratorSpecSupplier, AnnotationSpecSupplier { diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinAnonymousClassSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinAnonymousClassSpec.kt index effbd1c..36c4dc3 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinAnonymousClassSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinAnonymousClassSpec.kt @@ -4,12 +4,15 @@ import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeSpec import io.toolisticon.kotlin.generation.poet.KDoc import io.toolisticon.kotlin.generation.poet.TypeSpecSupplier +import kotlin.reflect.KClass @JvmInline @ExperimentalKotlinPoetApi value class KotlinAnonymousClassSpec(private val spec: TypeSpec) : KotlinGeneratorTypeSpec, KotlinAnonymousClassSpecSupplier, KotlinDocumentableSpec { + + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinAnonymousClassSpec = this override fun get(): TypeSpec = spec diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinClassSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinClassSpec.kt index 04581e2..1917607 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinClassSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinClassSpec.kt @@ -4,17 +4,15 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeSpec import io.toolisticon.kotlin.generation.poet.KDoc +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinClassSpec( override val className: ClassName, - private val spec: TypeSpec + private val spec: TypeSpec, ) : KotlinGeneratorTypeSpec, KotlinClassSpecSupplier, KotlinDocumentableSpec { - init { - //require(spec.is) { "Not a dataClass spec: $spec." } - } - + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinClassSpec = this override fun get(): TypeSpec = spec diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinCompanionObjectSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinCompanionObjectSpec.kt index ff891d9..7748bde 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinCompanionObjectSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinCompanionObjectSpec.kt @@ -4,12 +4,14 @@ import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeSpec import io.toolisticon.kotlin.generation.poet.KDoc import io.toolisticon.kotlin.generation.poet.TypeSpecSupplier +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinCompanionObjectSpec( private val spec: TypeSpec ) : KotlinGeneratorTypeSpec, KotlinCompanionObjectSpecSupplier, KotlinDocumentableSpec { + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinCompanionObjectSpec = this override fun get(): TypeSpec = spec diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinConstructorPropertySpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinConstructorPropertySpec.kt index 9e87f2b..ed30e54 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinConstructorPropertySpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinConstructorPropertySpec.kt @@ -3,6 +3,7 @@ package io.toolisticon.kotlin.generation.spec import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeName import io.toolisticon.kotlin.generation.poet.KDoc +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinConstructorPropertySpec( @@ -10,6 +11,7 @@ data class KotlinConstructorPropertySpec( val parameter: KotlinParameterSpec, ) : KotlinConstructorPropertySpecSupplier, KotlinDocumentableSpec { + override fun tag(type: KClass): T? = property.get().tag(type) override val name: String = property.name val type: TypeName = property.type override val kdoc: KDoc get() = KDoc(property.get().kdoc) diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinDataClassSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinDataClassSpec.kt index 29b3ffc..c6b1739 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinDataClassSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinDataClassSpec.kt @@ -6,6 +6,7 @@ import com.squareup.kotlinpoet.TypeSpec import io.toolisticon.kotlin.generation.KotlinCodeGeneration import io.toolisticon.kotlin.generation.KotlinCodeGeneration.typeSpec.isDataClass import io.toolisticon.kotlin.generation.poet.KDoc +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinDataClassSpec( @@ -18,6 +19,7 @@ data class KotlinDataClassSpec( require(spec.isDataClass) { "Not a dataClass spec: $spec." } } + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinDataClassSpec = this diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinEnumClassSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinEnumClassSpec.kt index 7342a85..fcb5d08 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinEnumClassSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinEnumClassSpec.kt @@ -4,6 +4,7 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeSpec import io.toolisticon.kotlin.generation.poet.KDoc +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinEnumClassSpec( @@ -15,6 +16,7 @@ data class KotlinEnumClassSpec( require(spec.isEnum) { "Not an enum spec: $spec" } } + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinEnumClassSpec = this override fun get(): TypeSpec = spec diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinFileSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinFileSpec.kt index 1ec4ea8..f7de3a8 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinFileSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinFileSpec.kt @@ -4,13 +4,15 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.FileSpec import io.toolisticon.kotlin.generation.WithClassName import io.toolisticon.kotlin.generation.poet.FileSpecSupplier +import kotlin.reflect.KClass data class KotlinFileSpec( private val spec: FileSpec -) : KotlinGeneratorSpec, KotlinFileSpecSupplier { +) : KotlinGeneratorSpec, KotlinFileSpecSupplier, TaggableSpec { val packageName: String = spec.packageName val rootName: String = spec.name + override fun tag(type: KClass): T? = get().tag(type) override val className: ClassName = ClassName(packageName, rootName) val fqn: String = "$packageName.$rootName" val fileName: String = "$fqn.kt" diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinFunSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinFunSpec.kt index b4692bc..08f5536 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinFunSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinFunSpec.kt @@ -4,6 +4,7 @@ import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.FunSpec import io.toolisticon.kotlin.generation.poet.FunSpecSupplier import io.toolisticon.kotlin.generation.poet.KDoc +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinFunSpec( @@ -14,6 +15,7 @@ data class KotlinFunSpec( override val kdoc: KDoc get() = KDoc(spec.kdoc) + override fun tag(type: KClass): T? = get().tag(type) override fun spec(): KotlinFunSpec = this override fun get(): FunSpec = spec } diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinInterfaceSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinInterfaceSpec.kt index e0e8623..b39aad2 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinInterfaceSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinInterfaceSpec.kt @@ -4,12 +4,15 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeSpec import io.toolisticon.kotlin.generation.poet.KDoc +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinInterfaceSpec( override val className: ClassName, private val spec: TypeSpec ) : KotlinGeneratorTypeSpec, KotlinInterfaceSpecSupplier, KotlinDocumentableSpec { + + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinInterfaceSpec = this override fun get(): TypeSpec = spec diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinObjectSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinObjectSpec.kt index 96e89a8..30e2cc1 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinObjectSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinObjectSpec.kt @@ -4,12 +4,15 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeSpec import io.toolisticon.kotlin.generation.poet.KDoc +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinObjectSpec( override val className: ClassName, private val spec: TypeSpec ) : KotlinGeneratorTypeSpec, KotlinObjectSpecSupplier, KotlinDocumentableSpec { + + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinObjectSpec = this override fun get(): TypeSpec = spec diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinParameterSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinParameterSpec.kt index fd33971..1512086 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinParameterSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinParameterSpec.kt @@ -5,6 +5,7 @@ import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.TypeName import io.toolisticon.kotlin.generation.poet.KDoc import io.toolisticon.kotlin.generation.poet.ParameterSpecSupplier +import kotlin.reflect.KClass @JvmInline @ExperimentalKotlinPoetApi @@ -19,6 +20,7 @@ value class KotlinParameterSpec( val name: String get() = spec.name val type: TypeName get() = spec.type + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinParameterSpec = this diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinPropertySpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinPropertySpec.kt index 67f9adf..03e2e55 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinPropertySpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinPropertySpec.kt @@ -5,6 +5,7 @@ import com.squareup.kotlinpoet.PropertySpec import com.squareup.kotlinpoet.TypeName import io.toolisticon.kotlin.generation.poet.KDoc import io.toolisticon.kotlin.generation.poet.PropertySpecSupplier +import kotlin.reflect.KClass @JvmInline @ExperimentalKotlinPoetApi @@ -20,6 +21,7 @@ value class KotlinPropertySpec(private val spec: PropertySpec) : KotlinGenerator val mutable: Boolean get() = spec.mutable + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinPropertySpec = this diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinTypeAliasSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinTypeAliasSpec.kt index a4296e2..c201b51 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinTypeAliasSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinTypeAliasSpec.kt @@ -4,6 +4,7 @@ import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeAliasSpec import io.toolisticon.kotlin.generation.poet.KDoc import io.toolisticon.kotlin.generation.poet.TypeAliasSpecSupplier +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi @@ -14,6 +15,7 @@ value class KotlinTypeAliasSpec(private val spec: TypeAliasSpec) : KotlinGenerat KotlinTypeAliasSpecSupplier, KotlinDocumentableSpec { + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinTypeAliasSpec = this diff --git a/kotlin-code-generation/src/main/kotlin/spec/KotlinValueClassSpec.kt b/kotlin-code-generation/src/main/kotlin/spec/KotlinValueClassSpec.kt index c8ecc48..85d1cf3 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/KotlinValueClassSpec.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/KotlinValueClassSpec.kt @@ -5,6 +5,7 @@ import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import com.squareup.kotlinpoet.TypeSpec import io.toolisticon.kotlin.generation.KotlinCodeGeneration.typeSpec.isValueClass import io.toolisticon.kotlin.generation.poet.KDoc +import kotlin.reflect.KClass @ExperimentalKotlinPoetApi data class KotlinValueClassSpec( @@ -16,6 +17,7 @@ data class KotlinValueClassSpec( require(spec.isValueClass) { "Not a valueClass spec: $spec." } } + override fun tag(type: KClass): T? = get().tag(type) override val kdoc: KDoc get() = KDoc(spec.kdoc) override fun spec(): KotlinValueClassSpec = this override fun get(): TypeSpec = spec diff --git a/kotlin-code-generation/src/main/kotlin/spec/_types.kt b/kotlin-code-generation/src/main/kotlin/spec/_types.kt index 049fce8..16f7fa7 100644 --- a/kotlin-code-generation/src/main/kotlin/spec/_types.kt +++ b/kotlin-code-generation/src/main/kotlin/spec/_types.kt @@ -8,29 +8,30 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration import io.toolisticon.kotlin.generation.WithClassName import io.toolisticon.kotlin.generation.poet.* import io.toolisticon.kotlin.generation.support.SUPPRESS_UNUSED +import kotlin.reflect.KClass interface KotlinGeneratorSpecSupplier { fun spec(): GENERATOR_SPEC } -interface KotlinGeneratorSpec, SPEC : PoetSpec, SUPPLIER : PoetSpecSupplier> : PoetSpecSupplier, KotlinGeneratorSpecSupplier { +sealed interface KotlinGeneratorSpec, SPEC : PoetSpec, SUPPLIER : PoetSpecSupplier> : PoetSpecSupplier, KotlinGeneratorSpecSupplier { override fun spec(): SELF val code: String get() = get().toString() } -interface KotlinGeneratorTypeSpec> : KotlinGeneratorSpec, TypeSpecSupplier { +sealed interface KotlinGeneratorTypeSpec> : KotlinGeneratorSpec, TypeSpecSupplier { override fun spec(): SELF } @ExperimentalKotlinPoetApi -interface KotlinDocumentableSpec { +sealed interface KotlinDocumentableSpec : TaggableSpec { val kdoc: KDoc } /** * Marker interface for typeSpecs that provide a className and can be easily wrapped in a fileSpec. */ -interface ToFileTypeSpecSupplier : TypeSpecSupplier, WithClassName +sealed interface ToFileTypeSpecSupplier : TypeSpecSupplier, WithClassName /** * Wraps supported typeSpec into a file without the need to create an extra builder. @@ -39,3 +40,27 @@ interface ToFileTypeSpecSupplier : TypeSpecSupplier, WithClassName fun ToFileTypeSpecSupplier.toFileSpec() = KotlinCodeGeneration.buildFile(className) { addType(this@toFileSpec) } + +/** + * Marks Spec as [com.squareup.kotlinpoet.Taggable]. + */ +sealed interface TaggableSpec { + /** + * @see [com.squareup.kotlinpoet.Taggable.tag] + */ + fun tag(type: KClass): T? +} + +/** + * Reified access to [TaggableSpec.tag]. + */ +inline fun TaggableSpec.tag(): T? = tag(T::class) + +/** + * Tags a spec with extra type. + */ +enum class ClassSpecType { + MAP, + LIST, + EXCEPTION +} diff --git a/kotlin-code-generation/src/main/kotlin/support/CodeBlockArray.kt b/kotlin-code-generation/src/main/kotlin/support/CodeBlockArray.kt index dd49c62..80a9637 100644 --- a/kotlin-code-generation/src/main/kotlin/support/CodeBlockArray.kt +++ b/kotlin-code-generation/src/main/kotlin/support/CodeBlockArray.kt @@ -28,7 +28,7 @@ data class CodeBlockArray( /** * Special format for concatenating codeBlocks. */ - val CODE_BLOCK_FORMAT = CodeBlockArray.Companion.Format(format = "", prefix = "", suffix = "") + private val CODE_BLOCK_FORMAT = Format(format = "", prefix = "", suffix = "") fun codeBlockArray(format: Format = CODE_BLOCK_FORMAT, vararg items: CodeBlock) = CodeBlockArray(format, items.toList()) diff --git a/kotlin-code-generation/src/test/kotlin/poet/TypeSpecBuilderTest.kt b/kotlin-code-generation/src/test/kotlin/poet/TypeSpecBuilderTest.kt index 07d7e7c..6da649e 100644 --- a/kotlin-code-generation/src/test/kotlin/poet/TypeSpecBuilderTest.kt +++ b/kotlin-code-generation/src/test/kotlin/poet/TypeSpecBuilderTest.kt @@ -8,13 +8,12 @@ import jakarta.annotation.Generated import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test - @OptIn(ExperimentalKotlinPoetApi::class) internal class TypeSpecBuilderTest { @Test fun `verify builder`() { - val builder: TypeSpecBuilder = TypeSpecBuilder(TypeSpec.classBuilder(ClassName("foo", "Bar"))) + val builder = TypeSpecBuilder(TypeSpec.classBuilder(ClassName("foo", "Bar"))) builder.addAnnotation(Generated::class) diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationTest.kt index 954585f..21b3d0d 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinAnnotationTest.kt @@ -4,6 +4,7 @@ import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildAnnotation import io.toolisticon.kotlin.generation.TestFixtures.MyAnnotation import io.toolisticon.kotlin.generation.builder.KotlinAnnotationSpecBuilder +import io.toolisticon.kotlin.generation.support.SUPPRESS_UNUSED import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import kotlin.reflect.KClass @@ -12,6 +13,7 @@ import kotlin.reflect.KClass @OptIn(ExperimentalKotlinPoetApi::class) internal class KotlinAnnotationTest { + @SuppressWarnings(SUPPRESS_UNUSED) annotation class Foo( val bar: String, val x: String = "", @@ -25,7 +27,7 @@ internal class KotlinAnnotationTest { addKClassMember("type", String::class) } - assertThat(annotation.code).isEqualTo("""@io.toolisticon.kotlin.generation.TestFixtures.MyAnnotation(name = "foo", type = kotlin.String::class)"""); + assertThat(annotation.code).isEqualTo("""@io.toolisticon.kotlin.generation.TestFixtures.MyAnnotation(name = "foo", type = kotlin.String::class)""") } @Test diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinClassExceptionTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinClassExceptionTest.kt deleted file mode 100644 index 6725a40..0000000 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinClassExceptionTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package io.toolisticon.kotlin.generation.spec - -import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi -import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildClass -import io.toolisticon.kotlin.generation.KotlinCodeGeneration.className -import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_NAME -import io.toolisticon.kotlin.generation.builder.KotlinFunSpecBuilder -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -@OptIn(ExperimentalKotlinPoetApi::class) -class KotlinClassExceptionTest { - - @Test - fun `create exception class`() { - val e = buildClass(className("my","DummyException")) { - superclass(RuntimeException::class) - primaryConstructor(KotlinFunSpecBuilder.constructorBuilder().apply { - addParameter("message", String::class) - } - - ) - addSuperclassConstructorParameter(FORMAT_NAME, "message") - } - - assertThat(e.code).isEqualToIgnoringWhitespace(""" - public class DummyException( - message: kotlin.String, - ) : java.lang.RuntimeException(message) - """.trimIndent()) - } -} diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinConstructorPropertyTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinConstructorPropertyTest.kt index f86f111..9f72539 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinConstructorPropertyTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinConstructorPropertyTest.kt @@ -4,7 +4,6 @@ package io.toolisticon.kotlin.generation.spec import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi import io.toolisticon.kotlin.generation.TestFixtures.notDeprecated import org.junit.jupiter.api.Assumptions.assumeFalse -import org.junit.jupiter.api.Assumptions.assumeTrue import org.junit.jupiter.api.Test @OptIn(ExperimentalKotlinPoetApi::class) diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinExceptionClassTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinExceptionClassTest.kt new file mode 100644 index 0000000..c987a83 --- /dev/null +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinExceptionClassTest.kt @@ -0,0 +1,42 @@ +package io.toolisticon.kotlin.generation.spec + +import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi +import io.toolisticon.kotlin.generation.KotlinCodeGeneration +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +@OptIn(ExperimentalKotlinPoetApi::class) +class KotlinExceptionClassTest { + + @Test + fun `runtime exception with message`() { + val exception = KotlinCodeGeneration.buildRuntimeExceptionClass("foo", "DummyException") { + addKdoc(" This DummyException indicates something really went wrong. Totally!") + messageTemplate("Something bad happened, expected=\$foo but got \$bar.") + addParameter("foo", Int::class) + addParameter("bar", Long::class) + includeCause("e") + }.toFileSpec() + + assertThat(exception.code).isEqualTo( + """ + package foo + + import java.lang.RuntimeException + import kotlin.Int + import kotlin.Long + import kotlin.Throwable + + /** + * This DummyException indicates something really went wrong. Totally! + */ + public class DummyException( + foo: Int, + bar: Long, + e: Throwable? = null, + ) : RuntimeException(""${'"'}Something bad happened, expected=${'$'}foo but got ${'$'}bar.""${'"'}, e) + + """.trimIndent() + ) + } +} From 4b5ee13698bebee73188368d6f2acc0f3907e0f5 Mon Sep 17 00:00:00 2001 From: Jan Galinski Date: Wed, 11 Sep 2024 23:58:43 +0200 Subject: [PATCH 6/7] Feature/51 delegate list and map (#53) Introduce opinionated builders for Exception, Delegate-List and Delegate-Map. refactor and simplify --- .../test/kotlin/DelegateStringListITest.kt | 41 +++++++ .../test/kotlin/DelegateStringLongMapITest.kt | 44 +++++++ .../src/test/kotlin/DummyExceptionITest.kt | 52 ++++++++ .../src/test/kotlin/HelloWorldExampleITest.kt | 1 - .../src/main/kotlin/KotlinCodeGeneration.kt | 116 +++++++++++++++--- .../KotlinAnnotationClassSpecBuilder.kt | 55 ++++++--- .../builder/KotlinAnnotationSpecBuilder.kt | 65 +++++++++- .../KotlinAnonymousClassSpecBuilder.kt | 34 ++--- .../kotlin/builder/KotlinClassSpecBuilder.kt | 46 ++++--- .../KotlinCompanionObjectSpecBuilder.kt | 44 +++---- .../KotlinConstructorPropertySpecBuilder.kt | 34 ++--- .../builder/KotlinDataClassSpecBuilder.kt | 40 +++--- .../builder/KotlinEnumClassSpecBuilder.kt | 35 +++--- .../kotlin/builder/KotlinFileSpecBuilder.kt | 46 ++++--- .../kotlin/builder/KotlinFunSpecBuilder.kt | 41 +++++-- .../builder/KotlinInterfaceSpecBuilder.kt | 27 ++-- .../kotlin/builder/KotlinObjectSpecBuilder.kt | 38 +++--- .../builder/KotlinParameterSpecBuilder.kt | 40 ++++-- .../builder/KotlinPropertySpecBuilder.kt | 40 ++++-- .../builder/KotlinTypeAliasSpecBuilder.kt | 24 ++-- .../builder/KotlinValueClassSpecBuilder.kt | 59 ++++++--- .../src/main/kotlin/builder/_types.kt | 8 +- .../DelegateListValueClassSpecBuilder.kt | 85 +++++++++++++ .../extra/DelegateMapValueClassSpecBuilder.kt | 85 +++++++++++++ .../extra/RuntimeExceptionSpecBuilder.kt | 69 ++++++++--- .../main/kotlin/poet/AnnotationSpecBuilder.kt | 15 ++- .../src/main/kotlin/poet/FileSpecBuilder.kt | 1 + .../src/main/kotlin/poet/FunSpecBuilder.kt | 1 + .../main/kotlin/poet/ParameterSpecBuilder.kt | 1 + .../main/kotlin/poet/PropertySpecBuilder.kt | 1 + .../main/kotlin/poet/TypeAliasSpecBuilder.kt | 1 + .../src/main/kotlin/poet/TypeSpecBuilder.kt | 1 + .../spec/DelegateListValueClassSpecTest.kt | 38 ++++++ .../kotlin/spec/KotlinExceptionClassTest.kt | 6 +- 34 files changed, 973 insertions(+), 261 deletions(-) create mode 100644 _itest/builder-itest/src/test/kotlin/DelegateStringListITest.kt create mode 100644 _itest/builder-itest/src/test/kotlin/DelegateStringLongMapITest.kt create mode 100644 _itest/builder-itest/src/test/kotlin/DummyExceptionITest.kt create mode 100644 kotlin-code-generation/src/main/kotlin/builder/extra/DelegateListValueClassSpecBuilder.kt create mode 100644 kotlin-code-generation/src/main/kotlin/builder/extra/DelegateMapValueClassSpecBuilder.kt create mode 100644 kotlin-code-generation/src/test/kotlin/spec/DelegateListValueClassSpecTest.kt diff --git a/_itest/builder-itest/src/test/kotlin/DelegateStringListITest.kt b/_itest/builder-itest/src/test/kotlin/DelegateStringListITest.kt new file mode 100644 index 0000000..8375d68 --- /dev/null +++ b/_itest/builder-itest/src/test/kotlin/DelegateStringListITest.kt @@ -0,0 +1,41 @@ +package io.toolisticon.kotlin.generation.itest + +import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi +import com.tschuchort.compiletesting.KotlinCompilation +import io.toolisticon.kotlin.generation.KotlinCodeGeneration +import io.toolisticon.kotlin.generation.itest.KotlinCodeGenerationITestConfig.ROOT_PACKAGE +import io.toolisticon.kotlin.generation.spec.toFileSpec +import io.toolisticon.kotlin.generation.test.KotlinCodeGenerationTest +import io.toolisticon.kotlin.generation.test.model.KotlinCompilationCommand +import org.assertj.core.api.Assertions.assertThat +import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi +import org.junit.jupiter.api.Test +import kotlin.reflect.KClass +import kotlin.reflect.full.primaryConstructor +import io.toolisticon.kotlin.generation.test.KotlinCodeGenerationTest.assertThat as compileAssertThat + +@Suppress("UNCHECKED_CAST") +@OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) +internal class DelegateStringListITest { + + @Test + fun `create and use string list`() { + val list = KotlinCodeGeneration.buildDelegateListValueClass(ROOT_PACKAGE, "StringList", String::class) { + propertyName("list") + }.toFileSpec() + + val result = KotlinCodeGenerationTest.compile(KotlinCompilationCommand(list)) + + + compileAssertThat(result).errorMessages().isEmpty() + compileAssertThat(result).hasExitCode(KotlinCompilation.ExitCode.OK) + + val klass: KClass = result.loadClass(list.className) + + val values = listOf("a", "b", "c") + + val instance: List = klass.primaryConstructor!!.call(values) as List + + assertThat(instance).hasToString("StringList(list=[a, b, c])") + } +} diff --git a/_itest/builder-itest/src/test/kotlin/DelegateStringLongMapITest.kt b/_itest/builder-itest/src/test/kotlin/DelegateStringLongMapITest.kt new file mode 100644 index 0000000..cc732a1 --- /dev/null +++ b/_itest/builder-itest/src/test/kotlin/DelegateStringLongMapITest.kt @@ -0,0 +1,44 @@ +package io.toolisticon.kotlin.generation.itest + +import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi +import com.squareup.kotlinpoet.asTypeName +import com.tschuchort.compiletesting.KotlinCompilation +import io.toolisticon.kotlin.generation.KotlinCodeGeneration +import io.toolisticon.kotlin.generation.itest.KotlinCodeGenerationITestConfig.ROOT_PACKAGE +import io.toolisticon.kotlin.generation.spec.toFileSpec +import io.toolisticon.kotlin.generation.test.KotlinCodeGenerationTest +import io.toolisticon.kotlin.generation.test.model.KotlinCompilationCommand +import org.assertj.core.api.Assertions.assertThat +import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi +import org.junit.jupiter.api.Test +import kotlin.reflect.KClass +import kotlin.reflect.full.primaryConstructor +import io.toolisticon.kotlin.generation.test.KotlinCodeGenerationTest.assertThat as compileAssertThat + +@Suppress("UNCHECKED_CAST") +@OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) +internal class DelegateStringLongMapITest { + + @Test + fun `create and use string long map`() { + val map = KotlinCodeGeneration.buildDelegateMapValueClass( + packageName = ROOT_PACKAGE, + simpleName = "StringLongMap", + valueType = Long::class.asTypeName() + ) { + propertyName("map") + }.toFileSpec() + + val result = KotlinCodeGenerationTest.compile(KotlinCompilationCommand(map)) + compileAssertThat(result).errorMessages().isEmpty() + compileAssertThat(result).hasExitCode(KotlinCompilation.ExitCode.OK) + + val klass: KClass = result.loadClass(map.className) + + val values = mapOf("a" to 1, "b" to 2, "c" to 3) + + val instance: Map = klass.primaryConstructor!!.call(values) as Map + + assertThat(instance).hasToString("StringLongMap(map={a=1, b=2, c=3})") + } +} diff --git a/_itest/builder-itest/src/test/kotlin/DummyExceptionITest.kt b/_itest/builder-itest/src/test/kotlin/DummyExceptionITest.kt new file mode 100644 index 0000000..70093a6 --- /dev/null +++ b/_itest/builder-itest/src/test/kotlin/DummyExceptionITest.kt @@ -0,0 +1,52 @@ +package io.toolisticon.kotlin.generation.itest + +import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi +import com.tschuchort.compiletesting.KotlinCompilation +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildRuntimeExceptionClass +import io.toolisticon.kotlin.generation.itest.KotlinCodeGenerationITestConfig.ROOT_PACKAGE +import io.toolisticon.kotlin.generation.spec.toFileSpec +import io.toolisticon.kotlin.generation.test.KotlinCodeGenerationTest +import io.toolisticon.kotlin.generation.test.model.KotlinCompilationCommand +import org.assertj.core.api.Assertions.assertThat +import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi +import org.junit.jupiter.api.Test +import kotlin.reflect.KClass +import kotlin.reflect.KProperty1 +import kotlin.reflect.full.memberProperties +import kotlin.reflect.full.primaryConstructor +import io.toolisticon.kotlin.generation.test.KotlinCodeGenerationTest.assertThat as compileAssertThat + +@OptIn(ExperimentalKotlinPoetApi::class, ExperimentalCompilerApi::class) +internal class DummyExceptionITest { + + @Test + fun `generate and create dummy exception`() { + val exceptionFile = buildRuntimeExceptionClass(ROOT_PACKAGE, "DummyException") { + messageTemplate("Dummy exception: expected: \$expected, actual: '\$actual'.") + addConstructorProperty("expected", Boolean::class) + addParameter("actual", String::class) + includeCause() + }.toFileSpec() + + + val result = KotlinCodeGenerationTest.compile(KotlinCompilationCommand(exceptionFile)) + + compileAssertThat(result).errorMessages().isEmpty() + compileAssertThat(result).hasExitCode(KotlinCompilation.ExitCode.OK) + + val c: KClass = result.loadClass(exceptionFile.className) + + val cause = IllegalStateException("foo") + val e: RuntimeException = c.primaryConstructor!!.call(true, "false", cause) as RuntimeException + + assertThat(e.localizedMessage).isEqualTo("Dummy exception: expected: true, actual: 'false'.") + + // TODO try to get value via pure kotlin without falling back to java + val expectedProperty: KProperty1 = c.memberProperties.single { it.name == "expected" } + val field = c.java.getDeclaredField("expected").apply { isAccessible = true } + + val expectedValue = field.get(e) as Boolean + + assertThat(expectedValue).isTrue() + } +} diff --git a/_itest/builder-itest/src/test/kotlin/HelloWorldExampleITest.kt b/_itest/builder-itest/src/test/kotlin/HelloWorldExampleITest.kt index 9f7511c..b88e1d7 100644 --- a/_itest/builder-itest/src/test/kotlin/HelloWorldExampleITest.kt +++ b/_itest/builder-itest/src/test/kotlin/HelloWorldExampleITest.kt @@ -34,7 +34,6 @@ internal class HelloWorldExampleITest { val file = buildFile(name) { addType(type) } - println(file.code) assertThat(file.packageName).isEqualTo("foo.bar") diff --git a/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt b/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt index 59cb7ac..1e62afd 100644 --- a/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt +++ b/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt @@ -1,4 +1,4 @@ -@file:Suppress(SUPPRESS_UNUSED) +@file:Suppress("unused") package io.toolisticon.kotlin.generation @@ -10,6 +10,8 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.anonymousCl import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.classBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.companionObjectBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.constructorPropertyBuilder +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.delegateListValueClassBuilder +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.delegateMapValueClassBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.fileBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.funBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.interfaceBuilder @@ -19,9 +21,10 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.propertyBui import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.runtimeExceptionClassBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.typeAliasBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.valueClassBuilder +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.className import io.toolisticon.kotlin.generation.builder.* -import io.toolisticon.kotlin.generation.builder.extra.RuntimeExceptionSpecBuilder -import io.toolisticon.kotlin.generation.builder.extra.RuntimeExceptionSpecBuilderReceiver +import io.toolisticon.kotlin.generation.builder.extra.* +import io.toolisticon.kotlin.generation.builder.extra.DelegateMapValueClassSpecBuilder.Companion.DEFAULT_KEY_TYPE import io.toolisticon.kotlin.generation.poet.FormatSpecifier.asCodeBlock import io.toolisticon.kotlin.generation.spec.* import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationContext @@ -29,9 +32,7 @@ import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationSpiRegistry import io.toolisticon.kotlin.generation.spi.registry.KotlinCodeGenerationServiceLoader import io.toolisticon.kotlin.generation.spi.strategy.KotlinFileSpecStrategy import io.toolisticon.kotlin.generation.spi.strategy.executeAll -import io.toolisticon.kotlin.generation.support.SUPPRESS_CLASS_NAME import io.toolisticon.kotlin.generation.support.SUPPRESS_MEMBER_VISIBILITY_CAN_BE_PRIVATE -import io.toolisticon.kotlin.generation.support.SUPPRESS_UNUSED import mu.KLogging import kotlin.reflect.KClass @@ -57,13 +58,14 @@ object KotlinCodeGeneration : KLogging() { * Build a [KotlinAnnotationClassSpec] using given className and receiver fn. * @see [KotlinAnnotationClassSpecBuilder.builder] */ - inline fun buildAnnotationClass(className: ClassName, block: KotlinAnnotationClassSpecBuilderReceiver = {}): KotlinAnnotationClassSpec = annotationClassBuilder(className).also(block).build() + inline fun buildAnnotationClass(className: ClassName, block: KotlinAnnotationClassSpecBuilderReceiver = {}) = annotationClassBuilder(className).also(block).build() /** * Build a [KotlinAnnotationClassSpec] using given package- and simpleName and receiver fn. * @see [KotlinAnnotationClassSpecBuilder.builder] */ - inline fun buildAnnotationClass(packageName: PackageName, simpleName: SimpleName, block: KotlinAnnotationClassSpecBuilderReceiver = {}): KotlinAnnotationClassSpec = buildAnnotationClass(className(packageName, simpleName), block) + @SuppressWarnings("unused") + inline fun buildAnnotationClass(packageName: PackageName, simpleName: SimpleName, block: KotlinAnnotationClassSpecBuilderReceiver = {}) = buildAnnotationClass(className(packageName, simpleName), block) /** * Build a [KotlinAnonymousClassSpec] using given receiver fn. @@ -83,6 +85,62 @@ object KotlinCodeGeneration : KLogging() { */ inline fun buildClass(packageName: PackageName, simpleName: SimpleName, block: KotlinClassSpecBuilderReceiver = {}) = buildClass(className(packageName, simpleName), block) + /** + * @see [DelegateListValueClassSpecBuilder] + */ + inline fun buildDelegateListValueClass( + packageName: PackageName, + simpleName: SimpleName, + items: KClass<*>, + block: DelegateListValueClassSpecBuilderReceiver = {} + ) = buildDelegateListValueClass(className = className(packageName, simpleName), items = items.asTypeName(), block = block) + + /** + * @see [DelegateListValueClassSpecBuilder] + */ + inline fun buildDelegateListValueClass( + packageName: PackageName, + simpleName: SimpleName, + items: TypeName, + block: DelegateListValueClassSpecBuilderReceiver = {} + ) = delegateListValueClassBuilder( + className = className(packageName, simpleName), + items = items + ).also(block).build() + + + /** + * @see [DelegateListValueClassSpecBuilder] + */ + inline fun buildDelegateListValueClass( + className: ClassName, + items: TypeName, + block: DelegateListValueClassSpecBuilderReceiver = {} + ) = delegateListValueClassBuilder(className, items).also(block).build() + + + /** + * @see [DelegateMapValueClassSpecBuilder] + */ + inline fun buildDelegateMapValueClass( + packageName: PackageName, + simpleName: SimpleName, + keyType: TypeName = DEFAULT_KEY_TYPE, + valueType: TypeName, + block: DelegateMapValueClassSpecBuilderReceiver = {} + ) = buildDelegateMapValueClass(className(packageName, simpleName), keyType, valueType, block) + + + /** + * @see [DelegateMapValueClassSpecBuilder] + */ + inline fun buildDelegateMapValueClass( + className: ClassName, + keyType: TypeName = DEFAULT_KEY_TYPE, + valueType: TypeName, + block: DelegateMapValueClassSpecBuilderReceiver = {} + ) = delegateMapValueClassBuilder(className, keyType, valueType).also(block).build() + /** * @see RuntimeExceptionSpecBuilder */ @@ -102,6 +160,7 @@ object KotlinCodeGeneration : KLogging() { * Build codeBlock using receiver-fn. * @see [CodeBlock.of] */ + @SuppressWarnings("unused") inline fun buildCodeBlock(block: CodeBlock.Builder.() -> Unit): CodeBlock = CodeBlock.builder().also(block).build() /** @@ -144,6 +203,7 @@ object KotlinCodeGeneration : KLogging() { * Build [KotlinEnumClassSpec]. * @see [KotlinEnumClassSpecBuilder.builder] */ + @SuppressWarnings("unused") inline fun buildEnumClass(packageName: PackageName, simpleName: SimpleName, block: KotlinEnumClassSpecBuilderReceiver = {}) = buildEnumClass(className(packageName, simpleName), block) /** @@ -156,6 +216,7 @@ object KotlinCodeGeneration : KLogging() { * Build [KotlinFileSpec]. * @see [KotlinFileSpecBuilder.builder] */ + @SuppressWarnings("unused") inline fun buildFile(packageName: PackageName, simpleName: SimpleName, block: KotlinFileSpecBuilderReceiver = {}): KotlinFileSpec = buildFile(className(packageName, simpleName), block) /** @@ -174,6 +235,7 @@ object KotlinCodeGeneration : KLogging() { * Build [KotlinInterfaceSpec]. * @see [KotlinInterfaceSpecBuilder.builder] */ + @SuppressWarnings("unused") inline fun buildInterface(packageName: PackageName, simpleName: SimpleName, block: KotlinInterfaceSpecBuilderReceiver = {}): KotlinInterfaceSpec = buildInterface(className(packageName, simpleName), block) @@ -193,12 +255,13 @@ object KotlinCodeGeneration : KLogging() { * Build [KotlinParameterSpec]. * @see [KotlinParameterSpecBuilder.builder] */ - inline fun buildParameter(name: ParameterName, typeName: TypeName, block: KotlinParameterSpecBuilderReceiver = {}): KotlinParameterSpec = parameterBuilder(name, typeName).also(block).build() + inline fun buildParameter(name: ParameterName, typeName: TypeName, block: KotlinParameterSpecBuilderReceiver = {}) = parameterBuilder(name, typeName).also(block).build() /** * Build [KotlinParameterSpec]. * @see [KotlinParameterSpecBuilder.builder] */ + @SuppressWarnings("unused") inline fun buildParameter(name: ParameterName, type: KClass<*>, block: KotlinParameterSpecBuilderReceiver = {}): KotlinParameterSpec = buildParameter(name, type.asTypeName(), block) /** @@ -236,7 +299,7 @@ object KotlinCodeGeneration : KLogging() { * Static access for all builders. */ @ExperimentalKotlinPoetApi - @Suppress(SUPPRESS_CLASS_NAME, SUPPRESS_MEMBER_VISIBILITY_CAN_BE_PRIVATE) + @Suppress("ClassName", SUPPRESS_MEMBER_VISIBILITY_CAN_BE_PRIVATE) object builder { /** * @see KotlinAnnotationClassSpecBuilder @@ -246,6 +309,7 @@ object KotlinCodeGeneration : KLogging() { /** * @see KotlinAnnotationClassSpecBuilder */ + @SuppressWarnings("unused") fun annotationClassBuilder(packageName: PackageName, simpleName: SimpleName) = annotationClassBuilder(className(packageName, simpleName)) /** @@ -256,11 +320,13 @@ object KotlinCodeGeneration : KLogging() { /** * @see KotlinAnnotationSpecBuilder */ + @SuppressWarnings("unused") fun annotationBuilder(type: KClass) = annotationBuilder(type.asClassName()) /** * @see KotlinAnnotationSpecBuilder */ + @SuppressWarnings("unused") fun annotationBuilder(packageName: PackageName, simpleName: SimpleName) = annotationBuilder(className(packageName, simpleName)) /** @@ -301,16 +367,29 @@ object KotlinCodeGeneration : KLogging() { /** * @see KotlinDataClassSpecBuilder */ + @SuppressWarnings("unused") fun dataClassBuilder(packageName: PackageName, simpleName: SimpleName) = dataClassBuilder(className(packageName, simpleName)) + /** + * @see DelegateListValueClassSpecBuilder + */ + fun delegateListValueClassBuilder(className: ClassName, items: TypeName) = DelegateListValueClassSpecBuilder.builder(className, items) + + /** + * @see DelegateMapValueClassSpecBuilder + */ + fun delegateMapValueClassBuilder(className: ClassName, keyType: TypeName = DEFAULT_KEY_TYPE, valueType: TypeName) = DelegateMapValueClassSpecBuilder.builder(className, keyType, valueType) + /** * @see KotlinEnumClassSpecBuilder */ + @SuppressWarnings("unused") fun enumClassBuilder(name: SimpleName) = KotlinEnumClassSpecBuilder.builder(name) /** * @see KotlinEnumClassSpecBuilder */ + @SuppressWarnings("unused") fun enumClassBuilder(packageName: PackageName, name: SimpleName) = enumClassBuilder(className(packageName, name)) /** @@ -319,7 +398,7 @@ object KotlinCodeGeneration : KLogging() { fun enumClassBuilder(className: ClassName) = KotlinEnumClassSpecBuilder.builder(className) /** - * @see KotlinExceptionClassSpecBuilder + * @see RuntimeExceptionSpecBuilder */ fun runtimeExceptionClassBuilder(className: ClassName) = RuntimeExceptionSpecBuilder.builder(className) @@ -376,27 +455,29 @@ object KotlinCodeGeneration : KLogging() { /** * @see KotlinPropertySpecBuilder */ + @SuppressWarnings("unused") fun propertyBuilder(name: PropertyName, type: TypeName) = KotlinPropertySpecBuilder.builder(name, type) /** * @see KotlinPropertySpecBuilder */ + @SuppressWarnings("unused") fun propertyBuilder(name: PropertyName, type: KClass<*>) = propertyBuilder(name, type.asTypeName()) /** * @see KotlinFunSpecBuilder */ - fun setterBuilder(): KotlinFunSpecBuilder = KotlinFunSpecBuilder.setterBuilder() + fun setterBuilder() = KotlinFunSpecBuilder.setterBuilder() /** * @see KotlinTypeAliasSpecBuilder */ - fun typeAliasBuilder(name: TypeAliasName, type: TypeName): KotlinTypeAliasSpecBuilder = KotlinTypeAliasSpecBuilder.builder(name, type) + fun typeAliasBuilder(name: TypeAliasName, type: TypeName) = KotlinTypeAliasSpecBuilder.builder(name, type) /** * @see KotlinTypeAliasSpecBuilder */ - fun typeAliasBuilder(name: String, type: KClass<*>): KotlinTypeAliasSpecBuilder = KotlinTypeAliasSpecBuilder.builder(name, type) + fun typeAliasBuilder(name: String, type: KClass<*>) = KotlinTypeAliasSpecBuilder.builder(name, type) /** * @see KotlinValueClassSpecBuilder @@ -406,6 +487,7 @@ object KotlinCodeGeneration : KLogging() { /** * @see KotlinValueClassSpecBuilder */ + @SuppressWarnings("unused") fun valueClassBuilder(packageName: PackageName, simpleName: SimpleName) = valueClassBuilder(className(packageName, simpleName)) } @@ -422,7 +504,7 @@ object KotlinCodeGeneration : KLogging() { /** * Static to spi. */ - @Suppress(SUPPRESS_CLASS_NAME) + @Suppress("ClassName") object spi { /** * The default classLoader supplier fn. @@ -442,7 +524,7 @@ object KotlinCodeGeneration : KLogging() { /** * TypeSpec helpers. */ - @Suppress(SUPPRESS_CLASS_NAME) + @Suppress("ClassName") object typeSpec { fun TypeSpec.hasModifier(modifier: KModifier) = this.modifiers.contains(modifier) @@ -451,7 +533,7 @@ object KotlinCodeGeneration : KLogging() { val TypeSpec.isValueClass: Boolean get() = hasModifier(KModifier.VALUE) } - @Suppress(SUPPRESS_CLASS_NAME) + @Suppress("ClassName") object name { fun Collection.asCodeBlock(): CodeBlock = this.map { it.asCodeBlock() }.joinToCode(prefix = "[", suffix = "]") @@ -463,7 +545,7 @@ object KotlinCodeGeneration : KLogging() { /** * Constants for kotlin-poet formats. */ - @Suppress(SUPPRESS_CLASS_NAME) + @Suppress("ClassName") object format { const val FORMAT_STRING = "%S" const val FORMAT_STRING_TEMPLATE = "%P" diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt index 6df0adf..47d1ea3 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt @@ -28,8 +28,14 @@ class KotlinAnnotationClassSpecBuilder internal constructor( companion object { + /** + * Creates new builder. + */ fun builder(name: String): KotlinAnnotationClassSpecBuilder = builder(simpleClassName(name)) + /** + * Creates new builder. + */ fun builder(className: ClassName): KotlinAnnotationClassSpecBuilder = KotlinAnnotationClassSpecBuilder(className = className) } @@ -41,31 +47,33 @@ class KotlinAnnotationClassSpecBuilder internal constructor( private var repeatable: Boolean = false private var mustBeDocumented: Boolean = false - + /** + * Add mustBeDocumented. + */ fun mustBeDocumented() = apply { this.mustBeDocumented = true } + + /** + * Add repeatable. + */ fun repeatable() = apply { this.repeatable = true } - fun target(vararg targets: AnnotationTarget) = apply { this.targets.addAll(targets) } - fun retention(retention: AnnotationRetention) = apply { - this._retention = retention - } + /** + * Add retention. + */ + fun retention(retention: AnnotationRetention) = apply { this._retention = retention } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { constructorProperties[spec.name] = spec } - override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } - override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + /** + * Add target. + */ + fun target(vararg targets: AnnotationTarget) = apply { this.targets.addAll(targets) } - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } - override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } + internal fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } + override fun build(): KotlinAnnotationClassSpec { if (constructorProperties.isNotEmpty()) { - delegate.primaryConstructorWithProperties(toList(constructorProperties.values)) + val constructor = delegate.primaryConstructorWithProperties(toList(constructorProperties.values)) + delegate.primaryConstructor(constructor.build()) } if (targets.isNotEmpty()) { delegate.addAnnotation(buildAnnotation(Target::class) { @@ -87,6 +95,19 @@ class KotlinAnnotationClassSpecBuilder internal constructor( return KotlinAnnotationClassSpec(className = className, spec = delegate.build()) } + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { constructorProperties[spec.name] = spec } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } + override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt index 6468976..2ac80b6 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt @@ -35,16 +35,29 @@ class KotlinAnnotationSpecBuilder internal constructor( DelegatingBuilder { companion object { + + /** + * Creates new builder. + */ fun builder(type: ClassName): KotlinAnnotationSpecBuilder = KotlinAnnotationSpecBuilder( delegate = AnnotationSpecBuilder.builder(type) ) + /** + * Creates new builder. + */ fun builder(type: ParameterizedTypeName): KotlinAnnotationSpecBuilder = KotlinAnnotationSpecBuilder( delegate = AnnotationSpecBuilder.builder(type) ) + /** + * Creates new builder. + */ fun builder(type: KClass): KotlinAnnotationSpecBuilder = builder(type.asClassName()) + /** + * Creates new builder from spec. + */ fun from(spec: KotlinAnnotationSpecSupplier) = KotlinAnnotationSpecBuilder( delegate = spec.get().toBuilder().wrap() ) @@ -69,31 +82,71 @@ class KotlinAnnotationSpecBuilder internal constructor( private var multiLine = false private val members: MutableList = mutableListOf() - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - + /** + * If marked multiline all members become a new line. + */ fun multiLine() = apply { multiLine = true } + /** + * Add member to annotation. + */ fun addMember(codeBlock: CodeBlock): KotlinAnnotationSpecBuilder = apply { members.add(codeBlock) } + /** + * Add member to annotation. + */ fun addMember(format: String, vararg args: Any): KotlinAnnotationSpecBuilder = addMember(buildCodeBlock(format, *args)) + /** + * Add member to annotation. + */ fun addNameMember(memberName: MemberName): KotlinAnnotationSpecBuilder = addMember("%M", memberName) + /** + * Add member to annotation. + */ fun addKClassMember(name: String, value: KClass<*>) = addMember(member.kclass(name, value)) + + /** + * Add member to annotation. + */ fun addKClassMembers(name: String, vararg values: KClass<*>) = addMember(member.kclasses(name, *values)) + /** + * Add member to annotation. + */ fun addStringMember(name: String, value: String) = addMember(member.string(name, value)) + + /** + * Add member to annotation. + */ fun addStringMembers(name: String, vararg values: String) = addMember(member.strings(name, *values)) + /** + * Add member to annotation. + */ fun addEnumMember(name: String, value: Enum<*>): KotlinAnnotationSpecBuilder = addMember(member.enum(name, value)) + + /** + * Add member to annotation. + */ fun addEnumMembers(name: String, vararg values: Enum<*>): KotlinAnnotationSpecBuilder = addMember(member.enums(name, *values)) + /** + * Add member to annotation. + */ fun addNumberMember(name: String, value: Number): KotlinAnnotationSpecBuilder = addMember(member.number(name, value)) + + /** + * Add member to annotation. + */ fun addNumberMembers(name: String, vararg values: Number): KotlinAnnotationSpecBuilder = addMember(member.numbers(name, *values)) + /** + * Remove all members. + */ fun clearMembers() = apply { members.clear() } - override fun builder(block: AnnotationSpecBuilderReceiver) = apply { delegate.builder.block() } override fun build(): KotlinAnnotationSpec { if (members.isNotEmpty()) { @@ -106,8 +159,12 @@ class KotlinAnnotationSpecBuilder internal constructor( return KotlinAnnotationSpec(spec = delegate.build()) } - override fun spec(): KotlinAnnotationSpec = build() + // + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: AnnotationSpecBuilderReceiver) = apply { delegate.builder.block() } override fun get(): AnnotationSpec = build().get() + override fun spec(): KotlinAnnotationSpec = build() + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt index 88fb3e3..4858d82 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt @@ -27,37 +27,43 @@ class KotlinAnonymousClassSpecBuilder internal constructor( DelegatingBuilder { companion object { + /** + * Creates new builder. + */ fun builder(): KotlinAnonymousClassSpecBuilder = KotlinAnonymousClassSpecBuilder() } internal constructor() : this(delegate = TypeSpecBuilder.anonymousClassBuilder()) - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } - override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } + internal fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } + fun primaryConstructor(primaryConstructor: FunSpecSupplier?) = builder { this.primaryConstructor(primaryConstructor?.get()) } + fun superclass(superclass: TypeName) = builder { this.superclass(superclass) } fun superclass(superclass: KClass<*>) = builder { this.superclass(superclass) } fun addSuperclassConstructorParameter(format: String, vararg args: Any) = builder { this.addSuperclassConstructorParameter(format, *args) } fun addSuperclassConstructorParameter(codeBlock: CodeBlock) = builder { this.addSuperclassConstructorParameter(codeBlock) } - override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } - override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } - fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } - override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } override fun build(): KotlinAnonymousClassSpec = KotlinAnonymousClassSpec(delegate.build()) + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } + override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } + override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } + override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinClassSpecBuilder.kt index 5c5bd77..dc2f057 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinClassSpecBuilder.kt @@ -4,6 +4,7 @@ package io.toolisticon.kotlin.generation.builder import com.squareup.kotlinpoet.* import io.toolisticon.kotlin.generation.KotlinCodeGeneration.simpleClassName +import io.toolisticon.kotlin.generation.PropertyName import io.toolisticon.kotlin.generation.builder.KotlinConstructorPropertySpecBuilder.Companion.primaryConstructorWithProperties import io.toolisticon.kotlin.generation.poet.* import io.toolisticon.kotlin.generation.spec.* @@ -17,7 +18,7 @@ import kotlin.reflect.KClass @ExperimentalKotlinPoetApi class KotlinClassSpecBuilder internal constructor( internal val className: ClassName, - private val delegate: TypeSpecBuilder + internal val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, KotlinAnnotatableDocumentableModifiableBuilder, KotlinConstructorPropertySupport, @@ -27,27 +28,23 @@ class KotlinClassSpecBuilder internal constructor( KotlinTypeSpecHolderBuilder { companion object { + /** + * Creates new builder. + */ fun builder(name: String): KotlinClassSpecBuilder = builder(simpleClassName(name)) + + /** + * Creates new builder. + */ fun builder(className: ClassName): KotlinClassSpecBuilder = KotlinClassSpecBuilder(className = className) } internal constructor(className: ClassName) : this(className, TypeSpecBuilder.classBuilder(className)) - private val constructorProperties: LinkedHashMap = LinkedHashMap() + internal val constructorProperties: LinkedHashMap = LinkedHashMap() private var isSetPrimaryConstructor: Boolean = false - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { constructorProperties[spec.name] = spec } - override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } - override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } - override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } - override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } + internal fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } fun primaryConstructor(primaryConstructor: FunSpecSupplier?) = apply { @@ -66,17 +63,32 @@ class KotlinClassSpecBuilder internal constructor( fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } - override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } override fun build(): KotlinClassSpec { val hasConstructorProperties = constructorProperties.isNotEmpty() - check(!(hasConstructorProperties && isSetPrimaryConstructor)) { "Decide if you want to use the constructorProperty support OR define a custom primary constructor, not both." } + check( !(hasConstructorProperties && isSetPrimaryConstructor)) { "Decide if you want to use the constructorProperty support OR define a custom primary constructor, not both." } if (hasConstructorProperties) { - delegate.primaryConstructorWithProperties(toList(constructorProperties.values)) + val constructor = delegate.primaryConstructorWithProperties(toList(constructorProperties.values)) + delegate.primaryConstructor(constructor.build()) } return KotlinClassSpec(className = className, spec = delegate.build()) } + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { constructorProperties[spec.name] = spec } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } + override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } + override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } + override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt index 50fbd0a..ca15fe4 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt @@ -28,21 +28,15 @@ class KotlinCompanionObjectSpecBuilder internal constructor( KotlinTypeSpecHolderBuilder { companion object { + /** + * Creates new builder. + */ fun builder(name: String? = null): KotlinCompanionObjectSpecBuilder = KotlinCompanionObjectSpecBuilder(name) } internal constructor(name: String? = null) : this(TypeSpecBuilder.Companion.companionObjectBuilder(name)) - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName) = builder { delegate.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { delegate.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } - override fun addType(typeSpec: TypeSpecSupplier) = builder { delegate.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - - fun addOriginatingElement(originatingElement: Element) = builder { + internal fun addOriginatingElement(originatingElement: Element) = builder { delegate.addOriginatingElement( originatingElement ) @@ -55,29 +49,23 @@ class KotlinCompanionObjectSpecBuilder internal constructor( ) } - fun superclass(superclass: TypeName) = builder { delegate.superclass(superclass) } - fun superclass(superclass: KClass<*>) = builder { delegate.superclass(superclass) } - - fun addSuperclassConstructorParameter(format: String, vararg args: Any) = builder { - delegate.addSuperclassConstructorParameter( - format, - *args - ) - } + fun addInitializerBlock(block: CodeBlock) = builder { delegate.addInitializerBlock(block) } - fun addSuperclassConstructorParameter(codeBlock: CodeBlock) = builder { - delegate.addSuperclassConstructorParameter( - codeBlock - ) - } + override fun build(): KotlinCompanionObjectSpec = KotlinCompanionObjectSpec(spec = delegate.build()) + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { delegate.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { delegate.addModifiers(*modifiers) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } - - fun addInitializerBlock(block: CodeBlock) = builder { delegate.addInitializerBlock(block) } - + override fun addType(typeSpec: TypeSpecSupplier) = builder { delegate.addType(typeSpec.get()) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } - override fun build(): KotlinCompanionObjectSpec = KotlinCompanionObjectSpec(spec = delegate.build()) + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinConstructorPropertySpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinConstructorPropertySpecBuilder.kt index b2045ee..6e4a297 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinConstructorPropertySpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinConstructorPropertySpecBuilder.kt @@ -1,15 +1,13 @@ package io.toolisticon.kotlin.generation.builder -import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi -import com.squareup.kotlinpoet.FunSpec -import com.squareup.kotlinpoet.KModifier -import com.squareup.kotlinpoet.TypeName +import com.squareup.kotlinpoet.* import io.toolisticon.kotlin.generation.Builder +import io.toolisticon.kotlin.generation.poet.FunSpecBuilder +import io.toolisticon.kotlin.generation.poet.FunSpecBuilder.Companion.wrap import io.toolisticon.kotlin.generation.poet.KDoc import io.toolisticon.kotlin.generation.poet.TypeSpecBuilder -import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpecSupplier -import io.toolisticon.kotlin.generation.spec.KotlinConstructorPropertySpec -import io.toolisticon.kotlin.generation.spec.KotlinConstructorPropertySpecSupplier +import io.toolisticon.kotlin.generation.poet.TypeSpecSupplier +import io.toolisticon.kotlin.generation.spec.* import kotlin.reflect.KClass /** @@ -26,6 +24,10 @@ class KotlinConstructorPropertySpecBuilder internal constructor( KotlinConstructorPropertySpecSupplier { companion object { + + /** + * Creates new builder. + */ fun builder(name: String, type: TypeName): KotlinConstructorPropertySpecBuilder = KotlinConstructorPropertySpecBuilder( name = name, type = type, @@ -33,22 +35,17 @@ class KotlinConstructorPropertySpecBuilder internal constructor( parameterBuilder = KotlinParameterSpecBuilder.builder(name = name, type = type) ) - internal fun TypeSpecBuilder.primaryConstructorWithProperties(constructorProperties: List) { - val constructor = FunSpec.constructorBuilder() + internal fun TypeSpecBuilder.primaryConstructorWithProperties(constructorProperties: List): FunSpecBuilder { + val constructor = FunSpec.constructorBuilder().wrap() constructorProperties.forEach { constructor.addParameter(it.parameter.get()) this.addProperty(it.property.get()) } - this.primaryConstructor(constructor.build()) + return constructor } } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { parameterBuilder.addAnnotation(spec) } - override fun addKdoc(kdoc: KDoc) = apply { parameterBuilder.addKdoc(kdoc) } - override fun addModifiers(vararg modifiers: KModifier) = apply { propertyBuilder.addModifiers(*modifiers) } - override fun tag(type: KClass<*>, tag: Any?) = apply { propertyBuilder.tag(type, tag) } - override fun build(): KotlinConstructorPropertySpec { val parameter = parameterBuilder.build() val property = propertyBuilder @@ -60,7 +57,14 @@ class KotlinConstructorPropertySpecBuilder internal constructor( return KotlinConstructorPropertySpec(parameter = parameter, property = property) } + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { parameterBuilder.addAnnotation(spec) } + override fun addKdoc(kdoc: KDoc) = apply { parameterBuilder.addKdoc(kdoc) } + override fun addModifiers(vararg modifiers: KModifier) = apply { propertyBuilder.addModifiers(*modifiers) } + override fun addTag(type: KClass<*>, tag: Any?) = apply { propertyBuilder.addTag(type, tag) } override fun spec(): KotlinConstructorPropertySpec = build() + // + } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt index 09db23e..4da498f 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt @@ -27,7 +27,14 @@ class KotlinDataClassSpecBuilder internal constructor( KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder { companion object : KLogging() { + /** + * Creates new builder. + */ fun builder(name: String): KotlinDataClassSpecBuilder = builder(simpleClassName(name)) + + /** + * Creates new builder. + */ fun builder(className: ClassName): KotlinDataClassSpecBuilder = KotlinDataClassSpecBuilder(className) } @@ -42,33 +49,36 @@ class KotlinDataClassSpecBuilder internal constructor( private val constructorProperties = LinkedHashMap() - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { this.constructorProperties[spec.name] = spec } - override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } - override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } + internal fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } fun primaryConstructor(primaryConstructor: FunSpecSupplier?) = builder { this.primaryConstructor(primaryConstructor?.get()) } - override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } - override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } - fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } - override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } override fun build(): KotlinDataClassSpec { check(constructorProperties.isNotEmpty()) { "Data class must have at least one property." } - delegate.primaryConstructorWithProperties(toList(constructorProperties.values)) + val constructor = delegate.primaryConstructorWithProperties(toList(constructorProperties.values)) + delegate.primaryConstructor(constructor.build()) return KotlinDataClassSpec(className = className, spec = delegate.build()) } + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { this.constructorProperties[spec.name] = spec } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } + override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } + override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } + override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt index 8193eaa..909e32f 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt @@ -28,7 +28,14 @@ class KotlinEnumClassSpecBuilder internal constructor( KotlinTypeSpecHolderBuilder { companion object { + /** + * Creates new builder. + */ fun builder(name: String): KotlinEnumClassSpecBuilder = builder(simpleClassName(name)) + + /** + * Creates new builder. + */ fun builder(className: ClassName): KotlinEnumClassSpecBuilder = KotlinEnumClassSpecBuilder(className) } @@ -36,30 +43,30 @@ class KotlinEnumClassSpecBuilder internal constructor( delegate.addModifiers(KModifier.ENUM) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } - override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - fun addEnumConstant(name: String): KotlinEnumClassSpecBuilder = apply { delegate.addEnumConstant(name) } fun addEnumConstant(name: String, typeSpec: TypeSpec = TypeSpec.anonymousClassBuilder().build()): KotlinEnumClassSpecBuilder = builder { this.addEnumConstant(name, typeSpec) } - fun addOriginatingElement(originatingElement: Element): KotlinEnumClassSpecBuilder = builder { this.addOriginatingElement(originatingElement) } + internal fun addOriginatingElement(originatingElement: Element): KotlinEnumClassSpecBuilder = builder { this.addOriginatingElement(originatingElement) } fun addTypeVariable(typeVariable: TypeVariableName): KotlinEnumClassSpecBuilder = builder { this.addTypeVariable(typeVariable) } fun primaryConstructor(primaryConstructor: FunSpecSupplier?): KotlinEnumClassSpecBuilder = builder { this.primaryConstructor(primaryConstructor?.get()) } + fun addInitializerBlock(block: CodeBlock): KotlinEnumClassSpecBuilder = builder { this.addInitializerBlock(block) } + + override fun build(): KotlinEnumClassSpec = KotlinEnumClassSpec(className, delegate.build()) + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } - - fun addInitializerBlock(block: CodeBlock): KotlinEnumClassSpecBuilder = builder { this.addInitializerBlock(block) } - + override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } override fun builder(block: TypeSpecBuilderReceiver): KotlinEnumClassSpecBuilder = apply { delegate.builder.block() } - override fun build(): KotlinEnumClassSpec = KotlinEnumClassSpec(className, delegate.build()) + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinFileSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinFileSpecBuilder.kt index dcce5df..6bfbc1a 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinFileSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinFileSpecBuilder.kt @@ -4,8 +4,11 @@ package io.toolisticon.kotlin.generation.builder import com.squareup.kotlinpoet.* import io.toolisticon.kotlin.generation.BuilderSupplier -import io.toolisticon.kotlin.generation.poet.* +import io.toolisticon.kotlin.generation.poet.FileSpecBuilder import io.toolisticon.kotlin.generation.poet.FileSpecBuilder.Companion.wrap +import io.toolisticon.kotlin.generation.poet.FileSpecBuilderReceiver +import io.toolisticon.kotlin.generation.poet.TypeAliasSpecSupplier +import io.toolisticon.kotlin.generation.poet.TypeSpecSupplier import io.toolisticon.kotlin.generation.spec.* import io.toolisticon.kotlin.generation.support.SUPPRESS_UNUSED import kotlin.reflect.KClass @@ -21,34 +24,46 @@ class KotlinFileSpecBuilder internal constructor( KotlinMemberSpecHolderBuilder, KotlinTypeSpecHolderBuilder { companion object { + /** + * Creates new builder. + */ fun builder(className: ClassName): KotlinFileSpecBuilder { require(className.packageName.isNotEmpty()) { "cannot build file for empty package." } return KotlinFileSpecBuilder(delegate = FileSpecBuilder.builder(className)) } + /** + * Creates new builder. + */ fun builder(memberName: MemberName): KotlinFileSpecBuilder = KotlinFileSpecBuilder( delegate = FileSpecBuilder.builder(memberName) ) + /** + * Creates new builder. + */ fun builder(packageName: String, fileName: String): KotlinFileSpecBuilder = KotlinFileSpecBuilder( delegate = FileSpecBuilder.builder(packageName, fileName) ) + /** + * Creates new builder. + */ fun scriptBuilder(fileName: String, packageName: String = ""): KotlinFileSpecBuilder = KotlinFileSpecBuilder( delegate = FileSpecBuilder.scriptBuilder(fileName, packageName) ) + /** + * Creates new builder. + */ fun builder(spec: KotlinFileSpec) = builder(spec.get()) + /** + * Creates new builder. + */ fun builder(spec: FileSpec) = KotlinFileSpecBuilder(delegate = spec.toBuilder().wrap()) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } - override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - fun addAliasedImport(kclass: KClass<*>, alias: String) = builder { this.addAliasedImport(kclass, alias) } fun addAliasedImport(className: ClassName, alias: String) = builder { this.addAliasedImport(className, alias) } fun addAliasedImport(className: ClassName, memberName: String, alias: String) = builder { this.addAliasedImport(className, memberName, alias) } @@ -74,19 +89,22 @@ class KotlinFileSpecBuilder internal constructor( fun nextControlFlow(controlFlow: String, vararg args: Any) = builder { this.nextControlFlow(controlFlow, *args) } fun endControlFlow() = builder { this.endControlFlow() } - override fun builder(block: FileSpecBuilderReceiver) = apply { - delegate.builder.block() - } - override fun build(): KotlinFileSpec { val spec = delegate.build() return KotlinFileSpec(spec = spec) } - override fun spec(): KotlinFileSpec = build() - override fun get(): FileSpec = build().get() - + // override val className: ClassName = delegate.className + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } + override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: FileSpecBuilderReceiver) = apply { delegate.builder.block() } + override fun get(): FileSpec = build().get() + override fun spec(): KotlinFileSpec = build() + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt index b8ab8eb..9124a99 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt @@ -27,40 +27,55 @@ class KotlinFunSpecBuilder internal constructor( KotlinFunSpecSupplier { companion object { + /** + * Creates new builder. + */ fun builder(name: String): KotlinFunSpecBuilder = KotlinFunSpecBuilder( delegate = FunSpecBuilder.builder(name) ) + /** + * Creates new builder. + */ fun builder(memberName: MemberName): KotlinFunSpecBuilder = KotlinFunSpecBuilder( delegate = FunSpecBuilder.builder(memberName) ) + /** + * Creates new builder. + */ fun constructorBuilder(): KotlinFunSpecBuilder = KotlinFunSpecBuilder( delegate = FunSpecBuilder.constructorBuilder() ) + /** + * Creates new builder. + */ fun getterBuilder(): KotlinFunSpecBuilder = KotlinFunSpecBuilder( delegate = FunSpecBuilder.getterBuilder() ) + /** + * Creates new builder. + */ fun setterBuilder(): KotlinFunSpecBuilder = KotlinFunSpecBuilder( delegate = FunSpecBuilder.setterBuilder() ) + /** + * Creates new builder. + */ fun builder(spec: KotlinFunSpec) = builder(spec.get()) + /** + * Creates new builder. + */ fun builder(spec: FunSpec) = KotlinFunSpecBuilder(delegate = spec.toBuilder().wrap()) } fun addParameter(parameter: KotlinParameterSpecSupplier) = builder { this.addParameter(parameter.get()) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } + internal fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun jvmModifiers(modifiers: Iterable) = builder { this.jvmModifiers(modifiers) } fun addTypeVariables(typeVariables: Iterable) = builder { this.addTypeVariables(typeVariables) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } @@ -106,10 +121,18 @@ class KotlinFunSpecBuilder internal constructor( fun endControlFlow() = builder { this.endControlFlow() } fun addStatement(format: String, vararg args: Any) = builder { this.addStatement(format, *args) } - override fun builder(block: FunSpecBuilderReceiver): KotlinFunSpecBuilder = apply { delegate.builder.block() } override fun build(): KotlinFunSpec = KotlinFunSpec(spec = delegate.build()) - override fun spec(): KotlinFunSpec = build() + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: FunSpecBuilderReceiver): KotlinFunSpecBuilder = apply { delegate.builder.block() } override fun get(): FunSpec = build().get() + override fun spec(): KotlinFunSpec = build() + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt index 47c8236..8dcb9f5 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt @@ -28,7 +28,15 @@ class KotlinInterfaceSpecBuilder internal constructor( KotlinTypeSpecHolderBuilder { companion object { private const val DEFAULT_IS_FUNCTIONAL = false + + /** + * Creates new builder. + */ fun builder(name: String, isFunctionInterface: Boolean = DEFAULT_IS_FUNCTIONAL): KotlinInterfaceSpecBuilder = builder(simpleClassName(name), isFunctionInterface) + + /** + * Creates new builder. + */ fun builder(className: ClassName, isFunctionInterface: Boolean = DEFAULT_IS_FUNCTIONAL): KotlinInterfaceSpecBuilder = KotlinInterfaceSpecBuilder(className, isFunctionInterface) } @@ -37,6 +45,14 @@ class KotlinInterfaceSpecBuilder internal constructor( delegate = if (funInterface) TypeSpecBuilder.funInterfaceBuilder(className) else TypeSpecBuilder.interfaceBuilder(className) ) + internal fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } + fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } + + fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } + + override fun build(): KotlinInterfaceSpec = KotlinInterfaceSpec(className = className, spec = delegate.build()) + + // override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } @@ -44,18 +60,11 @@ class KotlinInterfaceSpecBuilder internal constructor( override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } - fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } - override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } - - fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } - + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } - override fun build(): KotlinInterfaceSpec = KotlinInterfaceSpec(className = className, spec = delegate.build()) + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt index f8d6d74..a6542b4 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt @@ -27,38 +27,42 @@ class KotlinObjectSpecBuilder internal constructor( KotlinSuperInterfaceSupport, KotlinTypeSpecHolderBuilder { companion object { + + /** + * Creates new builder. + */ fun builder(name: String): KotlinObjectSpecBuilder = builder(simpleClassName(name)) + + /** + * Creates new builder. + */ fun builder(className: ClassName): KotlinObjectSpecBuilder = KotlinObjectSpecBuilder(className = className) } internal constructor(className: ClassName) : this(className, TypeSpecBuilder.objectBuilder(className)) + internal fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } + + fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } + fun primaryConstructor(primaryConstructor: FunSpecSupplier?) = builder { this.primaryConstructor(primaryConstructor?.get()) } + + fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } + + override fun build(): KotlinObjectSpec = KotlinObjectSpec(className = className, spec = delegate.build()) + + // override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } - override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } - - fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } - fun primaryConstructor(primaryConstructor: FunSpecSupplier?) = builder { this.primaryConstructor(primaryConstructor?.get()) } - fun superclass(superclass: TypeName) = builder { this.superclass(superclass) } - fun superclass(superclass: KClass<*>) = builder { this.superclass(superclass) } - - fun addSuperclassConstructorParameter(format: String, vararg args: Any) = builder { this.addSuperclassConstructorParameter(format, *args) } - fun addSuperclassConstructorParameter(codeBlock: CodeBlock) = builder { this.addSuperclassConstructorParameter(codeBlock) } - override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } - - fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } - + override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } override fun builder(block: TypeSpecBuilderReceiver): KotlinObjectSpecBuilder = apply { delegate.builder.block() } - override fun build(): KotlinObjectSpec = KotlinObjectSpec(className = className, spec = delegate.build()) + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt index 52e0513..c0bbed1 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt @@ -25,45 +25,71 @@ class KotlinParameterSpecBuilder internal constructor( companion object { + /** + * Creates new builder. + */ fun builder(name: String, type: TypeName, vararg modifiers: KModifier): KotlinParameterSpecBuilder = KotlinParameterSpecBuilder( delegate = ParameterSpecBuilder.builder(name, type, *modifiers) ) + /** + * Creates new builder. + */ fun builder(name: String, type: Type, vararg modifiers: KModifier): KotlinParameterSpecBuilder = builder(name, type.asTypeName(), *modifiers) + /** + * Creates new builder. + */ fun builder(name: String, type: KClass<*>, vararg modifiers: KModifier): KotlinParameterSpecBuilder = KotlinParameterSpecBuilder( delegate = ParameterSpecBuilder.builder(name, type.asTypeName(), *modifiers) ) + /** + * Creates new builder. + */ fun builder(name: String, type: TypeName, modifiers: Iterable): KotlinParameterSpecBuilder = KotlinParameterSpecBuilder( delegate = ParameterSpecBuilder.builder(name, type, modifiers) ) + /** + * Creates new builder. + */ fun builder(name: String, type: Type, modifiers: Iterable): KotlinParameterSpecBuilder = KotlinParameterSpecBuilder( delegate = ParameterSpecBuilder.builder(name, type.asTypeName(), modifiers) ) + /** + * Creates new builder. + */ fun builder(name: String, type: KClass<*>, modifiers: Iterable): KotlinParameterSpecBuilder = KotlinParameterSpecBuilder( delegate = ParameterSpecBuilder.builder(name, type.asTypeName(), modifiers) ) + /** + * Creates new builder. + */ fun builder(spec: KotlinParameterSpec) = builder(spec.get()) + /** + * Creates new builder. + */ fun builder(spec: ParameterSpec) = KotlinParameterSpecBuilder(delegate = spec.toBuilder().wrap()) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - fun defaultValue(format: String, vararg args: Any?) = builder { this.defaultValue(format, *args) } fun defaultValue(codeBlock: CodeBlock?) = builder { this.defaultValue(codeBlock) } - override fun builder(block: ParameterSpecBuilderReceiver) = apply { delegate.builder.block() } override fun build(): KotlinParameterSpec = KotlinParameterSpec(spec = delegate.build()) - override fun spec(): KotlinParameterSpec = build() + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: ParameterSpecBuilderReceiver) = apply { delegate.builder.block() } override fun get(): ParameterSpec = build().get() + override fun spec(): KotlinParameterSpec = build() + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt index 2688086..697faa0 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt @@ -26,38 +26,54 @@ class KotlinPropertySpecBuilder internal constructor( companion object { + /** + * Creates new builder. + */ fun builder(name: PropertyName, type: TypeName, vararg modifiers: KModifier): KotlinPropertySpecBuilder = KotlinPropertySpecBuilder( delegate = PropertySpecBuilder.builder(name, type, *modifiers) ) + /** + * Creates new builder. + */ fun builder(name: PropertyName, type: Type, vararg modifiers: KModifier): KotlinPropertySpecBuilder = builder( name = name, type = type.asTypeName(), modifiers = modifiers ) + /** + * Creates new builder. + */ fun builder(name: PropertyName, type: KClass<*>, vararg modifiers: KModifier): KotlinPropertySpecBuilder = builder(name, type.asTypeName(), *modifiers) + /** + * Creates new builder. + */ fun builder(name: PropertyName, type: TypeName, modifiers: Iterable): KotlinPropertySpecBuilder = KotlinPropertySpecBuilder( delegate = PropertySpecBuilder.builder(name, type, modifiers) ) + /** + * Creates new builder. + */ fun builder(name: PropertyName, type: KClass<*>, modifiers: Iterable): KotlinPropertySpecBuilder = KotlinPropertySpecBuilder( delegate = PropertySpecBuilder.builder(name, type.asTypeName(), modifiers) ) + /** + * Creates new builder. + */ fun builder(spec: KotlinPropertySpec) = builder(spec.get()) + /** + * Creates new builder. + */ fun builder(spec: PropertySpec) = KotlinPropertySpecBuilder(delegate = spec.toBuilder().wrap()) } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addKdoc(kdoc: KDoc): KotlinPropertySpecBuilder = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } + internal fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun mutable(mutable: Boolean = true) = builder { this.mutable(mutable) } @@ -72,10 +88,18 @@ class KotlinPropertySpecBuilder internal constructor( fun receiver(receiverType: TypeName?) = builder { this.receiver(receiverType) } fun receiver(receiverType: KClass<*>) = builder { this.receiver(receiverType) } - override fun builder(block: PropertySpecBuilderReceiver) = apply { delegate.builder.block() } override fun build(): KotlinPropertySpec = KotlinPropertySpec(spec = delegate.build()) - override fun spec(): KotlinPropertySpec = build() + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addKdoc(kdoc: KDoc): KotlinPropertySpecBuilder = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: PropertySpecBuilderReceiver) = apply { delegate.builder.block() } override fun get(): PropertySpec = build().get() + override fun spec(): KotlinPropertySpec = build() + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt index db32893..51c75dd 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt @@ -22,24 +22,34 @@ class KotlinTypeAliasSpecBuilder internal constructor( KotlinTypeAliasSpecSupplier { companion object { + + /** + * Creates new builder. + */ fun builder(name: String, type: TypeName): KotlinTypeAliasSpecBuilder = KotlinTypeAliasSpecBuilder(name, type) + + /** + * Creates new builder. + */ fun builder(name: String, type: KClass<*>): KotlinTypeAliasSpecBuilder = builder(name, type.asTypeName()) } internal constructor(name: String, type: TypeName) : this(delegate = TypeAliasSpecBuilder.builder(name, type)) - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } fun addTypeVariables(typeVariables: Iterable) = builder { this.addTypeVariables(typeVariables) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - override fun builder(block: TypeAliasSpecBuilderReceiver) = apply { delegate.builder.block() } override fun build() = KotlinTypeAliasSpec(spec = delegate.build()) - override fun spec(): KotlinTypeAliasSpec = build() - override fun get(): TypeAliasSpec = build().get() + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: TypeAliasSpecBuilderReceiver) = apply { delegate.builder.block() } + override fun get(): TypeAliasSpec = build().get() + override fun spec(): KotlinTypeAliasSpec = build() + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt index 1bdab00..78bf92e 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt @@ -5,7 +5,11 @@ package io.toolisticon.kotlin.generation.builder import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.jvm.jvmInline import io.toolisticon.kotlin.generation.KotlinCodeGeneration.simpleClassName -import io.toolisticon.kotlin.generation.poet.* +import io.toolisticon.kotlin.generation.builder.KotlinFunSpecBuilder.Companion.constructorBuilder +import io.toolisticon.kotlin.generation.poet.KDoc +import io.toolisticon.kotlin.generation.poet.TypeSpecBuilder +import io.toolisticon.kotlin.generation.poet.TypeSpecBuilderReceiver +import io.toolisticon.kotlin.generation.poet.TypeSpecSupplier import io.toolisticon.kotlin.generation.spec.* import io.toolisticon.kotlin.generation.support.SUPPRESS_UNUSED import javax.lang.model.element.Element @@ -17,7 +21,7 @@ import kotlin.reflect.KClass @ExperimentalKotlinPoetApi class KotlinValueClassSpecBuilder internal constructor( val className: ClassName, - private val delegate: TypeSpecBuilder + internal val delegate: TypeSpecBuilder ) : KotlinGeneratorTypeSpecBuilder, KotlinAnnotatableDocumentableModifiableBuilder, KotlinConstructorPropertySupport, @@ -27,49 +31,64 @@ class KotlinValueClassSpecBuilder internal constructor( KotlinTypeSpecHolderBuilder { companion object { + + /** + * Creates new builder. + */ fun builder(name: String): KotlinValueClassSpecBuilder = builder(simpleClassName(name)) + + /** + * Creates new builder. + */ fun builder(className: ClassName): KotlinValueClassSpecBuilder = KotlinValueClassSpecBuilder(className) } - lateinit var constructorProperty: KotlinConstructorPropertySpecSupplier + internal lateinit var constructorProperty: KotlinConstructorPropertySpecSupplier internal constructor(className: ClassName) : this(className = className, delegate = TypeSpecBuilder.classBuilder(className)) { delegate.addModifiers(KModifier.VALUE) delegate.builder.jvmInline() } - override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } - override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { this.constructorProperty = spec } - override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } - override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } - override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } - override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } - override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } - override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } - override fun tag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } + internal fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } fun addTypeVariable(typeVariable: TypeVariableName) = builder { this.addTypeVariable(typeVariable) } - override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } - override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } - fun addInitializerBlock(block: CodeBlock) = builder { this.addInitializerBlock(block) } - override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } + override fun build(): KotlinValueClassSpec = build { } - override fun build(): KotlinValueClassSpec { + /** + * Use internally when creating extra builders that re-use this builder. + */ + internal fun build(block: KotlinValueClassSpecBuilderReceiver): KotlinValueClassSpec { check(::constructorProperty.isInitialized) { "Value class must have exactly one property." } - val constructor = KotlinFunSpecBuilder.constructorBuilder() + val constructor = constructorBuilder() .addParameter(this.constructorProperty.spec().parameter) .build() delegate.addProperty(constructorProperty.spec().property.get()) delegate.builder.primaryConstructor(constructor.get()) + this.block() + return KotlinValueClassSpec(className = className, spec = delegate.build()) } + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec.get()) } + override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { this.constructorProperty = spec } + override fun contextReceivers(vararg receiverTypes: TypeName) = builder { this.contextReceivers(*receiverTypes) } + override fun addFunction(funSpec: KotlinFunSpecSupplier) = apply { delegate.addFunction(funSpec.get()) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc.get()) } + override fun addModifiers(vararg modifiers: KModifier) = builder { this.addModifiers(*modifiers) } + override fun addProperty(propertySpec: KotlinPropertySpecSupplier) = apply { delegate.addProperty(propertySpec.get()) } + override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = builder { this.addSuperinterface(superinterface, constructorParameter) } + override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = builder { this.addSuperinterface(superinterface, delegate) } + override fun addType(typeSpec: TypeSpecSupplier) = builder { this.addType(typeSpec.get()) } + override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } + // } @ExperimentalKotlinPoetApi diff --git a/kotlin-code-generation/src/main/kotlin/builder/_types.kt b/kotlin-code-generation/src/main/kotlin/builder/_types.kt index be17722..6b5f369 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/_types.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/_types.kt @@ -47,7 +47,7 @@ interface KotlinGeneratorTypeSpecBuilder : KotlinTaggableBuilder { +interface KotlinConstructorPropertySupport : KotlinTaggableBuilder { /** * Implementing builder needs to store the spec provided and apply it to the build. @@ -263,14 +263,14 @@ sealed interface KotlinTaggableBuilder { /** * @see com.squareup.kotlinpoet.Taggable#Builder#tag */ - fun tag(type: KClass<*>, tag: Any?): SELF + fun addTag(type: KClass<*>, tag: Any?): SELF /** * Store tag under key of ::class. */ - fun tag(tag: T): SELF = tag(tag::class, tag) + fun addTag(tag: T): SELF = addTag(tag::class, tag) - fun removeTag(type: KClass<*>): SELF = tag(type, null) + fun removeTag(type: KClass<*>): SELF = addTag(type, null) } /** diff --git a/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateListValueClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateListValueClassSpecBuilder.kt new file mode 100644 index 0000000..d844d04 --- /dev/null +++ b/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateListValueClassSpecBuilder.kt @@ -0,0 +1,85 @@ +package io.toolisticon.kotlin.generation.builder.extra + +import com.squareup.kotlinpoet.* +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.simpleClassName +import io.toolisticon.kotlin.generation.SimpleName +import io.toolisticon.kotlin.generation.builder.KotlinAnnotatableDocumentableModifiableBuilder +import io.toolisticon.kotlin.generation.builder.KotlinGeneratorTypeSpecBuilder +import io.toolisticon.kotlin.generation.builder.KotlinSuperInterfaceSupport +import io.toolisticon.kotlin.generation.builder.KotlinValueClassSpecBuilder +import io.toolisticon.kotlin.generation.poet.KDoc +import io.toolisticon.kotlin.generation.spec.ClassSpecType +import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpecSupplier +import io.toolisticon.kotlin.generation.spec.KotlinValueClassSpec +import kotlin.reflect.KClass + +/** + * Generator that wraps a list holding given elementType in a value class and delegates the list. + */ +@ExperimentalKotlinPoetApi +class DelegateListValueClassSpecBuilder internal constructor( + private val delegate: KotlinValueClassSpecBuilder, + private val elementType: TypeName, +) : KotlinGeneratorTypeSpecBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, + KotlinSuperInterfaceSupport { + + companion object { + /** + * Creates new builder. + */ + fun builder(name: SimpleName, elementType: TypeName) = builder( + className = simpleClassName(name), + elementType = elementType + ) + + /** + * Creates new builder. + */ + fun builder(className: ClassName, elementType: TypeName) = DelegateListValueClassSpecBuilder( + className = className, + elementType = elementType + ) + } + + private var propertyName: String = "delegate" + + internal constructor(className: ClassName, elementType: TypeName) : this( + delegate = KotlinValueClassSpecBuilder(className), + elementType = List::class.asClassName().parameterizedBy(elementType), + ) { + delegate.addTag(ClassSpecType.LIST) + } + + /** + * Modify the default property name. + */ + fun propertyName(propertyName: String) = apply { + require(propertyName.isNotBlank()) { "Property name cannot be blank." } + this.propertyName = propertyName + } + + override fun build(): KotlinValueClassSpec { + delegate.addConstructorProperty(propertyName, elementType) { + makePrivate() + } + val constructorProperty = delegate.constructorProperty + return delegate.build { + addSuperinterface(elementType, constructorProperty.name) + } + } + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc) } + override fun addModifiers(vararg modifiers: KModifier) = apply { delegate.addModifiers(*modifiers) } + override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = apply { delegate.addSuperinterface(superinterface, constructorParameter) } + override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = apply { this.delegate.addSuperinterface(superinterface, delegate) } + override fun addTag(type: KClass<*>, tag: Any?) = apply { delegate.addTag(type, tag) } + override fun builder(block: TypeSpec.Builder.() -> Unit) = apply { delegate.builder(block) } + // +} + +@ExperimentalKotlinPoetApi +typealias DelegateListValueClassSpecBuilderReceiver = DelegateListValueClassSpecBuilder.() -> Unit diff --git a/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateMapValueClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateMapValueClassSpecBuilder.kt new file mode 100644 index 0000000..8e0375f --- /dev/null +++ b/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateMapValueClassSpecBuilder.kt @@ -0,0 +1,85 @@ +package io.toolisticon.kotlin.generation.builder.extra + +import com.squareup.kotlinpoet.* +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.simpleClassName +import io.toolisticon.kotlin.generation.SimpleName +import io.toolisticon.kotlin.generation.builder.KotlinAnnotatableDocumentableModifiableBuilder +import io.toolisticon.kotlin.generation.builder.KotlinGeneratorTypeSpecBuilder +import io.toolisticon.kotlin.generation.builder.KotlinSuperInterfaceSupport +import io.toolisticon.kotlin.generation.builder.KotlinValueClassSpecBuilder +import io.toolisticon.kotlin.generation.poet.KDoc +import io.toolisticon.kotlin.generation.spec.ClassSpecType +import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpecSupplier +import io.toolisticon.kotlin.generation.spec.KotlinValueClassSpec +import kotlin.reflect.KClass + +/** + * Generator that wraps a map holding given key/valueType in a value class and delegates the map. + */ +@ExperimentalKotlinPoetApi +class DelegateMapValueClassSpecBuilder internal constructor( + private val delegate: KotlinValueClassSpecBuilder, + private val mapType: TypeName, +) : KotlinGeneratorTypeSpecBuilder, + KotlinAnnotatableDocumentableModifiableBuilder, + KotlinSuperInterfaceSupport { + + companion object { + val DEFAULT_KEY_TYPE = String::class.asTypeName() + + /** + * Creates new builder. + */ + fun builder(name: SimpleName, keyType: TypeName = DEFAULT_KEY_TYPE, valueType: TypeName) = builder(className = simpleClassName(name), keyType = keyType, valueType = valueType) + + /** + * Creates new builder. + */ + fun builder(className: ClassName, keyType: TypeName = DEFAULT_KEY_TYPE, valueType: TypeName) = DelegateMapValueClassSpecBuilder( + className = className, + keyType = keyType, + valueType = valueType + ) + } + + private var propertyName: String = "delegate" + + internal constructor(className: ClassName, keyType: TypeName, valueType: TypeName) : this( + delegate = KotlinValueClassSpecBuilder(className), + mapType = Map::class.asTypeName().parameterizedBy(keyType, valueType) + ) { + delegate.addTag(ClassSpecType.MAP) + } + + /** + * Modify the default property name. + */ + fun propertyName(propertyName: String) = apply { + require(propertyName.isNotBlank()) { "Property name cannot be blank." } + this.propertyName = propertyName + } + + override fun build(): KotlinValueClassSpec { + delegate.addConstructorProperty(propertyName, mapType) { + makePrivate() + } + val constructorProperty = delegate.constructorProperty + return delegate.build { + addSuperinterface(mapType, constructorProperty.name) + } + } + + // + override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec) } + override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc) } + override fun addModifiers(vararg modifiers: KModifier) = apply { delegate.addModifiers(*modifiers) } + override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = apply { delegate.addSuperinterface(superinterface, constructorParameter) } + override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) = apply { this.delegate.addSuperinterface(superinterface, delegate) } + override fun builder(block: TypeSpec.Builder.() -> Unit) = apply { delegate.builder(block) } + override fun addTag(type: KClass<*>, tag: Any?) = apply { delegate.addTag(type, tag) } + // +} + +@ExperimentalKotlinPoetApi +typealias DelegateMapValueClassSpecBuilderReceiver = DelegateMapValueClassSpecBuilder.() -> Unit diff --git a/kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt index 0e78fe0..35a090a 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt @@ -8,20 +8,16 @@ import com.squareup.kotlinpoet.TypeName import com.squareup.kotlinpoet.TypeSpec import com.squareup.kotlinpoet.asTypeName import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildParameter -import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.constructorBuilder import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_NAME import io.toolisticon.kotlin.generation.KotlinCodeGeneration.format.FORMAT_STRING_TEMPLATE import io.toolisticon.kotlin.generation.KotlinCodeGeneration.name.nullable import io.toolisticon.kotlin.generation.KotlinCodeGeneration.simpleClassName -import io.toolisticon.kotlin.generation.builder.KotlinAnnotatableDocumentableModifiableBuilder -import io.toolisticon.kotlin.generation.builder.KotlinClassSpecBuilder -import io.toolisticon.kotlin.generation.builder.KotlinFunSpecBuilder -import io.toolisticon.kotlin.generation.builder.KotlinGeneratorTypeSpecBuilder -import io.toolisticon.kotlin.generation.builder.KotlinSuperInterfaceSupport +import io.toolisticon.kotlin.generation.builder.* +import io.toolisticon.kotlin.generation.builder.KotlinConstructorPropertySpecBuilder.Companion.primaryConstructorWithProperties +import io.toolisticon.kotlin.generation.poet.FunSpecBuilder import io.toolisticon.kotlin.generation.poet.KDoc -import io.toolisticon.kotlin.generation.spec.ClassSpecType -import io.toolisticon.kotlin.generation.spec.KotlinAnnotationSpecSupplier -import io.toolisticon.kotlin.generation.spec.KotlinClassSpec +import io.toolisticon.kotlin.generation.spec.* +import io.toolisticon.kotlin.generation.spec.toList import kotlin.reflect.KClass /** @@ -33,12 +29,21 @@ class RuntimeExceptionSpecBuilder internal constructor( private val delegate: KotlinClassSpecBuilder, ) : KotlinGeneratorTypeSpecBuilder, KotlinAnnotatableDocumentableModifiableBuilder, + KotlinConstructorPropertySupport, KotlinSuperInterfaceSupport { + companion object { private val NULLABLE_THROWABLE = Throwable::class.asTypeName().nullable() private val FIND_TEMPLATE_PARAMS = Regex("\\$(\\w+)") + /** + * Creates new builder. + */ fun builder(name: String): RuntimeExceptionSpecBuilder = builder(simpleClassName(name)) + + /** + * Creates new builder. + */ fun builder(className: ClassName): RuntimeExceptionSpecBuilder = RuntimeExceptionSpecBuilder(className = className) /** @@ -53,10 +58,14 @@ class RuntimeExceptionSpecBuilder internal constructor( private val _messageTemplateParameters = LinkedHashMap() internal constructor(className: ClassName) : this(delegate = KotlinClassSpecBuilder(className = className)) { - tag(ClassSpecType.EXCEPTION) + addTag(ClassSpecType.EXCEPTION) delegate.superclass(RuntimeException::class) } + /** + * Sets a string message template. Placeholders `\$foo` are parsed and automatically used + * as parameters of type `Any`, unless explicitly overwritten by `addParameter` or `addConstructorProperty`. + */ fun messageTemplate(messageTemplate: String) = apply { _messageTemplate = messageTemplate @@ -65,12 +74,21 @@ class RuntimeExceptionSpecBuilder internal constructor( } } + /** + * Define the type of a placeholder parameter in the message template. + */ fun addParameter(name: String, type: KClass<*>) = addParameter(name, type.asTypeName()) + /** + * Define the type of a placeholder parameter in the message template. + */ fun addParameter(name: String, type: TypeName) = apply { _messageTemplateParameters[name] = type } + /** + * Include the cause (Throwable) in the constructor. + */ fun includeCause(name: String? = null) = apply { _cause = true to (name ?: _cause.second) } @@ -79,8 +97,16 @@ class RuntimeExceptionSpecBuilder internal constructor( require(::_messageTemplate.isInitialized) { "Message template must be initialized." } delegate.addSuperclassConstructorParameter(FORMAT_STRING_TEMPLATE, _messageTemplate) - val constructorBuilder: KotlinFunSpecBuilder = _messageTemplateParameters.entries.fold(constructorBuilder()) { acc, cur -> - acc.addParameter(cur.key, cur.value) + val constructorProperties = delegate.constructorProperties + + val constructorBuilder: FunSpecBuilder = if (constructorProperties.isNotEmpty()) { + delegate.delegate.primaryConstructorWithProperties(toList(constructorProperties.values)) + } else { + FunSpecBuilder.constructorBuilder() + } + + _messageTemplateParameters.entries.filterNot { constructorProperties.containsKey(it.key) }.forEach { (name, type) -> + constructorBuilder.addParameter(name, type) } if (_cause.first) { @@ -89,23 +115,26 @@ class RuntimeExceptionSpecBuilder internal constructor( defaultValue("null") } - constructorBuilder.addParameter(nullableCauseParameter) + constructorBuilder.addParameter(nullableCauseParameter.get()) } - return delegate.primaryConstructor(constructorBuilder).build() + // TODO bypass classSpecBuild until issue 47 is solved + return KotlinClassSpec( + className = delegate.className, + spec = delegate.delegate + .primaryConstructor(constructorBuilder.build()) + .build() + ) } // override fun addAnnotation(spec: KotlinAnnotationSpecSupplier) = apply { delegate.addAnnotation(spec) } + override fun addConstructorProperty(spec: KotlinConstructorPropertySpecSupplier) = apply { delegate.addConstructorProperty(spec) } override fun addKdoc(kdoc: KDoc) = apply { delegate.addKdoc(kdoc) } override fun addModifiers(vararg modifiers: KModifier) = apply { delegate.addModifiers(*modifiers) } override fun addSuperinterface(superinterface: TypeName, constructorParameter: String) = apply { delegate.addSuperinterface(superinterface, constructorParameter) } - override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock): RuntimeExceptionSpecBuilder { - TODO("Not yet implemented") - } - - //override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock) : RuntimeExceptionSpecBuilder= apply { delegate.addS } - override fun tag(type: KClass<*>, tag: Any?) = apply { delegate.tag(type, tag) } + override fun addSuperinterface(superinterface: TypeName, delegate: CodeBlock): RuntimeExceptionSpecBuilder = apply { this.delegate.addSuperinterface(superinterface, delegate) } + override fun addTag(type: KClass<*>, tag: Any?) = apply { delegate.addTag(type, tag) } override fun builder(block: TypeSpec.Builder.() -> Unit): RuntimeExceptionSpecBuilder = apply { delegate.builder(block) } // } diff --git a/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt index d9deb80..cf2de7c 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt @@ -9,14 +9,25 @@ import kotlin.reflect.KClass */ class AnnotationSpecBuilder( override val builder: AnnotationSpec.Builder -) : PoetSpecBuilder, PoetTaggableBuilder { +) : PoetSpecBuilder, + AnnotationSpecSupplier, + PoetTaggableBuilder { companion object { - fun AnnotationSpec.Builder.wrap() = AnnotationSpecBuilder(this) + internal fun AnnotationSpec.Builder.wrap() = AnnotationSpecBuilder(this) + /** + * Creates new builder. + */ fun builder(type: ClassName): AnnotationSpecBuilder = AnnotationSpec.builder(type).wrap() + /** + * Creates new builder. + */ fun builder(type: ParameterizedTypeName): AnnotationSpecBuilder = AnnotationSpec.builder(type).wrap() + /** + * Creates new builder. + */ fun builder(type: KClass): AnnotationSpecBuilder = builder(type.asClassName()) } diff --git a/kotlin-code-generation/src/main/kotlin/poet/FileSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/FileSpecBuilder.kt index abcfa74..7aca34a 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/FileSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/FileSpecBuilder.kt @@ -12,6 +12,7 @@ import kotlin.reflect.KClass class FileSpecBuilder( override val builder: FileSpec.Builder ) : PoetSpecBuilder, + FileSpecSupplier, PoetAnnotatableBuilder, PoetMemberSpecHolderBuilder, PoetTypeSpecHolderBuilder, diff --git a/kotlin-code-generation/src/main/kotlin/poet/FunSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/FunSpecBuilder.kt index 9569ae3..70e431d 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/FunSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/FunSpecBuilder.kt @@ -12,6 +12,7 @@ import kotlin.reflect.KClass class FunSpecBuilder( override val builder: FunSpec.Builder ) : PoetSpecBuilder, + FunSpecSupplier, PoetAnnotatableBuilder, PoetContextReceivableBuilder, PoetDocumentableBuilder, diff --git a/kotlin-code-generation/src/main/kotlin/poet/ParameterSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/ParameterSpecBuilder.kt index 88dd123..01ada1c 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/ParameterSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/ParameterSpecBuilder.kt @@ -10,6 +10,7 @@ import kotlin.reflect.KClass class ParameterSpecBuilder( override val builder: ParameterSpec.Builder ) : PoetSpecBuilder, + ParameterSpecSupplier, PoetAnnotatableBuilder, PoetTaggableBuilder, PoetDocumentableBuilder { diff --git a/kotlin-code-generation/src/main/kotlin/poet/PropertySpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/PropertySpecBuilder.kt index 4c86cca..d6d09d3 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/PropertySpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/PropertySpecBuilder.kt @@ -12,6 +12,7 @@ import kotlin.reflect.KClass class PropertySpecBuilder( override val builder: PropertySpec.Builder ) : PoetSpecBuilder, + PropertySpecSupplier, PoetAnnotatableBuilder, PoetContextReceivableBuilder, PoetTaggableBuilder, diff --git a/kotlin-code-generation/src/main/kotlin/poet/TypeAliasSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/TypeAliasSpecBuilder.kt index 755ef4e..a16d59b 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/TypeAliasSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/TypeAliasSpecBuilder.kt @@ -9,6 +9,7 @@ import kotlin.reflect.KClass class TypeAliasSpecBuilder( override val builder: TypeAliasSpec.Builder ) : PoetSpecBuilder, + TypeAliasSpecSupplier, PoetAnnotatableBuilder, PoetTaggableBuilder, PoetDocumentableBuilder { diff --git a/kotlin-code-generation/src/main/kotlin/poet/TypeSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/TypeSpecBuilder.kt index 9264495..013c1d4 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/TypeSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/TypeSpecBuilder.kt @@ -24,6 +24,7 @@ import kotlin.reflect.KClass class TypeSpecBuilder( override val builder: TypeSpec.Builder ) : PoetSpecBuilder, + TypeSpecSupplier, PoetAnnotatableBuilder, PoetContextReceivableBuilder, PoetDocumentableBuilder, diff --git a/kotlin-code-generation/src/test/kotlin/spec/DelegateListValueClassSpecTest.kt b/kotlin-code-generation/src/test/kotlin/spec/DelegateListValueClassSpecTest.kt new file mode 100644 index 0000000..01d1393 --- /dev/null +++ b/kotlin-code-generation/src/test/kotlin/spec/DelegateListValueClassSpecTest.kt @@ -0,0 +1,38 @@ +package io.toolisticon.kotlin.generation.spec + +import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi +import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildDelegateListValueClass +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +@ExperimentalKotlinPoetApi +internal class DelegateListValueClassSpecTest { + + @Test + fun `create delegate list`() { + + val list = buildDelegateListValueClass( + packageName = "xyz", + simpleName = "MyList", + items = String::class + ) { + propertyName("foo") + }.toFileSpec() + + assertThat(list.code).isEqualTo( + """ + package xyz + + import kotlin.String + import kotlin.collections.List + import kotlin.jvm.JvmInline + + @JvmInline + public value class MyList( + private val foo: List, + ) : List by foo + + """.trimIndent() + ) + } +} diff --git a/kotlin-code-generation/src/test/kotlin/spec/KotlinExceptionClassTest.kt b/kotlin-code-generation/src/test/kotlin/spec/KotlinExceptionClassTest.kt index c987a83..6eb2eeb 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/KotlinExceptionClassTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/KotlinExceptionClassTest.kt @@ -13,7 +13,9 @@ class KotlinExceptionClassTest { val exception = KotlinCodeGeneration.buildRuntimeExceptionClass("foo", "DummyException") { addKdoc(" This DummyException indicates something really went wrong. Totally!") messageTemplate("Something bad happened, expected=\$foo but got \$bar.") - addParameter("foo", Int::class) + addConstructorProperty("foo", Int::class) { + makePrivate() + } addParameter("bar", Long::class) includeCause("e") }.toFileSpec() @@ -31,7 +33,7 @@ class KotlinExceptionClassTest { * This DummyException indicates something really went wrong. Totally! */ public class DummyException( - foo: Int, + private val foo: Int, bar: Long, e: Throwable? = null, ) : RuntimeException(""${'"'}Something bad happened, expected=${'$'}foo but got ${'$'}bar.""${'"'}, e) From 1ceb4595015a8aaa866924c2423dc693f6a7aee1 Mon Sep 17 00:00:00 2001 From: Jan Galinski Date: Thu, 12 Sep 2024 00:09:50 +0200 Subject: [PATCH 7/7] Update for next development version --- _build/parent/pom.xml | 2 +- _build/report-generator/pom.xml | 2 +- _itest/builder-itest/pom.xml | 2 +- _itest/pom.xml | 2 +- _itest/spi-itest/pom.xml | 2 +- kotlin-code-generation-bom/pom.xml | 2 +- kotlin-code-generation-test/pom.xml | 2 +- kotlin-code-generation/pom.xml | 2 +- pom.xml | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/_build/parent/pom.xml b/_build/parent/pom.xml index 2d56614..d2e4ed2 100644 --- a/_build/parent/pom.xml +++ b/_build/parent/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-root - 0.0.7-SNAPSHOT + 0.0.7 ../../pom.xml diff --git a/_build/report-generator/pom.xml b/_build/report-generator/pom.xml index 2dd79bd..dfd8b52 100644 --- a/_build/report-generator/pom.xml +++ b/_build/report-generator/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-parent - 0.0.7-SNAPSHOT + 0.0.7 ../parent/pom.xml diff --git a/_itest/builder-itest/pom.xml b/_itest/builder-itest/pom.xml index 65bcb0f..d980e4c 100644 --- a/_itest/builder-itest/pom.xml +++ b/_itest/builder-itest/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-itest-root - 0.0.7-SNAPSHOT + 0.0.7 io.toolisticon.kotlin.generation.itest diff --git a/_itest/pom.xml b/_itest/pom.xml index 2b0cafd..5c205ed 100644 --- a/_itest/pom.xml +++ b/_itest/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-parent - 0.0.7-SNAPSHOT + 0.0.7 ../_build/parent/pom.xml diff --git a/_itest/spi-itest/pom.xml b/_itest/spi-itest/pom.xml index 4fac7d0..23a552c 100644 --- a/_itest/spi-itest/pom.xml +++ b/_itest/spi-itest/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-itest-root - 0.0.7-SNAPSHOT + 0.0.7 io.toolisticon.kotlin.generation.itest diff --git a/kotlin-code-generation-bom/pom.xml b/kotlin-code-generation-bom/pom.xml index caa48e4..faf9143 100644 --- a/kotlin-code-generation-bom/pom.xml +++ b/kotlin-code-generation-bom/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-root - 0.0.7-SNAPSHOT + 0.0.7 io.toolisticon.kotlin.generation diff --git a/kotlin-code-generation-test/pom.xml b/kotlin-code-generation-test/pom.xml index 8183db5..18f12ab 100644 --- a/kotlin-code-generation-test/pom.xml +++ b/kotlin-code-generation-test/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-parent - 0.0.7-SNAPSHOT + 0.0.7 ../_build/parent/pom.xml diff --git a/kotlin-code-generation/pom.xml b/kotlin-code-generation/pom.xml index 5ac4a78..f5b74a6 100644 --- a/kotlin-code-generation/pom.xml +++ b/kotlin-code-generation/pom.xml @@ -5,7 +5,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-parent - 0.0.7-SNAPSHOT + 0.0.7 ../_build/parent/pom.xml diff --git a/pom.xml b/pom.xml index cd5a88a..a1e783d 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ io.toolisticon.kotlin.generation._ kotlin-code-generation-root - 0.0.7-SNAPSHOT + 0.0.7 pom: ${project.artifactId} Root of kotlin-code-generation