ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

LSP 3.19 DocumentLink 协议深度解析:textDocument/documentLink 与 documentLink/resolve 全流程指南

LSP 3.19 DocumentLink 协议深度解析:textDocument/documentLink 与 documentLink/resolve 全流程指南 开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载本篇文章以 Language Server Protocol 3.19 规范中的 documentLink.md 为绝对主体系统讲解「文档链接Document Link」请求与「链接解析Resolve」请求的完整协议定义从客户端/服务端能力协商、消息结构与参数类型到DocumentLink数据模型的每个字段及其版本演进。阅读本文后你将能够在自己的语言服务器中正确声明documentLinkProvider、返回可被编辑器高亮并点击的链接并通过data字段 Resolve 请求实现按需解析链接目标同时理解该特性自 LSP 3.0 引入以来在 3.15 新增tooltip的完整演进脉络。一、DocumentLink 功能定位让编辑器中的可点击链接有标准协议在 IDE 中Markdown 文档里的相对链接、代码中的 URL 常量、注释里的 issue 引用等通常都希望被编辑器识别为可点击的链接。LSP 通过 Document Link 相关请求把这个能力标准化The document links request is sent from the client to the server to request the location of links in a document.规范给出的DocumentLink定义明确指出了它的职责边界/** * A document link is a range in a text document that links to an internal or * external resource, like another text document or a web site. */ interface DocumentLink { range: Range; target?: URI; tooltip?: string; data?: LSPAny; }也就是说一个 DocumentLink 就是文档中的一个范围range加上该范围指向的目标资源target。目标可以是另一个文本文档内部资源也可以是外部网站外部资源。客户端拿到链接后典型行为是渲染为可点击的控件用户通过ctrl click之类的快捷键触发跳转。围绕这一核心概念规范定义了两个请求请求方法名方向作用Document Link RequesttextDocument/documentLink客户端 → 服务端获取文档中所有链接的位置与目标Document Link Resolve RequestdocumentLink/resolve客户端 → 服务端针对单个链接补全其目标target两个请求的完整定义位于 documentLink.md并被 specification.md 以{% include_relative %}的方式整体嵌入到 3.19 规范正文的「语言特性」章节中。二、能力协商客户端与服务端如何声明支持与其他 LSP 特性一样DocumentLink 采用双向能力协商客户端声明自己能否使用该特性、支持到何种程度服务端声明自己能否提供该能力二者在initialize握手阶段完成对齐。2.1 客户端能力DocumentLinkClientCapabilities客户端在initialize参数中通过textDocument.documentLink属性声明能力对应结构定义如下位于Client Capability小节export interface DocumentLinkClientCapabilities { /** * Whether document link supports dynamic registration. */ dynamicRegistration?: boolean; /** * Whether the client supports the tooltip property on DocumentLink. * * since 3.15.0 */ tooltipSupport?: boolean; }两个字段含义dynamicRegistration客户端是否支持在握手完成后通过client/registerCapability动态注册 DocumentLink 服务。为true时服务端不必在初始化时静态声明能力可以按需注册。tooltipSupport客户端是否支持渲染DocumentLink上的tooltip属性。该字段自3.15.0起引入——这一点同时被 documentLink.md 的 JSDoc 注释和 metaModel.json 中的结构化定义含since: 3.15.0标记双重确认。一个典型的客户端声明示例如下{ capabilities: { textDocument: { documentLink: { dynamicRegistration: true, tooltipSupport: true } } } }2.2 服务端能力DocumentLinkOptions服务端在initialize的serverCapabilities中通过documentLinkProvider属性声明能力对应结构为位于Server Capability小节export interface DocumentLinkOptions extends WorkDoneProgressOptions { /** * Document links have a resolve provider as well. */ resolveProvider?: boolean; }resolveProvider服务端是否同时提供 Resolve 处理器。如果为true客户端在遇到target缺失的链接时会通过documentLink/resolve请求向服务端补充询问目标。继承自WorkDoneProgressOptions即服务端还可以声明workDoneProgress?: boolean表明自己支持在文档链接请求期间上报工作进度详见 workDoneProgress.md。服务端声明示例{ capabilities: { documentLinkProvider: { resolveProvider: true } } }2.3 注册选项DocumentLinkRegistrationOptions当使用动态注册dynamicRegistration时服务端通过DocumentLinkRegistrationOptions携带注册信息位于Registration Options小节export interface DocumentLinkRegistrationOptions extends TextDocumentRegistrationOptions, DocumentLinkOptions { }它同时继承了两组选项TextDocumentRegistrationOptions用于限定该注册对哪些文档生效如按语言 ID、文件路径模式过滤使动态注册的链接能力只作用于目标文档类型DocumentLinkOptions即上文提到的resolveProvider与进度选项。也就是说动态注册时服务端既能声明resolveProvider又能限定文档选择范围。一个client/registerCapability消息示例{ registrations: [ { id: doc-link-1, method: textDocument/documentLink, registerOptions: { documentSelector: [{ language: markdown }], resolveProvider: true } } ] }在 metaModel.json 中DocumentLinkRegistrationOptions被结构化为extends: [TextDocumentRegistrationOptions, DocumentLinkOptions]与规范正文完全一致。三、DocumentLink 数据结构逐字段精讲DocumentLink是两次请求共用的核心数据类型规范对其字段给出了精确定义interface DocumentLink { /** * The range this link applies to. */ range: Range; /** * The URI this link points to. If missing, a resolve request is sent later. */ target?: URI; /** * The tooltip text when you hover over this link. * * If a tooltip is provided, it will be displayed in a string that includes * instructions on how to trigger the link, such as {0} (ctrl click). * The specific instructions vary depending on OS, user settings, and * localization. * * since 3.15.0 */ tooltip?: string; /** * A data entry field that is preserved on a document link between a * DocumentLinkRequest and a DocumentLinkResolveRequest. */ data?: LSPAny; }逐字段说明range必填链接作用在文档中的文本范围。Range 采用零基坐标{ line, character }且end位置是排他的exclusive——需要包含整行含换行时应使用下一行起始作为 end。定义详见 range.md。例如{ start: { line: 5, character: 23 }, end: { line: 6, character: 0 } }target可选链接指向的 URI。当该字段缺失时意味着服务端约定稍后通过 Resolve 请求补全目标——这是懒解析lazy resolve模式的基础。tooltip可选since 3.15.0悬停提示文本。规范特别指出如果提供了 tooltip客户端会将其与触发说明拼接展示例如{0} (ctrl click)其中的{0}是触发快捷键占位符具体指令随操作系统、用户设置和本地化而变化。也就是说服务端只需要提供纯提示文字客户端负责附加操作指引。data可选一个不透明的数据载体类型为LSPAny用于在 DocumentLinkRequest 与 DocumentLinkResolveRequest 两次消息之间传递上下文。典型用法是服务端把内部标识如该链接属于 import 语句行号 xx塞进dataResolve 时原样带回从而在补全 target 时无需重新扫描整个文档。关于target的 URI 类型需要强调两点详见 uri.mdURI 在线路上以字符串传输格式遵循 RFC 3986scheme://authority/path?query#fragment结构DocumentUri与普通URI都是string的标记类型tagging interfaceDocumentUri用于保证内容可解析为合法 URI。此外URI 编码需要格外小心不同客户端对 URI 的编码方式可能不一致例如某些客户端会对盘符冒号做百分号编码客户端与服务端应保持各自使用形式的一致性且不能假设对方与自己采用相同的编码方式。file:///c:/project/readme.md与file:///C%3A/project/readme.md都是合法 URI但若双方不一致就可能被解析为不同的文档。四、Document Link RequesttextDocument/documentLink4.1 请求定义interface DocumentLinkParams extends WorkDoneProgressParams, PartialResultParams { /** * The document to provide document links for. */ textDocument: TextDocumentIdentifier; }要点方法名textDocument/documentLink参数DocumentLinkParams继承WorkDoneProgressParams可携带workDoneToken上报进度与PartialResultParams可携带partialResultToken支持部分结果流式返回业务字段只有一个textDocument即TextDocumentIdentifier——它仅包含一个uri: DocumentUri字段见 textDocumentIdentifier.md。响应结果DocumentLink[] | null。返回null表示当前文档没有链接返回数组则按顺序给出所有链接。部分结果partial result类型为DocumentLink[]即服务端可以分批次增量推送链接结果配合PartialResultParams使用相关机制参见 partialResultParams.md。错误处理请求处理过程中发生异常时返回携带 error code 与 message 的 LSP 错误响应。4.2 完整消息示例请求{ jsonrpc: 2.0, id: 1, method: textDocument/documentLink, params: { textDocument: { uri: file:///home/user/projects/demo/readme.md } } }响应其中第二条链接省略了target等待 Resolve 补全{ jsonrpc: 2.0, id: 1, result: [ { range: { start: { line: 1, character: 2 }, end: { line: 1, character: 28 } }, target: https://example.com/documentation, tooltip: 打开官方文档 }, { range: { start: { line: 4, character: 0 }, end: { line: 4, character: 22 } }, data: { kind: import, symbol: Foo } } ] }4.3 服务端实现要点一个典型的服务端处理流程是根据textDocument.uri定位文档内容通过正则或语法分析识别出可作为链接的文本范围Markdown 的text、代码中的 URL 字面量等对每个候选范围构造DocumentLink如果目标可以低成本确定如 Markdown 内联链接直接填充target如果目标需要昂贵计算如解析 import 语句后跨项目查表省略target而填充data交给 Resolve 阶段处理返回DocumentLink[]。选择直接返回 target还是data Resolve 补全本质是首屏响应速度与计算成本之间的权衡前者让客户端立刻可点击后者把昂贵解析推迟到用户真正触发链接时。五、Document Link Resolve RequestdocumentLink/resolve5.1 请求定义The document link resolve request is sent from the client to the server to resolve the target of a given document link.// 请求 method: documentLink/resolve params: DocumentLink // 响应 result: DocumentLink error: code and message set in case an exception happens during the document link resolve request.要点方法名documentLink/resolve参数直接就是DocumentLink本身——客户端把之前收到的那条target缺失的链接原样发回其中data字段被保留供服务端还原上下文响应补全后的DocumentLink通常即填上了target也可顺带补上tooltip触发条件客户端仅在服务端声明了resolveProvider: true时才会发出此请求且只针对target缺失的链接。5.2 完整消息示例请求{ jsonrpc: 2.0, id: 2, method: documentLink/resolve, params: { range: { start: { line: 4, character: 0 }, end: { line: 4, character: 22 } }, data: { kind: import, symbol: Foo } } }响应data原样带回target补全{ jsonrpc: 2.0, id: 2, result: { range: { start: { line: 4, character: 0 }, end: { line: 4, character: 22 } }, target: file:///home/user/projects/demo/src/foo.ts, data: { kind: import, symbol: Foo } } }5.3 服务端实现要点Resolve 处理器应利用data中保存的上下文如符号名、文档 URI、链接类型定位真正的目标文件返回补全后的链接。切勿依赖范围/文本内容重新猜测——这正是data字段在 DocumentLinkRequest 与 DocumentLinkResolveRequest 之间被保留preserved的设计目的。六、版本演进与结构化元模型佐证通过 specification.md 的版本历史与文档内的since标记可以还原 DocumentLink 特性的演进脉络3.02017 年首次加入textDocument/documentLink请求见 specification 3.0 版本的Added support for textDocument/documentLink request条目dynamicRegistration、range、target、data等核心要素自此定型3.15.0新增tooltip字段与客户端tooltipSupport能力位悬停提示文本标准化3.17 / 3.18 / 3.193.17 版本文档 与 3.19 版本文档内容完全一致说明该特性定义在近几个版本中保持稳定无需改动。此外仓库中的 metaModel.json 以机器可读的结构化形式完整记录了上述所有类型与请求可作为实现方的权威数据源实体metaModel.json 位置关键结构化信息DocumentLinkRequestL1788-L1825textDocument/documentLink结果为DocumentLink[] \| null含 partialResultDocumentLinkResolveRequestL1827-L1841documentLink/resolve服务端能力映射到documentLinkProvider.resolveProviderDocumentLinkParamsL6071-L6093mixins 为WorkDoneProgressParams、PartialResultParamsDocumentLinkL6095-L6135range必填target/tooltip/data可选DocumentLinkRegistrationOptionsL6137-L6150extends 两组选项DocumentLinkOptionsL9751-L9770resolveProvider?: booleanDocumentLinkClientCapabilitiesL12786-L12809dynamicRegistration、tooltipSupportsince 3.15.0对于使用代码生成方式实现 LSP 的语言如基于 TypeScript 的 SDK直接消费这份 metaModel 即可自动产出上述全部接口与请求类型避免手写协议代码的偏差。七、端到端工作流总结与实现清单一次完整的 DocumentLink 交互流程如下握手阶段客户端在initialize参数中声明textDocument.documentLink含dynamicRegistration、tooltipSupport服务端在initialize结果中声明documentLinkProvider含resolveProvider。若客户端支持动态注册而服务端选择后注册则通过client/registerCapability发送DocumentLinkRegistrationOptions。链接发现客户端在适当时机如文档打开、内容变化发送textDocument/documentLink请求携带TextDocumentIdentifier服务端返回DocumentLink[]可带workDoneToken进度、partialResultToken部分结果出错时返回 error code 与 message。懒解析客户端渲染链接后若用户触发了某个target缺失的链接且服务端声明了resolveProvider则客户端把原DocumentLink含data通过documentLink/resolve发回服务端补全target后返回。实现一个 DocumentLink 服务端时可对照以下清单自检在serverCapabilities.documentLinkProvider中声明能力是否开启resolveProvider处理textDocument/documentLink为每个链接填充range按成本决策填充target或仅填data若声明了resolveProvider实现documentLink/resolve处理器基于data上下文补全target若支持动态注册正确处理DocumentLinkRegistrationOptionsdocumentSelector过滤 resolveProvider确认 URI 编码方式与客户端保持一致参考 uri.md 的编码注意事项仅在客户端声明tooltipSupport时发送tooltip字段且内容不含触发快捷键占位说明由客户端自行拼接。参考资源协议正文本主题权威来源documentLink.md3.19 完整规范含版本历史specification.md结构化元模型可生成代码metaModel.json支撑类型定义range.md、textDocumentIdentifier.md、uri.md、workDoneProgress.md、partialResultParams.md早期版本对照3.17 版 documentLink.md赞分享开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载相关推荐Matter connectedhomeip 1.4 vs 1.5 版本演进完整指南数据模型新增了什么Matter connectedhomeip 1.4 vs 1.5 版本演进完整指南数据模型新增了什么 connectedhomeipMatter前称 P开发工具LSP 3.18 补全协议完全指南textDocument/completion、completionItem/resolve 与 Snippet 语法深度解析LSP 3.18 补全协议完全指南textDocument/completion、completionItem/resolve 与 Snippet 语法深度解开发工具LSP 3.19 Signature Help 协议深度解析textDocument/signatureHelp 请求、能力协商与实现指南LSP 3.19 Signature Help 协议深度解析textDocument/signatureHelp 请求、能力协商与实现指南 Signature开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表