ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Language Server Protocol 3.18 Inlay Hint 深度解析:文本内联提示的协议设计与实现指南

Language Server Protocol 3.18 Inlay Hint 深度解析:文本内联提示的协议设计与实现指南 开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载导读本文基于 language-server-protocol 仓库中 LSP 3.18 规范的 inlayHint.md 文档系统讲解内联提示Inlay Hint从客户端能力协商、服务端能力声明、textDocument/inlayHint请求、inlayHint/resolve惰性解析到workspace/inlayHint/refresh全量刷新的完整协议链路。读者学完后将掌握如何在语言服务器中声明并实现内联提示提供者、如何设计可交互的复合标签Label Part、如何通过 resolve 机制避免冗余计算以及如何结合 metaModel.json 验证协议元模型从而让编辑器在代码行内直接呈现类型标注、参数名等提示信息。1. 内联提示Inlay Hint是什么内联提示是 LSP 3.17 引入的一种文本内联 UI 能力它由客户端编辑器发起textDocument/inlayHint请求让服务器针对某个「文本文档 范围」二元组计算一组提示这些提示会被直接渲染在编辑器的文本行内与原有代码并排显示而不是弹出浮层或插入到文档中。典型应用场景包括在变量声明处内联显示推断出的类型标注const x: number 42中的: number在函数调用处内联显示每个实参对应的形参名如foo(bar: 1, baz: 2)在函数返回处显示返回值类型。与悬停Hover相比内联提示不打断光标流、不遮挡代码是「常驻型」的信息展示与补全Completion相比它不修改文档内容除非用户主动接受textEdits。从规范文档看内联提示的核心价值在于「就地在文本中呈现与编辑上下文相关的信息」。2. 客户端能力协商InlayHintClientCapabilities服务器要提供内联提示第一步是确认客户端是否支持该功能。客户端在initialize请求的capabilities.textDocument.inlayHint字段中声明其能力类型为InlayHintClientCapabilities自 3.17.0 起/** * Inlay hint client capabilities. * * since 3.17.0 */ export interface InlayHintClientCapabilities { /** * Whether inlay hints support dynamic registration. */ dynamicRegistration?: boolean; /** * Indicates which properties a client can resolve lazily on an inlay * hint. */ resolveSupport?: ClientInlayHintResolveOptions; }其中ClientInlayHintResolveOptions定义为export type ClientInlayHintResolveOptions { /** * The properties that a client can resolve lazily. */ properties: string[]; };两个可选字段的含义字段类型说明dynamicRegistrationboolean是否支持通过client/registerCapability动态注册内联提示提供者若不支持服务器只能在initialize时静态声明inlayHintProviderresolveSupport.propertiesstring[]客户端允许服务器惰性延迟解析的属性路径列表例如[label.location, tooltip, command]。声明后服务器可以在首次请求中省略这些字段待客户端后续用inlayHint/resolve请求补齐在 initialize.md 中TextDocumentClientCapabilities明确包含该可选属性/** * Capabilities specific to the textDocument/inlayHint request. * * since 3.17.0 */ inlayHint?: InlayHintClientCapabilities;对应的元模型定义也记录在 metaModel.json 的InlayHintClientCapabilities结构中since 3.17.0。3. 服务器能力声明InlayHintOptions与InlayHintRegistrationOptions服务器在initialize响应中通过capabilities.inlayHintProvider声明自身能力见 initialize.md/** * The server provides inlay hints. * * since 3.17.0 */ inlayHintProvider?: boolean | InlayHintOptions | InlayHintRegistrationOptions;3.1 静态注册选项InlayHintOptions服务器能力字段的类型为InlayHintOptions静态注册时使用/** * Inlay hint options used during static registration. * * since 3.17.0 */ export interface InlayHintOptions extends WorkDoneProgressOptions { /** * The server provides support to resolve additional * information for an inlay hint item. */ resolveProvider?: boolean; }关键点resolveProvider表示服务器支持inlayHint/resolve请求来为单个 hint 补充附加信息InlayHintOptions继承自WorkDoneProgressOptions因此可选携带workDoneProgress字段用于报告计算任务的进度服务器也可以直接声明inlayHintProvider: trueboolean 形式此时不提供任何附加选项通常也意味着不支持 resolve。3.2 动态注册选项InlayHintRegistrationOptions支持动态注册时使用inlayHintProvider可同时被静态声明和动态注册共用/** * Inlay hint options used during static or dynamic registration. * * since 3.17.0 */ export interface InlayHintRegistrationOptions extends InlayHintOptions, TextDocumentRegistrationOptions, StaticRegistrationOptions { }它组合了三组能力InlayHintOptionsresolve 与进度选项TextDocumentRegistrationOptions可限定该提供者作用于哪些文档通过documentSelectorStaticRegistrationOptions可携带id使动态注册与静态声明共用同一个注册 ID。InlayHintOptions与InlayHintRegistrationOptions均被记录在 metaModel.json 的类型列表中since 3.17.0。4. 请求与参数textDocument/inlayHint4.1 方法与参数methodtextDocument/inlayHintparamsInlayHintParams/** * A parameter literal used in inlay hint requests. * * since 3.17.0 */ export interface InlayHintParams extends WorkDoneProgressParams { /** * The text document. */ textDocument: TextDocumentIdentifier; /** * The visible document range for which inlay hints should be computed. */ range: Range; }参数语义textDocumentTextDocumentIdentifier唯一标识目标文档urirange可见文档范围。客户端通常传入当前编辑器可见区域服务器只需计算该范围内可见的提示从而显著降低计算量继承WorkDoneProgressParams可携带workDoneToken以支持进度上报。Range由零基的start/end两个Position组成end 为开区间不包含定义见 range.mdPosition使用零基的行号与字符偏移字符偏移的语义由初始化时协商的PositionEncodingKindutf-8/utf-16/utf-32决定默认且服务器必须支持utf-16详见 position.md。4.2 响应结果resultInlayHint[] | null服务器返回命中的提示数组返回null表示该范围内没有提示。在 metaModel.json 中该请求的元模型记录如下提取自requests列表{ method: textDocument/inlayHint, typeName: InlayHintRequest, result: { kind: or, items: [ { kind: array, element: { kind: reference, name: InlayHint } }, { kind: base, name: null } ] }, messageDirection: clientToServer, clientCapability: textDocument.inlayHint, serverCapability: inlayHintProvider, params: { kind: reference, name: InlayHintParams }, registrationOptions: { kind: reference, name: InlayHintRegistrationOptions }, since: 3.17.0 }可见该请求同时支持partialResult部分结果数组因此服务器可以在计算过程中分批返回InlayHint[]。请求出错时响应中通过error.code与error.message报告异常。5. 核心类型InlayHint与InlayHintLabelPart5.1InlayHint单个内联提示/** * Inlay hint information. * * since 3.17.0 */ export interface InlayHint { /** * The position of this hint. * * If multiple hints have the same position, they will be shown in the order * they appear in the response. */ position: Position; /** * The label of this hint. A human readable string or an array of * InlayHintLabelPart label parts. * * *Note* that neither the string nor the label part can be empty. */ label: string | InlayHintLabelPart[]; /** * The kind of this hint. Can be omitted in which case the client * should fall back to a reasonable default. */ kind?: InlayHintKind; /** * Optional text edits that are performed when accepting this inlay hint. * * *Note* that edits are expected to change the document so that the inlay * hint (or its nearest variant) is now part of the document and the inlay * hint itself is now obsolete. * * Depending on the client capability inlayHint.resolveSupport, * clients might resolve this property late using the resolve request. */ textEdits?: TextEdit[]; /** * The tooltip text when you hover over this item. * * Depending on the client capability inlayHint.resolveSupport clients * might resolve this property late using the resolve request. */ tooltip?: string | MarkupContent; /** * Render padding before the hint. * * Note: Padding should use the editors background color, not the * background color of the hint itself. That means padding can be used * to visually align/separate an inlay hint. */ paddingLeft?: boolean; /** * Render padding after the hint. * * Note: Padding should use the editors background color, not the * background color of the hint itself. That means padding can be used * to visually align/separate an inlay hint. */ paddingRight?: boolean; /** * A data entry field that is preserved on an inlay hint between * a textDocument/inlayHint and an inlayHint/resolve request. */ data?: LSPAny; }各字段要点与工程实践字段是否必填说明与注意点position必填提示锚定的位置。多个提示共享同一位置时按响应数组中的出现顺序依次渲染服务器可用此特性控制并列提示的先后label必填纯字符串或InlayHintLabelPart[]复合标签。字符串与每个 label part 的value都不能为空字符串kind可选Type 1类型标注或Parameter 2参数名省略时客户端回退到合理默认样式textEdits可选用户「接受」该提示时执行的文本编辑。规范强调编辑应使该提示或其最近变体成为文档真实内容的一部分此后该提示本身即失效obsoletetooltip可选悬停提示文本string | MarkupContentpaddingLeft/paddingRight可选在提示前后渲染留白。注意留白使用编辑器的背景色而非提示自身的背景色因此可用于在视觉上对齐/分隔多个内联提示data可选LSPAny类型的透传数据在textDocument/inlayHint与inlayHint/resolve之间原样保留通常存放服务器侧定位 hint 所需的内部标识其中tooltip、textEdits以及 label part 中的tooltip、location、command都是「可被 resolve 惰性补齐」的属性只要客户端在resolveSupport.properties中声明了对应路径服务器即可在首次响应中省略它们。5.2InlayHintLabelPart交互式复合标签复合标签让单个提示可以包含多个可交互片段例如「参数名 冒号 类型」拆成多个 part/** * An inlay hint label part allows for interactive and composite labels * of inlay hints. * * since 3.17.0 */ export interface InlayHintLabelPart { /** * The value of this label part. */ value: string; /** * The tooltip text when you hover over this label part. Depending on * the client capability inlayHint.resolveSupport, clients might resolve * this property late using the resolve request. */ tooltip?: string | MarkupContent; /** * An optional source code location that represents this * label part. * * The editor will use this location for the hover and for code navigation * features: This part will become a clickable link that resolves to the * definition of the symbol at the given location (not necessarily the * location itself), it shows the hover that shows at the given location, * and it shows a context menu with further code navigation commands. * * Depending on the client capability inlayHint.resolveSupport clients * might resolve this property late using the resolve request. */ location?: Location; /** * An optional command for this label part. * * Depending on the client capability inlayHint.resolveSupport, clients * might resolve this property late using the resolve request. */ command?: Command; }InlayHintLabelPart的三个可选能力赋予了内联提示「可交互」的特性tooltip悬停该片段时的提示内容location为片段附加源码位置。编辑器会据此提供悬停、跳转点击片段跳转到该位置对应符号的定义处注意「不一定指向该位置本身」以及带有更多导航命令的上下文菜单——相当于把内联提示片段变成一条迷你「go to definition」链接command点击片段时执行的命令如触发重命名、快速修复。5.3InlayHintKind提示种类/** * Inlay hint kinds. * * since 3.17.0 */ export namespace InlayHintKind { /** * An inlay hint that is for a type annotation. */ export const Type 1; /** * An inlay hint that is for a parameter. */ export const Parameter 2; } export type InlayHintKind 1 | 2;目前仅定义两个枚举值值名称典型用途1Type类型标注提示如const foo: number ...中的: number2Parameter参数提示如调用处显示的形参名该枚举同样出现在 metaModel.json 的InlayHintKind类型定义中since 3.17.0。6. 惰性解析inlayHint/resolve请求6.1 设计动机textDocument/inlayHint可能一次性返回大量提示而tooltip、label part 的location、command等属性往往只有在用户真正与某个提示交互时才需要。如果服务器在首次请求中就为每个 hint 计算全部属性会产生大量浪费。为此规范提供了resolve 机制客户端声明可延迟解析的属性服务器在首次响应中省略它们待需要时再通过inlayHint/resolve逐个补齐。6.2 协商与流程示例methodinlayHint/resolveparamsInlayHint携带data字段以关联原始 hintresultInlayHint补齐属性后的完整对象假设客户端在 initialize 时声明textDocument.inlayHint.resolveSupport { properties: [label.location] };那么一个包含不带location的 label part的 inlay hint在客户端实际使用它之前必须先用inlayHint/resolve请求解析补齐label.location。具体调用链如下客户端发送textDocument/inlayHint服务器返回 hint省略label.location但在data中保存内部标识用户悬停或点击某个 label part客户端发现其location缺失且属于resolveSupport.properties声明范围客户端发送inlayHint/resolve参数为原 hint 对象含data服务器依据data定位到源数据计算并返回补齐了tooltip/location/command等属性的完整InlayHint。对应客户端能力字段为textDocument.inlayHint.resolveSupport类型{ properties: string[]; }服务器能力字段为inlayHintProvider.resolveProvider这在 metaModel.json 的InlayHintResolveRequest元模型中亦有完整记录。若 resolve 过程中发生异常响应通过error.code与error.message报告。7. 全量刷新workspace/inlayHint/refresh请求7.1 作用与触发时机内联提示属于「拉取模型」pull-based正常情况下客户端自行发起请求。但当服务器检测到需要全量重算内联提示的配置/项目级变化时可以反向通知客户端刷新methodworkspace/inlayHint/refreshparamsnoneresultvoid服务器发起该请求后客户端应当重新请求各编辑器中当前显示的内联提示。规范同时强调两点约束客户端仍保留延迟重算的自由——例如某个编辑器当前不可见时客户端可以推迟到其可见时再重算该事件是全局性的——会强制客户端刷新当前显示的所有内联提示因此「应极其谨慎地使用」should be used with absolute care仅适用于诸如检测到项目级变化需要整体重算的场景。7.2 客户端工作区能力InlayHintWorkspaceClientCapabilities客户端是否支持该刷新请求通过工作区级能力声明property nameworkspace.inlayHint/** * Client workspace capabilities specific to inlay hints. * * since 3.17.0 */ export interface InlayHintWorkspaceClientCapabilities { /** * Whether the client implementation supports a refresh request sent from * the server to the client. * * Note that this event is global and will force the client to refresh all * inlay hints currently shown. It should be used with absolute care and * is useful for situations where a server, for example, detects a project wide * change that requires such a calculation. */ refreshSupport?: boolean; }在 initialize.md 的WorkspaceClientCapabilities中对应字段为/** * Client workspace capabilities specific to inlay hints. * * since 3.17.0 */ inlayHint?: InlayHintWorkspaceClientCapabilities;InlayHintWorkspaceClientCapabilities亦被记录在 metaModel.json 的workspace能力结构中。只有客户端声明refreshSupport: true后服务器才能安全地发送该刷新请求。8. 在 3.18 规范中的位置与阅读指引本文内容对应的权威文档为 _specifications/lsp/3.18/language/inlayHint.md它作为独立章节被 specification.md 以 include 方式嵌入 3.18 完整规范正文能力协商的完整上下文客户端/服务器/工作区三级能力见 initialize.md所有请求、类型、能力与文档的机器可读描述统一维护在 metaModel.json 中可用于自动生成客户端/服务器存根与协议校验依赖的基础类型定义见 position.mdPosition与PositionEncodingKind与 range.mdRange的 start/end 开区间语义3.17 与 3.18 版本的 inlay hint 章节内容保持一致均为since 3.17.0引入3.18 未对其做增量修改仅随 specification.md 整体进入 3.18 发布线。9. 实现要点速查面向语言服务器实现者的落地清单初始化协商读取客户端的textDocument.inlayHint含dynamicRegistration、resolveSupport.properties与workspace.inlayHint.refreshSupport决定是否声明inlayHintProvider能力声明静态声明inlayHintProvider: { resolveProvider: boolean }若支持动态注册使用InlayHintRegistrationOptions并通过client/registerCapability注册注意documentSelector与可选id主请求实现实现textDocument/inlayHint按params.range裁剪计算范围返回InlayHint[] | null可选用workDoneToken上报进度、用 partial results 分批返回resolve 实现若声明resolveProvider实现inlayHint/resolve通过data字段在两次请求间保留内部状态按客户端声明的属性路径惰性补齐tooltip、label.location、label.command等刷新实现当检测到配置或项目级变化需要全量重算时若客户端声明workspace.inlayHint.refreshSupport发送workspace/inlayHint/refreshparams 为 noneresult 为 void渲染细节kind省略时客户端回退默认样式同位置多 hint 按响应顺序渲染paddingLeft/paddingRight使用编辑器背景色用于视觉对齐textEdits用于「接受提示写入文档」场景写入后原 hint 应视为失效。10. 延伸阅读完整 3.18 规范正文specification.md初始化与能力协商细节general/initialize.md机器可读协议元模型metaModel.json 及对应的 metaModel.schema.json、metaModel.ts相邻的行内信息展示机制对比inlineValue.md内联值、hover.md悬停3.17 版本的同一章节内容等价_specifications/lsp/3.17/language/inlayHint.md赞分享开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载相关推荐OpenDesign 设计系统实战以 Cal.com 为范本的灰度极简设计系统规范与 Token 落地指南OpenDesign 设计系统实战以 Cal.com 为范本的灰度极简设计系统规范与 Token 落地指南 类别Productivity SaaS生产开发工具华硕笔记本风扇一次调好用 G-Helper 排查与调校风扇曲线华硕笔记本风扇一次调好用 G Helper 排查与调校风扇曲线 在 ROG Zephyrus、TUF、ProArt 这类机型上风扇问题常见形态是转速长期居开发工具微服务的事件驱动数据管理从分布式数据一致性问题到事件源架构doocs/advanced-java微服务的事件驱动数据管理从分布式数据一致性问题到事件源架构doocs/advanced java 本篇技术指南围绕微服务架构下分布式数据管理这一核心痛开发工具上一篇system-design-notes新闻流缓存架构2大优化技巧延迟降低50%的关键下一篇Outlook CalDav Synchronizer免费实现跨平台日历联系人同步的终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表