Preconditions
The @DslMarker
annotation can only be applied to annotation class
by design. However, once our own annotation is defined (e.g., annotation class MyDslMarker
), it can be applied to any target without restrictions.
In traditional examples—such as those found in the Kotlin documentation, their HTML library, other sources, Stack Overflow, and practically everywhere—the primary target for @MyDslMarker
annotations is a class (or possibly an object).
I could only find one or two mentions of applying it directly to a function, and none for properties or other targets.
A good example with fun
, also explaining how color styles are derived
Common Usage
@DslMarker
was specifically designed to restrict implicit access to outer context receivers from within inner lambdas. It is typically applied indirectly to a class that represents a context.
If the context class belongs to a third-party library—where you are unable to apply an annotation directly to it—you would handle it as follows (simplified):
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPE) // Added a target "TYPE"
@DslMarker
annotation class MyDslMarker
// Can't apply the annotation here because it's outside our codebase
class ThirdPartyClassContext {
fun doPrint() = println("Third-party")
}
@MyDslMarker
class OuterContext {
// Applying to the receiver type
fun third(init: (@MyDslMarker ThirdPartyClassContext).() -> Unit) {
ThirdPartyClassContext().init()
//...
}
}
@MyDslMarker
class OuterThing
fun outerThing(init: OuterContext.() -> Unit): OuterThing {
val context = OuterContext()
context.init()
return OuterThing()
// in the real code, of course, it would be more like:
// return OuterThing(context),
// but that is beside the point
}
fun main() {
outerThing {
third {
doPrint()
// As desired: 'fun third(init: (ThirdPartyClassContext).() -> Unit): Unit'
// cannot be called implicitly in this context due to the receiver restriction
third { }
}
}
}
This is a common use case and is often covered—for example, as described here.
However, these are the only two usage scenarios for @MyDslMarker
that are commonly discussed, with no reliable sources addressing its application to functions, properties, or other targets.
Why This Seems Important
-
Since it is neither prohibited nor specifically mentioned in the documentation, it is possible that using such annotations on functions, properties, or even other targets could have valid use cases, similar to the scenario of annotating a Type of
ThirdPartyClass
. -
When I apply
@MyDslMarker
to a method in aContext
class and then use that method, it appears in purple (more details about the colors here). This suggests that:
fun third(init: (@MyDslMarker ThirdPartyClassContext).() -> Unit) {
ThirdPartyClassContext().init()
}
and
@MyDslMarker
fun third(init: (@MyDslMarker ThirdPartyClassContext).() -> Unit) {
ThirdPartyClassContext().init()
}
are somehow different.
Final Questions
- Does anything actually change in the example above, apart from the color?
- If something does change, what are the use cases?
- While we could theoretically apply it to any available target (e.g., functions, properties, property getters, etc.), would this be practical, and if so, in what way?
// At a minimum, these targets are available:
@Target(
AnnotationTarget.CLASS,
AnnotationTarget.TYPE,
AnnotationTarget.FUNCTION,
AnnotationTarget.PROPERTY,
AnnotationTarget.PROPERTY_GETTER
)
@DslMarker
annotation class MyDslMarker
Unfortunately, the official documentation and related examples are, at best, sparse and uninformative.
Thank you for any insights! I believe answers to these questions will be helpful not only to me but to many others who are searching for relevant information—especially since the JetBrains team itself has not provided much clarity.