I'm trying to crate a type-safe groovy-style builder in Kotlin like it's described here. The problem is visibility of lambda receivers in nested lambdas. Here is a simple example.
html {
head(id = "head1")
body() {
head(id = "head2")
}
}
Receiver of the nested lambda is Body that doesn't have the 'head' method. Nevertheless this code compiles and prints into this:
<html>
<head id="head1"></head>
<head id="head2"></head>
<body></body>
</html>
It is expected but is there any way to get compilation error on the inner head?
As of Kotlin 1.0 this is not possible. There is an open feature request for this functionality.
This is possible since Kotlin 1.1, thanks to the introduction of the @DslMarker
annotation.
Here's an example of how it can be used:
@DslMarker
annotation class MyHtmlDsl
@MyHtmlDsl
class HeadBuilder
@MyHtmlDsl
class BodyBuilder
@MyHtmlDsl
class HtmlBuilder {
fun head(setup: HeadBuilder.() -> Unit) {}
fun body(setup: BodyBuilder.() -> Unit) {}
}
fun html(setup: HtmlBuilder.() -> Unit) {}
fun main(args: Array<String>) {
html {
head {}
body {
head { } // fun head(...) can't be called in this context by implicit receiver
}
}
}
See also the documentation at the announcement linked above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With