使用OmniSharp实现VS Code语言服务器文件系统事件响应问题
解决OmniSharp中DidChangeWatchedFiles未触发的问题
我之前用OmniSharp开发C#语言服务器时也踩过这个坑,针对你要监听未打开文件变更的需求,给你几个实用的解决步骤:
1. 手动实现注册选项类
OmniSharp确实没有直接封装DidChangeWatchedFilesRegistrationOptions接口,但我们可以自己定义符合LSP规范的类来替代——本质上只需要传递正确的JSON结构给客户端即可。
// 对应LSP的DidChangeWatchedFilesRegistrationOptions结构 public class CustomWatchedFilesRegistrationOptions { public IEnumerable<FileSystemWatcher> Watchers { get; set; } } // 对应每个监听规则 public class FileSystemWatcher { public string GlobPattern { get; set; } public int? Kind { get; set; } }
这里的Kind对应LSP的FileChangeType枚举:
- 1 = 创建(Created)
- 2 = 修改(Changed)
- 4 = 删除(Deleted)
可以用位运算组合,比如7表示监听所有类型的变更。
2. 正确注册能力并告知客户端
光实现IDidChangeWatchedFilesHandler还不够,必须在服务器初始化阶段明确声明支持该能力,并传递监听规则给客户端。
在你的语言服务器类的OnInitialize方法中添加以下逻辑:
public override async Task<InitializeResult> OnInitialize(InitializeRequest request, CancellationToken cancellationToken) { var initResult = await base.OnInitialize(request, cancellationToken); // 声明服务器支持文件变更监听的动态注册 initResult.Capabilities.Workspace.DidChangeWatchedFiles = new DidChangeWatchedFilesOptions { DynamicRegistration = true }; // 配置你需要监听的文件模式和事件类型 var registrationOptions = new CustomWatchedFilesRegistrationOptions { Watchers = new List<FileSystemWatcher> { new FileSystemWatcher { // 替换成你的自定义语言文件后缀,比如**.mylang GlobPattern = "**/*.yourlang", // 监听所有文件事件:创建+修改+删除 Kind = 1 | 2 | 4 } } }; // 注册处理器并传递选项 await RegisterCapabilityAsync( "workspace/didChangeWatchedFiles", registrationOptions, cancellationToken); return initResult; }
3. 确保客户端(VS Code)配置正确
VS Code默认会监听文件系统变更,但需要检查以下几点:
- 确认你的文件模式没有被
files.watcherExclude配置排除,比如在你的扩展package.json中不要添加相关排除规则 - 如果你的扩展有自定义配置,确保没有禁用VS Code的文件监听功能
4. 调试验证
- 开启OmniSharp的详细日志,查看服务器和客户端之间的通信,确认注册请求是否发送成功,客户端是否返回了确认响应
- 在你的
IDidChangeWatchedFilesHandler实现中添加日志或断点,验证是否接收到事件:
public class CustomWatchedFilesHandler : IDidChangeWatchedFilesHandler { public Task Handle(DidChangeWatchedFilesParams request, CancellationToken cancellationToken) { foreach (var change in request.Changes) { // 打印变更信息到日志,方便调试 Console.WriteLine($"Detected file change: {change.Uri} - Type: {change.Type}"); } return Task.CompletedTask; } }
内容的提问来源于stack exchange,提问作者Adrian Gabor
相关产品推荐
相关产品推荐

