【问题标题】:Kotlin type safe builder DSLs, safety for the outermost functionKotlin 类型的安全构建器 DSL,最外层功能的安全性
【发布时间】:2017-04-18 09:19:37
【问题描述】:

我将使用文档中的 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 更安全?

【问题讨论】:

    标签: kotlin dsl


    【解决方案1】:

    也许这可以以某种更优雅的方式完成,但我可以建议在具有为接收器类型定义的匹配签名的函数上使用 @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 块内调用,例如com.example.html { },所以这个技巧只是保护用户不会误调用顶级函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-02
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      • 2018-05-27
      相关资源
      最近更新 更多