@@ -75,6 +75,14 @@ private class RoutingProcessor(
75
75
val routeAnnotation = checkNotNull(func.getAnnotationsByType(Route ::class ).firstOrNull()) {
76
76
" Invalid state because a @Route was not found to '$qualifiedName '"
77
77
}
78
+ val isRegexRoute = routeAnnotation.regex.isNotBlank()
79
+ check(isRegexRoute || routeAnnotation.path.isNotBlank()) {
80
+ " Using @Route a path or a regex is required"
81
+ }
82
+ check(! isRegexRoute || routeAnnotation.name.isBlank()) {
83
+ " @Route using regex can't be named"
84
+ }
85
+
78
86
val parameters = mutableListOf<String >()
79
87
80
88
for (param in func.parameters) {
@@ -88,16 +96,17 @@ private class RoutingProcessor(
88
96
?.value
89
97
? : paramName
90
98
val paramType = param.type.resolve()
91
- if (routeAnnotation.path.contains(" {$customName ...}" )) {
99
+ if (! isRegexRoute && routeAnnotation.path.contains(" {$customName ...}" )) {
92
100
val listDeclaration = checkNotNull(resolver.getClassDeclarationByName<List <* >>()) {
93
101
" Class declaration not found to List<String>?"
94
102
}
95
103
check(paramType.declaration == listDeclaration) {
96
104
" Tailcard parameter must be a List<String>?"
97
105
}
98
- val genericArgument = checkNotNull(param.type.element?.typeArguments?.firstOrNull()?.type?.resolve()) {
99
- " No <String> type found at tailcard parameter"
100
- }
106
+ val genericArgument =
107
+ checkNotNull(param.type.element?.typeArguments?.firstOrNull()?.type?.resolve()) {
108
+ " No <String> type found at tailcard parameter"
109
+ }
101
110
check(genericArgument == resolver.builtIns.stringType) {
102
111
" Tailcard list items type must be non nullable String"
103
112
}
@@ -108,9 +117,10 @@ private class RoutingProcessor(
108
117
continue
109
118
}
110
119
111
- val isOptional = routeAnnotation.path.contains(" {$customName ?}" )
112
- val isRequired = routeAnnotation.path.contains(" {$customName }" )
113
- check(isOptional || isRequired) {
120
+ val isRegex = isRegexRoute && routeAnnotation.regex.contains(" (?<$customName >" )
121
+ val isOptional = ! isRegex && routeAnnotation.path.contains(" {$customName ?}" )
122
+ val isRequired = ! isRegex && routeAnnotation.path.contains(" {$customName }" )
123
+ check(isRegex || isOptional || isRequired) {
114
124
" '$qualifiedName ' has parameter '$paramName ' that is not declared as path parameter {$customName }"
115
125
}
116
126
val parsed = """ $paramName = %M.parameters["$customName "]"""
@@ -127,9 +137,13 @@ private class RoutingProcessor(
127
137
else -> """ name = "${routeAnnotation.name} """"
128
138
}
129
139
130
- configureSpec
131
- .beginControlFlow(""" %M(path = "${routeAnnotation.path} ", $named )""" , handle)
132
- .addStatement(""" $qualifiedName$params """ , * calls)
140
+ with (configureSpec) {
141
+ if (isRegexRoute) {
142
+ beginControlFlow(""" %M(%T(%S))""" , handle, Regex ::class , routeAnnotation.regex)
143
+ } else {
144
+ beginControlFlow(""" %M(path = %S, $named )""" , handle, routeAnnotation.path)
145
+ }
146
+ }.addStatement(""" $qualifiedName$params """ , * calls)
133
147
.endControlFlow()
134
148
}
135
149
0 commit comments