IDEA 插件与 配置缓存 不兼容。

IDEA 插件生成由 IntelliJ IDEA 使用的文件,从而可以从 IDEA 打开项目(文件 - 打开项目)。外部依赖项(包括关联的源代码和 Javadoc 文件)和项目依赖项都会被考虑。

如果您只是想将 Gradle 项目加载到 IntelliJ IDEA 中,请使用 IDE 的 导入工具。您不需要应用此插件将项目导入 IDEA,但如果您这样做,导入将考虑您可能拥有的任何额外的 IDEA 配置,这些配置不会直接修改生成的文件 - 有关更多详细信息,请参阅 配置 部分。

IDEA 插件生成的具体内容取决于使用了哪些其他插件

始终

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

Java 插件

此外,将 Java 配置添加到 IDEA 模块和项目文件中。

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 中打开项目

cleanIdea删除

依赖于: cleanIdeaProject, cleanIdeaModule

删除所有 IDEA 配置文件

cleanIdeaProject删除

删除 IDEA 项目文件

cleanIdeaModule删除

删除 IDEA 模块文件

cleanIdeaWorkspace删除

删除 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)”。这样就不需要显式执行清理任务。

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

挂钩到生成生命周期

插件提供对象来模拟 Gradle 生成的元数据文件中的各个部分。生成生命周期如下:

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

  2. 使用表示现有文件的域对象执行 beforeMerged 挂钩。

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

  4. 使用表示要持久化的文件内容的域对象执行 whenMerged 挂钩。

  5. 使用将要持久化的 XML 的原始表示执行 withXml 挂钩。

  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”属性配置此路径变量,以便它可以进行适当的合并,而不会创建重复项。