
开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载workspace/didDeleteFiles是 Language Server ProtocolLSP自 3.16 起引入的文件操作file operations通知家族成员之一用于让语言服务器在客户端内发生文件删除时及时感知并同步内部状态。本文以本仓库 3.18 版规范文档 为骨架结合 3.18 元模型 中的类型定义完整讲解该通知的消息格式、能力协商、注册选项与实现要点帮助读者在自己的语言服务器中正确实现删除事件驱动的状态同步。一、协议定位文件操作通知家族的事后通知LSP 的文件操作机制由六种消息组成覆盖创建create、重命名rename、删除delete三类文件操作且每种操作都分为事前请求与事后通知两种形态操作类型事前will / 请求事后did / 通知创建workspace/willCreateFilesworkspace/didCreateFiles重命名workspace/willRenameFilesworkspace/didRenameFiles删除workspace/willDeleteFilesworkspace/didDeleteFiles其中willDeleteFiles 是客户端在实际删除文件之前发送的请求可返回WorkspaceEdit提前修改工作区而本文主角workspace/didDeleteFiles则是客户端在文件已经删除之后发送的通知Notification。原始规范对它的定义非常精炼The did delete files notification is sent from the client to the server when files were deleted from within the client.要点有两层触发源删除必须发生在客户端内部既包括用户在客户端界面上的直接删除操作也包括通过应用工作区编辑workspace edit触发的删除——这与 willDeleteFiles 的触发条件完全一致。 2消息性质它是 Notification:arrow_right:单向箭头客户端发出后不期待任何响应服务端无需也无法返回结果或错误码。二、消息定义method、方向与参数规范原文对workspace/didDeleteFiles的定义如下methodworkspace/didDeleteFiles方向客户端 → 服务端NotificationparamsDeleteFilesParams一个符合规范的 JSON-RPC 通知消息形如{ jsonrpc: 2.0, method: workspace/didDeleteFiles, params: { files: [ { uri: file:///home/user/project/src/old-module.ts } ] } }DeleteFilesParams与FileDelete两个类型在 willDeleteFiles 文档中有完整 TypeScript 定义二者均标注since 3.16.0/** * The parameters sent in notifications/requests for user-initiated deletes * of files. * * since 3.16.0 */ export interface DeleteFilesParams { /** * An array of all files/folders deleted in this operation. */ files: FileDelete[]; } /** * Represents information on a file/folder delete. * * since 3.16.0 */ export interface FileDelete { /** * A file:// URI for the location of the file/folder being deleted. */ uri: string; }解读与实战要点files是数组一次删除操作可能涉及多个文件/文件夹例如批量删除、整个目录删除服务端应遍历处理全部条目而不是只取第一个。FileDelete.uri必须是file://URI在元模型 metaModel.json 中其类型为DocumentUri服务端收到后需自行解析为本地路径若删除对象是文件夹URI 指向该文件夹本身不会展开列出其子文件这一点与RenameFilesParams在 metaModel.json 中的注释当文件夹被重命名时只包含该文件夹而不包含其子项一致。由于是通知服务端不得向客户端回发响应处理过程中即使出错也只能记录日志或通过window/logMessage等通道上报而不是返回错误。三、能力协商客户端与服务端的双向声明与所有 LSP 扩展消息一样workspace/didDeleteFiles的使用建立在能力协商之上双方在initialize阶段互相声明支持情况。规范原文给出两段能力定义客户端能力Client Capability属性名可选workspace.fileOperations.didDelete属性类型boolean含义声明客户端支持发送workspace/didDeleteFiles通知。服务端能力Server Capability属性名可选workspace.fileOperations.didDelete属性类型FileOperationRegistrationOptions含义声明服务端有兴趣接收workspace/didDeleteFiles通知。对应的initialize交换示意// 客户端发送 { method: initialize, params: { capabilities: { workspace: { fileOperations: { didDelete: true } } } } } // 服务端响应 { result: { capabilities: { workspace: { fileOperations: { didDelete: { filters: [ /* 见下文 */ ] } } } } } }两个值得注意的设计细节同一属性名、不同含义workspace.fileOperations.didDelete在客户端侧是布尔开关在服务端侧却是带过滤条件的注册选项对象——客户端用它表示我会发服务端用它表示我想收且只收符合过滤条件的。服务端能力值由FileOperationRegistrationOptions提供这意味着服务端可以在initialize时静态声明过滤条件也可以稍后通过client/registerCapability动态注册/调整见 registerCapability。这是 LSP 中静态注册 动态注册双轨机制的典型体现。四、注册选项深入用过滤器精确表达我想收哪些删除事件FileOperationRegistrationOptions是本通知服务端能力的关键类型其定义位于 metaModel.jsonexport interface FileOperationRegistrationOptions { /** * The actual filters. */ filters: FileOperationFilter[]; }它只有一个必填字段filters数组而FileOperationFiltermetaModel.json又由两部分组成export interface FileOperationFilter { /** * A Uri scheme like file or untitled. */ scheme?: string; /** * The actual file operation pattern. */ pattern: FileOperationPattern; }scheme可选URI scheme如file、untitled。留空通常表示匹配默认的filescheme。pattern必填真正的匹配模式FileOperationPattern其定义见 metaModel.jsonexport interface FileOperationPattern { /** * The glob pattern to match. */ glob: string; /** * Whether to match files or folders with this pattern. * Matches both if undefined. */ matches?: FileOperationPatternKind; /** * Additional options used during matching. */ options?: FileOperationPatternOptions; }glob 语法服务端必须兼容元模型文档对glob字段给出了完整的语法说明这是服务端实现匹配逻辑时的硬标准语法含义示例*匹配一个路径段内的零个或多个字符*.ts?匹配一个路径段内的单个字符file?.ts**匹配任意数量的路径段含零个**/*.ts{}子模式分组 OR 表达式**/*.{ts,js}匹配所有 TS 与 JS 文件[]路径段内字符范围example.[0-9]匹配example.0、example.1……[!...]路径段内字符范围取反example.[!0-9]匹配example.a、example.b但不匹配example.0matches 与 optionsmatches可选取值来自枚举FileOperationPatternKindmetaModel.json仅有两个合法字符串值file只匹配文件与folder只匹配文件夹不设置时文件与文件夹都匹配。options可选为FileOperationPatternOptionsmetaModel.json目前只有一个可选字段ignoreCase: boolean置true表示忽略大小写匹配。服务端注册选项示例结合上述类型一个只关心工作区内被删除的 TypeScript/JavaScript 源文件、忽略大小写的静态声明可以写成{ capabilities: { workspace: { fileOperations: { didDelete: { filters: [ { scheme: file, pattern: { glob: **/*.{ts,js}, matches: file, options: { ignoreCase: true } } } ] } } } } }从源码结构看服务端在解析自身声明的filters时应逐条过滤客户端上报的DeleteFilesParams.files只有 URI 的 scheme 与glob模式同时命中的条目才被真正处理。这也解释了为什么规范把服务端能力设计成注册选项而非布尔值——服务端可以借此把不感兴趣的文件类型排除在事件流之外避免不必要的状态同步开销。五、与workspace/willDeleteFiles的配合事前拦截 事后同步理解didDeleteFiles的价值需要把它与 willDeleteFiles 放在一起看。二者参数类型相同都是DeleteFilesParams但语义与时机完全不同维度workspace/willDeleteFilesworkspace/didDeleteFiles消息类型请求Request通知Notification发送时机文件实际删除之前文件已经删除之后响应可返回WorkspaceEdit \| null无响应典型用途删除前修补引用如更新 import、阻止破坏性删除删除后清理缓存、失效诊断、刷新索引规范在 willDeleteFiles 中明确指出只要删除由客户端内触发用户操作或应用 workspace edit客户端都会在真正删除前发起该请求同时提示如果计算编辑耗时过长或服务端持续失败客户端可能丢弃结果以保证删除操作快速可靠。也就是说事前阶段will服务端有机会在删除发生前通过返回WorkspaceEdit把引用该文件的代码一并修正如删除模块后同步清理 import 语句事后阶段did服务端必须在收到通知后把内部与该文件相关的状态彻底作废——包括但不限于符号/大纲缓存、跳转索引、诊断结果、未保存的打开文档映射等。对于语言服务器实现者一个稳健的做法是用workspace/willDeleteFiles处理删除前需要动工作区内容的场景用workspace/didDeleteFiles兜底处理删除后无论如何都要清理本地状态的场景。由于通知无响应服务端可以在didDeleteFiles处理器中执行耗时清理而不会阻塞客户端。六、服务端实现要点与消息示例以一个 TypeScript 语言服务器的伪代码为例展示从能力声明到事件处理的完整链路// 1. initialize 阶段静态声明 const result { capabilities: { workspace: { fileOperations: { didDelete: { filters: [ { scheme: file, pattern: { glob: **/*.ts, matches: file } } ] } } } } }; // 2. 分发器根据 method 路由到处理器 if (msg.method workspace/didDeleteFiles) { const params msg.params; // DeleteFilesParams for (const entry of params.files) { const path uriToPath(entry.uri); // 解析 file:// URI if (!matchesFilters(entry.uri)) continue; // 按 filters 过滤 invalidateCache(path); // 失效本地缓存 clearDiagnostics(path); // 清除该文件诊断 rebuildIndex(path); // 从索引/图中移除该文件 } // 通知无需响应不要 reply }客户端侧实际发送的完整通知JSON-RPC 2.0{ jsonrpc: 2.0, method: workspace/didDeleteFiles, params: { files: [ { uri: file:///workspace/src/legacy-helper.ts }, { uri: file:///workspace/src/legacy-helper.spec.ts } ] } }实现时务必注意三点不要响应通知Notification 语义下服务端若试图返回结果客户端不会消费反而可能造成协议层混乱URI 与路径的转换FileDelete.uri是DocumentUrifile://形式Windows 盘符、URL 编码如空格为%20都需要正确处理转换失败应记录日志并跳过该条目幂等与并发删除通知可能与textDocument/didClose、workspace/didChangeWatchedFiles等消息交错到达状态清理逻辑应设计为可重复执行且线程安全。七、源码佐证与继续阅读本文全部类型定义均可在本仓库的权威元模型中直接核验DeleteFilesParams/FileDelete见 metaModel.jsonDeleteFilesParams与 metaModel.jsonFileDeleteFileOperationRegistrationOptions/FileOperationFilter见 metaModel.json 与 metaModel.jsonFileOperationPattern/FileOperationPatternOptions/FileOperationPatternKind见 metaModel.json、metaModel.json、metaModel.json。相关规范文档均位于_specifications/lsp/3.18/workspace/目录本文主体didDeleteFiles.md事前请求含DeleteFilesParams、FileDelete完整 TS 定义willDeleteFiles.md同家族的创建/重命名通知与请求didCreateFiles.md、didRenameFiles.md、willCreateFiles.md、willRenameFiles.md小结workspace/didDeleteFiles虽然只是一个客户端删除文件后告知服务端的简单通知但完整的实现链路涉及能力协商、注册过滤器、URI 解析与状态清理四件事。把FileOperationRegistrationOptions的过滤语义用好可以让语言服务器只关注真正影响自己分析结果的删除事件从而在保持协议兼容性的同时把状态同步的开销降到最低。赞分享开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载相关推荐Language Server Protocol 文件删除事件workspace/didDeleteFiles 通知详解Language Server Protocol 文件删除事件workspace/didDeleteFiles 通知详解 导读 workspace/didDe开发工具Roc 编译器数字字面量快照解析以 int_i64_max 为例看 i64 最大值如何走完整个编译流水线Roc 编译器数字字面量快照解析以 int_i64_max 为例看 i64 最大值如何走完整个编译流水线 本指南以仓库中 test/snapshots/num开发工具语言服务器协议LSPtelemetry/event 遥测通知机制深度解析语言服务器协议LSP telemetry/event 遥测通知机制深度解析 telemetry/event 是语言服务器协议Language Server开发工具上一篇PyWxDump 环境配置实战指南新手 6 步跑通从体检到压测的全流程下一篇beautiful-react-hooks 之 useMouse一次获取鼠标位置与全部鼠标事件的组合 Hook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考