You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:06:04