Skip to content

Commit

Permalink
Processor call attribute support
Browse files Browse the repository at this point in the history
Added support to get call directly instead of its attributes.
Now processor has no reference to core module.
Annotation tests are being moved to feature modules
  • Loading branch information
programadorthi committed Nov 19, 2024
1 parent 8ab73c9 commit 3c9527c
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 33 deletions.
14 changes: 14 additions & 0 deletions core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import kotlinx.kover.gradle.plugin.dsl.KoverProjectExtension

plugins {
kotlin("multiplatform")
alias(libs.plugins.ksp)
id("org.jetbrains.kotlinx.kover")
alias(libs.plugins.maven.publish)
}
Expand All @@ -20,6 +21,11 @@ kotlin {
api(libs.ktor.http)
}
}
commonTest {
dependencies {
implementation(projects.ksp.coreAnnotations)
}
}
}
}

Expand All @@ -36,3 +42,11 @@ configure<KoverProjectExtension> {
}
}
}

dependencies {
add("kspJvmTest", projects.ksp.coreProcessor)
}

ksp {
arg("Routing_Module_Name", "Core")
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package dev.programadorthi.routing.sample
package dev.programadorthi.routing.core

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 dev.programadorthi.routing.core.application.ApplicationCall
import io.ktor.http.Parameters
import io.ktor.util.Attributes

Expand All @@ -29,7 +29,9 @@ fun named(name: String) {
}

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

Expand All @@ -54,12 +56,16 @@ fun regex2(number: Int) {
}

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

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

Expand All @@ -73,22 +79,22 @@ fun multiParameters(part1: Int, part2: String) {
println(">>>> Parts: $part1 and $part2")
}

@Route("/call")
fun call(call: ApplicationCall) {
println(">>>> call: $call")
}

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

class Routes {
//@Route("/path")
fun run() {
println(">>>> I'm routing")
}
""".trimIndent()
)
}
1 change: 0 additions & 1 deletion ksp/core-processor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ kotlin {
sourceSets {
jvmMain {
dependencies {
implementation(projects.core)
implementation(projects.ksp.coreAnnotations)
implementation(libs.kotlin.poet)
implementation(libs.kotlin.poet.ksp)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,11 @@ import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.MemberName
import com.squareup.kotlinpoet.ksp.toTypeName
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 {
Expand Down Expand Up @@ -66,7 +64,7 @@ private class RoutingProcessor(
val configureSpec = FunSpec
.builder("configure")
.addModifiers(KModifier.INTERNAL)
.receiver(dev.programadorthi.routing.core.Route::class)
.receiver(route)

resolver
.getSymbolsWithAnnotation(Route::class.java.name)
Expand Down Expand Up @@ -110,9 +108,11 @@ private class RoutingProcessor(
check(classKind == ClassKind.OBJECT || classKind == ClassKind.CLASS) {
"$qualifiedName must be a class or object. ${classKind.type} is not supported"
}
check(superTypes.any { type ->
type.resolve().declaration.qualifiedName?.asString() == VOYAGER_SCREEN_QUALIFIED_NAME
}) {
check(
superTypes.any { type ->
type.resolve().declaration.qualifiedName?.asString() == VOYAGER_SCREEN_QUALIFIED_NAME
}
) {
"@Route can be applied to object or class that inherit from '$VOYAGER_SCREEN_QUALIFIED_NAME' only"
}
logger.info(">>>> transforming class: $qualifiedName")
Expand Down Expand Up @@ -230,16 +230,17 @@ private class RoutingProcessor(
when {
classKind == ClassKind.OBJECT -> funcBuilder.addStatement(template, member)
hasZeroOrOneParameter -> funcBuilder.add(template, member)
else -> funcBuilder
.addStatement(template, member)
.indent()
else ->
funcBuilder
.addStatement(template, member)
.indent()
}

for (param in parameters) {
check(param.isVararg.not()) {
"Vararg is not supported as fun parameter"
}
var applied = param.tryApplyCallProperty(hasZeroOrOneParameter, resolver, funcBuilder)
var applied = param.tryApplyCallProperty(hasZeroOrOneParameter, funcBuilder)
if (!applied) {
applied = param.tryApplyBody(hasZeroOrOneParameter, funcBuilder)
}
Expand Down Expand Up @@ -377,17 +378,25 @@ private class RoutingProcessor(

private fun KSValueParameter.tryApplyCallProperty(
hasZeroOrOneParameter: Boolean,
resolver: Resolver,
builder: CodeBlock.Builder,
): Boolean {
val paramType = type.resolve()
val propertyName = when (paramType.declaration) {
resolver.getClassDeclarationByName<Application>() -> "application"
resolver.getClassDeclarationByName<Parameters>() -> "parameters"
resolver.getClassDeclarationByName<Attributes>() -> "attributes"
val paramName = name?.asString()
val asTypeName = paramType.toTypeName()
if (asTypeName == applicationCall) {
when {
hasZeroOrOneParameter -> builder.add(CALL_TEMPLATE, paramName, call, "")
else -> builder.addStatement(CALL_TEMPLATE, paramName, call, ",")
}
return true
}

val propertyName = when (asTypeName) {
application -> "application"
parameters -> "parameters"
attributes -> "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, ",")
Expand Down Expand Up @@ -437,6 +446,12 @@ private class RoutingProcessor(
}

private companion object {
private val route = ClassName("dev.programadorthi.routing.core", "Route")
private val application = ClassName("dev.programadorthi.routing.core.application", "Application")
private val applicationCall = ClassName("dev.programadorthi.routing.core.application", "ApplicationCall")
private val parameters = ClassName("io.ktor.http", "Parameters")
private val attributes = ClassName("io.ktor.util", "Attributes")

private val screen = MemberName("dev.programadorthi.routing.voyager", "screen")
private val composable = MemberName("dev.programadorthi.routing.compose", "composable")
private val handle = MemberName("dev.programadorthi.routing.core", "handle")
Expand All @@ -446,6 +461,7 @@ private class RoutingProcessor(
private val receiveNullable =
MemberName("dev.programadorthi.routing.core.application", "receiveNullable")

private const val CALL_TEMPLATE = """%L = %M%L"""
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 = ")"
Expand All @@ -461,5 +477,4 @@ private class RoutingProcessor(

private const val CONSTRUCTOR_NAME = "<init>"
}

}

0 comments on commit 3c9527c

Please sign in to comment.