调试器与 XDebugger 扩展¶
IntelliJ Platform 的调试能力位于 Execution API 之上。运行配置负责描述“调试什么”,Execution API 负责启动会话,XDebugger API 负责把断点、栈帧、变量、表达式求值、暂停/继续等调试体验接入 IDE。
官方 SDK 对 Execution 和 Run Configuration 有详细页面;XDebugger 相关 API 常需要结合现有 JetBrains 语言插件源码、API 文档和目标产品能力一起查。实现前务必确认目标 IDE 中存在
com.intellij.modules.xdebugger,并在plugin.xml声明依赖。
依赖声明¶
如果插件扩展调试器能力,通常需要:
<depends>com.intellij.modules.xdebugger</depends>
如果调试器依赖具体语言,例如 Java、Python、JavaScript,还要声明对应插件依赖,并在 Gradle 中加入匹配依赖。不要只在 IDEA 中验证,因为部分产品没有对应语言调试能力。
Execution 与 Debugger 的关系¶
调试启动链路:
- 用户选择 Run Configuration 和 Debug Executor。
- 平台选择能处理该配置的
ProgramRunner。 - 创建
ExecutionEnvironment。 RunProfile.getState()返回调试所需的RunProfileState。ProgramRunner启动进程或连接远程目标。- 创建 XDebugger Session 和 Debug Tool Window 内容。
如果只是“以 Debug 模式启动外部进程”,通常从 Run Configuration 和 Execution API 开始;如果要在 Debug Tool Window 中展示自定义断点、栈帧和变量,则进入 XDebugger API。
断点类型¶
自定义断点通常围绕 XBreakpointType 设计:
| 类型 | 适合场景 |
|---|---|
| 行断点 | 文件某一行可暂停 |
| 异常断点 | 某类运行时事件触发暂停 |
| 字段/函数/地址断点 | 语言或运行时自定义目标 |
设计断点时要明确:
- 哪些文件类型或 PSI 位置允许创建断点。
- 断点如何序列化和恢复。
- 断点条件、日志表达式、命中次数是否支持。
- 调试后端如何把 IDE 断点映射到运行时断点。
断点 UI 和可创建位置应尽量贴合语言语义,不要让用户在无效位置创建永远不会命中的断点。
XDebugProcess¶
XDebugProcess 表示一个调试进程或调试连接。它通常负责:
- 初始化和关闭调试后端连接。
- 处理 Resume、Pause、Stop、Step Over、Step Into、Step Out。
- 把后端事件转换为 IDE 会话状态。
- 管理断点注册、更新、移除。
- 创建当前暂停位置的栈帧。
设计建议:
- 后端通信放在后台线程。
- UI 更新回到平台要求的线程。
- Stop 操作必须可靠释放进程、socket、临时文件和监听器。
- 对网络或远程调试场景提供超时和取消。
栈帧、变量与求值¶
调试暂停后,IDE 需要展示:
- 当前源位置。
- 调用栈。
- 当前帧变量。
- 对象子节点。
- 表达式求值结果。
常见 API 概念:
| 概念 | 作用 |
|---|---|
XStackFrame |
一层调用栈 |
XSourcePosition |
源文件和行号 |
XValue |
变量或表达式结果 |
XCompositeNode |
变量树节点 |
XDebuggerEvaluator |
表达式求值 |
变量树要懒加载。大型对象、数组、Map、远程值都不应一次性展开,否则 Debug Tool Window 会卡顿。
Source Position 映射¶
调试器最容易出错的地方是运行时位置到 IDE 文件的映射:
- 本地文件路径与远程路径可能不同。
- 生成代码需要映射到源文件。
- 多模块项目中同名文件可能存在多份。
- 行号可能是 0-based 或 1-based,必须统一。
- 动态语言和模板语言可能需要 PSI 或 source map 辅助。
如果后端返回路径,先通过 VFS 找文件;如果返回逻辑符号,优先通过索引或 PSI resolve 到声明。映射失败时,应在 Debug Console 或 Notification 中给出可操作信息。
调试控制台¶
调试会话通常需要控制台:
- 展示后端日志。
- 展示程序 stdout/stderr。
- 支持可点击文件路径。
- 支持表达式求值或 REPL。
可复用 Execution API 的 Console、ProcessHandler 和 Console Filter。不要自己做一个与 Run/Debug Tool Window 割裂的日志窗口,除非调试模型确实不适合标准 UI。
与 Run Configuration 的集成¶
调试器通常需要一个 Run Configuration:
- 保存连接参数、可执行文件、工作目录、环境变量。
- 校验 SDK、解释器、端口、目标文件是否存在。
- 区分 Run 和 Debug 的执行状态。
- 支持从上下文创建配置和 gutter debug。
如果同一个配置既支持 Run 又支持 Debug,RunProfileState 应根据 Executor 或 ProgramRunner 选择启动普通进程还是调试会话。
测试建议¶
调试器测试成本高,但至少应覆盖:
- 配置校验。
- 本地启动失败提示。
- 断点序列化。
- 路径映射。
- 停止会话后资源释放。
- 后端断开连接。
- 大变量树展开不会卡住 UI。
- 多项目或多模块同名文件映射。
实现前检查清单¶
plugin.xml声明了com.intellij.modules.xdebugger。- 目标产品确实包含需要的调试能力。
- Run Configuration 与 Debug Executor 集成清晰。
- 断点只允许在有效位置创建。
XDebugProcess.stop()能幂等释放资源。- 后端事件到 UI 的线程切换正确。
- Source Position 映射有失败路径和用户提示。
- 变量树懒加载,表达式求值可取消。