What is the purpose of the @DslMarker annotation in Kotlin DSLs?
The @DslMarker annotation helps control the scope in Kotlin DSLs by preventing unintentional access to members of outer DSL receivers, making the DSL usage safer and clearer.
Click to reveal answer
beginner
How do you define a custom @DslMarker annotation in Kotlin?
You define it by creating a new annotation class and marking it with <code>@DslMarker</code>. For example:<br><pre>@DslMarker<br>annotation class MyDslMarker</pre>
Click to reveal answer
intermediate
What happens if you don't use @DslMarker in nested DSLs?
Without @DslMarker, you can accidentally access members from outer DSL scopes, which can cause confusion or errors because the DSL context is unclear.
Click to reveal answer
intermediate
In a Kotlin DSL, how does @DslMarker affect the resolution of members when nested receivers have the same annotation?
When nested receivers share the same @DslMarker annotation, Kotlin restricts access to members of outer receivers, so you can only access members of the closest receiver with that annotation.
Click to reveal answer
advanced
Can you use multiple different @DslMarker annotations in the same Kotlin DSL?
Yes, you can define multiple @DslMarker annotations for different DSL parts. Each controls scope separately, allowing fine-grained control over nested DSL scopes.
Click to reveal answer
What does the @DslMarker annotation primarily help with in Kotlin DSLs?
AControlling scope to avoid accidental access to outer receivers
BImproving runtime performance
CAutomatically generating DSL code
DChanging the visibility of functions
✗ Incorrect
@DslMarker helps control scope by restricting access to outer receivers in nested DSLs, preventing mistakes.
How do you apply a @DslMarker annotation to a DSL class?
ABy inheriting from a special DSL base class
BBy marking the class as <code>open</code>
CBy using the <code>override</code> keyword
DBy annotating the class with the custom <code>@DslMarker</code> annotation
✗ Incorrect
You annotate the DSL class with your custom @DslMarker annotation to control scope.
What happens if two nested DSL receivers have different @DslMarker annotations?
AAccess is restricted to the closest receiver with the same annotation
BOnly the outer receiver's members are accessible
CBoth receivers' members are accessible without restriction
DOnly the inner receiver's members are accessible
✗ Incorrect
If the annotations differ, Kotlin treats them as separate scopes, so members from both receivers are accessible.
Why might you want to create multiple @DslMarker annotations in a complex DSL?
ATo separate scope control for different DSL parts
BTo speed up compilation
CTo reduce code size
DTo enable inheritance between DSL classes
✗ Incorrect
Multiple @DslMarker annotations allow you to control scope separately for different DSL components.
Which of the following is a correct way to define a @DslMarker annotation?
Aclass MyDslMarker @DslMarker
B@DslMarker annotation class MyDslMarker
Cfun MyDslMarker() @DslMarker
Dval MyDslMarker = @DslMarker
✗ Incorrect
The correct syntax is to declare an annotation class and mark it with @DslMarker.
Explain how @DslMarker helps manage scope in Kotlin DSLs and why it is important.
Think about how nested blocks in a DSL might access variables or functions from outer blocks.
You got /3 concepts.
Describe the steps to create and use a custom @DslMarker annotation in a Kotlin DSL.
Start with creating the annotation, then apply it to classes, then observe the effect.
You got /3 concepts.
Practice
(1/5)
1. What is the main purpose of the @DslMarker annotation in Kotlin DSLs?
easy
A. To limit function visibility and prevent accidental calls to outer DSL scopes inside nested blocks.
B. To mark a function as deprecated in DSL usage.
C. To automatically generate DSL builder classes.
D. To enable inline functions in DSL builders.
Solution
Step 1: Understand DSL nesting problem
In nested DSL blocks, functions from outer scopes can be accidentally called inside inner blocks, causing confusion.
Step 2: Role of @DslMarker
@DslMarker annotation marks DSL builder classes to restrict visibility of outer scope functions inside nested DSL blocks, preventing accidental calls.
Final Answer:
To limit function visibility and prevent accidental calls to outer DSL scopes inside nested blocks. -> Option A
Assuming all functions from outer scopes are visible
Ignoring effect of multiple DSL markers
Confusing which DSL marker applies where
4. Given the following Kotlin DSL code, what is the error and how to fix it?
@DslMarker
annotation class MyDsl
@MyDsl
class Outer {
fun outerFun() = println("Outer")
fun inner(block: Inner.() -> Unit) {
Inner().apply(block)
}
}
@MyDsl
class Inner {
fun innerFun() = println("Inner")
}
fun main() {
Outer().apply {
outerFun()
inner {
outerFun() // Error here
innerFun()
}
}
}
medium
A. Error: innerFun() is not visible; fix by removing @MyDsl annotation.
B. Error: Cannot call outerFun() inside inner block due to DSL marker scope control; fix by qualifying with this@Outer.outerFun().
C. Error: inner block is not called; fix by changing Inner().block() to Inner().apply(block).
D. No error; code runs fine.
Solution
Step 1: Identify cause of error
Inside the inner block, outerFun() is not directly visible because @MyDsl restricts access to outer scope functions.
Step 2: Fix by explicit qualification
Use explicit label this@Outer.outerFun() to call the outer function inside the inner block, bypassing DSL marker restriction.
Final Answer:
Error: Cannot call outerFun() inside inner block due to DSL marker scope control; fix by qualifying with this@Outer.outerFun(). -> Option B
Quick Check:
Use explicit this@Outer to access outer functions [OK]
Hint: Use this@Outer to call outer functions blocked by DSL marker [OK]
Common Mistakes:
Removing @DslMarker annotation instead of qualifying call
Ignoring the need for explicit receiver labels
Assuming innerFun() visibility causes error
5. You want to create a Kotlin DSL for building HTML-like structures with nested tags. You define two builder classes HtmlBuilder and BodyBuilder, both annotated with the same @DslMarker annotation. How does using @DslMarker help prevent mistakes when writing nested DSL code like html { body { div { ... } } }?
hard
A. It prevents calling functions from HtmlBuilder inside BodyBuilder blocks unless explicitly qualified, avoiding accidental outer scope calls.
B. It automatically generates HTML tags for each builder class.
C. It allows calling any function from HtmlBuilder inside BodyBuilder without restrictions.
D. It disables nested DSL blocks to simplify code.
Solution
Step 1: Understand nested DSL structure
In nested DSLs like HTML, inner blocks (BodyBuilder) are inside outer blocks (HtmlBuilder).
Step 2: Role of @DslMarker in nested builders
@DslMarker annotation restricts visibility of outer builder functions inside inner builder blocks, preventing accidental calls to outer scope functions without explicit qualification.
Final Answer:
It prevents calling functions from HtmlBuilder inside BodyBuilder blocks unless explicitly qualified, avoiding accidental outer scope calls. -> Option A