LSP workspace/didRenameFiles 文件重命名通知详解:能力协商、RenameFilesParams 与注册模式实战 开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载workspace/didRenameFiles是 Language Server ProtocolLSP3.16 引入的文件操作file operations系列消息之一用于在客户端内部完成文件/文件夹重命名后把这一事实以通知notification形式告知语言服务器使其同步更新内部索引、符号缓存或文档状态。本文以 didRenameFiles.md 为骨架结合同仓库的 willRenameFiles.md、willCreateFiles.md 等配套文档与 metaModel.json 元数据系统讲解该通知的协议定义、双向能力协商、参数结构、注册过滤规则以及它与workspace/willRenameFiles、workspace/didChangeWatchedFiles的职责边界。一、消息概述何时、由谁、向哪里发送根据原文档定义workspace/didRenameFiles是一条从客户端发往服务器client → server的通知The did rename files notification is sent from the client to the server when files were renamed from within the client.其协议要素可概括为要素值方法名methodworkspace/didRenameFiles消息方向客户端 → 服务器参数类型paramsRenameFilesParams消息类型通知notification服务器无需响应引入版本3.16.0见 metaModel.json 中since: 3.16.0标注两个关键限定词值得注意from within the client通知只在由客户端内部发起的重命名时发送——包括用户直接在客户端界面里的重命名操作以及客户端应用WorkspaceEdit中的RenameFile资源操作所引发的重命名见 resourceChanges.md。如果重命名发生在客户端外部例如其他进程改动了磁盘则不触发该通知这属于文件系统监听workspace/didChangeWatchedFiles的范畴。were renamed过去时通知在重命名已经完成之后发送属于事后告知与下文将提到的workspace/willRenameFiles事前请求形成互补。二、双向能力协商client capability 与 server capability与 LSP 中绝大多数功能一样workspace/didRenameFiles的启用需要通过初始化阶段的能力协商来完成且客户端与服务器使用同一个属性路径workspace.fileOperations.didRename只是两侧的值类型不同。2.1 客户端能力Client Capability原文档定义如下属性名可选workspace.fileOperations.didRename属性类型boolean语义该能力表示客户端支持发送workspace/didRenameFiles通知。客户端在initialize请求的capabilities字段中声明典型 JSON 形式如下{ capabilities: { workspace: { fileOperations: { didRename: true } } } }对应 TypeScript 接口中该字段的元数据描述可在 metaModel.json 中找到The client has support for sending didRenameFiles notifications.该字段为可选字段optional: true。2.2 服务器能力Server Capability属性名可选workspace.fileOperations.didRename属性类型FileOperationRegistrationOptions语义该能力表示服务器有兴趣接收workspace/didRenameFiles通知。与客户端侧的简单boolean不同服务器侧的值类型是FileOperationRegistrationOptions——一个携带**过滤规则filters**的结构体用来声明服务器只关心哪些路径上的重命名事件。metaModel 中的对应条目同样标注了可选性并说明 The server is interested in receiving didRenameFiles notifications.见 metaModel.json。服务器在initialize响应的capabilities中声明{ capabilities: { workspace: { fileOperations: { didRename: { filters: [ { pattern: { glob: **/*.{ts,tsx}, matches: file, options: { ignoreCase: true } } } ] } } } } }服务器能力采用FileOperationRegistrationOptions而非布尔值意味着服务器可以精细控制自己感兴趣的重命名范围只接收与项目技术栈相关的文件类型事件从而减少不必要的消息处理开销。三、通知参数RenameFilesParams 与 FileRenameworkspace/didRenameFiles的参数类型为RenameFilesParams。该类型的完整定义并未重复出现在 didRenameFiles 文档中而是由配套的 willRenameFiles.md 统一给出RenameFilesParams同时被workspace/willRenameFiles请求复用。其 TypeScript 定义如下/** * The parameters sent in notifications/requests for user-initiated renames * of files. * * since 3.16.0 */ export interface RenameFilesParams { /** * An array of all files/folders renamed in this operation. When a folder * is renamed, only the folder will be included, and not its children. */ files: FileRename[]; }要点解析files是一次重命名操作中所有被重命名的文件/文件夹的数组当重命名的是文件夹时数组中只包含该文件夹本身不包含其子文件/子目录——这是为了保持事件紧凑服务器需要自行推断文件夹下所有受影响的后代路径。每个FileRename元素携带新旧两个 URI/** * Represents information on a file/folder rename. * * since 3.16.0 */ export interface FileRename { /** * A file:// URI for the original location of the file/folder being renamed. */ oldUri: string; /** * A file:// URI for the new location of the file/folder being renamed. */ newUri: string; }字段说明字段类型含义oldUristring重命名前文件/文件夹的原始位置file://URInewUristring重命名后文件/文件夹的新位置file://URI协议要求 URI 统一使用file://scheme文档强调 A file:// URI。服务器收到通知后可基于oldUri与newUri的成对映射安全地迁移内部缓存例如把符号索引、诊断结果、跳转映射中所有指向oldUri的条目更新为newUri。一个实际通知的 JSON 报文示例{ jsonrpc: 2.0, method: workspace/didRenameFiles, params: { files: [ { oldUri: file:///home/user/project/src/utils.ts, newUri: file:///home/user/project/src/helpers.ts }, { oldUri: file:///home/user/project/src/legacy-lib, newUri: file:///home/user/project/src/lib } ] } }四、服务器能力中的过滤规则FileOperationRegistrationOptions 深度拆解由于服务器能力的值类型是FileOperationRegistrationOptions理解其内部结构是正确配置服务器的前提。该类型的完整定义与 glob 语法说明集中在 willCreateFiles.md 中拆解如下。4.1 顶层结构/** * The options to register for file operations. * * since 3.16.0 */ interface FileOperationRegistrationOptions { /** * The actual filters. */ filters: FileOperationFilter[]; }filters为过滤器数组每个FileOperationFilter由可选的scheme与必填的pattern组成export interface FileOperationFilter { /** * A Uri like file or untitled. */ scheme?: string; /** * The actual file operation pattern. */ pattern: FileOperationPattern; }scheme用于限定 URI scheme例如file本地磁盘或untitled未保存的新建文档省略时对所有 scheme 生效pattern声明具体的 glob 匹配模式。4.2 FileOperationPattern 与 glob 语法interface FileOperationPattern { glob: string; matches?: FileOperationPatternKind; options?: FileOperationPatternOptions; }glob字段支持的语法规则与workspace/didChangeWatchedFiles中的 glob 一致见 didChangeWatchedFiles.md语法含义示例*匹配路径段中的零个或多个字符*.ts?匹配路径段中的单个字符config?.json**匹配任意数量的路径段含零个**/src/**{}子模式的 OR 分组**/*.{ts,js}匹配所有 TypeScript 与 JavaScript 文件[]路径段中的字符范围example.[0-9]匹配example.0、example.1…[!...]取反的字符范围example.[!0-9]匹配example.a、example.b但不匹配example.0配套的两个辅助类型export namespace FileOperationPatternKind { export const file: file file; export const folder: folder folder; } export type FileOperationPatternKind file | folder; export interface FileOperationPatternOptions { /** * The pattern should be matched ignoring casing. */ ignoreCase?: boolean; }matches限定模式针对文件、文件夹还是两者——file只匹配文件folder只匹配文件夹缺省时两者都匹配options.ignoreCase设为true时匹配忽略大小写。4.3 一个完整的服务器声明示例{ capabilities: { workspace: { fileOperations: { didRename: { filters: [ { scheme: file, pattern: { glob: **/*.{ts,tsx,js,jsx}, matches: file, options: { ignoreCase: false } } }, { pattern: { glob: **/{src,lib}/**, matches: folder } } ] } } } } }该声明表示服务器只关心本地磁盘上、后缀为.ts/.tsx/.js/.jsx的文件重命名以及src、lib目录下文件夹的重命名。五、生命周期视角didRenameFiles 与 willRenameFiles 的前后呼应要正确理解workspace/didRenameFiles必须把它放到文件重命名完整事件链中看待。同名文档 willRenameFiles.md 定义了它的孪生请求workspace/willRenameFiles维度workspace/willRenameFiles请求workspace/didRenameFiles通知时机重命名发生之前重命名完成之后方向客户端 → 服务器客户端 → 服务器是否需要响应需要返回WorkspaceEdit \| null不需要参数RenameFilesParams复用同一类型RenameFilesParams目的让服务器有机会干预通过返回WorkspaceEdit在重命名前调整工作区让服务器事后同步内部状态两个消息使用完全相同的RenameFilesParams与FileRename数据结构能力协商也共享workspace.fileOperations.willRename/workspace.fileOperations.didRename这两个并列的属性路径。典型场景下的完整时序为用户在客户端中触发重命名或客户端应用含RenameFile的 WorkspaceEdit客户端发送workspace/willRenameFiles请求服务器可返回WorkspaceEdit以调整受影响的引用如更新导入语句供客户端在真正重命名前应用客户端执行实际重命名客户端发送workspace/didRenameFiles通知服务器据此清理/迁移索引与缓存。需要特别说明的是协议允许客户端只支持其中某一个方向。比如客户端只发送didRenameFiles而不发送willRenameFiles服务器就只能在事后响应而无法事前干预。文档还提醒客户端可能丢弃willRenameFiles的计算结果例如服务器计算耗时过长或持续失败以保持重命名操作的快速与可靠——因此服务器不应把必然被调用作为设计前提didRenameFiles反而更适合承担状态同步兜底。六、与相邻机制的边界didRenameFiles vs didChangeWatchedFiles vs resourceChanges这三者容易混淆建议按如下口径区分workspace/didRenameFiles文件操作通知只在客户端主动发起重命名时发送一次携带完整的新旧 URI 映射语义精确、结构化。workspace/didChangeWatchedFiles文件系统事件通知客户端在检测到被监听路径的任意文件系统事件创建、修改、删除时发送见 didChangeWatchedFiles.md。它的粒度是FileEventURI FileChangeType不包含新旧路径映射——客户端外部或无法归因到用户操作的文件变动都从这里流入。该文档同时建议服务器应优先通过注册机制获取这些事件而非各自实现文件系统监听跨 OS 监听复杂、每个服务器各自轮询会造成 CPU/内存浪费、同一客户端往往同时启动多个服务器。WorkspaceEdit中的RenameFile资源操作这是服务器 → 客户端的反向通道见 resourceChanges.md。服务器可以在返回的WorkspaceEdit.documentChanges中放入RenameFile含oldUri、newUri、可选options与annotationId请求客户端执行重命名。客户端应用该编辑时若同时声明了workspace.fileOperations.didRename能力也会向服务器回发workspace/didRenameFiles通知重命名由应用 workspace edit触发同样属于 from within the client。用户/客户端界面操作重命名 ──► willRenameFiles(请求) ──► 实际重命名 ──► didRenameFiles(通知) 外部文件系统变动 ──► didChangeWatchedFiles(通知FileEvent 粒度) 服务器请求客户端改文件 ──► WorkspaceEdit.documentChanges 中的 RenameFile(反向资源操作)七、服务器实现要点与最佳实践结合上述协议细节服务器处理workspace/didRenameFiles时可参考以下实践能力声明要克制filters中只声明确实需要的 glob 范围。声明得越窄收到的无关事件越少RenameFilesParams.files数组的有效命中率越高。以oldUri → newUri为单位更新索引逐对处理files数组把内部符号表、文档 URI 集合、跳转映射中所有引用oldUri的条目改写为newUri处理完成后可主动触发依赖方刷新如重新发布相关文档的诊断。文件夹重命名需自行展开协议规定文件夹重命名只上报文件夹本身only the folder will be included, and not its children服务器需要基于oldUri前缀自行推导全部后代路径的影响面。与willRenameFiles分工若客户端同时支持willRenameFiles把干预性编辑如改 import、改引用放在请求阶段把状态同步放在didRenameFiles阶段不要假设willRenameFiles一定被调用客户端可能因超时丢弃其结果。与 watched files 协同对于无法被客户端主动操作归因的重命名如 Git 检出、外部工具批量改名仍应依赖workspace/didChangeWatchedFiles兜底两者互补而非互斥。注意能力字段的可选性workspace.fileOperations.didRename在客户端与服务器两侧都是可选字段optional: true。服务器应在初始化时检查客户端是否声明了该能力未声明则不要依赖该通知。八、仓库中的证据与延伸阅读本文核心协议定义didRenameFiles.md参数类型RenameFilesParams/FileRename完整定义willRenameFiles.md注册选项FileOperationRegistrationOptions、glob 语法与过滤器结构willCreateFiles.md同族文件操作消息创建通知 didCreateFiles.md、删除通知 didDeleteFiles.md、删除前请求 willDeleteFiles.md反向资源操作与RenameFile变更字面量resourceChanges.md、workspaceEdit.md含failureHandling、resourceOperations等客户端能力说明文件系统事件通知的对比口径didChangeWatchedFiles.md机器可读的协议元数据since: 3.16.0、messageDirection: clientToServer、registrationOptions引用等metaModel.json。该系列文件同样存在于 3.18 与 3.19 规范目录如 3.18 版 didRenameFiles、3.19 版 didRenameFiles定义保持稳定说明该通知自 3.16 引入后一直是文件操作支持中的稳定组成部分。赞分享开发工具【免费下载链接】language-server-protocolDefines a common protocol for language servers.项目地址https://gitcode.com/gh_mirrors/la/language-server-protocol点击查看免费下载相关推荐LSP 3.17 文档重命名机制详解didClose/didOpen 语义与 workspace/didRenameFiles、willRenameFiles 协作实践LSP 3.17 文档重命名机制详解didClose/didOpen 语义与 workspace/didRenameFiles、willRenameFiles开发工具LSP workspace/willRenameFiles 请求详解在文件重命名前拦截并注入 WorkspaceEdit 的协议机制LSP workspace/willRenameFiles 请求详解在文件重命名前拦截并注入 WorkspaceEdit 的协议机制 导读 workspace开发工具LSP 文本格式化请求textDocument/formatting协议详解从能力协商到 FormattingOptionsLSP 文本格式化请求textDocument/formatting协议详解从能力协商到 FormattingOptions 本篇指南聚焦语言服务器协议开发工具上一篇CCPD数据集性能基准测试Faster-RCNN、SSD、YOLOv3全面对比下一篇FreeRTOS CBMC 证明基础设施本地运行 FreeRTOS 内核内存安全证明的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考