深入解析 @likec4/lsp:为 Neovim、Zed 等第三方编辑器打造的零依赖 LikeC4 独立语言服务器
【免费下载链接】likec4 Visualize, collaborate, and evolve the software architecture with always actual and live diagrams from your code 项目地址: https://gitcode.com/GitHub_Trending/li/likec4
导读
LikeC4 是一个从代码中可视化、协作并演进软件架构的开源项目,其语言服务器(Language Server)在 VSCode 扩展与官方 Web IDE 中承担着语法高亮、补全、跳转、语义 Token 等核心体验。@likec4/lsp 是 1.54.0 版本起从这一基础设施中独立发布的自包含语言服务器包,目标是将 LikeC4 DSL 的编辑能力开放给 Neovim、Zed、Emacs、JetBrains、Helix 等任何支持 LSP 协议的第三方编辑器。本文将结合该包的源码与构建配置,讲解其安装使用、命令行传输方式、编程式 API、零运行时依赖的实现原理,以及它如何复用 @likec4/language-server 的完整语言能力。
一、包的定位与版本脉络
@likec4/lsp 的定位在 package.json 中描述为 "Standalone LikeC4 Language Server for editor integrations",即面向第三方编辑器集成的独立语言服务器。从 CHANGELOG.md 可以还原它的演进历史:
- 1.54.0:正式引入独立的 @likec4/lsp 包(PR #2843),用于 Neovim、Zed 等第三方编辑器集成;它被描述为 "Self-contained, fully-bundled CJS language server with zero runtime dependencies"(自包含、完全打包、零运行时依赖),并修复了 issue #2840。
- 1.55.1:修复编程式配置文件(likec4.config.ts)在 VSCode 扩展与独立 LSP 中未被加载的问题(PR #2896),说明该包与 VSCode 扩展共享同一套语言服务内核。
- 1.55.0 ~ 1.59.3:后续版本持续演进,当前仓库中版本为 1.59.3。
值得注意的是,尽管 CHANGELOG 中提到 "fully-bundled CJS",当前仓库的 tsdown.config.mts 实际以 format: 'esm' 输出,并通过 minify: true 与 deps: { onlyBundle: false } 将包括 langium、vscode-languageserver 在内的全部依赖打进产物,实现运行时零依赖的目标。
二、安装与命令行用法
2.1 全局安装
npm install -g @likec4/lsp
安装后获得 likec4-lsp 可执行命令,package.json 中的 bin 字段将其指向 bin/likec4-lsp.mjs,后者仅做一件事:
#!/usr/bin/env node
import { startStandaloneLsp } from '../dist/standalone.mjs'
startStandaloneLsp()
即直接调用 standalone.ts 中导出的 startStandaloneLsp 启动服务器。
2.2 传输方式自动检测
likec4-lsp 会根据命令行参数自动选择 LSP 传输通道,这与 vscode-languageserver/node 的 createConnection 行为一致(源码注释见 standalone.ts):
likec4-lsp –stdio # 标准输入输出(大多数编辑器采用)
likec4-lsp –node-ipc # Node IPC(VSCode 扩展常用)
likec4-lsp –socket=<port> # TCP Socket,按端口号
likec4-lsp –pipe=<name> # 命名管道(Windows)
编辑器侧只需将启动命令与参数写入自身的 LSP 客户端配置即可,无需任何额外依赖。
三、第三方编辑器集成示例
3.1 Neovim
官方推荐配合 likec4.nvim 插件使用,插件安装时自动全局安装语言服务器:
{
'likec4/likec4.nvim',
build = 'npm install -g @likec4/lsp'
}
3.2 Emacs(eglot / lsp-mode)
@likec4/lsp 以 –stdio 方式接入 eglot:
;; eglot
(add-to-list 'eglot-server-programs
'((likec4-mode) . ("likec4-lsp" "–stdio")))
同样可配合 lsp-mode 使用;Zed 用户可参考社区维护的 zed-likec4 集成方案。这些配置示例均出自 README.md,可直接复制到对应编辑器的配置中。
四、编程式 API:startStandaloneLsp
对于想要深度集成的场景(例如自定义插件宿主),@likec4/lsp 也导出了编程式入口,类型声明为 standalone.d.ts 中的 dist/standalone.d.ts:
const { startStandaloneLsp } = require('@likec4/lsp')
startStandaloneLsp({
loggerOptions: {
logLevel: 'debug',
},
})
4.1 StandaloneLspOptions 详解
从 standalone.ts 的源码可以看到完整的选项结构:
| enableWatcher | boolean | false | 是否启用文件系统监听(WithFileSystem 注入的依据) |
| loggerOptions.useStdErr | boolean | true | 日志输出到 stderr,避免污染 stdout 上的 LSP 协议流 |
| loggerOptions.logLevel | 'trace' \\| 'debug' \\| 'info' \\| 'warning' \\| 'error' | 'info' | 日志级别 |
| loggerOptions.enableTelemetry | boolean | false | 是否启用遥测 |
| loggerOptions.nonBlocking | boolean | false | 是否启用非阻塞(异步)日志 |
| loggerOptions.colors | boolean | false | 日志是否使用颜色 |
源码中 configureLanguageServerLogger 的默认参数为 { enableTelemetry: false, useStdErr: true, logLevel: 'info' },随后通过展开运算符与 options?.loggerOptions 合并,因此用户传入的配置会覆盖默认值。
4.2 启动流程
startStandaloneLsp 的启动流程在 standalone.ts 中一目了然:
五、零运行时依赖的打包原理
README 宣称 "Self-contained, fully-bundled CommonJS binary with zero runtime dependencies",其实现关键在于 tsdown.config.mts:
- entry: ['src/standalone.ts']:单一入口,从 startStandaloneLsp 出发反向打包整条依赖链;
- format: 'esm' + minify: true:输出压缩产物(当前仓库版本为 ESM 格式);
- deps: { onlyBundle: false }:关闭"仅打包外部依赖"的选项,把所有第三方依赖全部打进产物,从而让 npm 安装后运行时不再需要解析任何外部包;
- nodeProtocol: true:Node 内置模块协议处理,保证产物可直接在 Node 中运行。
对照 package.json,其 dependencies 中只声明了 bundle-require、esbuild、fdir 三个构建期依赖,而 devDependencies 中才包含真正被捆绑进产物的 @likec4/language-server、@likec4/layouts、@likec4/log、langium、vscode-languageserver 等;同时 files 字段只发布 bin、dist 与 package.json,!**/*.map 排除 sourcemap,进一步缩小安装体积。引擎要求 node >= 22.22.3,部署前需确认运行时版本。
六、底层能力:复用 @likec4/language-server 的完整 LSP 服务
@likec4/lsp 本身并不重复实现语言功能,而是通过 module.ts 中的 createLanguageServices 组装 @likec4/language-server 的全部服务。从模块导入可以看出它继承了完整的编辑体验:
- 编辑能力:LikeC4CompletionProvider(补全)、LikeC4HoverProvider(悬停)、LikeC4CodeActionProvider(代码动作)、LikeC4CodeLensProvider(Code Lens)、LikeC4SemanticTokenProvider(语义 Token)、LikeC4DocumentSymbolProvider / WorkspaceSymbolProvider(符号)、LikeC4DocumentHighlightProvider、LikeC4DocumentLinkProvider、LikeC4Formatter(格式化);
- 模型与验证:LikeC4ModelBuilder、LikeC4ModelParser、DeploymentsIndex、FqnIndex、LikeC4DocumentValidator 与注册的校验规则,确保 DSL 错误实时反馈;
- 工作区管理:IndexManager、LangiumDocuments、LikeC4WorkspaceManager、ProjectsManager,支撑多文件项目、多 project 与多 metadata 扩展的索引。
而 standalone.ts 在组装时额外注入了三个关键模块:
const services = createLanguageServices({
connection,
…WithFileSystem(options?.enableWatcher ?? false),
…WithLikeC4ManualLayouts,
…WithWasmGraphviz,
})
- WithFileSystem:文件系统读写与(可选的)文件变更监听,enableWatcher 即控制此模块;
- WithLikeC4ManualLayouts:对 DSL 中手动布局(manual layout)标注的读取与解析;
- WithWasmGraphviz:以 WebAssembly 形态内嵌 Graphviz 布局引擎,使得在纯 Node 环境下也能计算自动布局,这是独立服务器可以脱离 VSCode 运行的关键支撑之一。
也正因如此,1.55.1 中关于 likec4.config.ts 未被加载的修复(PR #2896)能同时惠及 VSCode 扩展与独立 LSP——两者底层共享同一套 createLanguageServices 与工作区管理逻辑,packages/vscode 扩展与 @likec4/lsp 只是同一语言内核的两种宿主。
七、常见使用场景与注意事项
八、总结
@likec4/lsp 是 LikeC4 走向"任意编辑器可用"的关键一环:它以极小的对外接口(一个 CLI、一个 startStandaloneLsp 函数)封装了 @likec4/language-server 完整且厚重的语言能力,通过构建期全量打包实现零运行时依赖,让 Neovim、Zed、Emacs、Helix 等编辑器的接入成本降低到只需配置一行启动命令。对于希望深度定制的团队,StandaloneLspOptions 提供了 watcher 与日志层面的控制点,而其背后共享的 createLanguageServices 内核,也保证了第三方集成与官方 VSCode 扩展在补全、校验、语义 Token、布局计算等体验上的一致性。若需进一步研究底层实现,可继续阅读 packages/language-server/src/module.ts、packages/language-server/src/workspace 与 packages/lsp/src/standalone.ts。
【免费下载链接】likec4 Visualize, collaborate, and evolve the software architecture with always actual and live diagrams from your code 项目地址: https://gitcode.com/GitHub_Trending/li/likec4
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



