Skip to content
DSL Building with @DelegatesTo
step 1/5

Reading — step 1 of 5

Learn

~1 min readTraits and DSL Composition

For Gradle-style DSLs, you want IDE autocompletion and compile-time validation inside the closure. The @DelegatesTo annotation tells Groovy where to route undefined names.

import groovy.lang.DelegatesTo

class HtmlBuilder {
    private List parts = []
    void p(String text) { parts << "<p>${text}</p>" }
    void h1(String text) { parts << "<h1>${text}</h1>" }
    String build() { "<html><body>${parts.join('')}</body></html>" }
}

String html(@DelegatesTo(HtmlBuilder) Closure body) {
    def builder = new HtmlBuilder()
    body.delegate = builder
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.call()
    return builder.build()
}

def result = html {
    h1 "Welcome"
    p "This is a paragraph"
    p "Another paragraph"
}
println result

The @DelegatesTo(HtmlBuilder) tells:

  • IDE: provide autocomplete for HtmlBuilder methods inside the block
  • Static checker: verify these are valid methods
  • Runtime: actually delegates the calls (the real behavior)

Strategies for inner DSLs:

  • DELEGATE_FIRST — delegate methods win
  • OWNER_FIRST (default) — calling code's methods win
  • DELEGATE_ONLY / OWNER_ONLY — exclusive

Type information for nested closures:

String section(@DelegatesTo(SectionBuilder) Closure body) { ... }

String page(@DelegatesTo(PageBuilder) Closure body) {
    def b = new PageBuilder()
    body.delegate = b
    body.call()
    b.build()
}

page {
    section { ... }    // IDE knows this 'section' delegates to SectionBuilder
}

This is how Gradle's build files work:

plugins {
    id 'java'        // PluginsBlock methods
}

dependencies {
    implementation 'commons-io:commons-io:2.11'   // DependencyHandler methods
}

Each top-level closure delegates to a different builder type — IDE shows the right autocomplete based on which block you're in.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…