Using the IntelliJ IDEA plugin

IntelliJ IDEA from JetBrains is another IDE we can use to develop applications. Gradle has the IDEA plugin to generate the project files for IntelliJ IDEA. This means we can simply open the project in IntelliJ IDEA. The dependencies are set correctly so as to compile the project in the IDE. In this section, we will see how we can generate those files and customize file generation.

IntelliJ IDEA supports a folder-based and file-based format for the project files. The IDEA plugin generates files for the file-based format. The file format for the project files is XML. The workspace project file has the extension .iws and contains personal settings. The project information is stored in a file with extension .ipr. The project file can be saved in a version control system, because it doesn't have reference to local paths. The workspace project file has a lot of personal settings and shouldn't be put in a version control system.

For a Java project, we have a third project file with the exension .iml. This file contains dependency references with local path locations. We shouldn't put this file in a version control system. The IDEA plugin can just, like the Eclipse plugin, download associated source files for a dependency. We can also configure and download the associated Javadoc files. The IDEA plugin works together with the Java plugin. If we have a Gradle build file and apply both the Java and IDEA plugins, a specific Java configuration is added to the project files.

Let's create an example build file and apply the IDEA plugin, as shown in the following code snippet:

apply plugin: 'java'
apply plugin: 'idea'

version = 1.0

sourceCompatibility = 1.6
targetCompatibility = 1.6

description = 'Sample project'

ext {
    slf4jVersion = '1.6.6'
    slf4jGroup = 'org.slf4j'
}

configurations {
    extraLib 
}
repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.8'
    extraLib "$slf4jGroup:slf4j-api:$slf4jVersion", "$slf4jGroup:slf4j-simple:$slf4jVersion"
}

First, we execute the tasks task and see which tasks are added by the plugin,as follows:

$ gradle tasks --all
...
IDE tasks
---------
cleanIdea - Cleans IDEA project files (IML, IPR)
    cleanIdeaModule
    cleanIdeaProject
idea - Generates IDEA project files (IML, IPR, IWS)
    ideaModule - Generates IDEA module files (IML)
    ideaProject - Generates IDEA project file (IPR)
    ideaWorkspace - Generates an IDEA workspace file (IWS)
...

We have an idea task that is dependent on the following three other tasks: ideaWorkspace, ideaModule, and ideaProject. Each of these tasks can generate a project file. To remove the module and project files, we can execute the cleanIdeaModule and cleanIdeaProject tasks or simply the cleanIdea task. There is no cleanIdeaWorkspace task, because the workspace file contains personal settings. These settings are probably set via the user interface of IntelliJ IDEA and shouldn't be removed by a Gradle task.

When we run the idea task from the command line and look at the output which is as follows, we see that all the tasks are executed and we now have three project files:

$ gradle idea
:ideaModule
:ideaProject
:ideaWorkspace
:idea

BUILD SUCCESSFUL

Total time: 4.477 secs

Customizing file generation

The IDEA plugin has several ways to customize the configuration in the generated files. The plugin will look in the project settings and use the information in the generated files. For example, we can set the source and target compatibility versions in our Gradle project and the plugin will use them to set a correct value in the generated project file.

We can use a DSL to change the configuration information before the file is generated. Gradle also offers hooks where we can manipulate model objects before and after the project information and DSL configuration is applied. To change the generated XML structure, we can implement the withXml hook. We can alter the XML just before it is written to disk. To change the contents of the workspace file, we should use the withXml hook. The workspace file has an empty model object and has no DSL, because the contents are very specific and they contain a lot of personal settings.

Customizing using DSL

The IDEA plugin adds a new idea configuration script block that is used to change the project files' contents. For the module and project files, we can use a DSL to set the configuration settings. Each file has its own configuration script block.

For module file generation, we can change the name of the file. But, it is best to leave it unchanged. Gradle will make sure the file names are unique within a multi-project build. IntelliJ IDEA requires that the module names be unique for a multi-module project.

IntelliJ IDEA has several scopes for dependencies. We can customize which dependency configuration apply to which scope. The following table shows the default mapping of IntelliJ IDEA scopes with Gradle dependency configurations:

IntelliJ IDEA scope

Gradle configuration

Compile

project.configurations.compile

Runtime

project.configurations.runtime-project.configurations.compile

Test

project.configurations.testRuntime-project.configuations.runtime

Provided

Not set

Each scope has a plus and minus key. We can add additional configurations using the plus key and remove configurations with the minus key.

In the following example build file, we see the different options and methods of the DSL used to change the project file contents:

apply plugin: 'java'
apply plugin: 'idea'

idea {
    project {
        // Set JDK name. Default is from Java version
        // used to run Gradle.
        jdkName = '1.6'

        // Set Java language level for the project. 
        // Default value is project.sourceCompatibility.
        languageLevel = '1.6'  // Or JDK_1_6

        // For multi-project builds we can define other modules.
        // Default value is project.allprojects*.idea.module.
        modules = project(':other').idea.module

        // Set resource wildcard pattern. 
        // Default value is ['!?*.java', '!?*.groovy']
        wildcards += '!?*.xsd'
    }
}

The following example build file shows some of the options we can use to change the module file:

apply plugin: 'java'
apply plugin: 'idea'

configurations { extraLib }
sourceSets { api }

idea {
    module {
        // Download associated Javadoc files for dependencies.
        // Default value is false.
        downloadJavadoc = true

        // Download associated source files for dependencies.
        // Default value is true.
        downloadSources = true

        // Set which directories to exclude.
        excludeDirs += file('.settings')

        // Set specific JDK for this module, or use the value 'inherited'
        // to use project JDK. Default value is 'inherited'.
        jdkName = 'inherited'

        // Directory with the source files. 
        // Default value is project.sourceSets.main.allSource
        sourceDirs += project.sourceSets.api.allSource

        // Directory with the test source files. 
        // Default value is project.sourceSets.test.allSource
        testSourceDirs += project.sourceSets.api.allSource

        // Set configurations for the IntelliJ IDEA scopes.
        scopes.COMPILE.plus += configurations.extraLib
        scopes.TEST.minus += configurations.extraLib
    }
}

Customizing with merged hooks

With the merge hooks, we can access the model objects and manipulate them to customize file generation. In the following table, we can see the type of argument that is passed to the beforeMerged and whenMerged hooks:

Model

Merge hook argument

Description

Project

org.gradle.plugins.ide.idea.model.Project

Model object with properties for project file generation.

Module

org.gradle.plugins.ide.idea.model.Module

Model object with properties for module file generation.

The project script block has an ipr script block that we must use to define the beforeMerged and whenMerged hooks. The module script block has the iml configuration script block to define those hooks.

In the following example build file, we see some of the things we can do by using the merge hooks:

apply plugin: 'java'
apply plugin: 'idea'

version = 1.0

description = 'Sample project'

repositories {
    mavenCentral()
}

dependencies {
    testCompile 'junit:junit:4.8'
}


idea {
    project {
        ipr {
            beforeMerged { iprProject ->
                iprProject.wildCards.removeAll()
            }

            whenMerged { iprProject ->
                iprProject.wildCards.add '!?*.xsd'               
            }
        }
    }

    module {
        iml {
            beforeMerged { imlModule ->
                imlModule.outputDir = null
            }

            whenMerged { imlModule ->
                imlModule.jdkName = '1.6'
                module.dependencies*.exported = true
                imlModule.excludeFolders.add file('.svn')
            }
        }
    }
}

Customizing with XML manipulation

At the lowest level, we can manipulate the XML before it is written to disk. For workspace file configuration changes, this is the best way. We can also use it for the project and module files. We must implement a closure with the withXml hook to customize the XML structure. The closure has a single argument of type org.gradle.api.XmlProvider. We can use the asNode() method to get a Groovy groovy.util.Node object. This is the easiest way to manipulate the XML. The asString() method returns a StringBuilder object and the asElement() returns an org.w3c.dom.Element object.

In the following example build file, we make some changes to the XML for the project, module, and workspace files:

apply plugin: 'java'
apply plugin: 'idea'

idea {
    project {
        ipr {
            withXml { xml ->
                def projectRoot = xml.asNode()
                projectRoot.component.find {
                    it.@name == 'ProjectRootManager'
                }.@'assert-keyword' = true

                def javadoc = projectRoot.component.find {
                    it.@name == 'JavadocGenerationManager'
                }
                javadoc.option.find {
                    it.@name == 'OPEN_IN_BROWSER'
                }.@value = false               
            }
        }
    }

    module {
        iml {
            withXml { xml ->
                def moduleRoot = xml.asNode()
                def facetManager = moduleRoot.component.find {
                    it.@name == 'FacetManager'
                }
                facetManager.plus {
                    facet(type: 'Spring', name: 'Spring') {
                        configuration {
                            fileset(id: 'fileset1', name: 'XML Application Context') {
                                file 'file://$MODULE_DIR$/src/main/resources/applicationContext.xml'
                            }
                        }
                    }
                }
            }
        }
    }

    workspace {
        iws {
            withXml { xml ->
                def workspaceRoot = xml.asNode()
                def coverageViewManager = workspaceRoot.component.find {
                    it.@name == 'CoverageViewManager'
                }
                coverageViewManager.option.find {
                    it.@name == 'myFlattenPackages'
                }.@value = 'false'
            }       
        }
    }
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.150.231