From 1c7066fe7ce05e53a7dc945aae706ecc35fd1e93 Mon Sep 17 00:00:00 2001 From: Jan Galinski Date: Wed, 11 Sep 2024 17:48:33 +0200 Subject: [PATCH] provide list and map, clean up and refactor, fixes #51 --- .../test/kotlin/DelegateStringListITest.kt | 41 ++++++++ .../test/kotlin/DelegateStringLongMapITest.kt | 42 +++++++++ .../src/test/kotlin/DummyExceptionITest.kt | 52 +++++++++++ .../src/test/kotlin/HelloWorldExampleITest.kt | 1 - .../src/main/kotlin/KotlinCodeGeneration.kt | 40 +++++++- .../KotlinAnnotationClassSpecBuilder.kt | 33 +++---- .../builder/KotlinAnnotationSpecBuilder.kt | 9 +- .../KotlinAnonymousClassSpecBuilder.kt | 27 +++--- .../kotlin/builder/KotlinClassSpecBuilder.kt | 37 ++++---- .../KotlinCompanionObjectSpecBuilder.kt | 39 +++----- .../KotlinConstructorPropertySpecBuilder.kt | 30 +++--- .../builder/KotlinDataClassSpecBuilder.kt | 31 ++++--- .../builder/KotlinEnumClassSpecBuilder.kt | 26 +++--- .../kotlin/builder/KotlinFileSpecBuilder.kt | 27 +++--- .../kotlin/builder/KotlinFunSpecBuilder.kt | 18 ++-- .../builder/KotlinInterfaceSpecBuilder.kt | 19 ++-- .../kotlin/builder/KotlinObjectSpecBuilder.kt | 30 +++--- .../builder/KotlinParameterSpecBuilder.kt | 14 +-- .../builder/KotlinPropertySpecBuilder.kt | 17 ++-- .../builder/KotlinTypeAliasSpecBuilder.kt | 14 +-- .../builder/KotlinValueClassSpecBuilder.kt | 45 +++++---- .../src/main/kotlin/builder/_types.kt | 2 +- .../DelegateListValueClassSpecBuilder.kt | 93 +++++++++---------- .../extra/DelegateMapValueClassSpecBuilder.kt | 73 +++++++++++++++ .../extra/RuntimeExceptionSpecBuilder.kt | 38 +++++--- .../main/kotlin/poet/AnnotationSpecBuilder.kt | 4 +- .../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 | 4 +- .../kotlin/spec/KotlinExceptionClassTest.kt | 6 +- 34 files changed, 541 insertions(+), 277 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/DelegateMapValueClassSpecBuilder.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..b8d9c8d --- /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) { + + }.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(delegate=[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..54007d3 --- /dev/null +++ b/_itest/builder-itest/src/test/kotlin/DelegateStringLongMapITest.kt @@ -0,0 +1,42 @@ +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() + ).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(delegate={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 c5a812f..1e62afd 100644 --- a/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt +++ b/kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt @@ -11,6 +11,7 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.classBuilde 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 @@ -20,11 +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.DelegateListValueClassSpecBuilder -import io.toolisticon.kotlin.generation.builder.extra.DelegateListValueClassSpecBuilderReceiver -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 @@ -33,7 +33,6 @@ import io.toolisticon.kotlin.generation.spi.registry.KotlinCodeGenerationService import io.toolisticon.kotlin.generation.spi.strategy.KotlinFileSpecStrategy import io.toolisticon.kotlin.generation.spi.strategy.executeAll 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 @@ -119,6 +118,29 @@ object KotlinCodeGeneration : KLogging() { 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 */ @@ -348,8 +370,16 @@ object KotlinCodeGeneration : KLogging() { @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 */ diff --git a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt index 00e1f40..aca9a77 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationClassSpecBuilder.kt @@ -44,28 +44,16 @@ class KotlinAnnotationClassSpecBuilder internal constructor( fun mustBeDocumented() = apply { this.mustBeDocumented = true } fun repeatable() = apply { this.repeatable = true } + fun retention(retention: AnnotationRetention) = apply { this._retention = retention } fun target(vararg targets: AnnotationTarget) = apply { this.targets.addAll(targets) } - 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 addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } - override fun builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } + 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 +75,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 197d6c1..53825a6 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnnotationSpecBuilder.kt @@ -69,7 +69,7 @@ class KotlinAnnotationSpecBuilder internal constructor( private var multiLine = false private val members: MutableList = mutableListOf() - override fun addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } + fun multiLine() = apply { multiLine = true } @@ -93,7 +93,6 @@ class KotlinAnnotationSpecBuilder internal constructor( fun clearMembers() = apply { members.clear() } - override fun builder(block: AnnotationSpecBuilderReceiver) = apply { delegate.builder.block() } override fun build(): KotlinAnnotationSpec { if (members.isNotEmpty()) { @@ -106,8 +105,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 e89e852..2895935 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinAnonymousClassSpecBuilder.kt @@ -32,15 +32,6 @@ class KotlinAnonymousClassSpecBuilder internal constructor( 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 addTag(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) } @@ -51,13 +42,23 @@ class KotlinAnonymousClassSpecBuilder 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) } - 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 054ddc5..f3528fb 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, @@ -33,20 +34,9 @@ class KotlinClassSpecBuilder internal constructor( 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 addTag(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) } @@ -66,17 +56,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 f3e437b..129ed71 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinCompanionObjectSpecBuilder.kt @@ -33,15 +33,6 @@ class KotlinCompanionObjectSpecBuilder internal constructor( 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 addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } - fun addOriginatingElement(originatingElement: Element) = builder { delegate.addOriginatingElement( originatingElement @@ -55,29 +46,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 c220e05..7ec90a9 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 /** @@ -33,22 +31,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 addTag(type: KClass<*>, tag: Any?) = apply { propertyBuilder.addTag(type, tag) } - override fun build(): KotlinConstructorPropertySpec { val parameter = parameterBuilder.build() val property = propertyBuilder @@ -60,7 +53,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 661bbfa..be102d2 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinDataClassSpecBuilder.kt @@ -42,33 +42,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 addTag(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()) } - 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 0aa1fef..9ac6bba 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinEnumClassSpecBuilder.kt @@ -36,15 +36,6 @@ 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 addTag(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) } @@ -52,14 +43,23 @@ class KotlinEnumClassSpecBuilder internal constructor( 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 923bb96..06072fc 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 @@ -43,12 +46,6 @@ class KotlinFileSpecBuilder internal constructor( 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 addTag(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 +71,23 @@ 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 48de3b1..594ef12 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinFunSpecBuilder.kt @@ -54,12 +54,6 @@ class KotlinFunSpecBuilder internal constructor( 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 addTag(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) } fun addTypeVariables(typeVariables: Iterable) = builder { this.addTypeVariables(typeVariables) } @@ -106,10 +100,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 2fedf6f..97d6f47 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinInterfaceSpecBuilder.kt @@ -37,6 +37,14 @@ class KotlinInterfaceSpecBuilder internal constructor( delegate = if (funInterface) TypeSpecBuilder.funInterfaceBuilder(className) else TypeSpecBuilder.interfaceBuilder(className) ) + 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 +52,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 addTag(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 f854959..d5d726f 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinObjectSpecBuilder.kt @@ -33,32 +33,28 @@ class KotlinObjectSpecBuilder internal constructor( internal constructor(className: ClassName) : this(className, TypeSpecBuilder.objectBuilder(className)) - 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 addTag(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) } + 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 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 35a7672..9bb22b7 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinParameterSpecBuilder.kt @@ -52,18 +52,20 @@ class KotlinParameterSpecBuilder internal constructor( fun builder(spec: ParameterSpec) = KotlinParameterSpecBuilder(delegate = spec.toBuilder().wrap()) } + fun defaultValue(format: String, vararg args: Any?) = builder { this.defaultValue(format, *args) } + fun defaultValue(codeBlock: CodeBlock?) = builder { this.defaultValue(codeBlock) } + + override fun build(): KotlinParameterSpec = KotlinParameterSpec(spec = delegate.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) } - - 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 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 4353a57..7ee9138 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinPropertySpecBuilder.kt @@ -51,11 +51,6 @@ class KotlinPropertySpecBuilder internal constructor( 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 addTag(type: KClass<*>, tag: Any?) = builder { this.tag(type, tag) } fun addOriginatingElement(originatingElement: Element) = builder { this.addOriginatingElement(originatingElement) } @@ -72,10 +67,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 fccda62..62097c9 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinTypeAliasSpecBuilder.kt @@ -28,18 +28,20 @@ class KotlinTypeAliasSpecBuilder internal constructor( 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 addTag(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 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 cb2bb16..ad7f4e4 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/KotlinValueClassSpecBuilder.kt @@ -6,7 +6,10 @@ import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.jvm.jvmInline import io.toolisticon.kotlin.generation.KotlinCodeGeneration.simpleClassName import io.toolisticon.kotlin.generation.builder.KotlinFunSpecBuilder.Companion.constructorBuilder -import io.toolisticon.kotlin.generation.poet.* +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 @@ -18,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, @@ -39,29 +42,18 @@ class KotlinValueClassSpecBuilder internal constructor( 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 addTag(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 builder(block: TypeSpecBuilderReceiver) = apply { delegate.builder.block() } - override fun build(): KotlinValueClassSpec = build { } + override fun build(): KotlinValueClassSpec = build { } - fun build(block: KotlinValueClassSpecBuilderReceiver): 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 = constructorBuilder() @@ -71,10 +63,25 @@ class KotlinValueClassSpecBuilder internal constructor( delegate.addProperty(constructorProperty.spec().property.get()) delegate.builder.primaryConstructor(constructor.get()) - block() + 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 ba96f82..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. diff --git a/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateListValueClassSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateListValueClassSpecBuilder.kt index c8ec938..84898ce 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateListValueClassSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateListValueClassSpecBuilder.kt @@ -1,80 +1,71 @@ 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.ParameterizedTypeName.Companion.plusParameter -import com.squareup.kotlinpoet.KModifier +import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy -import com.squareup.kotlinpoet.TypeName -import com.squareup.kotlinpoet.TypeSpec -import com.squareup.kotlinpoet.asClassName -import io.toolisticon.kotlin.generation.KotlinCodeGeneration.buildConstructorProperty 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.KotlinFunSpecBuilder.Companion.constructorBuilder 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 @ExperimentalKotlinPoetApi class DelegateListValueClassSpecBuilder internal constructor( - private val delegate: KotlinValueClassSpecBuilder, - private val listType: TypeName, + private val delegate: KotlinValueClassSpecBuilder, + private val listType: TypeName, ) : KotlinGeneratorTypeSpecBuilder, - KotlinAnnotatableDocumentableModifiableBuilder, - KotlinSuperInterfaceSupport { + KotlinAnnotatableDocumentableModifiableBuilder, + KotlinSuperInterfaceSupport { - companion object { - fun builder(name: SimpleName, itemsType: TypeName) = - builder(className = simpleClassName(name), itemsType = itemsType) + companion object { + fun builder(name: SimpleName, itemsType: TypeName) = + builder(className = simpleClassName(name), itemsType = itemsType) - fun builder(className: ClassName, itemsType: TypeName) = DelegateListValueClassSpecBuilder( - className = className, - itemsType = itemsType - ) - } + fun builder(className: ClassName, itemsType: TypeName) = DelegateListValueClassSpecBuilder( + className = className, + itemsType = itemsType + ) + } - private var propertyName :String = "items" + private var propertyName: String = "delegate" - internal constructor(className: ClassName, itemsType: TypeName) : this( - delegate = KotlinValueClassSpecBuilder(className), - listType = List::class.asClassName().parameterizedBy(itemsType), - ) + internal constructor(className: ClassName, itemsType: TypeName) : this( + delegate = KotlinValueClassSpecBuilder(className), + listType = List::class.asClassName().parameterizedBy(itemsType), + ) { + delegate.addTag(ClassSpecType.LIST) + } - fun propertyName(propertyName: String) = apply { - require(propertyName.isNotBlank()) { "Property name cannot be blank." } - this.propertyName = propertyName - } + fun propertyName(propertyName: String) = apply { + require(propertyName.isNotBlank()) { "Property name cannot be blank." } + this.propertyName = propertyName + } - override fun build(): KotlinValueClassSpec { - delegate.addConstructorProperty(propertyName, listType) { - makePrivate() - } - return delegate.build { - addSuperinterface(listType, delegate.constructorProperty.name) - } + override fun build(): KotlinValueClassSpec { + delegate.addConstructorProperty(propertyName, listType) { + makePrivate() } + val constructorProperty = delegate.constructorProperty + return delegate.build { + addSuperinterface(listType, 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) } - // + // + 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 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..176be0d --- /dev/null +++ b/kotlin-code-generation/src/main/kotlin/builder/extra/DelegateMapValueClassSpecBuilder.kt @@ -0,0 +1,73 @@ +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 + +@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() + + fun builder(name: SimpleName, keyType: TypeName = DEFAULT_KEY_TYPE, valueType: TypeName) = builder(className = simpleClassName(name), keyType = keyType, valueType = valueType) + + 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) + } + + 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 8d19d8c..cbed10b 100644 --- a/kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/builder/extra/RuntimeExceptionSpecBuilder.kt @@ -13,15 +13,13 @@ 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.FunSpecSupplier 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,6 +31,7 @@ class RuntimeExceptionSpecBuilder internal constructor( private val delegate: KotlinClassSpecBuilder, ) : KotlinGeneratorTypeSpecBuilder, KotlinAnnotatableDocumentableModifiableBuilder, + KotlinConstructorPropertySupport, KotlinSuperInterfaceSupport { companion object { private val NULLABLE_THROWABLE = Throwable::class.asTypeName().nullable() @@ -79,8 +78,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,14 +96,21 @@ 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) } diff --git a/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt b/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt index d9deb80..69f36e7 100644 --- a/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt +++ b/kotlin-code-generation/src/main/kotlin/poet/AnnotationSpecBuilder.kt @@ -9,7 +9,9 @@ import kotlin.reflect.KClass */ class AnnotationSpecBuilder( override val builder: AnnotationSpec.Builder -) : PoetSpecBuilder, PoetTaggableBuilder { +) : PoetSpecBuilder, + AnnotationSpecSupplier, + PoetTaggableBuilder { companion object { fun AnnotationSpec.Builder.wrap() = AnnotationSpecBuilder(this) 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 index 961322c..aa690ce 100644 --- a/kotlin-code-generation/src/test/kotlin/spec/DelegateListValueClassSpecTest.kt +++ b/kotlin-code-generation/src/test/kotlin/spec/DelegateListValueClassSpecTest.kt @@ -27,8 +27,8 @@ internal class DelegateListValueClassSpecTest { @JvmInline public value class MyList( - private val items: List, - ) : List by items + private val `delegate`: List, + ) : List by delegate """.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)