Kotlin type DSLs constructor seguro, security para la function más externa

Voy a usar el ejemplo oficial de la documentation que implementa una DSL para la creación de HTML.

Desde Kotlin 1.1, la anotación @DslMarker nos permite restringir el scope de las funciones en nuestras classs, como hace el ejemplo con la anotación @HtmlTagMarker . Esto nos da un error al intentar escribir código incorrectamente estructurado como este:

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

Sin embargo, esto no impide anidar la function más externa, que es el punto de input al DSL. Por ejemplo, con el ejemplo tal como está ahora, esto puede escribirse sin problemas:

 html { html { } } 

¿Hay alguna manera de hacer un DSL más seguro a este respecto?

Probablemente esto se puede hacer de alguna manera de una manera más elegante, pero puedo sugerir el uso de la anotación @Deprecated con DeprecationLevel.ERROR en una function con una firma coincidente definida para el tipo de receptor, por ejemplo:

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

O esta puede ser una function miembro. Por cierto, la finalización de IDE se comporta de forma un tanto diferente en function de si es una extensión o un miembro.

Esto hará que las llamadas como la interna sean inválidas:

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

(demostración de este código)

La function de nivel superior todavía se puede llamar dentro de un bloque DSL por su FQN, por ejemplo, com.example.html { } , por lo que este truco solo protege a los usuarios de llamar a la function de nivel superior por error.

  • Acceder a las properties de una tarea en gradle kotlin
  • El module debe ser configurado
  • ¿Puedo inferir el tipo de una propiedad en el delegado?
  • Runnable no se ejecuta en la barra de acción flotante en Android
  • Java 2 minutos de retraso a veces cuando se conecta el zócalo?
  • Rellene Cadena con Firestre
  • gradle no puede comstackr classs de Java usando la class kotlin
  • Suprimir "Usar syntax de acceso a la propiedad" para el método o class
  • ¿Qué es una forma concisa de copyr profundamente una MutableList 2D?
  • ¿Cómo puedo get el time que lleva una function probar el performance de las funciones en Kotlin?
  • Dagger2 no se inyecta