Skip to content

Commit

Permalink
Composable codegen support
Browse files Browse the repository at this point in the history
  • Loading branch information
programadorthi committed Nov 15, 2024
1 parent b77572f commit 3865580
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ private class RoutingProcessor(
) : SymbolProcessor {
private var invoked = false

private val fileName: String
get() = options["Routing_Module_Name"] ?: "Module"

private val composableEnabled: Boolean
get() = options["Routing_Compose_Enable"]?.toBooleanStrictOrNull() ?: false

override fun process(resolver: Resolver): List<KSAnnotated> {
if (invoked) {
return emptyList()
Expand Down Expand Up @@ -97,7 +103,13 @@ private class RoutingProcessor(
"@Route with regex can't be named"
}

val isComposable = annotations.any { it.shortName.asString() == "Composable" }

if (isRegexRoute) {
check(!isComposable) {
// TODO: Add regex support to composable handle
"Combining @Route(regex = ...) and @Composable are not supported for $qualifiedName"
}
if (routeAnnotation.method.isBlank()) {
configureSpec
.beginControlFlow(
Expand All @@ -123,14 +135,18 @@ private class RoutingProcessor(
routeAnnotation.name.isBlank() -> "name = null"
else -> """name = "${routeAnnotation.name}""""
}
var memberName = handle
if (composableEnabled && isComposable) {
memberName = composable
}
if (routeAnnotation.method.isBlank()) {
configureSpec
.beginControlFlow("%M(path = %S, $named)", handle, routeAnnotation.path)
.beginControlFlow("%M(path = %S, $named)", memberName, routeAnnotation.path)
} else {
val template =
"""%M(path = %S, $named, method = %M(value = "${routeAnnotation.method}"))"""
configureSpec
.beginControlFlow(template, handle, routeAnnotation.path, routeMethod)
.beginControlFlow(template, memberName, routeAnnotation.path, routeMethod)
}
}

Expand Down Expand Up @@ -320,7 +336,7 @@ private class RoutingProcessor(
FileSpec
.builder(
packageName = "dev.programadorthi.routing.generated",
fileName = "${options["Routing_Module_Name"] ?: "Module"}Routes",
fileName = "${fileName}Routes",
)
.addFileComment("Generated by Kotlin Routing")
.addFunction(this)
Expand Down Expand Up @@ -358,6 +374,7 @@ private class RoutingProcessor(
}

private companion object {
private val composable = MemberName("dev.programadorthi.routing.compose", "composable")
private val handle = MemberName("dev.programadorthi.routing.core", "handle")
private val routeMethod = MemberName("dev.programadorthi.routing.core", "RouteMethod")
private val call = MemberName("dev.programadorthi.routing.core.application", "call")
Expand Down
8 changes: 8 additions & 0 deletions samples/ksp-sample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ plugins {
kotlin("multiplatform")
alias(libs.plugins.ksp)
id("dev.programadorthi.routing") version "0.0.99"
alias(libs.plugins.jetbrains.compose)
alias(libs.plugins.compose.compiler)
}

ksp {
arg("Routing_Compose_Enable", "true")
}

kotlin {
Expand All @@ -18,7 +24,9 @@ kotlin {
commonMain {
dependencies {
implementation(projects.core)
implementation(projects.integration.compose)
implementation(projects.ksp.coreAnnotations)
implementation(compose.runtime)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package dev.programadorthi.routing.sample

import androidx.compose.runtime.Composable
import dev.programadorthi.routing.annotation.Body
import dev.programadorthi.routing.annotation.Path
import dev.programadorthi.routing.annotation.Route
import dev.programadorthi.routing.core.application.Application
import io.ktor.http.Parameters
import io.ktor.util.Attributes

@Route("/compose")
@Composable
fun compose() {
println(">>>> I'm routing")
}

@Route(path = "/compose/{id}")
@Composable
fun compose(id: Double) {
println(">>>> ID: $id")
}

@Route(path = "/composeNamed/{name}", name = "composeNamed")
@Composable
fun composeNamed(name: String) {
println(">>>> name: $name")
}

@Route(path = "/composeCustom/{random}", name = "composeCustom")
@Composable
fun composeCustom(@Path("random") value: String) {
println(">>>> value: $value")
}

@Route(path = "/composeOptional/{id?}")
@Composable
fun composeOptional(id: Char?) {
println(">>>> Optional ID: $id")
}

@Route(path = "/composeTailcard/{param...}")
@Composable
fun composeTailcard(param: List<String>?) {
println(">>>> Tailcard params: $param")
}

@Route("/compose-with-body")
@Composable
fun composeWithBody(@Body user: User) {
println(">>>> with body $user")
}

@Route("/compose-with-null-body")
@Composable
fun composeWithNullBody(@Body user: User?) {
println(">>>> null body $user")
}

@Route("/compose", method = "PUSH")
@Composable
fun composeByPushMethod() {
println(">>>> I'm pushing a route")
}

@Route("/compose/{part1}/{part2}")
@Composable
fun composeMultiParameters(part1: Int, part2: String) {
println(">>>> Parts: $part1 and $part2")
}

@Route("/compose-call/{part1}/{part2}")
@Composable
fun composeCallParameters(
application: Application,
parameters: Parameters,
attributes: Attributes,
) {
println(
"""
>>>> application: $application
>>>> parameters: $parameters
>>>> attributes: $attributes
""".trimIndent()
)
}

0 comments on commit 3865580

Please sign in to comment.