0

I have a simple kotlin 1.7.10 program - I have an interface called Rule and property annotation called NextRule + 2 implementations like

import kotlin.reflect.KClass

interface Rule {
    fun process(s: String): String
}

@Target(AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.SOURCE)
@MustBeDocumented
annotation class NextRule


class EndRule() : Rule {

    override fun process(s: String) = "$s END"
}

class StartRule(
    @NextRule
    private val endRule: EndRule
) : Rule {
    override fun process(s: String): String = "$s START"
}

I want to create a function that would take an object that implements Rule interface and return for each field that also implements a Rule and is annotated with NextRule its KClass - basically a function like Rule -> Seq<KClass<out Rule>> - something like

fun getAllNextRuleAnnotatedClasses(rule: Rule): List<KClass<out Rule>> {
    for(property in rule::class.properties){
        if(property.returnType.class implements Rule && property isAnnotatedWith NextRule){
            yield property::class
        }
    }
}

How to achieve that ?

Clyde Barrow
  • 1,924
  • 8
  • 30
  • 60
  • What's the use case for this? Why go to all that trouble (as we often mention, reflection is unsafe, ugly, slow, insecure, etc.), when you could simply add a `nextRule` method or property in your `Rule` interface, and call that directly? – gidds Feb 20 '23 at 19:33
  • I have a `nextRule: () -> Rule` method but I want to create the graph of rules at the statrtup to check there are no cycles there - how would you achieve that ? – Clyde Barrow Feb 21 '23 at 14:11

1 Answers1

1

You can try this :

fun getAllNextRuleAnnotatedClasses(rule: Rule): List<KClass<out Rule>> {
    return rule::class.memberProperties
        .filter { it.returnType.classifier == Rule::class }
        .filter { it.findAnnotation<NextRule>() != null }
        .map { it.returnType.classifier as KClass<out Rule> }
}
majdibo
  • 226
  • 2
  • 5