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

如何仅获取CSharpCompilation增量部分的错误诊断?

如何针对Roslyn编译增量获取错误诊断?

我之前在处理大型项目的Roslyn代码改写时,也遇到过一模一样的问题——全局调用Compilation.GetDiagnostics()实在太慢,哪怕用了增量编译也没明显改善。核心原因是默认的全局诊断会遍历整个编译的所有节点,哪怕你只改了一个方法。下面几个可行的方案,能帮你只针对增量部分获取诊断:

  • 针对修改的语法节点调用SemanticModel.GetDiagnostics()
    当你通过Compilation.Update得到新的编译实例后,别直接全局获取诊断,先定位到你改写的具体语法节点(比如MethodDeclarationSyntax),然后获取该节点对应的SemanticModel,再调用semanticModel.GetDiagnostics(node.Span)。这样Roslyn只会检查这个节点范围内的语法和语义错误,完全不用扫描整个项目。
    举个简单的代码示例:

    // newCompilation是增量更新后的编译实例
    // modifiedMethod是你改写后的MethodDeclarationSyntax节点
    var semanticModel = newCompilation.GetSemanticModel(modifiedMethod.SyntaxTree);
    var diagnostics = semanticModel.GetDiagnostics(modifiedMethod.Span);
    
  • 利用CompilationWithAnalyzers做增量分析
    如果你在代码操作中用到了Roslyn分析器,CompilationWithAnalyzers提供了更精准的增量诊断能力。你可以跟踪哪些SyntaxTree被修改,创建CompilationWithAnalyzers实例后,调用GetAnalyzerDiagnosticsAsync时指定只分析变化的树。这种方式会直接跳过未修改的部分,速度提升非常明显。

  • 过滤全局诊断到增量区域
    如果出于某些原因必须调用全局的Compilation.GetDiagnostics(),你可以在获取所有诊断后,过滤出属于你修改的SyntaxTree或具体节点的诊断。比如:

    var allDiagnostics = newCompilation.GetDiagnostics();
    var relevantDiagnostics = allDiagnostics.Where(d => 
        d.Location.SourceTree == modifiedSyntaxTree &&
        modifiedMethod.Span.Contains(d.Location.SourceSpan)
    ).ToList();
    

    不过这个方案效率不如前两个,因为它还是会先扫描整个项目,只是后续做了过滤,适合一些简单场景。

另外要注意:确保你正确使用Compilation.Update——只替换真正修改过的SyntaxTree,其他树复用原来的实例,这样Roslyn才能真正利用增量编译的优化,避免不必要的全量重新编译。

内容的提问来源于stack exchange,提问作者m1o2

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:51:18