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

Roslyn代码修复:创建带单行注释的格式化空方法

Roslyn代码修复:生成格式规范的仅含单行注释的空方法

修改前后对比

修改前:

public class Bla
{
    public void Blub()
    {
        Console.WriteLine("");
    }
}

修改后期望效果:

public class Bla
{
    public void Blub()
    {
        // I told you so
    }
}

三次尝试及问题

版本1 - 通过WithStatements添加注释

代码:

private static async Task<Document> RemoveContainOfDownMethod(Document document, BaseMethodDeclarationSyntax downMethodDeclaration, CancellationToken cancellationToken)
{
    SyntaxTree? documentSyntaxTree = await document.GetSyntaxTreeAsync(cancellationToken);
    if (documentSyntaxTree == null || downMethodDeclaration.Body == null)
    {
        return document;
    }

    var commentTrivia = SyntaxFactory.Comment("// I told you so.");
    var emptyBlock = SyntaxFactory.Block()
        .WithOpenBraceToken(downMethodDeclaration.Body.OpenBraceToken)
        .WithCloseBraceToken(downMethodDeclaration.Body.CloseBraceToken)
        .WithStatements(SyntaxFactory.SingletonList<StatementSyntax>(
            SyntaxFactory.EmptyStatement().WithLeadingTrivia(commentTrivia)));

    CompilationUnitSyntax newDocument = documentSyntaxTree.GetCompilationUnitRoot(cancellationToken)
        .ReplaceNode(
            downMethodDeclaration.Body,
            emptyBlock
                .WithLeadingTrivia(downMethodDeclaration.Body.GetLeadingTrivia())
                .WithTrailingTrivia(downMethodDeclaration.Body.GetTrailingTrivia()));

    return document.WithSyntaxRoot(newDocument);
}

生成结果:

public class Bla
{
    public void Blub()
    {
        // I told you so                                        ;
    }
}

问题:

  • 存在尾随分号

版本2 - 通过WithCloseBraceToken添加注释

代码:

private static async Task<Document> RemoveContainOfDownMethod(Document document, BaseMethodDeclarationSyntax downMethodDeclaration, CancellationToken cancellationToken)
{
    SyntaxTree? documentSyntaxTree = await document.GetSyntaxTreeAsync(cancellationToken);
    if (documentSyntaxTree == null || downMethodDeclaration.Body == null)
    {
        return document;
    }

    SyntaxTrivia commentTrivia = SyntaxFactory.Comment("// I told you so");
    BlockSyntax emptyBlock = SyntaxFactory.Block()
            .WithOpenBraceToken(SyntaxFactory.Token(SyntaxKind.OpenBraceToken))
            .WithCloseBraceToken(SyntaxFactory.Token(SyntaxKind.CloseBraceToken).WithLeadingTrivia(commentTrivia));

    CompilationUnitSyntax newDocument = documentSyntaxTree.GetCompilationUnitRoot(cancellationToken)
        .ReplaceNode(
            downMethodDeclaration.Body,
            emptyBlock
                .WithLeadingTrivia(downMethodDeclaration.Body.GetLeadingTrivia())
                .WithTrailingTrivia(downMethodDeclaration.Body.GetTrailingTrivia()));

    return document.WithSyntaxRoot(newDocument);
}

生成结果:

public class Bla
{
    public void Blub()
    {
        // I told you so        }
}

问题:

  • 方法闭合大括号前缺少换行

版本3 - 通过WithCloseBraceToken添加注释并使用NormalizeWhitespace

代码:

private static async Task<Document> RemoveContainOfDownMethod(Document document, BaseMethodDeclarationSyntax downMethodDeclaration, CancellationToken cancellationToken)
{
    SyntaxTree? documentSyntaxTree = await document.GetSyntaxTreeAsync(cancellationToken);
    if (documentSyntaxTree == null || downMethodDeclaration.Body == null)
    {
        return document;
    }

    SyntaxTrivia commentTrivia = SyntaxFactory.Comment("// I told you so");
    BlockSyntax emptyBlock = SyntaxFactory.Block()
            .WithOpenBraceToken(SyntaxFactory.Token(SyntaxKind.OpenBraceToken))
            .WithCloseBraceToken(SyntaxFactory.Token(SyntaxKind.CloseBraceToken).WithLeadingTrivia(commentTrivia));

    CompilationUnitSyntax newDocument = documentSyntaxTree.GetCompilationUnitRoot(cancellationToken)
        .ReplaceNode(
            downMethodDeclaration.Body,
            emptyBlock
                .WithLeadingTrivia(downMethodDeclaration.Body.GetLeadingTrivia())
                .WithTrailingTrivia(downMethodDeclaration.Body.GetTrailingTrivia()))
        .NormalizeWhitespace();

    return document.WithSyntaxRoot(newDocument);
}

生成结果:

public class Bla
{
    public void Blub()
    {
    // I told you so
    }
}

问题:

  • 注释缩进错误

正确实现方案

核心思路是给空Block的闭合大括号添加包含缩进、换行、注释的完整Trivia集合,同时复用原方法块的格式信息,确保输出和原代码风格一致。

private static async Task<Document> RemoveContainOfDownMethod(Document document, BaseMethodDeclarationSyntax downMethodDeclaration, CancellationToken cancellationToken)
{
    SyntaxTree? documentSyntaxTree = await document.GetSyntaxTreeAsync(cancellationToken);
    if (documentSyntaxTree == null || downMethodDeclaration.Body == null)
    {
        return document;
    }

    // 提取原方法内的缩进格式,保证注释缩进和原代码一致
    var originalIndent = downMethodDeclaration.Body.Statements.FirstOrDefault()?.GetLeadingTrivia()
        .Where(t => t.IsKind(SyntaxKind.WhitespaceTrivia) || t.IsKind(SyntaxKind.EndOfLineTrivia))
        .TakeWhile(t => !t.IsKind(SyntaxKind.EndOfLineTrivia))
        .Aggregate("", (acc, t) => acc + t.ToFullString());

    // 构建闭合大括号的前导Trivia:缩进 + 换行 + 注释 + 换行
    var commentTriviaList = SyntaxFactory.TriviaList(
        SyntaxFactory.Whitespace(originalIndent ?? "    "),
        SyntaxFactory.EndOfLine("\r\n"),
        SyntaxFactory.Comment("// I told you so"),
        SyntaxFactory.EndOfLine("\r\n")
    );

    // 创建新的空Block,复用原开、闭大括号Token并设置正确Trivia
    var emptyBlock = SyntaxFactory.Block()
        .WithOpenBraceToken(downMethodDeclaration.Body.OpenBraceToken)
        .WithCloseBraceToken(downMethodDeclaration.Body.CloseBraceToken.WithLeadingTrivia(commentTriviaList))
        .WithLeadingTrivia(downMethodDeclaration.Body.GetLeadingTrivia())
        .WithTrailingTrivia(downMethodDeclaration.Body.GetTrailingTrivia());

    var newRoot = documentSyntaxTree.GetCompilationUnitRoot(cancellationToken)
        .ReplaceNode(downMethodDeclaration.Body, emptyBlock);

    return document.WithSyntaxRoot(newRoot);
}

关键说明

  1. 动态提取缩进:从原方法内的语句获取缩进格式,避免硬编码缩进导致的风格不匹配
  2. 完整Trivia集合:给闭合大括号的前导Trivia添加缩进、换行、注释、换行,确保注释单独占一行且位置正确
  3. 复用原Token:保留原方法块的开、闭大括号Token,避免重新生成Token丢失原格式信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 17:31:05