ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Language Server Protocol 文件删除事件:workspace/didDeleteFiles 通知详解

Language Server Protocol 文件删除事件:workspace/didDeleteFiles 通知详解 开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载导读workspace/didDeleteFiles是 LSPLanguage Server Protocol中用于向语言服务器同步客户端侧文件删除事件的通知。本文以 3.17 版本规范文档为骨架完整讲解该通知的职责、客户端/服务端双侧 capability 声明方式、DeleteFilesParams与FileDelete参数结构并结合仓库中的willDeleteFiles请求、文件操作注册选项FileOperationRegistrationOptions及initialize阶段的能力协商代码说明如何在真实项目中落地“删除后及时清理索引/缓存”的实战方案。通知语义何时触发、由谁发出根据 didDeleteFiles.md 的定义The did delete files notification is sent from the client to the server when files were deleted from within the client.方向client → server客户端单向推送无需服务端应答触发条件文件删除操作发生在客户端内部例如用户在编辑器资源管理器中右键删除或执行了会删除文件的命令时机文件已经被删除之后才发送因此它属于“事后同步”语义服务端不能借此阻止删除只能据此更新自身状态与删除相关的两个消息形成明确分工消息方向时机用途workspace/willDeleteFiles请求client → server删除发生前服务端可返回WorkspaceEdit对工作区做预处理workspace/didDeleteFiles通知client → server删除发生后服务端同步删除结果、清理索引/缓存本文主角didDeleteFiles对应的是后半段“删除后清理”的场景。消息定义速览* method: workspace/didDeleteFiles * params: DeleteFilesParamsmethod 字符串workspace/didDeleteFilesparams 类型DeleteFilesParams定义详见下文返回值无通知不产生响应在 metaModel.json 的元数据中该通知被标记为messageDirection: clientToServer、since: 3.16.0并且其registrationOptions指向FileOperationRegistrationOptions与本文后续的服务端注册选项一致。参数结构DeleteFilesParams 与 FileDeleteDeleteFilesParams的定义位于 willDeleteFiles.md删除类请求与通知共用同一参数类型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[]; }其中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 中被建模为包含单个string类型属性uri的结构文档注释与规范完全一致与重命名参数RenameFilesParams不同删除不涉及oldUri/newUri成对字段只需一个目标 URI 即可。一个 JSON 示例{ files: [ { uri: file:///workspace/src/legacy_parser.ts }, { uri: file:///workspace/src/utils/old_helpers.ts } ] }客户端能力声明workspace.fileOperations.didDelete客户端若支持发送workspace/didDeleteFiles通知必须在initialize请求中声明 capability属性名可选workspace.fileOperations.didDelete属性类型boolean对应的客户端侧类型定义见 initialize.mdWorkspaceClientCapabilities中fileOperations对象包含didDelete、willDelete、didCreate、willCreate、didRename、willRename六个布尔字段以及dynamicRegistration用于声明是否支持文件操作的动态注册fileOperations?: { /** * Whether the client supports dynamic registration for file * requests/notifications. */ dynamicRegistration?: boolean; /** * The client has support for sending didCreateFiles notifications. */ didCreate?: boolean; /** * The client has support for sending willCreateFiles requests. */ willCreate?: boolean; /** * The client has support for sending didRenameFiles notifications. */ didRename?: boolean; /** * The client has support for sending willRenameFiles requests. */ willRename?: boolean; /** * The client has support for sending didDeleteFiles notifications. */ didDelete?: boolean; /** * The client has support for sending willDeleteFiles requests. */ willDelete?: boolean; };客户端声明示例{ capabilities: { workspace: { fileOperations: { didDelete: true } } } }注意didDelete是可选项未声明即表示客户端不会发送该通知服务端不应期待接收。服务端能力声明与注册选项服务端若希望接收workspace/didDeleteFiles通知必须在initialize响应中声明属性名可选workspace.fileOperations.didDelete属性类型FileOperationRegistrationOptions服务端侧类型见 initialize.md 的ServerCapabilities.workspace.fileOperationsdidDelete等六个字段的类型全部为FileOperationRegistrationOptions。FileOperationRegistrationOptions的完整定义位于 willCreateFiles.md/** * The options to register for file operations. * * since 3.16.0 */ interface FileOperationRegistrationOptions { /** * The actual filters. */ filters: FileOperationFilter[]; }过滤器FileOperationFilter 与 FileOperationPatternfilters由FileOperationFilter数组构成服务端通过它声明对哪些文件的删除事件感兴趣export interface FileOperationFilter { /** * A Uri like file or untitled. */ scheme?: string; /** * The actual file operation pattern. */ pattern: FileOperationPattern; }scheme可选的 URI scheme如file、untitled缺省时匹配任意 schemepattern必填的文件操作模式。interface FileOperationPattern { /** * The glob pattern to match. Glob patterns can have the following syntax: * - * to match zero or more characters in a path segment * - ? to match on one character in a path segment * - ** to match any number of path segments, including none * - {} to group sub patterns into an OR expression. (e.g. **​/*.{ts,js} * matches all TypeScript and JavaScript files) * - [] to declare a range of characters to match in a path segment * (e.g., example.[0-9] to match on example.0, example.1, …) * - [!...] to negate a range of characters to match in a path segment * (e.g., example.[!0-9] to match on example.a, example.b, but * not example.0) */ glob: string; /** * Whether to match files or folders with this pattern. * * Matches both if undefined. */ matches?: FileOperationPatternKind; /** * Additional options used during matching. */ options?: FileOperationPatternOptions; }matches的取值由FileOperationPatternKind限定export namespace FileOperationPatternKind { /** * The pattern matches a file only. */ export const file: file file; /** * The pattern matches a folder only. */ export const folder: folder folder; } export type FileOperationPatternKind file | folder;options目前支持大小写匹配控制export interface FileOperationPatternOptions { /** * The pattern should be matched ignoring casing. */ ignoreCase?: boolean; }服务端声明示例下面的声明表示服务端只关心filescheme 下所有 TypeScript/JavaScript 源码文件以及dist目录的删除事件{ capabilities: { workspace: { fileOperations: { didDelete: { filters: [ { scheme: file, pattern: { glob: **/*.{ts,js}, matches: file } }, { pattern: { glob: **/dist/**, matches: folder } } ] } } } } }多个 filter 之间是**或OR**关系命中任意一个即可收到通知glob 语法遵循规范中列出的*、?、**、{}、[]、[!...]六种形式未命中 filter 的删除不会触发通知服务端无需自己再过滤。动态注册客户端声明fileOperations.dynamicRegistration: true后服务端还可以通过workspace/registerCapability在运行时追加或调整删除事件的订阅范围注册选项同样使用FileOperationRegistrationOptions。这是文件操作能力区别于静态 capability 的扩展手段具体流程可参考 _includes/messages/3.17/registerCapability.md。与 willDeleteFiles 请求的配合虽然didDeleteFiles是事后通知但完整可靠的删除同步通常需要和 willDeleteFiles.md 配合workspace/willDeleteFiles删除前由客户端发起请求服务端可返回WorkspaceEdit | null在文件真正删除前对工作区做预处理例如迁移引用、改写路径。规范同时提醒客户端可能因计算耗时过长或服务端频繁失败而丢弃结果以保证删除操作快速可靠。workspace/didDeleteFiles删除后由客户端推送通知服务端据此做无副作用的同步动作如清理文档索引、失效缓存、刷新诊断。两者能力声明一一对应willDelete/didDelete但可以只声明其一只做事后清理的服务端可以仅声明didDelete。仓库中的元数据佐证在 metaModel.json 中两个删除消息均以结构化条目存在workspace/didDeleteFilesparams引用DeleteFilesParamsregistrationOptions引用FileOperationRegistrationOptions标注since: 3.16.0文档描述为“删除发生在客户端内后由客户端发送给服务端”workspace/willDeleteFiles同为clientToServer方向、since 3.16.0注册选项一致。FileDelete类型在元数据中被建模为单属性uri: string结构。这些条目与规范 Markdown 完全对齐可作为实现或生成 SDK 时的机器可读依据。典型应用场景与实现建议场景一索引与缓存失效服务端通常维护文件级索引符号表、跳转数据、折叠范围等。收到didDeleteFiles后将每个FileDelete.uri对应的索引条目标记为失效或直接移除避免后续跳转、补全命中已删除文件。场景二跨文件引用清理删除文件可能使其他文件出现悬空引用。此时更合适的做法是同时订阅willDeleteFiles在删除前用WorkspaceEdit改写引用didDeleteFiles则用于兜底清理。场景三按目录批量同步当用户删除整个文件夹时files数组中只需包含被删除的顶层文件夹 URI此行为在重命名参数RenameFilesParams中有明确约定文件夹重命名只包含文件夹本身不包含子项删除语义同理由客户端决定粒度。服务端可借助matches: folder的 filter 匹配这类事件。实现建议服务端处理伪代码function onDidDeleteFiles(params: DeleteFilesParams): void { for (const file of params.files) { const uri file.uri; index.remove(uri); // 清理文档索引 cache.invalidate(uri); // 失效缓存 diagnostics.clear(uri); // 清除该文件的诊断 } }总结workspace/didDeleteFiles是 client → server 方向的通知在客户端内部删除发生后触发客户端用workspace.fileOperations.didDelete: boolean声明发送能力服务端用workspace.fileOperations.didDelete: FileOperationRegistrationOptions声明接收兴趣后者通过FileOperationFilterFileOperationPatternglob精确限定订阅范围参数DeleteFilesParams.files: FileDelete[]承载被删除文件的file://URI 列表规范与 metaModel.json 均将其标记为since 3.16.0如需在删除前干预应使用 willDeleteFiles.md 请求与didDeleteFiles构成“事前干预 事后同步”的完整闭环。相关参考文件didDeleteFiles.md、willDeleteFiles.md、willCreateFiles.md注册选项定义、initialize.md能力协商、metaModel.json机器可读元数据。赞分享开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载相关推荐Dagger TypeScript SDK ExecError 类详解捕获容器 exec 失败的命令、退出码与输出流Dagger TypeScript SDK ExecError 类详解捕获容器 exec 失败的命令、退出码与输出流 ExecError 是 Dagger T开发工具Node.js v20.13.0 Iron (LTS) 发布解读性能优化、API 稳定化与诊断能力升级Node.js v20.13.0 Iron LTS 发布解读性能优化、API 稳定化与诊断能力升级 本篇技术指南以 Node.js 官网博客中 v20.1开发工具Context7 MCP 服务器安装与使用完全指南为 LLM 与 AI 编程助手注入实时更新的库文档Context7 MCP 服务器安装与使用完全指南为 LLM 与 AI 编程助手注入实时更新的库文档 Context7 是一个面向 LLM 与 AI 编程助手开发工具上一篇3步搭建高性能WebSocket服务器的终极指南快速实现实时通信应用下一篇终极指南快速搭建微信小程序商城 DTS-SHOP 创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进