Hi, We want to extend the tooling API to expose the Intellij IDEA model, similar to the way we expose the Eclipse model. This will allow tools that want to know about the IDEA model for a build to integrate with Gradle (the obvious, and probably only, candidate being IDEA itself).
At the moment, we expose several models through the tooling API. You can separate these models into 2 groups: the Gradle model, and the Eclipse model. The Gradle model provides the Gradle view of the build. The Eclipse model provides the Gradle model mapped onto the Eclipse view of the world. This Eclipse model is exactly the same one we use to generate the .classpath and .project files when you run 'gradle eclipse'. I think we didn't quite get the relationship between the Gradle and Eclipse models right with the first cut of the tooling API. Rather than just add in the IDEA model the same way, I think we should clean this up. The Gradle model is represented using various subtypes of Project (for this discussion, I'm referring to org.gradle.tooling.model.*, not org.gradle.api.*): * Project provides some basic identifying information about a project. * BuildableProject extends Project and provides information about the tasks of the project. * HierarchicalProject extends Project and provides information about the project hierarchy. The Eclipse model is also represented using various subtypes of Project: * EclipseHierarchicalProject extends HierarchicalProject and provides some basic information about an Eclipse project. * EclipseProject extends EclipseHierarchicalProject and BuildableProject and provides the full details of an Eclipse project. What this basically means is that an Eclipse project is-a Gradle project. Which isn't correct. Often there is a one-to-one relationship between the two, but not always. We want our Eclipse mapping to handle the case where there are multiple Eclipse projects per Gradle project (eg to separate out, say, integration tests, or any other source set). We probably also want our Eclipse mapping to handle the case where there are multiple Gradle projects mapped onto a single Eclipse project. So this means, in general, we want a many-to-many-relationship between Gradle project and Eclipse project. For the time being, we probably don't need to expose this relationship in the tooling API model, but we should separate the concepts of Eclipse project and Gradle project. Another consideration is that what the tooling API calls a 'project', IDEA calls a 'module'. The tooling API does not yet have a concept that matches an IDEA 'project'. So, if we here to add the IDEA model the same way as the Eclipse model, we'd add something called an IdeaModule which extends Project, and something called an IdeaProject which does not. I think there are a few separate concepts here, which we might make explicit as interfaces: * An identifiable thing. Not sure what to call this thing, but it's what Project currently represents. Let's call it a 'model element' for now. It has an identity, description and some root directory. * A source element. Has source directories, external dependencies, inter-element dependencies, and other configuration. * A buildable element. Has tasks, which can be executed. * A composite element. A container of other elements. We can mix these together to model the various things we need: * Gradle project = source element, buildable element, composite element. * Gradle build = composite element. * Eclipse project = source element, buildable element. * Eclipse workspace = composite element. * IDEA module = source element, buildable element. * IDEA project = composite element. So, a plan might be: Rename Project to ModelElement: * Extract all the methods of Project onto a new super-interface called ModelElement. Deprecate Project. * Extract all the methods of BuildableProject onto a new super-interface called BuildableModelElement. Deprecate BuildableProject. * Extract all the methods of HierarchicalProject onto a new super-interface called CompositeModelElement. Deprecate HierarchicalProject. * Change ProjectConnection.getModel() and model() to work with <T extends ModelElement>, instead of <T extends Project>. Then, add: * GradleProject extends ModelElement, BuildableModelElement, CompositeModelElement. * IdeaProject extends ModelElement, CompositeModelElement. * IdeaModule extends ModelElement, BuildableModelElement. At some point, we might also add a SourceModelElement interface. A variation of the above would be to deprecate BuildableProject and HierarchicalProject and duplicate their methods onto GradleProject, IdeaProject and IdeaModule, instead of adding BuildableModelElement and CompositeModelElement (ie don't try to model the abstract concepts). -- Adam Murdoch Gradle Co-founder http://www.gradle.org VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting http://www.gradleware.com
