@@ -21,20 +21,21 @@ import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.propertyBui
21
21
import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.runtimeExceptionClassBuilder
22
22
import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.typeAliasBuilder
23
23
import io.toolisticon.kotlin.generation.KotlinCodeGeneration.builder.valueClassBuilder
24
- import io.toolisticon.kotlin.generation.KotlinCodeGeneration.className
25
24
import io.toolisticon.kotlin.generation.builder.*
26
25
import io.toolisticon.kotlin.generation.builder.extra.*
27
26
import io.toolisticon.kotlin.generation.builder.extra.DelegateMapValueClassSpecBuilder.Companion.DEFAULT_KEY_TYPE
28
27
import io.toolisticon.kotlin.generation.poet.FormatSpecifier.asCodeBlock
29
28
import io.toolisticon.kotlin.generation.spec.*
30
29
import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationContext
30
+ import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationContextFactory
31
31
import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationSpiRegistry
32
+ import io.toolisticon.kotlin.generation.spi.KotlinCodeGenerationStrategy
32
33
import io.toolisticon.kotlin.generation.spi.registry.KotlinCodeGenerationServiceLoader
33
- import io.toolisticon.kotlin.generation.spi.strategy.KotlinFileSpecStrategy
34
34
import io.toolisticon.kotlin.generation.spi.strategy.executeAll
35
35
import io.toolisticon.kotlin.generation.support.SUPPRESS_MEMBER_VISIBILITY_CAN_BE_PRIVATE
36
36
import mu.KLogging
37
37
import kotlin.reflect.KClass
38
+ import kotlin.reflect.full.isSubclassOf
38
39
39
40
/* *
40
41
* 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.
@@ -559,34 +560,65 @@ object KotlinCodeGeneration : KLogging() {
559
560
const val NBSP = " ·"
560
561
}
561
562
563
+ /* *
564
+ * Generator Function that takes a context and an input, finds matching strategies and generates source file(s).
565
+ *
566
+ * Invokes the contextFactory and calls `generateFiles(context, input)`.
567
+ *
568
+ * @param INPUT the type of the input (base source of generation)
569
+ * @param CONTEXT the context (containing registry, ...) used for generation.
570
+ * @param input the instance of the input
571
+ * @param contextFactory factory fn to create the context (containing the spi registry) used for generation from input
572
+ * @return [KotlinFileSpecList] containing the generated files
573
+ * @throws IllegalStateException when no matching strategy is found.
574
+ */
575
+ inline fun <reified CONTEXT : KotlinCodeGenerationContext <CONTEXT >, reified INPUT : Any > generateFiles (
576
+ contextFactory : KotlinCodeGenerationContextFactory <CONTEXT ,INPUT >,
577
+ input : INPUT
578
+ ): KotlinFileSpecList = generateFiles(context = contextFactory.invoke(input), input = input)
562
579
563
580
/* *
564
- * Generator Function that takes an input and generates source file(s).
581
+ * Generator Function that takes a context and an input, finds matching strategies and generates source file(s).
565
582
*
566
583
* @param INPUT the type of the input (base source of generation)
567
584
* @param CONTEXT the context (containing registry, ...) used for generation.
568
- * @param STRATEGY the [KotlinFileSpecStrategy] to apply (using `executeAll()`
569
585
* @param input the instance of the input
570
- * @param contextFactory fn that creates the context based on input.
571
- * @return list of [KotlinFileSpec]
572
- * @throws IllegalStateException when no strategy is found.
573
- */
574
- inline fun <INPUT : Any ,
575
- CONTEXT : KotlinCodeGenerationContext <CONTEXT >,
576
- reified STRATEGY : KotlinFileSpecStrategy <CONTEXT , INPUT >> generateFiles (
577
- input : INPUT ,
578
- contextFactory : (INPUT ) -> CONTEXT ,
579
- ): List <KotlinFileSpec > {
580
- val context = contextFactory.invoke(input)
581
- val strategies: List <STRATEGY > = context.registry.strategies.filter(STRATEGY ::class ).mapNotNull {
586
+ * @param context the context (containing the spi registry) used for generation
587
+ * @return [KotlinFileSpecList] containing the generated files
588
+ * @throws IllegalStateException when no matching strategy is found.
589
+ */
590
+ inline fun <reified CONTEXT : KotlinCodeGenerationContext <CONTEXT >, reified INPUT : Any > generateFiles (
591
+ context : CONTEXT ,
592
+ input : INPUT
593
+ ): KotlinFileSpecList {
594
+
595
+ val strategyCandidates = context.registry.strategies.filter { it.specType.isSubclassOf(KotlinFileSpecIterable ::class ) }
596
+ .filter { it.contextType.isSubclassOf(CONTEXT ::class ) }
597
+ .filter { it.inputType.isSubclassOf(INPUT ::class ) }
598
+ .map {
599
+ @Suppress(" UNCHECKED_CAST" )
600
+ it as KotlinCodeGenerationStrategy <CONTEXT , INPUT , KotlinFileSpecIterable >
601
+ }
602
+
603
+ // find all matching strategies
604
+ val matchingStrategies: List <KotlinCodeGenerationStrategy <CONTEXT , INPUT , KotlinFileSpecIterable >> = strategyCandidates.mapNotNull {
582
605
if (it.test(context, input)) {
583
606
it
584
607
} else {
585
608
logger.info { " strategy-filter: removing ${it.name} " }
586
609
null
587
610
}
611
+ }.also {
612
+ check(it.isNotEmpty()) { " No applicable strategy found/filtered for context=`${CONTEXT ::class .simpleName} `, input=`${input::class .simpleName} `." }
613
+ }
614
+
615
+ // generate files
616
+ val sourceFiles = matchingStrategies.executeAll(context, input).flatten().also {
617
+ check(it.isNotEmpty()) { " No files where generated for context=`${CONTEXT ::class .simpleName} `, input=`${input::class .simpleName} `." }
588
618
}
589
- check(strategies.isNotEmpty()) { " No applicable strategy found/filtered for `${STRATEGY ::class } `." }
590
- return context.registry.strategies.filter(STRATEGY ::class ).executeAll(context, input)
619
+
620
+ // wrap to spec list
621
+ return KotlinFileSpecList (sourceFiles)
591
622
}
623
+
592
624
}
0 commit comments