2017-04-18 16 views
5

Bazı HTML oluşturma için bir DSL uygulayan belgelerden official example kullanıyorum.Kotlin tipi kasa oluşturucu DSL'ler, en dış işlev için güvenlik

Kotlin 1.1, @DslMarker ek açıklamasından bu yana, örneğin @HtmlTagMarker ek açıklamasında olduğu gibi, sınıflarımızdaki işlevlerin kapsamını kısıtlamamızı sağlar.

html { 
    body { 
     body { // this in an error, as it's a function call on the outside Html element 
     } 
    } 
} 

Ancak bu DSL giriş noktasıdır dıştaki fonksiyonu, iç içe engellemez: Böyle yanlış yapılandırılmış kod yazmak için çalışırken Bu bize bir hata verir. şimdi olduğu gibi Örneğin, örnek ile bu sorunsuz aşağı yazılabilir:

html { 
    html { 
    } 
} 

bu konuda daha güvenli DSL yapmak için herhangi bir yolu var mı? örneğin,

cevap

6

Muhtemelen bu şekilde daha şık bir şekilde yapılabilir, ancak alıcı türü için tanımlanan bir eşleştirme imzasıyla bir fonksiyonu üzerinde DeprecationLevel.ERROR ile @Deprecated ek açıklama kullanarak önerebilir:

@Deprecated("Cannot be used in a html block.", level = DeprecationLevel.ERROR) 
fun HtmlReceiver.html(action: HtmlReceiver.() -> Unit): Nothing = error("...") 

Veya bu üye bir işlev olabilir. Bu arada IDE tamamlaması, bir uzantı veya üye olup olmamasına bağlı olarak biraz farklı davranır.

html { 
    html { // Error: Cannot be used in a html block. 
    } 
} 

(demo of this code)

üst düzey işlev hala FQN örneğin bir DSL blok içinde çağrılabilir:

İç kısım geçersiz gibi arama yapacak com.example.html { }, bu nedenle bu hileyi sadece kullanıcıların yanlışlıkla üst düzey işlevini çağırmasını engeller.

+0

Bu temel olarak mükemmel, teşekkürler! – zsmb13