How to ConfigurableFileCollection.setFrom with Provider?

Migrating my plugin from Convention Mapping to Lazy Configuration I need to replace:

task.conventionMapping.with {
    sourceDirs = {
        extension.mainSourceSets.get()*.allSource.srcDirs.flatten() as Set
    }
}
//Extension: final SetProperty<SourceSet> mainSourceSets
//Task: @InputFiles Set<File> sourceDirs

with something like:

task.sourceDirs.setFrom(extension.mainSourceSets.get()*.allSource)
//Task: @InputFiles final ConfigurableFileCollection sourceDirs 

Unfortunately, it doesn’t work as extension.mainSourceSets is null when assignment is executed. I would like to have something similar to:

task.sourceDirs.setFrom(project.providers.provider() {
    extension.mainSourceSets.get()*.allSource
})

but ConfigurableFileCollection.setFrom() doesn’t seem to work with that argument (tested with 5.4 and 6.3).

Q. How can I achieve that using the new API?

I reported a feature request - https://github.com/gradle/gradle/issues/12845

Thanks to @Stefan_Wolf’s suggestion in that topic I solved my case with:

task.sourceDirs.setFrom({ 
    extension.mainSourceSets.get()*.allSource*.srcDirs
} as Callable<Set<SourceDirectorySet>>)

There were two elements which prevent me from doing it before:

  1. I missed originally try to play with Closure, but it didn’t work due to missing .srcDirs in my code which resulted in empty FileCollection which was failing my test.

  2. Closure has to be coerced into Callable with a proper type to help determine what is returned to prevent:

java.lang.ClassCastException: class ArrayList1_groovyProxy cannot be cast to class java.util.Iterator (ArrayList1_groovyProxy is in unnamed module of loader org.codehaus.groovy.runtime.ProxyGeneratorAdapter$InnerLoader @38f617f4; java.util.Iterator is in module java.base of loader ‘bootstrap’)

Hi Marcin,

What is extension.mainSourceSets? If it is a provider, why don’t you use this?

task.sourceDirs.setFrom(extension.mainSourceSets.map { it*.allSource*.srcDirs })

Cheers,
Stefan

You are right, it is even simpler, thanks.

Btw, setFrom(Object... paths) is very flexible, but not very intuitive. Is there a plan to provide also more typed API for that?

We don’t have plans for that. What would you expect? Have separate methods for the different types it supports?

Cheers,
Stefan

That was the first thing that sprang to my head. As a downside, it would overblow that interface, still probably not covering all the cases that available.

Yeah, the interface would become much bigger, without covering all the cases. So for now, I think the Javadoc is enough. Do you have some improvements for the Javadocs?

Cheers,
Stefan