折腾

这篇文章主要介绍一下DAP的框架,以及debugpy的简单实现。

Debug Adapter Protocal

DAP和LSP是一样的,本质上就是用JSON格式定义的对象消息。DAP用来链接某种语言的调试器和IDE或者编辑器端的一个协议。IDE只需要对着这个协议编写代码,就可以利用已有的DAP来快速实现调试功能。或者对着这个协议编写代码,就可以把调试器的快速集成到已经采用这个DAP的IDE里。理想情况下,只需要对语言的调试功能实现一次,就可以用在不同的开发工具中。在此之前,各大IDE的调试功能都是特化实现的,当然也包括对语言的智能支持(这部分对应LSP)。比如VS,Jetbrain这些重量级的IDE,对某种语言开发的智能功能基本上是内置支持,或者也可以用非常强大的插件(Visual Assist,Resharper)来增强,优点是高效,健壮,功能强大。缺点是不能用在其他轻量级编辑器中。随着现在各种轻量级的编辑器越来越多,开发者都喜欢用自己顺手的编辑器,对语言的智能支持是编辑器的最核心的功能。没有DAP或者LSP之前,也是各自实现一套,几乎没有迁移能力。VSCode算是第一次明确LSP和DAP这些协议。让各种编辑器都可以低成本的享受到支持不同语言的功能。

一般认为,DAP应该能满足让代码编辑器实现以下功能:

  • 源码、函数、条件断点等。
  • 调试时变量值显示
  • 多线程和多进程调试支持
  • 查看复杂的数据结构
  • 监视表达式
  • 自动补全,交互式求值
  • 输出日志

withDAP

协议基本的通信方式

协议分成Request,Response, Event三种消息类型。因为语言调试的复杂性,所以具体的消息实现种类非常多。不在这里做详细介绍。 用几个简单的场景说明一下大概的流程:

初始化

首先编辑器发送Initialize类型的请求,查询DAP是否有相应的功能

interface InitializeRequest extends Request {
  command: 'initialize';
  arguments: InitializeRequestArguments;
}

interface InitializeRequestArguments {
  clientID?: string;
  clientName?: string;
  adapterID: string;
  locale?: string;
  linesStartAt1?: boolean;
  columnsStartAt1?: boolean;
  pathFormat?: 'path' | 'uri' | string;
  supportsVariableType?: boolean;
  supportsVariablePaging?: boolean;
  supportsRunInTerminalRequest?: boolean;
  supportsMemoryReferences?: boolean;
  supportsProgressReporting?: boolean;
  supportsInvalidatedEvent?: boolean;
  supportsMemoryEvent?: boolean;
}

DAP做响应, 列出支持的功能,完成初始化流程。

interface InitializeResponse extends Response {
  body?: Capabilities;
}

大概就是这种通信的流程。

这里列出完整规范

打断点

断点调试是调试功能的核心,这里用一张图展示整个流程。 这个是一个编辑器断点调试时通过DAP和GDB通信的流程。

详细的消息格式在上面给出的协议规范里。

当调试器触发一个断点时,会发出stop消息,此时DAP把stop消息转发一下,编辑器端收到stop后可以请求栈的状态,然后DAP从调试器当中获取数据再发给编辑器,编辑器做展示。

详细地来说,触发stop之后(里面有线程编号),编辑器根据需求请个线程的栈信息,得到响应,再根据需要请求栈下的Scope,得到响应,根据需要请求Scope下的变量, 得到响应。再根据需要(比如要展开一个复杂的数据结构)请求这个数据结构下的变量。 这样层层递进。

Threads
   StackTrace
      Scopes
         Variables
            ...
               Variables

Debugpy,一个Python的DAP实现

Debugpy是针对python实现的DAP,是 vscode python插件使用的DAP。这里简单的介绍一下实现细节

Lucida avatar
Lucida
劳力人士