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

通过CompilationAnalysisContext.ReportDiagnostic上报的Roslyn诊断在VS中不显示

Roslyn分析器:CompilationAction上报的诊断在Visual Studio中无法显示

问题背景

使用Visual Studio 2022的「Analyzer with Code Fix」模板创建Roslyn分析器,单元测试中Rule1(通过SymbolAction上报)和Rule2(通过CompilationAction上报)均能正常生成诊断,但在Visual Studio界面中仅能看到Rule1的诊断。调试确认两个context.ReportDiagnostic调用都已执行,且VS设置中未抑制任何诊断。由于业务需要检查多个符号间的关系,改用SymbolAnalysisContext.ReportDiagnostic重写成本过高。

复现代码

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class DummyAnalyzer : DiagnosticAnalyzer
{
    private static readonly DiagnosticDescriptor Rule1 = new ("D001", "SymbolAction", "SymbolAction", "Test", DiagnosticSeverity.Warning, true);
    private static readonly DiagnosticDescriptor Rule2 = new ("D002", "CompilationAction", "CompilationAction", "Test", DiagnosticSeverity.Warning, true);

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Rule1, Rule2];

    public override void Initialize(AnalysisContext context)
    {
        context.EnableConcurrentExecution();

        context.RegisterSymbolAction(c => c.ReportDiagnostic(Diagnostic.Create(Rule1, c.Symbol.Locations.FirstOrDefault())), SymbolKind.Method);

        context.RegisterCompilationAction(CompilationAction);
    }

    private void CompilationAction(CompilationAnalysisContext context)
    {
        foreach (var syntaxTree in context.Compilation.SyntaxTrees)
        {
            var compilationUnitSyntax = syntaxTree.GetRoot(context.CancellationToken) as CompilationUnitSyntax;
            var typeDeclarationSyntax = compilationUnitSyntax?.Members.OfType<BaseNamespaceDeclarationSyntax>().SelectMany(syntax => syntax.Members).OfType<TypeDeclarationSyntax>().FirstOrDefault();
            if (typeDeclarationSyntax != null)
                context.ReportDiagnostic(Diagnostic.Create(Rule2, typeDeclarationSyntax.GetLocation()));
        }
    }
}

解决方法

核心原因

Visual Studio的**实时分析(Live Analysis)**默认会跳过全编译级别的分析动作(如CompilationAction),因为这类动作遍历整个编译单元,性能开销较大,仅在全编译(如项目重建)时才会执行。

具体修复步骤

  1. 配置CompilationAction的执行上下文
    在Initialize方法中,为RegisterCompilationAction添加分析选项,明确指定允许该动作在实时分析中执行:

    context.RegisterCompilationAction(CompilationAction, 
        new CompilationAnalysisOptions(ExecutionContext = AnalysisExecutionContext.LiveAnalysis));
    
  2. 优化CompilationAction的性能
    实时分析会频繁触发,必须确保动作执行高效,避免卡顿。可以限制仅处理当前活跃文档的语法树:

    private void CompilationAction(CompilationAnalysisContext context)
    {
        // 获取当前活跃文档路径(仅在VS实时分析中有效)
        context.Options.AnalyzerConfigOptionsProvider.GlobalOptions.TryGetValue(
            "build_metadata.AdditionalFiles.ActiveDocumentPath", 
            out var activeDocumentPath);
    
        foreach (var syntaxTree in context.Compilation.SyntaxTrees)
        {
            // 跳过非活跃文档的语法树,减少不必要的计算
            if (!string.IsNullOrEmpty(activeDocumentPath) && 
                !syntaxTree.FilePath.Equals(activeDocumentPath, StringComparison.OrdinalIgnoreCase))
            {
                continue;
            }
    
            var compilationUnitSyntax = syntaxTree.GetRoot(context.CancellationToken) as CompilationUnitSyntax;
            var typeDeclarationSyntax = compilationUnitSyntax?.Members.OfType<BaseNamespaceDeclarationSyntax>()
                .SelectMany(syntax => syntax.Members)
                .OfType<TypeDeclarationSyntax>()
                .FirstOrDefault();
            
            if (typeDeclarationSyntax != null)
            {
                context.ReportDiagnostic(Diagnostic.Create(Rule2, typeDeclarationSyntax.GetLocation()));
            }
        }
    }
    
  3. 验证全编译场景
    如果配置后实时分析仍未显示诊断,可以右键项目选择「重建」触发全编译,确认诊断是否出现,以此排除增量分析的干扰。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 07:20:03