格式化方法签名会丢失缩进

时间:2015-05-04 13:23:00

标签: c# roslyn

我正在创建一个代码修复程序,它会转换检测到的方法public的访问修饰符。实现很简单:删除所有现有的访问修饰符并在前面添加public。然后我替换节点并返回解决方案。

然而,这会产生一个如下所示的修饰符列表:publicvirtual void Method()。在粘贴彼此的修改器之上,该行代码被错误地缩进。它看起来像这样:

        [TestClass]
        public class MyClass
        {
            [TestMethod]
publicvirtual void Method()
            {

            }
        }

因此,作为解决方案,我会格式化代码。使用

var formattedMethod = Formatter.Format(newMethod, 
                                       newMethod.Modifiers.Span,
                                       document.Project.Solution.Workspace,
                                       document.Project.Solution.Workspace.Options);

我可以格式化修饰符,但它们仍然错误地缩进:

        [TestClass]
        public class MyClass
        {
            [TestMethod]
public virtual void Method()
            {

            }
        }

我认为这是因为琐事,但是使用原始方法的主要琐事预先设置格式化方法并没有什么不同。我想避免格式化整个文档,因为这不是格式化整个文档的操作。

此代码修复的完整相关实现:

private Task<Solution> MakePublicAsync(Document document, SyntaxNode root, MethodDeclarationSyntax method)
{
    var removableModifiers = new[]
    {
        SyntaxFactory.Token(SyntaxKind.InternalKeyword),
        SyntaxFactory.Token(SyntaxKind.ProtectedKeyword),
        SyntaxFactory.Token(SyntaxKind.PrivateKeyword)
    };

    var modifierList = new SyntaxTokenList()
                            .Add(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
                            .AddRange(method.Modifiers.Where(x => !removableModifiers.Select(y => y.RawKind).Contains(x.RawKind)));

    var newMethod = method.WithModifiers(modifierList);
    var formattedMethod = Formatter.Format(newMethod, newMethod.Modifiers.Span, document.Project.Solution.Workspace, document.Project.Solution.Workspace.Options);

    var newRoot = root.ReplaceNode(method, formattedMethod.WithLeadingTrivia(method.GetLeadingTrivia()));
    var newDocument = document.WithSyntaxRoot(newRoot);

    return Task.FromResult(newDocument.Project.Solution);
}

2 个答案:

答案 0 :(得分:2)

不要手动调用Formatter.Format,只需将Formatter.Annotation放在固定节点上,CodeFix引擎就会自动为您调用它。

问题是您需要在树的根上调用Format,但是要指定要格式化的树的范围,否则格式化程序将在上运行树你传入,没有来自其父母的上下文。

答案 1 :(得分:0)

问题是我在字符串表示中缩进了我的测试,如下所示:

        var original = @"
    using System;
    using System.Text;

    namespace ConsoleApplication1
    {
        class MyClass
        {   
            void Method(Nullable<int> myVar = 5)
            {

            }
        }
    }";

正如您所看到的,左边距和实际代码之间仍然有一个标签。显然,Roslyn格式化程序无法处理这种情况(诚然,这不是常见情况)。

在不同的情况下,您可能对格式化程序感兴趣,这就是我接受凯文答案的原因。