2017-04-18 52 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