我将使用实现DSL的文档中的official example来创建HTML。
从Kotlin 1.1开始,@DslMarker
注释允许我们限制类中函数的范围,例如@HtmlTagMarker
注释的示例。当尝试编写错误的结构化代码时,这会给我们一个错误:
html {
body {
body { // this in an error, as it's a function call on the outside Html element
}
}
}
但是,这并不能防止嵌套最外层的功能,这是DSL的入口点。例如,使用现在的示例,可以毫无问题地写下来:
html {
html {
}
}
在这方面有没有办法让DSL更安全?
答案 0 :(得分:10)
也许这可以通过某种方式以更优雅的方式完成,但我可以建议在@Deprecated
上使用DeprecationLevel.ERROR
注释,并为具有为接收器类型定义的匹配签名的函数,例如:< / p>
@Deprecated("Cannot be used in a html block.", level = DeprecationLevel.ERROR)
fun HtmlReceiver.html(action: HtmlReceiver.() -> Unit): Nothing = error("...")
或者这可以是成员函数。顺便说一句,根据它是扩展还是成员,IDE完成的行为略有不同。
这将使内部调用无效:
html {
html { // Error: Cannot be used in a html block.
}
}
顶层函数仍然可以通过其FQN在DSL块内调用,例如com.example.html { }
,所以这个技巧只能保护用户不要错误地调用顶级函数。