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

如何为C# Source Generator生成的警告添加自动代码修复建议?

实现C# Source Generator诊断与自动代码修复的关联方案

核心思路

Source Generator输出的诊断和Analyzer的诊断共用一套体系,代码修复的实现逻辑也完全一致——通过诊断ID绑定来关联诊断与对应的修复动作,以下是具体实现步骤:


1. 定义固定的诊断规则

首先在Source Generator中,你需要创建一个明确的DiagnosticDescriptor实例,确保诊断有唯一ID、描述等信息,这是后续关联修复的核心标识:

private static readonly DiagnosticDescriptor MyFixableWarning = new(
    id: "SG0001", // 唯一诊断ID,修复提供者将通过此ID关联
    title: "需要自动修复的代码问题",
    messageFormat: "代码片段 '{0}' 不符合规范,可自动修复",
    category: "CustomSourceGenerator",
    defaultSeverity: DiagnosticSeverity.Warning, // 支持Hidden级别,只需改为DiagnosticSeverity.Hidden
    isEnabledByDefault: true,
    description: "Source Generator检测到的可自动修复代码问题");

在Generator的Execute方法中,当检测到需要警告的场景时,通过GeneratorExecutionContext输出诊断,并关联具体的代码位置:

public void Execute(GeneratorExecutionContext context)
{
    // 模拟检测到问题的逻辑
    foreach (var syntaxTree in context.Compilation.SyntaxTrees)
    {
        var root = syntaxTree.GetRoot(context.CancellationToken);
        var targetNodes = root.DescendantNodes().OfType<IdentifierNameSyntax>();
        foreach (var node in targetNodes)
        {
            if (node.Identifier.Text == "NeedFix")
            {
                // 输出诊断,绑定到具体代码节点
                var diagnostic = Diagnostic.Create(
                    MyFixableWarning,
                    node.GetLocation(),
                    node.Identifier.Text);
                context.ReportDiagnostic(diagnostic);
            }
        }
    }
}

2. 实现代码修复提供者(Code Fix Provider)

创建一个继承自CodeFixProvider的类,通过指定FixableDiagnosticIds来关联上面定义的诊断ID,然后编写具体的修复逻辑:

基础框架实现

[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(MyCodeFixProvider))]
[Shared]
public class MyCodeFixProvider : CodeFixProvider
{
    // 绑定要处理的诊断ID,必须和Source Generator输出的诊断ID完全一致
    public override ImmutableArray<string> FixableDiagnosticIds 
        => ImmutableArray.Create("SG0001");

    // 指定批量修复的提供者,用默认实现即可
    public override FixAllProvider GetFixAllProvider() 
        => WellKnownFixAllProviders.BatchFixer;

    // 注册修复动作
    public override async Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
        var diagnostic = context.Diagnostics.First();
        var diagnosticSpan = diagnostic.Location.SourceSpan;

        // 定位到触发诊断的语法节点
        var targetNode = root.FindToken(diagnosticSpan.Start).Parent;
        if (targetNode == null) return;

        // 注册修复动作,指定显示名称、修复逻辑、等价键(用于批量修复)
        context.RegisterCodeFix(
            CodeAction.Create(
                title: "自动修复代码问题",
                createChangedDocument: c => FixCodeIssueAsync(context.Document, targetNode, c),
                equivalenceKey: "SG0001_Fix"),
            diagnostic);
    }
}

编写具体修复逻辑

实现FixCodeIssueAsync方法,根据你的需求修改代码,示例为替换标识符:

private async Task<Document> FixCodeIssueAsync(Document document, SyntaxNode targetNode, CancellationToken cancellationToken)
{
    var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
    
    // 创建新的语法节点,替换原有节点(示例:将NeedFix改为FixedCode)
    var newNode = SyntaxFactory.IdentifierName("FixedCode")
                               .WithTriviaFrom(targetNode); // 保留原有注释、空格等

    // 生成新的语法树并返回修改后的文档
    var newRoot = root.ReplaceNode(targetNode, newNode);
    return document.WithSyntaxRoot(newRoot);
}

3. 项目配置与关联注意事项

  • 项目设置:确保包含Source Generator和Code Fix Provider的项目,在.csproj中添加以下配置,标记为Roslyn组件:
    <PropertyGroup>
      <LangVersion>latest</LangVersion>
      <IsRoslynComponent>true</IsRoslynComponent>
      <Nullable>enable</Nullable>
    </PropertyGroup>
    
  • ID一致性:必须保证Source Generator中定义的诊断ID和Code Fix Provider的FixableDiagnosticIds完全匹配,否则无法关联。
  • Hidden级别诊断:如果需要用Hidden级别,只需将DiagnosticDescriptor的defaultSeverity改为DiagnosticSeverity.Hidden,Visual Studio依然会为其显示修复选项(可通过快速操作菜单触发)。

4. 验证与测试

创建测试项目引用该组件项目,编写包含NeedFix标识符的代码,Visual Studio会自动显示警告,点击灯泡图标即可看到“自动修复代码问题”的选项,执行后代码会被替换为FixedCode。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 09:15:33