diff --git a/ksp/core-processor/jvm/src/dev/programadorthi/routing/ksp/RoutingProcessor.kt b/ksp/core-processor/jvm/src/dev/programadorthi/routing/ksp/RoutingProcessor.kt index fa5f20c..c5efe95 100644 --- a/ksp/core-processor/jvm/src/dev/programadorthi/routing/ksp/RoutingProcessor.kt +++ b/ksp/core-processor/jvm/src/dev/programadorthi/routing/ksp/RoutingProcessor.kt @@ -27,6 +27,9 @@ import com.squareup.kotlinpoet.ksp.writeTo 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 public class RoutingProcessorProvider : SymbolProcessorProvider { override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { @@ -39,7 +42,6 @@ private class RoutingProcessor( ) : SymbolProcessor { private var invoked = false - @OptIn(KspExperimental::class) override fun process(resolver: Resolver): List { if (invoked) { return emptyList() @@ -135,7 +137,6 @@ private class RoutingProcessor( .endControlFlow() } - @OptIn(KspExperimental::class) private fun KSFunctionDeclaration.generateHandleBody( isRegexRoute: Boolean, routeAnnotation: Route, @@ -157,8 +158,11 @@ private class RoutingProcessor( check(param.isVararg.not()) { "Vararg is not supported as fun parameter" } - var applied = param.tryApplyBody(hasZeroOrOneParameter, funcBuilder) - if (!isRegexRoute && !applied) { + var applied = param.tryApplyCallProperty(hasZeroOrOneParameter, resolver, funcBuilder) + if (!applied) { + applied = param.tryApplyBody(hasZeroOrOneParameter, funcBuilder) + } + if (!applied && !isRegexRoute) { applied = param.tryApplyTailCard( routePath = routeAnnotation.path, resolver = resolver, @@ -288,6 +292,26 @@ private class RoutingProcessor( return true } + private fun KSValueParameter.tryApplyCallProperty( + hasZeroOrOneParameter: Boolean, + resolver: Resolver, + builder: CodeBlock.Builder, + ): Boolean { + val paramType = type.resolve() + val propertyName = when (paramType.declaration) { + resolver.getClassDeclarationByName() -> "application" + resolver.getClassDeclarationByName() -> "parameters" + resolver.getClassDeclarationByName() -> "attributes" + else -> return false + } + val paramName = name?.asString() + when { + hasZeroOrOneParameter -> builder.add(CALL_PROPERTY_TEMPLATE, paramName, call, propertyName, "") + else -> builder.addStatement(CALL_PROPERTY_TEMPLATE, paramName, call, propertyName, ",") + } + return true + } + private fun FunSpec.generateFile(ksFiles: Set) { FileSpec .builder( @@ -337,6 +361,7 @@ private class RoutingProcessor( private val receiveNullable = MemberName("dev.programadorthi.routing.core.application", "receiveNullable") + private const val CALL_PROPERTY_TEMPLATE = """%L = %M.%L%L""" private const val BODY_TEMPLATE = "%L = %M.%M()%L" private const val FUN_INVOKE_END = ")" private const val FUN_INVOKE_START = "%M(" diff --git a/samples/ksp-sample/src/main/kotlin/Main.kt b/samples/ksp-sample/src/main/kotlin/Main.kt index 1e67ec5..e9b6b6c 100644 --- a/samples/ksp-sample/src/main/kotlin/Main.kt +++ b/samples/ksp-sample/src/main/kotlin/Main.kt @@ -43,4 +43,6 @@ suspend fun main() { delay(500) router.call(uri = "/path/13579/partition") delay(500) + router.call(uri = "/call/p01/p02") + delay(500) } diff --git a/samples/ksp-sample/src/main/kotlin/dev/programadorthi/routing/sample/Routes.kt b/samples/ksp-sample/src/main/kotlin/dev/programadorthi/routing/sample/Routes.kt index 17b29f7..e282650 100644 --- a/samples/ksp-sample/src/main/kotlin/dev/programadorthi/routing/sample/Routes.kt +++ b/samples/ksp-sample/src/main/kotlin/dev/programadorthi/routing/sample/Routes.kt @@ -4,6 +4,9 @@ import dev.programadorthi.routing.annotation.Body import dev.programadorthi.routing.annotation.Path import dev.programadorthi.routing.annotation.Route import dev.programadorthi.routing.core.RouteMethod +import dev.programadorthi.routing.core.application.Application +import io.ktor.http.Parameters +import io.ktor.util.Attributes data class User( val id: Int, @@ -70,6 +73,19 @@ fun multiParameters(part1: Int, part2: String) { println(">>>> Parts: $part1 and $part2") } +@Route("/call/{part1}/{part2}") +fun callParameters( + application: Application, + parameters: Parameters, + attributes: Attributes, +) { + println(""" + >>>> application: $application + >>>> parameters: $parameters + >>>> attributes: $attributes + """.trimIndent()) +} + class Routes { //@Route("/path") fun run() {