JetBrains Platform
Plugin and extension development for JetBrains products.
面向插件开发者的语言服务器协议
语言服务器协议 (LSP) 是 Microsoft 开发的一项开放标准协议,用于开发工具与语言服务器之间的通信。 我们将 LSP 整合到 IntelliJ 平台,使插件开发者能够使用特定 LSP 服务器集成引入自定义语言支持。 语言服务器可以提供针对特定语言的功能,例如代码补全、文档和格式设置,这比从头开始实现语言支持要容易得多,省时省力。 它还减少了持续维护和跟踪相关语言与工具更改的需要,使不同开发环境更易获得一致的语言支持。
但是,请记住,与处理和呈现语言服务器提供的数据相比,IntelliJ 平台提供的规范自定义语言支持仍然提供了与 IDE 功能更广泛的集成。 因此,LSP 方式不应被视为现有语言 API 的替代方案,而应被视为附加值。
从 2023.2 发布周期开始,LSP API 作为 IntelliJ 平台的一部分在以下 IDE 中公开提供:
- IntelliJ IDEA Ultimate
- WebStorm
- PhpStorm
- PyCharm Professional
- DataSpell
- RubyMine
- CLion
- Aqua
- DataGrip
- GoLand
- Rider
下面几部分将解释如何构建与语言服务器的简单集成,发现可用的功能和文档,以及了解基于 IntelliJ 的 IDE 中 LSP 支持的当前状态。
插件配置
为了在基于 Gradle 构建系统的第三方插件中充分利用语言服务器协议 API,我们建议将 Gradle IntelliJ Plugin 升级到 1.15.0 或更高版本。 此插件会将 LSP API 源和代码文档附加到项目中。
LSP 在基于 IntelliJ 的 IDE 的 2023.2 EAP7 中可用,因此插件必须以 IntelliJ IDEA Ultimate 232-EAP-SNAPSHOT
或更高版本为目标,或者在全面推出后以 v2023.2 为目标。
示例 build.gradle.kts
配置:
plugins { // ... id("org.jetbrains.intellij") version "1.15.0" } intellij { version = "232-EAP-SNAPSHOT" type = "IU" }
对于基于 IntelliJ Platform Plugin Template 的项目,将 Gradle IntelliJ Plugin 更新到最新版本,并按如下所示修改 gradle.properties
文件:
platformType = IU platformVersion = 232-EAP-SNAPSHOT pluginSinceBuild = 232 pluginUntilBuild = 232.*
plugin.xml 配置文件需要指定对 IntelliJ IDEA Ultimate 模块的依赖:
com.intellij.modules.platform com.intellij.modules.ultimate
通过以上更改,我们可以访问 LSP API 及其源代码和文档。
LSP API 源捆绑在 IntelliJ IDEA Ultimate 中,可以在 [IDE]/lib/src/src_lsp-openapi.zip
归档中找到。 如果您使用的是 Gradle IntelliJ Plugin 1.15.0+,它们会自动解析和映射。
支持的功能
IntelliJ 平台内的初始 LSP 支持涵盖以下功能:
- 错误/警告高亮显示 (textDocument/publishDiagnostics)
- 这些错误/警告的快速修复 (textDocument/codeAction)
- 代码补全 (textDocument/completion)
- 转到声明 (textDocument/definition)
更多功能即将公布。
基本实现
最低限度的 LSP 集成必须实现 LspServerSupportProvider
以及服务描述符,并将其注册为 com.intellij.platform.lsp.serverSupportProvider
扩展点:
import com.intellij.platform.lsp.api.LspServerSupportProvider import com.intellij.platform.lsp.api.ProjectWideLspServerDescriptor class FooLspServerSupportProvider : LspServerSupportProvider { override fun fileOpened(project: Project, file: VirtualFile, serverStarter: LspServerStarter) { if (file.extension == "foo") { serverStarter.ensureServerStarted(FooLspServerDescriptor(project)) } } } private class FooLspServerDescriptor(project: Project) : ProjectWideLspServerDescriptor(project, "Foo") { override fun isSupportedFile(file: VirtualFile) = file.extension == "foo" override fun createCommandLine() = GeneralCommandLine("foo", "--stdio") }
提供 LSP 服务器支持提供程序扩展点的实现后,将其注册到 plugin.xml
文件中,如下所示:
com.intellij.modules.platform com.intellij.modules.ultimate
作为参考,请查看 Prisma ORM 开源插件实现:https://github.com/JetBrains/intellij-plugins/tree/master/prisma/src/org/intellij/prisma/ide/lsp
语言服务器集成
语言服务器是一个独立进程,用于分析源代码并向开发工具提供针对特定语言的功能。 在 IDE 中创建使用 LSP 的插件时,可以通过两种方式向最终用户提供语言服务器:
- 将语言服务器实现二进制文件捆绑为随插件交付的资源。
- 为用户提供定义语言服务器二进制文件在其环境中的位置的功能。
Prisma ORM 插件采用第一种方式,分发 prisma-language-server.js
脚本并使用本地 Node.js 解释器来运行。
对于更复杂的情况,您可能需要带有专属设置实现的详细配置。
要实现最低限度但功能齐全的插件,请执行以下步骤:
- 在
LspServerSupportProvider.fileOpened()
方法中,启动相关 LSP 服务器描述符,它可以使用LspServerDescriptor.isSupportedFile()
检查方法来确定给定文件是否受支持。 - 说明如何通过实现
LspServerDescriptor.createCommandLine()
启动服务器。
自定义
- 为了微调或禁用基于 LSP 的功能的实现,插件可以重写
LspServerDescriptor
类的相应属性。 请参阅属性文档,了解更多详细信息:lspGoToDefinitionSupport
lspCompletionSupport
lspDiagnosticsSupport
lspCodeActionsSupport
lspCommandsSupport
- 要处理来自 LSP 服务器的自定义(未记录)请求和通知,请重写
LspServerDescriptor.createLsp4jClient
。 - 要将自定义(未记录)请求和通知发送到 LSP 服务器,请重写
LspServerDescriptor.lsp4jServerClass
并实现LspClientNotification
和/或LspRequest
类。
如需了解详情,请参见捆绑的 LSP API 源代码及其代码文档。
测试
用于测试的实用程序类尚未提取供公众使用,但我们将尽快提供合适的方法来测试基于 LSP 的第三方插件。
故障排除
所有 IDE 和 LSP 服务器通信日志均传递到 IDE 日志文件。
要将其包含以供预览,请将以下条目添加到 Help | Diagnostic Tools | Debug Log Settings…(帮助 | 诊断工具 | 调试日志设置…)配置对话框中:
#com.intellij.platform.lsp
有关详情,请参阅 IntelliJ 平台 SDK 文档中的 Logging 部分。
限制
- 当前 LSP API 实现假设 IDE LSP 服务器通讯渠道为
stdio
。 - IDE 不会向服务器发送 workspace/didChangeWatchedFiles 通知。
结论
将语言服务器协议 (LSP) 集成到基于 IntelliJ 的 IDE 的插件中时,需要在简单快速的语言支持和具有 IDE 功能的复杂自定义语言支持插件之间做出权衡。
考虑基于 LSP 的方式时,务必按以下标准评估向最终用户提供的语言服务器:
- 语言服务器的操作系统依赖。
- 最新版本在线可用性。
- 与版本间重大更改的兼容性。
- 请求用户提供语言服务器二进制路径的可行性。
解决与语言服务器进程的集成问题后,查阅 IntelliJ SDK 文档仍然很重要。 这将全面概述与 IntelliJ 平台内 LSP 标准无缝集成的可用功能。
请注意,与语言服务器协议的集成作为基于 IntelliJ 的付费 IDE 的扩展而创建。 因此,使用语言服务器集成的插件可能无法在 JetBrains 产品的 Community 版本和 Google 的 Android Studio 中使用。
如果您遇到问题或需要帮助,请通过 JetBrains Platform Slack 工作区中的 #intellij-platform
频道联系我们或在 YouTrack 中提交问题。
本博文英文原作者: