How to init SourceTask's property ‘source’ with extension property?

My plugin registers an extension and some custom task that inherited from org.gradle.api.tasks.SourceTask.

class MyPlugin implements Plugin<Project> {
    private final Instantiator instantiator
    private final FileResolver fileResolver
    @Inject
    MyPlugin (Instantiator instantiator, FileResolver fileResolver) {
        this.instantiator = instantiator
        this.fileResolver = fileResolver
    }
    void apply(Project project) {
        MyPluginExtension extension = project.extensions.create("myPlugin", MyPluginExtension, project, instantiator, fileResolver)
        project.tasks.create('doSomething', MyCustomTask) {}
    }
}

class MyPluginExtension {
    final MySourceSetContainer source
    MyPluginExtension(Project project, Instantiator instantiator, FileResolver fileResolver) {
        source = instantiator.newInstance(ImplMySourceSetContainer, project, instantiator, fileResolver)
    }
    void source(Closure closure) {
        ConfigureUtil.configure(closure, source)
    }
}

class MyCustomTask extends SourceTask {
    @TaskAction
    void act() {
        // something
    }
}

And now, if I configure build script:

myPlugin {
    source{
        main {
            something {
                srcDirs "src/main/resources"
            }
        }
    }
}
doSomething {
    source = myPlugin.source.main.something.asFileTree
}

- All works fine. But I want to initialize task property source by value from MyPluginExtension.

source = extension.source.findAll().inject(project.files().asFileTree, { result, item -> result + item.html.asFileTree })

I can’t extract extension property at the execution phase as it described in the userguide (Writing Custom Plugins - Gradle User Guide Version 4.2.1), because getter for source that declared in superclass org.gradle.api.tasks.SourceTask marked with annotation @org.gradle.api.tasks.SkipWhenEmpty and task will be skipped.

How can I initialize task’s property with value from extension before execution phase?
Thx.

1 Like

Resolved by wrapping source init in closure:

class MyPlugin implements Plugin<Project> {
    // ...
    void apply(Project project) {
        MyPluginExtension extension = project.extensions.create("myPlugin", MyPluginExtension, project, instantiator, fileResolver)
        project.tasks.create('doSomething', MyCustomTask) { task ->
            task.source = { 
                extension.source.findAll().inject(new HashSet<File>(), { result, item -> result + item.html.srcDirs }) 
            }
        }
    }
}