2017-04-18 29 views
5

我打算使用实现DSL创建HTML的文档中的official exampleKotlin类型安全制造商DSL,最外层功能的安全

由于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在这方面更安全吗?

回答

6

也许这可以以某种方式在一个更优雅的方式做,但我可以建议使用@Deprecated批注与DeprecationLevel.ERROR上的接收器类型定义的匹配签名的功能,例如:

@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. 
    } 
} 

(demo of this code)

顶层功能仍然可以称为通过其FQN例如DSL块内所以这个技巧只能保护用户不会错误地调用顶层函数。

+0

这基本上是完美的,谢谢! – zsmb13