Search code examples
kotlinreflection

Why do lines 14 and 21 not compile (for my Kotlin function)?


I have a function named collectCustomizerFunctions which should create a MutableList<KCallable<*>> of all the functions of a specified class and its sub-classes which are annotated with CustomizerFunction.

Recursively, customizerFuns (the MutableList<KCallable<*>>) should have all of the "cutomizer functions" added to it.

When I try to build my Gradle project, it fails with two exceptions:

e: collectCustomizerFuns.kt:14:33 Type inference failed. The value of the type parameter T should be mentioned in input types (argument types, receiver type or expected type). Try to specify it explicitly.

e: collectCustomizerFuns.kt:21:30 Type mismatch: inferred type is Any but CapturedType(*) was expected

Here is my code:

3  | import kotlin.reflect.KClass
4  | import kotlin.reflect.KCallable
5  | import kotlin.reflect.full.allSuperclasses
6  |
7  | @Utility
8  | public tailrec fun <T: Any> collectCustomizerFuns(
9  |        specClass: KClass<T>,
10 |        customizerFuns: MutableList<KCallable<*>>
11 | ): Unit {
12 |         // add annotated functions of this class
13 |         for (member in specClass.members) {
14 |                 if (CustomizerFunction::class in member.annotations) {     <--- ERROR
15 |                         customizerFuns.add(member)
16 |                 } else {}
17 |         }   
18 | 
19 |         // add annotated functions of all super-classes
20 |         for (superclass in specClass.allSuperclasses) {
21 |                 collectCustomizerFuns<Any>(superclass, customizerFuns)     <--- ERROR                                                                                                                         
22 |         }   
23 | }

I have been trying to fix these bugs for a while now, and would appreciate any help!

Also, please provide any constructive criticism you want regarding this function, it would help a lot!


Solution

  • For the first error, member.annotations returns List<Annotation>. You have to fetch actual classes of these annotations.

    For the second error, remove the type where you call collectCustomizerFuns. Let kotlin infers the type by itself :).

    So try this:

    public tailrec fun <T: Any> collectCustomizerFuns(
        specClass: KClass<T>,
        customizerFuns: MutableList<KCallable<*>>
    ) {
        // add annotated functions of this class
        for (member in specClass.members) {
            if (CustomizerFunction::class in member.annotations.map { it.annotationClass }) {
                customizerFuns.add(member)
            } else {
            }
        }
    
        // add annotated functions of all super-classes
        for (superclass in specClass.allSuperclasses ) {
            collectCustomizerFuns(superclass, customizerFuns)
        }
    }
    

    By the way, you can remove Unit from the method signature.