Skip to content

Commit 700a71a

Browse files
committed
[WIP] support templates
Heavily WIP, depends on google/ksp#2068
1 parent 859c521 commit 700a71a

File tree

11 files changed

+130
-21
lines changed

11 files changed

+130
-21
lines changed

integration-plugin/src/main/kotlin/me/snoty/integration/plugin/processor/NodeKoinModulesProcessor.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class NodeKoinModulesProcessor(private val logger: KSPLogger, private val codeGe
3434
val generatedModule = TypeSpec.objectBuilder(getGeneratedModule(clazz))
3535
.addAnnotation(Module::class)
3636
.addSerializersModule(node)
37+
.addTemplateModule(node)
3738
.build()
3839

3940
val defaultModule = TypeSpec.objectBuilder(getDefaultModule(clazz))

integration-plugin/src/main/kotlin/me/snoty/integration/plugin/processor/NodeMetadataProcessor.kt

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import com.google.devtools.ksp.processing.*
66
import com.google.devtools.ksp.symbol.KSAnnotated
77
import com.google.devtools.ksp.symbol.KSClassDeclaration
88
import com.squareup.kotlinpoet.FileSpec
9+
import com.squareup.kotlinpoet.FunSpec
10+
import com.squareup.kotlinpoet.PropertySpec
911
import com.squareup.kotlinpoet.ksp.writeTo
1012
import me.snoty.integration.common.annotation.RegisterNode
1113
import me.snoty.integration.common.model.metadata.NodeMetadata
@@ -50,11 +52,20 @@ class NodeMetadataProcessor(private val logger: KSPLogger, private val codeGener
5052
)
5153

5254
val fileSpec = FileSpec.scriptBuilder("${clazz.simpleName.asString()}Metadata", clazz.packageName.asString())
53-
.addCode("internal val $NODE_METADATA = %T(\n", NodeMetadata::class)
54-
.addDataClassInitializer(metadata, replacements = mapOf(
55-
NodeMetadata::settingsClass.name to "${settingsClass.simpleName.asString()}::class",
56-
))
57-
.addCode(")\n")
55+
.addProperty(
56+
PropertySpec.builder(NODE_METADATA, NodeMetadata::class)
57+
.initializer("provideMetadata()")
58+
.build()
59+
)
60+
.addFunction(
61+
FunSpec.builder("provideMetadata")
62+
.addCode("return ")
63+
.addDataClassInitializer(metadata, replacements = mapOf(
64+
NodeMetadata::settingsClass.name to "${settingsClass.simpleName.asString()}::class",
65+
))
66+
.returns(NodeMetadata::class)
67+
.build()
68+
)
5869
.build()
5970

6071
fileSpec

integration-plugin/src/main/kotlin/me/snoty/integration/plugin/processor/PluginKoinModules.kt

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,22 @@ import com.squareup.kotlinpoet.ksp.toClassName
77
import kotlinx.serialization.InternalSerializationApi
88
import kotlinx.serialization.modules.SerializersModule
99
import me.snoty.integration.common.annotation.RegisterNode
10+
import me.snoty.integration.common.wiring.node.NodeDescriptor
1011
import me.snoty.integration.common.wiring.node.NodeSettings
12+
import me.snoty.integration.common.wiring.node.template.NodeTemplate
13+
import me.snoty.integration.plugin.utils.addDataClassInitializer
14+
import me.snoty.integration.plugin.utils.getTemplateFiles
1115
import org.koin.core.annotation.Scope
1216
import org.koin.core.annotation.Scoped
1317
import org.koin.core.annotation.Single
18+
import org.slf4j.LoggerFactory
1419
import kotlin.reflect.KClass
1520

1621
fun TypeSpec.Builder.addSerializersModule(registerNode: RegisterNode): TypeSpec.Builder {
1722
val serializationModule = "kotlinx.serialization.modules"
1823

1924
return addFunction(
20-
FunSpec.builder("provide${registerNode.type}SerializersModule")
21-
.addAnnotation(Single::class)
22-
.addAnnotation(Scoped::class)
23-
.addAnnotation(AnnotationSpec.get(Scope(name = registerNode.type)))
25+
providerBuilder(registerNode.type, registerNode)
2426
.returns(SerializersModule::class)
2527
.addAnnotation(AnnotationSpec.get(OptIn(InternalSerializationApi::class)))
2628
.addStatement(
@@ -42,6 +44,28 @@ fun TypeSpec.Builder.addSerializersModule(registerNode: RegisterNode): TypeSpec.
4244
)
4345
}
4446

47+
fun TypeSpec.Builder.addTemplateModule(registerNode: RegisterNode): TypeSpec.Builder = apply {
48+
val descriptor = NodeDescriptor(registerNode.subsystem, registerNode.type)
49+
val templates = getTemplateFiles(descriptor) ?: return@apply
50+
51+
LoggerFactory.getLogger("NodeKoinModulesProcessor").info("Generating templates for $descriptor")
52+
53+
templates.forEach { (file, content) ->
54+
addFunction(
55+
providerBuilder(file.nameWithoutExtension, registerNode)
56+
.returns(NodeTemplate::class)
57+
.addDataClassInitializer(NodeTemplate(node = descriptor, name = file.nameWithoutExtension, template = content))
58+
.build()
59+
)
60+
}
61+
}
62+
63+
fun providerBuilder(name: String, registerNode: RegisterNode) = FunSpec.builder("provide$name")
64+
.addAnnotation(Single::class)
65+
.addAnnotation(Scoped::class)
66+
.addAnnotation(AnnotationSpec.get(Scope(name = registerNode.type)))
67+
68+
4569
@OptIn(KspExperimental::class)
4670
fun <T : Any> gimmeTypeName(get: () -> KClass<T>) = runCatching {
4771
get().asClassName()

integration-plugin/src/main/kotlin/me/snoty/integration/plugin/utils/InitializerUtils.kt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package me.snoty.integration.plugin.utils
22

3-
import com.squareup.kotlinpoet.FileSpec
3+
import com.squareup.kotlinpoet.FunSpec
44
import com.squareup.kotlinpoet.asTypeName
55
import kotlin.reflect.KClass
66
import kotlin.reflect.full.isSubtypeOf
@@ -10,7 +10,14 @@ import kotlin.reflect.full.withNullability
1010
import kotlin.reflect.typeOf
1111

1212
// TODO: support generics
13-
fun FileSpec.Builder.addDataClassInitializer(copyFrom: Any, level: Int = 1, replacements: Map<String, Any> = emptyMap()): FileSpec.Builder = apply {
13+
14+
fun FunSpec.Builder.addDataClassInitializer(copyFrom: Any, replacements: Map<String, Any> = emptyMap()): FunSpec.Builder = apply {
15+
addCode("%T(\n", copyFrom::class.asTypeName())
16+
addDataClassInitializer(copyFrom, level = 1, replacements = replacements)
17+
addCode(")\n")
18+
}
19+
20+
fun FunSpec.Builder.addDataClassInitializer(copyFrom: Any, level: Int, replacements: Map<String, Any> = emptyMap()): FunSpec.Builder = apply {
1421
copyFrom::class.primaryConstructor!!.parameters.forEach { param ->
1522
val prop = copyFrom::class.memberProperties.first { it.name == param.name }
1623
val value = prop.call(copyFrom)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package me.snoty.integration.common.wiring.node.template
2+
3+
import kotlinx.serialization.Serializable
4+
import me.snoty.integration.common.wiring.node.NodeDescriptor
5+
6+
@Serializable
7+
data class NodeTemplate(
8+
val node: NodeDescriptor,
9+
val name: String,
10+
val template: String,
11+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package me.snoty.integration.common.wiring.node.template
2+
3+
import me.snoty.integration.common.wiring.node.NodeDescriptor
4+
5+
interface NodeTemplateRegistry {
6+
fun getAllTemplates(): Map<NodeDescriptor, List<NodeTemplate>>
7+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello World!
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package me.snoty.backend.integration.flow.node
2+
3+
import me.snoty.integration.common.wiring.node.NodeDescriptor
4+
import me.snoty.integration.common.wiring.node.template.NodeTemplate
5+
import me.snoty.integration.common.wiring.node.template.NodeTemplateRegistry
6+
import org.koin.core.annotation.Single
7+
8+
@Single
9+
class NodeTemplateRegistryImpl(templates: List<NodeTemplate>) : NodeTemplateRegistry {
10+
private val templates: Map<NodeDescriptor, List<NodeTemplate>> = templates
11+
.groupBy { it.node }
12+
13+
override fun getAllTemplates(): Map<NodeDescriptor, List<NodeTemplate>>
14+
= templates
15+
}

src/main/kotlin/me/snoty/backend/server/resources/WiringResources.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import io.ktor.server.routing.*
55
import kotlinx.serialization.json.Json
66
import me.snoty.backend.hooks.HookRegistry
77
import me.snoty.backend.server.resources.wiring.flowResource
8+
import me.snoty.backend.server.resources.wiring.nodeMetadataResource
89
import me.snoty.backend.server.resources.wiring.nodeResource
910
import me.snoty.backend.server.routing.Resource
1011
import org.koin.core.annotation.Named
@@ -15,6 +16,10 @@ import org.koin.core.annotation.Single
1516
fun wiringResources(json: Json, hookRegistry: HookRegistry) = Resource {
1617
route("wiring/node") {
1718
hookRegistry.executeHooks(Routing::class, this)
19+
20+
route("metadata") {
21+
nodeMetadataResource()
22+
}
1823
}
1924

2025
authenticate("jwt-auth") {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package me.snoty.backend.server.resources.wiring
2+
3+
import io.ktor.server.response.*
4+
import io.ktor.server.routing.*
5+
import kotlinx.serialization.Serializable
6+
import me.snoty.integration.common.wiring.node.template.NodeTemplate
7+
import me.snoty.integration.common.wiring.node.template.NodeTemplateRegistry
8+
import me.snoty.backend.server.koin.get as getDependency
9+
import me.snoty.integration.common.model.metadata.NodeMetadata
10+
import me.snoty.integration.common.wiring.node.NodeDescriptor
11+
import me.snoty.integration.common.wiring.node.NodeRegistry
12+
13+
fun Routing.nodeMetadataResource() {
14+
val nodeRegistry: NodeRegistry = getDependency()
15+
get {
16+
@Serializable
17+
data class NodeDescription(val descriptor: NodeDescriptor, val metadata: NodeMetadata)
18+
19+
val nodeDescriptions = nodeRegistry.getMetadata().map { (descriptor, metadata) ->
20+
NodeDescription(descriptor, metadata)
21+
}
22+
23+
call.respond(nodeDescriptions)
24+
}
25+
26+
val nodeTemplateRegistry: NodeTemplateRegistry = getDependency()
27+
get("/template") {
28+
@Serializable
29+
data class NodeTemplates(val descriptor: NodeDescriptor, val templates: List<NodeTemplate>)
30+
31+
val nodeTemplates = nodeTemplateRegistry.getAllTemplates().map { (descriptor, templates) ->
32+
NodeTemplates(descriptor, templates)
33+
}
34+
35+
call.respond(nodeTemplates)
36+
}
37+
}

src/main/kotlin/me/snoty/backend/server/resources/wiring/NodeResource.kt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,6 @@ fun Routing.nodeResource(json: Json) {
3636
return json.decodeFromJsonElement(serializer, settingsJson)
3737
}
3838

39-
get("list") {
40-
@Serializable
41-
data class NodeDescription(val descriptor: NodeDescriptor, val metadata: NodeMetadata)
42-
43-
val nodeDescriptions = nodeRegistry.getMetadata().map { (descriptor, metadata) ->
44-
NodeDescription(descriptor, metadata)
45-
}
46-
47-
call.respond(nodeDescriptions)
48-
}
4939
post("create") {
5040
val user = call.getUser()
5141

0 commit comments

Comments
 (0)