How a method call symbol is resolved in Gradle

Hi,

I have a simple build.gradle below:

plugins{
    id 'java'
}
repositories {
    mavenCentral()
}


sourceSets {
    main{
        java{
            exclude {
                'test/**/sub'
            }
        }
    }
}

My question is how exclude symbol is resolved to a method in PatternFilterable by Gradle.
My thought process is as following:
sourceSets(Closure) call is delegated to SourceSetContainerter, main is a source set in the container. main(Closesure) call is delegated to SourceSet and java(Closure) is a method in SourceSet. java(Closure) is delegated to SourceDirectorySet. In SourceDirectorySet, it has a property called filter which is of type PatternFilterable. In PatternFilterable, there is a method exclude(Closure). But how exclude can be resolved to the method in the filter without something like filter.exclude{ … }?

Thanks a lot for your help!
-Michael

SourceDirectorySet extends PatternFilterable, so it also has the mentioned exclude method itself.
Iirc with the PatternFilterable methods on SourceDirectorySet itself you filter the contained directories.
With the PatternFilterable methods on filter you filter the files like saying “only all Java files”.

But actually, your exclude would exclude everything.

The closure you give to exclude gets a FileTreeElement as argument and and has to return a boolean value whether to exclude or not. As you use Groovy DSL, test/**/sub evaluated as boolean means true as it is a non-empty string.

I highly recommend switching to Kotlin DSL. By now it is the default DSL, you immediately get type-safe build scripts, actually helpful error messages if you mess up the syntax, and an amazingly better IDE support when using a good IDE like IntelliJ IDEA or Android Studio.

That makes sense. Thank you for your help! Appreciate it!

1 Like

Hello,

I hope all is well on your end. One more question:

Which exclude runs first between exclude in SourceDirectorySet and exclude in SourceDirectorySet.filter?

According to the document in SourceDirectorySet, exclude in SourceDirectorySet is applied first, then filter exclude is applied:


SourceDirectorySet
filter The filter used to select the source from the source directories. These filter patterns are applied after the include and exclude patterns of this source directory set. Generally, the filter patterns are used to restrict the contents to certain types of files, eg *.java.


But when I run the following build script, it shows filter.exclude is called first, then exlucde in SourceDirectorySet:

plugins{
    id 'java'
}
repositories {
    mavenCentral()
}


sourceSets {
    main{
        java{
            exclude {
                println "SourceDirectorySet  is called: " + it.file
                true
            }
            filter.exclude{
                println "filter.exclude is called: " + it.file
                false
            }
        }
    }
}

output:

filter.exclude is called: C:\gradleDebug\test\src\main\java\org
SourceDirectorySet  is called: C:\gradleDebug\test\src\main\java\org

Anything am I missing here?

Thanks,
-Michael

I have no idea, never really used them, let alone combined.
But you might as well have found a bug you should report. :man_shrugging:

1 Like