ceedee
01/09/2024, 2:23 PMKoTypeDeclarations
? I want to find issues in Android Retrofit service implementations, where a non-basic Kotlin type is used that does not end on the suffix “Dto”, like this:
interface UrlShortenerService {
@POST("short")
@FormUrlEncoded
fun getShortUrls(
@Field("url") urls: List<Url>,
@Field("expire") expireDate: String
): Single<List<UrlShortenerResponseDto>>
}
In the above example, Url
is not ending on Dto
- but I want to enforce that.
I have created this test:
@Test
fun `all interface methods annotated with HTTP verbs only use DTO classes`() {
Konsist
.scopeFromProject()
.interfaces()
.assertTrue { classDeclaration ->
classDeclaration
.functions(includeNested = false, includeLocal = false)
.all { method ->
!hasHttpVerbAnnotation(method) ||
method.parameters.all { parameter ->
isKotlinTypeOrDtoClass(parameter.type)
} && isKotlinTypeOrDtoClassOrUnit(method.returnType)
}
}
}
private fun isKotlinTypeOrDtoClass(type: KoTypeDeclaration) = type.isKotlinType || type.name.endsWith("Dto")
private fun isKotlinTypeOrDtoClassOrUnit(type: KoTypeDeclaration?) = type?.let { isKotlinTypeOrDtoClass(it) } ?: true
private fun hasHttpVerbAnnotation(method: KoFunctionDeclaration) = method.hasAnnotation { annotation ->
annotation.name == "POST" ||
annotation.name == "GET" ||
annotation.name == "PUT" ||
annotation.name == "PATCH" ||
annotation.name == "DELETE" ||
annotation.name == "HEAD"
}
But as isKotlinType
returns true
for Collections like List
, this is not sufficient to detect the case I mentioned above. I could check for isGenericType
but that does not tell me WHICH type is used there. Is there a way to achieve this?