kotlinadvanced
Type-Safe DSL Builder
Build domain-specific languages with Kotlin: receiver lambdas, @DslMarker, and nested builders.
kotlinPress ⌘/Ctrl + Shift + C to copy
@DslMarker
annotation class HtmlDsl
// HTML DSL
@HtmlDsl
class HTML {
private val children = mutableListOf<String>()
fun head(block: Head.() -> Unit) {
val head = Head().apply(block)
children.add("<head>${head.render()}</head>")
}
fun body(block: Body.() -> Unit) {
val body = Body().apply(block)
children.add("<body>${body.render()}</body>")
}
fun render() = "<html>${children.joinToString("\n")}</html>"
}
@HtmlDsl
class Head {
private val elements = mutableListOf<String>()
fun title(text: String) { elements.add("<title>$text</title>") }
fun meta(name: String, content: String) {
elements.add("""<meta name="$name" content="$content">""")
}
fun render() = elements.joinToString("\n")
}
@HtmlDsl
class Body {
private val elements = mutableListOf<String>()
fun h1(text: String) { elements.add("<h1>$text</h1>") }
fun p(text: String) { elements.add("<p>$text</p>") }
fun div(cssClass: String = "", block: Body.() -> Unit) {
val inner = Body().apply(block)
val cls = if (cssClass.isNotEmpty()) """ class="$cssClass""" else ""
elements.add("<div$cls>${inner.render()}</div>")
}
fun ul(block: UL.() -> Unit) {
val ul = UL().apply(block)
elements.add("<ul>${ul.render()}</ul>")
}
fun render() = elements.joinToString("\n")
}
@HtmlDsl
class UL {
private val items = mutableListOf<String>()
fun li(text: String) { items.add("<li>$text</li>") }
fun render() = items.joinToString("\n")
}
fun html(block: HTML.() -> Unit): String = HTML().apply(block).render()
// Query DSL
@DslMarker
annotation class QueryDsl
@QueryDsl
class Query {
var table: String = ""
private val columns = mutableListOf<String>()
private val conditions = mutableListOf<String>()
private var orderBy: String? = null
private var limit: Int? = null
fun select(vararg cols: String) { columns.addAll(cols) }
fun where(condition: String) { conditions.add(condition) }
fun orderBy(column: String, desc: Boolean = false) {
orderBy = "$column${if (desc) " DESC" else ""}"
}
fun limit(n: Int) { limit = n }
fun build(): String {
val cols = if (columns.isEmpty()) "*" else columns.joinToString(", ")
var sql = "SELECT $cols FROM $table"
if (conditions.isNotEmpty()) sql += " WHERE ${conditions.joinToString(" AND ")}"
orderBy?.let { sql += " ORDER BY $it" }
limit?.let { sql += " LIMIT $it" }
return sql
}
}
fun query(block: Query.() -> Unit): String = Query().apply(block).build()
fun main() {
// HTML DSL
val page = html {
head {
title("My Page")
meta("description", "A Kotlin DSL example")
}
body {
h1("Welcome")
div("container") {
p("This is built with a type-safe DSL")
ul {
li("Item 1")
li("Item 2")
li("Item 3")
}
}
}
}
println(page)
// Query DSL
val sql = query {
table = "users"
select("name", "email", "age")
where("age > 18")
where("active = true")
orderBy("name")
limit(10)
}
println(sql)
}Use Cases
- Configuration DSLs for frameworks
- Type-safe HTML/SQL builders
- Domain-specific API abstractions
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
kotlinadvanced
DSL for HTML Generation
Build a type-safe HTML DSL with Kotlin: lambda receivers, @DslMarker, and nested builders.
Best for: Type-safe template generation
#kotlin#dsl
kotlinintermediate
Type-Safe Builder for Configuration
Build configuration DSLs: server config, dependency injection setup, and nested builder patterns.
Best for: Application configuration DSLs
#kotlin#builder
kotlinadvanced
Builder Inference and Generic DSLs
Use @BuilderInference for type-safe DSL builders with generic type inference and collection construction.
Best for: Type-safe collection construction
#kotlin#builder
kotlinadvanced
Type-Safe DSL Builder Pattern
Create type-safe DSLs in Kotlin with receiver lambdas, @DslMarker, and nested builder scopes.
Best for: HTML/XML document generation
#kotlin#dsl