I think the key thing to understand here is that exclude and matching do different things. Exclude configures the filetree with the provided pattern and returns “this”. Matching on the other hand creates and returns a new filetree. So when you call matching inside the configuration closure above, fileTree() is creating a filetree, then executing the closure (where matching creates a second tree) but what is returned is the first filetree (ie the result of the project.fileTree(string, closure) method). In the fileTree().matching() form, what is being returned is the result of the matching() method (the second filetree).