Skip to content

Commit

Permalink
Regex parameter support
Browse files Browse the repository at this point in the history
  • Loading branch information
programadorthi committed Nov 13, 2024
1 parent 1c4a2fd commit 9de7294
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dev.programadorthi.routing.annotation

@Target(AnnotationTarget.FUNCTION)
public annotation class Route(
val path: String,
val name: String = ""
val path: String = "",
val name: String = "",
val regex: String = "",
)
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ private class RoutingProcessor(
val routeAnnotation = checkNotNull(func.getAnnotationsByType(Route::class).firstOrNull()) {
"Invalid state because a @Route was not found to '$qualifiedName'"
}
val isRegexRoute = routeAnnotation.regex.isNotBlank()
check(isRegexRoute || routeAnnotation.path.isNotBlank()) {
"Using @Route a path or a regex is required"
}
check(!isRegexRoute || routeAnnotation.name.isBlank()) {
"@Route using regex can't be named"
}

val parameters = mutableListOf<String>()

for (param in func.parameters) {
Expand All @@ -88,16 +96,17 @@ private class RoutingProcessor(
?.value
?: paramName
val paramType = param.type.resolve()
if (routeAnnotation.path.contains("{$customName...}")) {
if (!isRegexRoute && routeAnnotation.path.contains("{$customName...}")) {
val listDeclaration = checkNotNull(resolver.getClassDeclarationByName<List<*>>()) {
"Class declaration not found to List<String>?"
}
check(paramType.declaration == listDeclaration) {
"Tailcard parameter must be a List<String>?"
}
val genericArgument = checkNotNull(param.type.element?.typeArguments?.firstOrNull()?.type?.resolve()) {
"No <String> type found at tailcard parameter"
}
val genericArgument =
checkNotNull(param.type.element?.typeArguments?.firstOrNull()?.type?.resolve()) {
"No <String> type found at tailcard parameter"
}
check(genericArgument == resolver.builtIns.stringType) {
"Tailcard list items type must be non nullable String"
}
Expand All @@ -108,9 +117,10 @@ private class RoutingProcessor(
continue
}

val isOptional = routeAnnotation.path.contains("{$customName?}")
val isRequired = routeAnnotation.path.contains("{$customName}")
check(isOptional || isRequired) {
val isRegex = isRegexRoute && routeAnnotation.regex.contains("(?<$customName>")
val isOptional = !isRegex && routeAnnotation.path.contains("{$customName?}")
val isRequired = !isRegex && routeAnnotation.path.contains("{$customName}")
check(isRegex || isOptional || isRequired) {
"'$qualifiedName' has parameter '$paramName' that is not declared as path parameter {$customName}"
}
val parsed = """$paramName = %M.parameters["$customName"]"""
Expand All @@ -127,9 +137,13 @@ private class RoutingProcessor(
else -> """name = "${routeAnnotation.name}""""
}

configureSpec
.beginControlFlow("""%M(path = "${routeAnnotation.path}", $named)""", handle)
.addStatement("""$qualifiedName$params""", *calls)
with(configureSpec) {
if (isRegexRoute) {
beginControlFlow("""%M(%T(%S))""", handle, Regex::class, routeAnnotation.regex)
} else {
beginControlFlow("""%M(path = %S, $named)""", handle, routeAnnotation.path)
}
}.addStatement("""$qualifiedName$params""", *calls)
.endControlFlow()
}

Expand Down
4 changes: 4 additions & 0 deletions samples/ksp-sample/src/main/kotlin/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,8 @@ suspend fun main() {
delay(500)
router.call(uri = "/tailcard/p1/p2/p3/p4")
delay(500)
router.call(uri = "/foo/hello") // regex1
delay(500)
router.call(uri = "/456") // regex2
delay(500)
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ fun tailcard(param: List<String>?) {
println(">>>> Tailcard params: $param")
}

@Route(regex = ".+/hello")
fun regex1() {
println(">>>> Routing with regex")
}

@Route(regex = "/(?<number>\\d+)")
fun regex2(number: Int) {
println(">>>> Routing with regex to number: $number")
}

class Routes {
//@Route("/path")
fun run() {
Expand Down

0 comments on commit 9de7294

Please sign in to comment.