Skip to content

Commit

Permalink
Merge branch 'release/0.0.5'
Browse files Browse the repository at this point in the history
  • Loading branch information
jangalinski committed Aug 29, 2024
2 parents 64e9fa7 + 09c7964 commit c0db8ec
Show file tree
Hide file tree
Showing 49 changed files with 558 additions and 498 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The one-stop lib for code generation for kotlin (jvm) and code generation testin
[![codecov](https://codecov.io/gh/toolisticon/kotlin-code-generation/graph/badge.svg?token=kyJ82m5DAT)](https://codecov.io/gh/toolisticon/kotlin-code-generation)
[![Kotlin](https://img.shields.io/badge/kotlin-2.0.20-blue.svg?logo=kotlin)](http://kotlinlang.org)
[![sponsored](https://img.shields.io/badge/sponsoredBy-Holisticon-RED.svg)](https://holisticon.de/)
[![javadoc](https://javadoc.io/badge2/io.toolisticon.kotlin.generation/kotlin-code-generation/javadoc.svg)](https://javadoc.io/doc/io.toolisticon.kotlin.generation/kotlin-code-generation)

**Usage:**

Expand Down
2 changes: 1 addition & 1 deletion _build/parent/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.toolisticon.kotlin.generation._</groupId>
<artifactId>kotlin-code-generation-root</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
<relativePath>../../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion _build/report-generator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.toolisticon.kotlin.generation._</groupId>
<artifactId>kotlin-code-generation-parent</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion _itest/builder-itest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.toolisticon.kotlin.generation._</groupId>
<artifactId>kotlin-code-generation-itest-root</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
</parent>

<groupId>io.toolisticon.kotlin.generation.itest</groupId>
Expand Down
2 changes: 1 addition & 1 deletion _itest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.toolisticon.kotlin.generation._</groupId>
<artifactId>kotlin-code-generation-parent</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
<relativePath>../_build/parent/pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion _itest/spi-itest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.toolisticon.kotlin.generation._</groupId>
<artifactId>kotlin-code-generation-itest-root</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
</parent>

<groupId>io.toolisticon.kotlin.generation.itest</groupId>
Expand Down
16 changes: 15 additions & 1 deletion _itest/spi-itest/src/test/kotlin/SpiITest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,34 @@ import com.squareup.kotlinpoet.ExperimentalKotlinPoetApi
import com.tschuchort.compiletesting.KotlinCompilation
import io.toolisticon.kotlin.generation.KotlinCodeGeneration
import io.toolisticon.kotlin.generation.KotlinCodeGeneration.className
import io.toolisticon.kotlin.generation.KotlinCodeGeneration.spi.registry
import io.toolisticon.kotlin.generation.spi.strategy.executeSingle
import io.toolisticon.kotlin.generation.test.KotlinCodeGenerationTest
import io.toolisticon.kotlin.generation.test.model.KotlinCompilationCommand
import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.junit.jupiter.api.Test

internal class SpiITest {

@Test
fun `init fails when only strategy is excluded`() {
assertThatThrownBy {
registry(
contextTypeUpperBound = TestContext::class,
exclusions = setOf("io.toolisticon.kotlin.generation.itest.spi.TestDataClassStrategy")
)
}.isInstanceOf(IllegalStateException::class.java)
.hasMessage("No serviceInstances found, configure `META-INF/services/io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationSpi`, and/or check your exclusions filter.")
}

@Test
fun `use spi defined strategies and processors to generate code`() {
val registry = KotlinCodeGeneration.spi.registry(TestContext::class)
val registry = registry(contextTypeUpperBound = TestContext::class)
val context = TestContext(registry)


val input = MapInput(
className = className(packageName = "foo.bar", simpleName = "ExampleDataClass"),
fields = mapOf(
Expand Down
2 changes: 1 addition & 1 deletion kotlin-code-generation-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.toolisticon.kotlin.generation._</groupId>
<artifactId>kotlin-code-generation-root</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
</parent>

<groupId>io.toolisticon.kotlin.generation</groupId>
Expand Down
2 changes: 1 addition & 1 deletion kotlin-code-generation-test/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.toolisticon.kotlin.generation._</groupId>
<artifactId>kotlin-code-generation-parent</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
<relativePath>../_build/parent/pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion kotlin-code-generation/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>io.toolisticon.kotlin.generation._</groupId>
<artifactId>kotlin-code-generation-parent</artifactId>
<version>0.0.4</version>
<version>0.0.5</version>
<relativePath>../_build/parent/pom.xml</relativePath>
</parent>

Expand Down
64 changes: 61 additions & 3 deletions kotlin-code-generation/src/main/kotlin/KotlinCodeGeneration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,22 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.valueClassB
import io.toolisticon.kotlin.generation.builder.*
import io.toolisticon.kotlin.generation.poet.FormatSpecifier.asCodeBlock
import io.toolisticon.kotlin.generation.spec.*
import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationContext
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

/**
* Kotlin Code Generation is a wrapper lib for kotlin poet. This is the central class that allows access to builders and tools via simple static helpers.
*/
@ExperimentalKotlinPoetApi
object KotlinCodeGeneration {
object KotlinCodeGeneration : KLogging() {

/**
* Build a [KotlinAnnotationSpec] using given type and receiver fn.
Expand Down Expand Up @@ -98,6 +102,7 @@ object KotlinCodeGeneration {
* @see [KotlinConstructorPropertySpecBuilder.builder]
*/
inline fun buildConstructorProperty(name: PropertyName, type: TypeName, block: KotlinConstructorPropertySpecBuilderReceiver = {}) = constructorPropertyBuilder(name, type).also(block).build()

/**
* Build [KotlinConstructorPropertySpec].
* @see [KotlinConstructorPropertySpecBuilder.builder]
Expand All @@ -121,6 +126,7 @@ object KotlinCodeGeneration {
* @see [KotlinEnumClassSpecBuilder.builder]
*/
inline fun buildEnumClass(className: ClassName, block: KotlinEnumClassSpecBuilderReceiver = {}) = KotlinEnumClassSpecBuilder.builder(className).also(block).build()

/**
* Build [KotlinEnumClassSpec].
* @see [KotlinEnumClassSpecBuilder.builder]
Expand All @@ -132,6 +138,7 @@ object KotlinCodeGeneration {
* @see [KotlinFileSpecBuilder.builder]
*/
inline fun buildFile(className: ClassName, block: KotlinFileSpecBuilderReceiver = {}): KotlinFileSpec = fileBuilder(className).also(block).build()

/**
* Build [KotlinFileSpec].
* @see [KotlinFileSpecBuilder.builder]
Expand All @@ -149,6 +156,7 @@ object KotlinCodeGeneration {
* @see [KotlinInterfaceSpecBuilder.builder]
*/
inline fun buildInterface(className: ClassName, block: KotlinInterfaceSpecBuilderReceiver = {}): KotlinInterfaceSpec = interfaceBuilder(className).also(block).build()

/**
* Build [KotlinInterfaceSpec].
* @see [KotlinInterfaceSpecBuilder.builder]
Expand All @@ -161,6 +169,7 @@ object KotlinCodeGeneration {
* @see [KotlinObjectSpecBuilder.builder]
*/
inline fun buildObject(className: ClassName, block: KotlinObjectSpecBuilderReceiver = {}): KotlinObjectSpec = objectBuilder(className).also(block).build()

/**
* Build [KotlinObjectSpec].
* @see [KotlinObjectSpecBuilder.builder]
Expand All @@ -172,6 +181,7 @@ object KotlinCodeGeneration {
* @see [KotlinParameterSpecBuilder.builder]
*/
inline fun buildParameter(name: ParameterName, typeName: TypeName, block: KotlinParameterSpecBuilderReceiver = {}): KotlinParameterSpec = parameterBuilder(name, typeName).also(block).build()

/**
* Build [KotlinParameterSpec].
* @see [KotlinParameterSpecBuilder.builder]
Expand All @@ -183,6 +193,7 @@ object KotlinCodeGeneration {
* @see [KotlinPropertySpecBuilder.builder]
*/
inline fun buildProperty(name: PropertyName, typeName: TypeName, block: KotlinPropertySpecBuilderReceiver = {}): KotlinPropertySpec = propertyBuilder(name, typeName).also(block).build()

/**
* Build [KotlinPropertySpec].
* @see [KotlinPropertySpecBuilder.builder]
Expand All @@ -200,6 +211,7 @@ object KotlinCodeGeneration {
* @see [KotlinValueClassSpecBuilder.builder]
*/
inline fun buildValueClass(className: ClassName, block: KotlinValueClassSpecBuilderReceiver = {}): KotlinValueClassSpec = valueClassBuilder(className).also(block).build()

/**
* Build [KotlinValueClassSpec].
* @see [KotlinValueClassSpecBuilder.builder]
Expand All @@ -217,6 +229,7 @@ object KotlinCodeGeneration {
* @see KotlinAnnotationClassSpecBuilder
*/
fun annotationClassBuilder(className: ClassName) = KotlinAnnotationClassSpecBuilder.builder(className)

/**
* @see KotlinAnnotationClassSpecBuilder
*/
Expand All @@ -226,6 +239,7 @@ object KotlinCodeGeneration {
* @see KotlinAnnotationSpecBuilder
*/
fun annotationBuilder(type: ClassName) = KotlinAnnotationSpecBuilder.builder(type)

/**
* @see KotlinAnnotationSpecBuilder
*/
Expand All @@ -240,6 +254,7 @@ object KotlinCodeGeneration {
* @see KotlinClassSpecBuilder
*/
fun classBuilder(className: ClassName) = KotlinClassSpecBuilder.builder(className)

/**
* @see KotlinClassSpecBuilder
*/
Expand All @@ -259,6 +274,7 @@ object KotlinCodeGeneration {
* @see KotlinDataClassSpecBuilder
*/
fun dataClassBuilder(className: ClassName) = KotlinDataClassSpecBuilder.builder(className)

/**
* @see KotlinDataClassSpecBuilder
*/
Expand All @@ -268,10 +284,12 @@ object KotlinCodeGeneration {
* @see KotlinEnumClassSpecBuilder
*/
fun enumClassBuilder(name: SimpleName) = KotlinEnumClassSpecBuilder.builder(name)

/**
* @see KotlinEnumClassSpecBuilder
*/
fun enumClassBuilder(packageName: PackageName, name: SimpleName) = enumClassBuilder(className(packageName, name))

/**
* @see KotlinEnumClassSpecBuilder
*/
Expand All @@ -281,6 +299,7 @@ object KotlinCodeGeneration {
* @see KotlinFileSpecBuilder
*/
fun fileBuilder(className: ClassName) = KotlinFileSpecBuilder.builder(className)

/**
* @see KotlinFileSpecBuilder
*/
Expand All @@ -295,6 +314,7 @@ object KotlinCodeGeneration {
* @see KotlinInterfaceSpecBuilder
*/
fun interfaceBuilder(className: ClassName) = KotlinInterfaceSpecBuilder.builder(className)

/**
* @see KotlinInterfaceSpecBuilder
*/
Expand All @@ -304,6 +324,7 @@ object KotlinCodeGeneration {
* @see KotlinObjectSpecBuilder
*/
fun objectBuilder(className: ClassName) = KotlinObjectSpecBuilder.builder(className)

/**
* @see KotlinObjectSpecBuilder
*/
Expand All @@ -313,6 +334,7 @@ object KotlinCodeGeneration {
* @see KotlinParameterSpecBuilder
*/
fun parameterBuilder(name: ParameterName, type: TypeName) = KotlinParameterSpecBuilder.builder(name, type)

/**
* @see KotlinParameterSpecBuilder
*/
Expand All @@ -322,6 +344,7 @@ object KotlinCodeGeneration {
* @see KotlinPropertySpecBuilder
*/
fun propertyBuilder(name: PropertyName, type: TypeName) = KotlinPropertySpecBuilder.builder(name, type)

/**
* @see KotlinPropertySpecBuilder
*/
Expand All @@ -331,6 +354,7 @@ object KotlinCodeGeneration {
* @see KotlinTypeAliasSpecBuilder
*/
fun typeAliasBuilder(name: TypeAliasName, type: TypeName): KotlinTypeAliasSpecBuilder = KotlinTypeAliasSpecBuilder.builder(name, type)

/**
* @see KotlinTypeAliasSpecBuilder
*/
Expand All @@ -340,6 +364,7 @@ object KotlinCodeGeneration {
* @see KotlinValueClassSpecBuilder
*/
fun valueClassBuilder(className: ClassName) = KotlinValueClassSpecBuilder.builder(className)

/**
* @see KotlinValueClassSpecBuilder
*/
Expand All @@ -350,6 +375,7 @@ object KotlinCodeGeneration {
* Create [ClassName] for given package and simpleName.
*/
fun className(packageName: PackageName, simpleName: SimpleName) = ClassName(packageName, simpleName)

/**
* Create [ClassName] with default packageName.
*/
Expand All @@ -370,8 +396,9 @@ object KotlinCodeGeneration {
*/
fun registry(
contextTypeUpperBound: KClass<*> = Any::class,
classLoader: ClassLoader = defaultClassLoader()
): KotlinCodeGenerationSpiRegistry = KotlinCodeGenerationServiceLoader(contextTypeUpperBound = contextTypeUpperBound, classLoader = classLoader).invoke()
classLoader: ClassLoader = defaultClassLoader(),
exclusions: Set<String> = emptySet()
): KotlinCodeGenerationSpiRegistry = KotlinCodeGenerationServiceLoader(contextTypeUpperBound = contextTypeUpperBound, classLoader = classLoader, exclusions = exclusions).invoke()
}

/**
Expand Down Expand Up @@ -415,4 +442,35 @@ object KotlinCodeGeneration {

const val NBSP = "·"
}


/**
* Generator Function that takes an input and generates source file(s).
*
* @param INPUT the type of the input (base source of generation)
* @param CONTEXT the context (containing registry, ...) used for generation.
* @param STRATEGY the [KotlinFileSpecStrategy] to apply (using `executeAll()`
* @param input the instance of the input
* @param contextFactory fn that creates the context based on input.
* @return list of [KotlinFileSpec]
* @throws IllegalStateException when no strategy is found.
*/
inline fun <INPUT : Any,
CONTEXT : KotlinCodeGenerationContext<CONTEXT>,
reified STRATEGY : KotlinFileSpecStrategy<CONTEXT, INPUT>> generateFiles(
input: INPUT,
contextFactory: (INPUT) -> CONTEXT,
): List<KotlinFileSpec> {
val context = contextFactory.invoke(input)
val strategies: List<STRATEGY> = context.registry.strategies.filter(STRATEGY::class).mapNotNull {
if (it.test(context, input)) {
it
} else {
logger.info { "strategy-filter: removing ${it.name}" }
null
}
}
check(strategies.isNotEmpty()) { "No applicable strategy found/filtered for `${STRATEGY::class}`." }
return context.registry.strategies.filter(STRATEGY::class).executeAll(context, input)
}
}
Loading

0 comments on commit c0db8ec

Please sign in to comment.