2017-04-18 21 views
5

Zamierzam użyć official example z dokumentacji, która implementuje DSL do tworzenia HTML.Dyski bezpieczne dla budlin typu Kotlin, bezpieczeństwo dla najbardziej zewnętrznej funkcji

Od czasu wersji Kotlin 1.1 adnotacja @DslMarker pozwala nam ograniczyć zakres funkcji w naszych klasach, podobnie jak w przypadku przykładu z adnotacją @HtmlTagMarker. To daje nam błąd podczas próby zapisu nieprawidłowo zorganizowanego kodu:

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

Jednak to nie przeszkadza gniazdowania funkcję zewnętrzną, która jest punktem wyjścia do DSL. Na przykład, na przykładzie, jak to jest teraz, to może być zapisane bez problemów:

html { 
    html { 
    } 
} 

Czy istnieje jakiś sposób, aby DSL bezpieczniejsze w tym zakresie?

Odpowiedz

6

Prawdopodobnie może to jakoś zrobić w bardziej elegancki sposób, ale mogę zaproponować pomocą @Deprecated adnotacji z DeprecationLevel.ERROR na funkcji z podpisem dopasowania określonej dla typu odbiornika, na przykład:

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

Lub może to być funkcja członka. Nawiasem mówiąc, zakończenie IDE zachowuje się nieco inaczej w zależności od tego, czy jest to rozszerzenie czy członek.

to, aby połączenia, jak na wewnętrznej nieprawidłowe:

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

(demo of this code)

Funkcja najwyższego poziomu może być jeszcze zwane w bloku DSL, na przykład przez jego FQN com.example.html { }, więc ta sztuczka tylko chroni użytkowników przed wywołaniem omyłkowo funkcji najwyższego poziomu.

+0

To w zasadzie doskonałe, dzięki! – zsmb13

Powiązane problemy