The JetBrains Blog

Structuring IntelliJ Plugins with Optional Content Modules

8.5内容质量
Structuring IntelliJ Plugins with Optional Content Modules

TL;DR · AI 摘要

JetBrains 推出 Plugin Model v2,支持通过可选内容模块构建 IntelliJ 插件,提升插件的灵活性和兼容性。

核心要点

  • Plugin Model v2 支持可选内容模块,允许插件根据 IDE 功能动态加载。
  • IntelliJ IDEA 2026.1 中 CSS PSI 功能免费提供,无需订阅。
  • 使用 Gradle 构建插件时,需配置 Kotlin 和 Plugin content module 支持插件。

结构提纲

按章节快速跳转。

  1. JetBrains 推出 Plugin Model v2,支持构建更灵活的 IntelliJ 插件。

  2. Plugin Model v2 主要用于 Split Mode(远程开发)插件,支持动态加载功能。

  3. 通过将 CSS PSI 功能移至可选内容模块,实现插件的模块化构建。

  4. Gradle 构建脚本配置

    使用 IntelliJ Platform Gradle Plugin 2.16.0 及以上版本,配置 Kotlin 和 Plugin content module 支持。

  5. 模块化插件的 plugin.xml 文件应保持简洁,不再需要 com.intellij.modules.platform 依赖。

  6. 通过创建 Kotlin 模块 css,并将其作为子项目依赖,实现插件内容模块的构建。

思维导图

用一张图看清主题之间的关系。

查看大纲文本(无障碍 / 无 JS 友好)
  • IntelliJ 插件开发
    • Plugin Model v2
      • 支持可选内容模块
      • 适用于 Split Mode 插件
    • 构建配置
      • 使用 Gradle 和 Kotlin
      • 配置 Plugin content module 支持
    • 模块化插件
      • CSS PSI 功能模块化
      • 依赖 IDE 内置模块

金句 / Highlights

值得收藏与分享的关键句。

  • Plugin Model v2 是一种实验性方式,用于结构化、打包和构建插件,并支持未来场景。

    第 2 段

    ⬇︎ 下载 PNG𝕏 分享到 X
  • 在 IntelliJ IDEA 2026.1 中,CSS PSI 功能免费提供,无需订阅。

    第 3 段

    ⬇︎ 下载 PNG𝕏 分享到 X
  • 使用 IntelliJ Platform Gradle Plugin 2.16.0 及以上版本,可以为 Gradle 子模块提供流线型配置。

    第 4 段

    ⬇︎ 下载 PNG𝕏 分享到 X
#IntelliJ#插件开发#JetBrains#Gradle
打开原文

使用可选内容模块构建 IntelliJ 插件 - JetBrains 博客

JetBrains 平台

JetBrains 产品的插件和扩展开发。

关注

  • 关注:
  • X X
  • RSS RSS

前往插件市场

IntelliJ 平台

插件

使用可选内容模块构建 IntelliJ 插件

Róbert Novotný

如果插件的某一部分只有在特定的 IDE 功能可用时才加载,会怎样?现在,Plugin Model v2 作为一种实验性的方法,可用于构建、打包和组织插件,并以面向未来的方式支持此类场景。其主要使用场景是 Split Mode(远程开发)插件。

在本文中,让我们创建一个插件,将与 CSS PSI 相关的功能移动到一个可选的插件内容模块中。

IDE 包含一个捆绑的插件内容模块,提供 CSS 支持,而我们的可选插件内容模块依赖于它。在 IntelliJ IDEA 2026.1 中,CSS PSI 可以免费使用,无需订阅,因此该内容模块将自动可用。在 IntelliJ IDEA 2025.3 中,只有在用户拥有订阅时才会加载该模块。

包含单个插件内容模块的插件,该模块依赖于 IDE 插件内容模块

新插件

使用 IDE 插件生成器创建插件。从 IntelliJ IDEA 2026.1 开始,如果已安装 Plugin DevKit,可以在 File | New Project 中找到该生成器。删除样板代码,如注释和依赖项,并设置正确的插件描述元数据。

更重要的是,将 Gradle 构建脚本设置为依赖于 IntelliJ IDEA 2025.3。这是 Plugin Model v2 仍处于实验阶段,但对第三方插件一般可用的版本。

code
dependencies {
    intellijPlatform {
        intellijIdea("2025.3")
    }
}

为模块化构建准备 Gradle 构建脚本

IntelliJ 平台 Gradle 插件 2.16.0 及以上版本为 Gradle 子模块提供了简化的配置,这些子模块对应于 IntelliJ 插件内容模块。

每个这样的 Gradle 子模块都需要两个 Gradle 插件:Kotlin 和插件内容模块支持。

在 build.gradle.kts 中启用这些插件。

code
subprojects {
    apply(plugin = "org.jetbrains.kotlin.jvm")
    apply(plugin = "org.jetbrains.intellij.platform.module")
}

为模块化构建准备插件描述文件

在模块化插件中,插件描述文件 plugin.xml 是最小化的。即使 com.intellij.modules.platform 依赖项也不再需要,因为它会自动提供。

操作、扩展和监听器不再属于这里。它们在对应的插件内容模块描述文件中声明。

创建插件内容模块

在 IDE 中,创建一个空的 Kotlin 模块 css,使用 Gradle 构建。它对应于一个 Gradle 子项目和一个插件内容模块。最初,其构建脚本应简化为一个空文件。所有必要的配置将由父构建脚本及其 Gradle 插件提供。

为了让它正常工作,需要在主构建脚本中将此 Gradle 子项目声明为依赖项。

code
dependencies {
    intellijPlatform {
        // ...
    }
    implementation(project(":css"))
}

然后,设置插件内容模块描述符。注意其命名和位置。与通常的 plugin.xml 不同,插件内容模块描述符应位于 src/main/resources 目录下,处于类路径的根目录。描述符的名称来源于父项目名称。换句话说,创建 src/main/resources/mincssrel.css.xml 文件,并包含一个空的 <idea-plugin> 元素。

准备好这个插件内容模块描述符后,最后的配置步骤是:在插件描述符中声明插件内容模块。在 plugin.xml 中,通过 loading 属性将此模块声明为可选。

xml
<idea-plugin>
    <!-- 简化起见,省略部分内容 -->
    <content>
        <module name="mincssrel.css" loading="optional" />
    </content>
</idea-plugin>

loading 属性可以省略,但建议显式指定,以避免混淆。

依赖 PSI 功能

CSS PSI 功能位于 IDE 插件内容模块 intellij.css 中。在 css 插件内容模块的两个位置添加此依赖项:首先,在插件内容模块的 Gradle 构建脚本中,其次,在插件内容模块描述符中。这些声明有两个方面:Gradle 决定哪些内容进行编译,而插件内容模块描述符决定哪些内容进行加载。

现在,css/build.gradle.kts 文件获得了适当的内容。使用 IntelliJ 平台 Gradle 插件提供的 bundledModule 表示法,在 intellijPlatform 块中添加依赖项。

kotlin
dependencies {
    intellijPlatform {
        bundledModule("intellij.css")
    }
}

src/main/resources/mincssrel.css.xml 描述符将不再为空。通过引用完整模块名称(包括前缀)来声明对这个捆绑插件内容模块的依赖。

xml
<idea-plugin>
    <dependencies>
        <module name="intellij.css" />
    </dependencies>
</idea-plugin>

插件内容模块依赖项是 Plugin Model v2 的一部分。每个 <module> 元素声明了一个强制性的、非可选的依赖项。如果此依赖项不可用,mincssrel.css 模块将不会加载。

一般来说,如果插件没有可用的插件内容模块,它将被禁用。

CSS PSI

为了验证功能是否正常工作,创建一个 CssAction 操作,并在插件内容模块描述符 mincssrel.css.xml 中声明它。

xml
<actions>
    <action id="org.intellij.sdk.css.CssAction"
            class="org.intellij.sdk.css.CssAction"
            text="Invoke CSS Action"
    />
</actions>

然后,提供源代码。从静态样式表字符串创建一个内存中的 CSS 文件,在后台线程上通过 readAction 读取 PSI,遍历规则集,收集 CSS 选择器名称,并在事件调度线程(EDT)上通过对话框显示它们。

kotlin
import com.intellij.lang.css.CSSLanguage
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.*
import com.intellij.openapi.progress.currentThreadCoroutineScope
import com.intellij.openapi.project.*
import com.intellij.openapi.ui.Messages
import com.intellij.psi.PsiFileFactory
import com.intellij.psi.css.*
import com.intellij.util.concurrency.annotations.RequiresReadLock
import kotlinx.coroutines.*
import org.intellij.lang.annotations.Language

@Language("CSS")
private const val SAMPLE_STYLESHEET = """
body {
  font-family: sans-serif;
}

h1 {
  font-size: 2.5em;
}    
"""
kotlin
class CssAction : DumbAwareAction() {
    override fun actionPerformed(e: AnActionEvent) {
        val project = e.project ?: return
        currentThreadCoroutineScope().launch {
            val selectorNames = readAction {
                project.createSampleCssPsiFile()?.getSelectorNames() ?: emptyList()
            }
            val selectorsMessage = selectorNames.joinToString(", ")
            withContext(Dispatchers.EDT) {
                Messages.showInfoMessage(selectorsMessage, "CSS Selector List")
            }
        }
    }

    private fun Project.createSampleCssPsiFile(): CssFile? {
        val psiFile = PsiFileFactory
            .getInstance(this)
            .createFileFromText(CSSLanguage.INSTANCE, SAMPLE_STYLESHEET)
        return psiFile as? CssFile
    }

    @RequiresReadLock
    private fun CssFile.getSelectorNames() = stylesheet.rulesetList.rulesets.flatMap {
        it.selectors.toList()
    }.map {
        it.presentableText
    }
}

运行插件

如果 IDE 中存在 intellij.css 插件内容模块,则 CSS 动作可以访问 CSS PSI。如果不存在,则此 mincssrel.css 插件内容模块不会加载。

在 IntelliJ IDEA 2025.3 中,CSS PSI 功能需要订阅才能使用。在 IntelliJ IDEA 2026.1 及更新版本中,即使没有订阅,CSS PSI 也可用。

为了演示这一点,将一个专用的 Gradle 运行任务添加到主构建脚本 build.gradle.kts 中。

code
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType.IntellijIdea
// ...
// 省略 Gradle 构建脚本内容
// ...
val runIde261 by intellijPlatformTesting.runIde.registering {
    type = IntellijIdea
    version = "2026.1"
}

运行 runIde261 任务,打开“搜索所有内容”,然后调用 CSS 动作。这演示了由 intellij.css IDE 插件内容模块和 CSS PSI 支持的可选功能。

总结

插件可以声明一个可选的插件内容模块,以隔离平台特定的功能,其依赖项决定了它何时可以加载。插件内容模块的数量没有限制。对于更复杂的示例,请参阅 multi-module-plugin 仓库,该仓库展示了两个插件内容模块:一个必选模块和一个可选模块,它们之间存在 API 依赖关系。

要查看本文的视觉摘要,请观看 Gradle Setup Powering Multi-module IntelliJ Plugins。要继续远程开发的故事,请阅读 Make Your Plugin Remote Development-Ready 作为后续内容。

插件开发

远程开发

  • 分享
  • Facebook
  • Twitter
  • LinkedIn

上一篇

JetBrains 市场生态系统安全更新:解决恶意第三方 AI 插件问题