In Kotlin, I frequently come across the following pattern:
class DlgManager {
fun dismiss(dlg: Dialogue) {
// ...
dlg.onDismiss()
// ...
}
}
class Dialogue {
// Never call this directly, always go through DlgManager!
fun onDismiss() {
// ...
}
}
I would like to make it impossible for arbitrary callers to call onDismiss
except if the caller is DlgManager
. Is this possible with an annotation?
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class RestrictCallers(val caller: KClass<out Any>)
class DlgManager {
fun dismiss(dlg: Dialogue) {
// ...
dlg.onDismiss()
// ..
}
}
class Dialogue {
@RestrictCallers(DlgManager::class)
fun onDismiss() {
// ...
}
}
How would such an implementation of @RestrictCallers look like?
To do precisely what you want to do would require going outside normal language rules and writing a compiler plugin.
However you can get pretty close using an opt-in annotation if you don't mind annotating acceptable callers as well.
To do this, define your opt-in annotation:
@RequiresOptIn(message = "Only to be called by annotated callers")
@Retention(AnnotationRetention.BINARY)
annotation class RestrictOnDismissCallers
Annotate onDismiss
:
class Dialogue {
@RestrictOnDismissCallers
fun onDismiss() {
// ...
}
}
Then an error will be generated by any function trying to call onDismiss
except for those annotated with the opt-in annotation, such as:
@OptIn(RestrictOnDismissCallers::class)
fun dismiss(dlg: Dialogue)