I have written a Gradle plugin for NetBeans based on what Geertjan Wielenga wrote. The project can be found here https://github.com/kelemen/netbeans-gradle-project where the latest compiled binary (nbm) can also be donwloaded. However, I think I have reached the limit of the Tooling API of Gradle. These are the main limitations of the Tooling API (for me):
- The Tooling API is very specialized and there can be many things in the
Gradle script which is not accessible through any model. - The performance is relatively poor because, the API returns everything
in a single call (including sources of dependencies). - Once an operation (parsing a model, executing a task, etc.) has been
started, it cannot be canceled. That is, I don’t see any way to do it.
Changes I would like ====================
Lower level Tooling API -----------------------
Rather than as done currently (returning a parsed model), it would be more desirable to have the hierarchy of ‘org.gradle.api.Project’ instances returned along with the path to the the settings.gradle and a reference to the ‘Project’ which is the project of the base directory (specified when loading the project).
If I have access to the ‘Project’ instances, it would be desirable to have some means to collect the dependencies of a project. The dependencies of each group (compile, runtime, etc.) should be fetchable separately and also their sources (and javadoc) need to be optional to fetch.
It would be nice if it would be possible to execute Gradle tasks by specifying, the objects of the previous paragraph. This would avoid the need to parse the build scripts again and executing a task could be more quick. Although in most cases, reparsing the projects is a more safe approach, there are cases where better performance is more desirable. Such a case is when executing the tests of a single class.
Accessing dynamically created methods and fields in Java is inconvenient, so a few convenience method for accessing these would be good. For example: A method which takes an object (e.g.: project) and the name of a property (e.g.: “sourceCompatibility”) and returns what where returned in the Gradle script (by calling: project.sourceCompatibility in the examples).
The main limitations of these is that Gradle must already be on the classpath and the user is tied to that particular implementation. One way to overcome this is to always return a WrappedGradleObject instance for objects of the Gradle API. This wrapper object can have methods to access fields dynamically. For example: Object getProperty(String propertyName). Objects whose classes are defined in the JDK should be returned directly (without wrapping).
Replacement
If you do not want to implement the above mentioned changes, the following things would still be necessary:
- Access to the “sourceCompatibility” and “targetCompatibility”, as well as the
character encoding of the source files. - Being able to separately retrieve the dependency groups of a project (and also being
able to separately retrieve the sources). - Support for configurations of project dependencies. - Convenience methods to get all the dependencies (considering transitive dependencies)
of a project for a particular dependency group (e.g.: get every runtime dependency).
Cancellation ------------
Since executing a task can be very slow, cancellation would be desirable, so that accidentally started tasks can be canceled. If it is implemented, the cancellation should be based on something else than thread interrupts (e.g: cancellation tokens like in .NET).