How to understand Gradle dependencies block?

I am new to Gradle and have some confuse when learning Gradle.Say, I have a denpendency config:

dependencies {
    classpath 'com.android.tools.build:gradle:2.3.3'
}

I realize that classpath is a configuration for dependency and the closure after dependencies is delegate to DependencyHandler object, and I referred the api of DependencyHandler found that it has a Dependency add(String configurationName, Object dependencyNotation); method, but why there is no add here? why can we add the dependency just like configurationName "group:name:version:classifier@extension" other than

dependencies {
    //classpath 'com.android.tools.build:gradle:2.3.3'

    add ('classpath', 'com.android.tools.build:gradle:2.3.3')
}

Anyone some explain please…
Thanks

Here’s the very brief answer. We’re using dynamic methods in Groovy to resolve a method to call when the method doesn’t otherwise exist and is the same name as a configuration.

See: https://github.com/gradle/gradle/blob/9bc33a9fd10a2d1aae16ac7b13b0b62370d51da2/subprojects/dependency-management/src/main/java/org/gradle/api/internal/artifacts/dsl/dependencies/DefaultDependencyHandler.java#L207

2 Likes

@eljobe Thanks very much for your reply.
Can you explain more about

Some brief examples will be huge help :kiss:

Sure.

Take a look at the MethodMixin interface.

Essentially, implementing that interface means we are going to start messing with Groovy’s dynamic method resolution logic. Specifically, in the implementation of DynamicObject we look for objects that are MethodMixin instances and call their getAdditionalMethods method to see what other methods they want to claim to have. See BeanDynamicObject.MetaClassAdapter.hasMethod.

That gets us into the call to the DefaultDependencyHandler's getAdditionalMethods() which returns the DynamicMethods instance which then takes the string name of the method which is being attempted to be called and looks in the project configurations to see if we have a configuration by that name. If we do, then we call the doAdd method with that configuration and the rest of the arguments.

I don’t understand your request for examples. This isn’t a generic pattern that you can apply elsewhere in your code. It is code that we wrote in Gradle to make it possible to more concisely declare your dependencies. I thought you just wanted to understand how it worked. So, that’s what I’m trying to explain. But, the code is open-source, so you can just check it out and poke around in the codebase reading how things work if you like.

1 Like