Search code examples
jenkinsgroovy

How to define/declare the type of a Closure delegate?


I'm trying to define a builder pattern to construct the command-line arguments of a Cucumber action for our Jenkins CI/CD pipeline. In it, I'm trying to write the data class with a Closure method as well in the event someone prefers that syntax (trying to be flexible). So I defined this (abridged for brevity):

class CucumberArgs {
    private Boolean _help
    
    CucumberArgs() {}

    Boolean getHelp() {
        return this._help;
    }

    CucumberArgs help(Boolean value) {
        this._help = value;
        return this;
    }
    
    static CucumberArgs with(Closure<CucumberArgs> builder) {
        builder.delegate = new CucumberArgs();
        builder.resolveStrategy = Closure.DELEGATE_ONLY;
        return builder.call();
    }

    @Override
    String toString() {
        if(this._help) {
            return 'cucumber-js --help'
        }
    }
}

def args = CucumberArgs.with {
    help(true);
}

println args
// 'cucumber-js --help'

As I've said, there's a lot more to the code, but it's a succinct example of what I'm doing. In IntelliJ, I get the message that No candidates found for method call help. I'm sure the answer has been given before, but I can't seem to pick the right search query. Official documentation is preferred, but I'd be fine with a working code sample.


Solution

  • So I threw this into Intellij in a Groovy Console and ran it. I did make a little clean up, but it was mostly cosmetic. I couldn't get it to fail so I think mostly what you had was fine. You weren't returning a string in all cases in toString(), and I added the @DelegatesTo so Intellij would know what your delegate would be. That recognizes the help method, but even without that it worked. That was the most substantive change.

    class CucumberArgs {
        private Boolean _help
    
        CucumberArgs() {}
    
        Boolean getHelp() {
            return this._help
        }
    
        CucumberArgs help(Boolean value) {
            this._help = value
            return this
        }
    
        static CucumberArgs with(@DelegatesTo(CucumberArgs) Closure<CucumberArgs> builder) {
            builder.delegate = new CucumberArgs()
            builder.resolveStrategy = Closure.DELEGATE_ONLY
            return builder.call()
        }
    
        @Override
        String toString() {
            if(this._help) {
                return 'cucumber-js --help'
            } else {
                return ''
            }
        }
    }
    
    def args = CucumberArgs.with {
        help(true)
    }
    
    println args
    // 'cucumber-js --help'