Chapter 28. The Idea Plugin

The Idea plugin generates files that are used by IntelliJ Idea IDE, thus making it possible to open the project from Idea (File - Open Project). Both external (including associated source and javadoc files) and project dependencies are considered.

The Idea plugin will create different content depending on which other plugins being used:

Table 28.1. IDEA support for other plugins

PluginDescription
NoneGenerates an IDEA module file. Also generates an IDEA project and workspace file if the project is the root project.
Java Adds java configuration to the module and project files.

One focus of the Idea tasks is to be open to customizations. They provide a couple of hooks to add or remove content from the generated files.

28.1. Usage

To use the Idea plugin, include in your build script:

Example 28.1. Using the Idea plugin

build.gradle

apply plugin: 'idea'

The IDEA plugin adds a number of tasks to your project, as discussed below. The main task that you use is the idea task.

28.2. Tasks

The Idea plugin adds the tasks shown below to a project.

Table 28.2. Idea plugin - Tasks

Task name Depends on Type Description
idea ideaProject, ideaModule, ideaWorkspace - Generates all the idea configuration files
cleanIdea cleanIdeaProject, cleanIdeaModule, cleanIdeaWorkspace Delete Removes all idea configuration files
cleanIdeaProject - Delete Removes the idea project file
cleanIdeaModule - Delete Removes the idea module file
cleanIdeaWorkspace - Delete Removes the idea workspace file
ideaProject - IdeaProject Generates the .ipr file. The Idea plugin adds this task only to the root project.
ideaModule - IdeaModule Generates the .iml file
ideaWorkspace - IdeaWorkspace Generates the .iws file

Table 28.3. IdeaModule task

Property Type Default Value Default Value with Java Plugin Description
moduleDir File projectDir projectDir The content root directory of the module. Must not be null.
outputFile File projectDir/<project.name>.iml - The iml file. Used to look for existing files and as the target for generation. Must not be null.
sourceDirs Set<File> empty set The source dirs of sourceSets.main The dirs containing the production sources. Must not be null.
testSourceDirs Set<File> empty set The source dirs of sourceSets.test The dirs containing the test sources. Must not be null.
excludeDirs Set<File> empty set - The dirs to be excluded by idea. Must not be null.
outputDir File null sourceSets.main.classesDir The idea output dir for the production sources. If null no entry for output dirs is created.
testOutputDir File null sourceSets.test.classesDir The idea output dir for the test sources. If null no entry for test output dirs is created.
javaVersion String null - If this is null the value of the existing or default ipr XML (inherited) is used. If it is set to inherited, the project SDK is used. Otherwise the SDK for the corresponding value of java version is used for this module
downloadSources boolean true - Whether to download and add source jars associated with the dependency jars.
downloadJavadoc boolean false - Whether to download and add javadoc jars associated with the dependency jars.
scopes Map [:] COMPILE(compile), RUNTIME(runtime - compile), TEST(testRuntime - runtime) The keys of this map are the Idea scopes. Each key points to another map that has two keys, plus and minus. The values of those keys are sets of Configuration objects. The files of the plus configurations are added minus the files from the minus configurations.
variables Map<String, File> [:] - The variables to be used for replacing absolute paths in the iml entries. For example, you might add a GRADLE_USER_HOME variable to point to the Gradle user home dir.

Table 28.4. IdeaProject task

Property Type Default Value Default Value with Java Plugin Description
subprojects Set<Project> rootProject.allprojects - The subprojects that should be mapped to modules in the ipr file. The subprojects will only be mapped, if the Idea plugin has been applied to them.
outputFile File projectDir/<project.name>.ipr - The ipr file. Used to look for existing files and as the target for generation. Must not be null.
javaVersion String 1.6 - The java version used for defining the project sdk.
wildcards Set<String> ['!?*.java', '!?*.groovy'] - The wildcard resource patterns. Must not be null.

Table 28.5. IdeaWorkspace task

Property Type Default Value Default Value with Java Plugin Description
outputFile File projectDir/<project.name>.iws - The iws file. Used to look for existing files and as the target for generation. Must not be null.

Table 28.6. Task Hooks

Method Project Task Argument Module Task Argument Workspace Task Argument Description
beforeConfigured { arg -> } Project Module Workspace Gets called directly after the domain objects have been populated with the content of the existing XML file (if there is one).
whenConfigured { arg -> } Project Module Workspace Gets called after the domain objects have been populated with the content of the existing XML file and the content from the build script.
withXml { arg -> } XmlProvider XmlProvider XmlProvider The root node of the XML just before the XML is written to disk.

28.3. Customizing the generated files

Both, the IdeaProject and the IdeaModule task provide the same hooks and behavior for customizing the generated content. The IdeaWorkspace only provides a hook for direct XML manipulation.

The plugin recognizes existing idea files. If an idea module, project or workspace file does not exists, a default one is used. Otherwise the existing ones are merged.

28.3.1. Merging

The first option to customize the Idea files is to have an existing Idea ipr or iml file before the tasks are run. Existing files will be merged together with the generated content. Any section of the existing Idea files that are not the target of generated content will neither be changed nor removed.

28.3.1.1. Disabling merging with a complete overwrite

If you want Gradle to completely overwrite existing Idea files you can specify this on the command line by executing something like gradle cleanIdea idea or gradle cleanIdeaModule ideaModule. You can specify this also in the build script. Just make the generating tasks depending on the deleting tasks. You can tailor this to your needs. You could make the idea task dependent on the cleanIdea task. If you only want to overwrite for example the module files you simply make the ideaModule task dependent on the cleanIdeaModule task.

28.3.2. Hooking into the generation lifecycle

The Idea plugin provides a couple of domain classes that model Idea project and module files. But only the sections that are autogenerated by Gradle. The generation lifecycle is the following. If there is an existing Idea file, its whole XML is parsed and stored in memory. Then the domain objects are populated with the relevant content of the the existing XML. After that the build script information is used to further populate those objects (e.g. add additional dependencies). Then all sections modelled by the domain objects are removed from the XML in memory. After that the domain objects are used to inject their content into the XML. Finally the XML is written to disk. The lifecycle provides hooks to modify the result according to your needs.

28.3.2.1. Partial Overwrite

Doing a complete overwrite removes all your manual customizations. This might be not what you want. Therefore Gradle provides the option for a partial overwrite. You can hook into the phase just after the existing Idea files have populated the domain objects. You could then for example remove all the dependencies from the module object.

Example 28.2. Partial Overwrite for Module

build.gradle

ideaModule {
    beforeConfigured { module ->
        module.dependencies.clear()
    }
}


The generated XML will have all sections of the existing Idea module file, except for the dependencies, where only the information of the build script is used. You could do something similar for the project file.

Example 28.3. Partial Overwrite for Project

build.gradle

ideaProject {
    beforeConfigured { project ->
        project.modulePaths.clear()
    }
}


28.3.2.2. Modifying the fully populated domain objects

You can also hook into the phase after the existing Idea files and the build script metadata have populated the domain objects. You could then for example export all the dependencies of the module object.

Example 28.4. Export Dependencies

build.gradle

ideaModule {
    whenConfigured { module ->
        module.dependencies*.exported = true
    }
}


28.3.2.3. Modifying the XML

You can also hook into the phase after the XML DOM is fully populated but not written to disk. That hook provides total control over what is generated.

Example 28.5. Customizing the XML

build.gradle

ideaProject {
    withXml { provider ->
        provider.node.component.find { it.@name == 'VcsDirectoryMappings' }.mapping.@vcs = 'Git'
    }
}


28.4. Further things to consider

The paths of the dependencies in the generated Idea files are absolute. If you manually define a path variable, pointing to the gradle dependency cache, Idea will automatically replace the absolute dependency paths with this path variable. If you use such a path variable, you need to tell the ideaModule task the name of this variable, so that it can do a proper merge without creating duplicates.