I am trying to write a check to prevent returning a Type with a certain annotation.
Such as,
const val TEST_CONTENT =
"""
| package sample.test
|
| @Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS)
| annotation class SampleAnnotation
|
| @SampleAnnotation
| internal interface ConditionalReturnedType
|
| interface TestCase {
| // this is not allowed
| fun someFunction(whatever: String): ConditionalReturnedType
| }
""".trimIndent()
and the rule that I have so far is as following
override fun visitNamedFunction(function: KtNamedFunction) {
super.visitNamedFunction(function)
if (BindingContext.EMPTY == bindingContext) {
return
}
val returnType = function.createTypeBindingForReturnType(bindingContext)?.type ?: return
// HERE Annotations is always EMPTY
val annotations = returnType.annotations
val hasRequiredAnnotation = annotations.hasAnnotation(FqName("SampleAnnotation"))
if (!hasRequiredAnnotation) return
if (isAnAllowedCondition(function, returnType)) {
// Allow returning the type for this condition
return
}
report(CodeSmell(/** */))
}
I can verify that returnType
is correct, but annotations
for the type are always empty.
Is there an alternative way of getting annotations or am I doing some rookie mistake here? :)
My Test is as following,
@Test
fun `negative cuz it doesnt match allowed conditions`() {
val actual = subject.compileAndLintWithContext(ENVIRONMENT.env, TEST_CONTENT)
assertThat(actual).hasSize(1)
assertThat(actual[0].message)
.isEqualTo("Ops. You shouldn't return that.")
}
So, there were 2 issues.
visitClass
and checked the annotation there as well, and it was always empty - which was weird and made me realise the issue is with the test. For some reason, having the code block with|
made annotation line to be removed while compiling.| @SampleAnnotation
this was not exist in compiled file at all. Removing the|
solves that.KotlinType
for returnType. So instead, I needed to reach to KtClass object somehow adding the following I was able to get the annotation.