IDEA 插件与配置缓存不完全兼容。应用后,配置缓存会自动禁用。

IDEA 插件生成供 IntelliJ IDEA 使用的文件,从而可以在 IDEA 中打开项目(File - Open Project)。它会考虑外部依赖(包括相关的源代码和 Javadoc 文件)和项目依赖。

如果您只是想将 Gradle 项目加载到 IntelliJ IDEA 中,那么请使用 IDE 的导入功能。您不需要应用此插件就可以将项目导入 IDEA,但是如果应用了,导入将考虑您所有未直接修改生成文件的额外 IDEA 配置——有关更多详细信息,请参阅配置部分。

IDEA 插件具体生成什么取决于使用了哪些其他插件

始终

生成一个 IDEA 模块文件。如果项目是根项目,还会生成一个 IDEA 项目和工作区文件。

Java 插件

额外向 IDEA 模块和项目文件添加 Java 配置。

IDEA 插件的一个重点是开放定制。该插件提供了一套标准化的钩子,用于从生成的文件中添加和删除内容。

用法

要使用 IDEA 插件,请在构建脚本中包含以下内容

build.gradle.kts
plugins {
    idea
}
build.gradle
plugins {
    id 'idea'
}

IDEA 插件向您的项目添加了许多任务。idea 任务为项目生成一个 IDEA 模块文件。当项目是根项目时,idea 任务还会生成一个 IDEA 项目和工作区。IDEA 项目包括 Gradle 构建中每个项目的模块。

当项目是根项目时,IDEA 插件还会添加一个 openIdea 任务。此任务生成 IDEA 配置文件并在 IDEA 中打开结果。这意味着您只需从根项目运行 ./gradlew openIdea,即可在一个方便的步骤中生成并打开 IDEA 项目。

IDEA 插件还会向项目添加一个 cleanIdea 任务。此任务会删除已生成的 文件(如果存在)。

任务

IDEA 插件向项目添加了以下任务。请注意,clean 任务不依赖于 cleanIdeaWorkspace 任务。这是因为工作区通常包含大量用户特定的临时数据,并且不希望在 IDEA 外部对其进行操作。

idea

依赖于ideaProject, ideaModule, ideaWorkspace

生成所有 IDEA 配置文件

openIdea

依赖于idea

生成所有 IDEA 配置文件并在 IDEA 中打开项目

cleanIdeaDelete

依赖于cleanIdeaProject, cleanIdeaModule

删除所有 IDEA 配置文件

cleanIdeaProjectDelete

删除 IDEA 项目文件

cleanIdeaModuleDelete

删除 IDEA 模块文件

cleanIdeaWorkspaceDelete

删除 IDEA 工作区文件

ideaProjectGenerateIdeaProject

生成 .ipr 文件。此任务仅添加到根项目。

ideaModuleGenerateIdeaModule

生成 .iml 文件

ideaWorkspaceGenerateIdeaWorkspace

生成 .iws 文件。此任务仅添加到根项目。

配置

该插件添加了一些配置选项,允许自定义其生成的 IDEA 项目和模块文件。这些选项以模型属性和直接修改生成文件的低级机制的形式存在。例如,您可以添加源目录和资源目录,以及注入自己的 XML 片段。前一种配置类型被 IDEA 的导入工具所支持,而后一种则不支持。

以下是您可以使用的配置属性

ideaIdeaModel

顶层元素,以 DSL 友好的方式启用 IDEA 插件的配置

idea.project IdeaProject

允许配置项目信息

idea.module IdeaModule

允许配置模块信息

idea.workspace IdeaWorkspace

允许配置工作区 XML

请点击链接到类型,查看使用这些配置属性的示例。

自定义生成文件

IDEA 插件提供了钩子和行为,可以以更受控和更详细的方式自定义生成的内容。此外,withXml 钩子是修改工作区文件的唯一实用方法,因为其对应的域对象本质上是空的。

本节讨论的技术不适用于 IDEA 的导入功能

这些任务识别现有的 IDEA 文件并将其与生成的内容合并。

合并

现有 IDEA 文件中作为生成内容目标的区段将被修改或覆盖,具体取决于特定区段。其余区段将保持不变。

通过完全覆盖禁用合并

要完全重写现有的 IDEA 文件,请执行清除任务及其相应的生成任务,如“gradle cleanIdea idea”(按此顺序)。如果您想将其设置为默认行为,请将“tasks.idea.dependsOn(cleanIdea)”添加到您的构建脚本中。这样就不需要显式执行清除任务。

此策略也可用于插件将生成的单个文件。例如,可以使用“gradle cleanIdeaModule ideaModule”来处理“.iml”文件。

挂钩生成生命周期

该插件提供了建模 Gradle 生成的元数据文件部分的 对象。生成生命周期如下:

  1. 读取文件;如果文件不存在,则使用 Gradle 提供的默认版本

  2. beforeMerged 钩子以表示现有文件的域对象执行

  3. 将现有内容与从 Gradle 构建推断或在 eclipse DSL 中显式定义的配置合并

  4. whenMerged 钩子以表示将要持久化的文件内容的域对象执行

  5. withXml 钩子以将要持久化的 XML 的原始表示执行

  6. 最终的 XML 被持久化

以下是每种模型类型使用的域对象:

IdeaProject
IdeaModule
IdeaWorkspace

部分重写现有内容

“完全重写”会导致所有现有内容被丢弃,从而丢失直接在 IDE 中所做的任何更改。beforeMerged 钩子使得只覆盖现有内容的某些部分成为可能。以下示例从 Module 域对象中删除所有现有依赖项:

build.gradle.kts
import org.gradle.plugins.ide.idea.model.Module

idea.module.iml {
    beforeMerged(Action<Module> {
        dependencies.clear()
    })
}
build.gradle
idea.module.iml {
    beforeMerged { module ->
        module.dependencies.clear()
    }
}

生成的模块文件将只包含 Gradle 生成的依赖项条目,而不包含原始文件中可能存在的任何其他依赖项条目。(对于依赖项条目,这也是默认行为。)模块文件的其他部分将保持不变或合并。项目文件中的模块路径也可以进行同样的操作

build.gradle.kts
import org.gradle.plugins.ide.idea.model.Project

idea.project.ipr {
    beforeMerged(Action<Project> {
        modulePaths.clear()
    })
}
build.gradle
idea.project.ipr {
    beforeMerged { project ->
        project.modulePaths.clear()
    }
}

修改完全填充的域对象

whenMerged 钩子允许您操作完全填充的域对象。通常,这是自定义 IDEA 文件的首选方式。以下是如何导出 IDEA 模块的所有依赖项:

示例 4. 导出依赖项
build.gradle.kts
import org.gradle.plugins.ide.idea.model.Module
import org.gradle.plugins.ide.idea.model.ModuleDependency

idea.module.iml {
    whenMerged(Action<Module> {
        dependencies.forEach {
            (it as ModuleDependency).isExported = true
        }
    })
}
build.gradle
idea.module.iml {
    whenMerged { module ->
        module.dependencies*.exported = true
    }
}

修改 XML 表示

withXml 钩子允许您在文件写入磁盘之前操作内存中的 XML 表示。尽管 Groovy 的 XML 支持和 Kotlin 的扩展函数弥补了很多不足,但这种方法不如操作域对象方便。作为回报,您可以完全控制生成的文件,包括域对象未建模的部分。

示例 5. 自定义 XML
build.gradle.kts
import org.w3c.dom.Element

idea.project.ipr {
    withXml(Action<XmlProvider> {
        fun Element.firstElement(predicate: (Element.() -> Boolean)) =
            childNodes
                .run { (0 until length).map(::item) }
                .filterIsInstance<Element>()
                .first { it.predicate() }

        asElement()
            .firstElement { tagName == "component" && getAttribute("name") == "VcsDirectoryMappings" }
            .firstElement { tagName == "mapping" }
            .setAttribute("vcs", "Git")
    })
}
build.gradle
idea.project.ipr {
    withXml { provider ->
        provider.node.component
                .find { it.@name == 'VcsDirectoryMappings' }
                .mapping.@vcs = 'Git'
    }
}

识别其他测试目录

将此插件与 Java 插件一起使用时,在添加额外的源集后,您可能希望告知 IDEA 它们何时包含测试源而不是生产源,以便 IDE 可以适当处理这些目录。这可以通过使用此插件的 Module 块来实现。

build.gradle.kts
sourceSets {
    create("intTest") {
        java {
            setSrcDirs(listOf("src/integration"))
        }
    }
}

idea {
    module {
        testSources.from(sourceSets["intTest"].java.srcDirs)
    }
}
build.gradle
sourceSets {
    intTest {
        java {
            srcDirs = ['src/integration']
        }
    }
}

idea {
    module {
        testSources.from(sourceSets.intTest.java.srcDirs)
    }
}
使用 JVM 测试套件插件时,测试源将自动正确识别。

其他注意事项

生成的 IDEA 文件中的依赖项路径是绝对的。如果您手动定义指向 Gradle 依赖项缓存的路径变量,IDEA 将自动用此路径变量替换绝对依赖项路径。您可以通过“idea.pathVariables”属性配置此路径变量,以便进行正确的合并而不会创建重复项。