What is the Groovy magic for this task command

I know there are some Groovy syntax under the Gradle. like following command:
task myTask { configure closure }
will become: task(name, configureClosure)
But how about:
task myTask(type: SomeType) { configure closure }
How this command translate to Groovy task command?


SomeType is short notation for SomeType.class (Groovy feature), and type: SomeType is short notation for Map (again Groovy feature).

To use named arguments in Groovy, the method must define the Map<String, ?> as the first argument. The Closure can only reside outside argument list if it is the last one.

With these information, we can nail the actual method down to https://docs.gradle.org/current/javadoc/org/gradle/api/Project.html#task-java.util.Map-java.lang.String-groovy.lang.Closure-

Thanks for your reply Pierre1.
How about myTask? is this a method?
I know task is a method,
type: SomeType is named argument.
{ configure closure } is closure.
What is myTask part?

As you said, task is a method. The method signature is:

Task task​(Map<String,​?> args, String name, Closure configureClosure)

You’re just calling that method when you write:

task myTask(type: SomeType) { configure closure }

Named arguments appear first in the method signature. Otherwise, you’re looking at the same arguments. myTask is just the value passed for the String name argument.

Now, you might say that myTask isn’t 'myTask' or "myTask", so how is it treated as a String? That’s not Groovy syntax. That’s just because Gradle is doing an AST transform and converting what would normally be a variable reference to a String when evaluating the Gradle file. Therefore, the quotes are optional, but if you don’t add them, the AST transform is effectively just adding them for you.

1 Like

Thanks @jjustinic for your reply.

If it is task (myTask, type: SomeType) { configure closure }, I understand the myTask is the name inside:
Task task​(Map<String,​?> args, String name, Closure configureClosure)
but, it is the: myTask(type: SomeType), there is (), it looks like a function call. How this function works?

What you’re writing is not a function call. You’re removing the function call and writing only the arguments. task(...) is the function call. Parenthesis are usually optional in Groovy.

With the AST transform to quote the task name, this function call:

task myTask(type: SomeType) { configure closure }

can be written any of these ways (plus more):

task(myTask, type: SomeType) { configure closure }
task('myTask', type: SomeType) { configure closure }
task myTask, type: SomeType, { configure closure }
task 'myTask', type: SomeType, { configure closure }
task(type: SomeType, 'myTask') { configure closure }

They’re all the same function call. Groovy is just flexible with how you list the arguments and only including the parenthesis around some of the arguments.

Thanks @jjustinic.
I try:

task hello(type:Copy) {
        doLast {
                println 'Hello world!'

it works, but if I try:

task hello, type:Copy {
        doLast {
                println 'Hello world!'

it is not working, I am using Gradle version 6.5.

Sorry, I missed a comma in the no parenthesis examples (edited above).

In the case of a type, you need the comma before the closure. The comma would be optional for some of the other named arguments with different argument types, like dependsOn: 'otherTask'. It just depends on if the syntax is unambiguous to Groovy.

Regardless, just because you can call the task function many different ways, there’s not really a good reason to do so. The convention for an eager task is to write it as (but it’s still the same method call as the other ways):

task hello(type: Copy) {

I try with the comma, it works now.
And I search in the internet, here is article about it:

it is another way to explain it, I am not sure about the methodmissing in the article, but I know, the myTask is argument for the task method.
Thanks @jjustinic.