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

Formatting a method signature loses indentation

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

然而,这会导致修饰符列表如下所示: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);
}

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

问题是你需要在树的根上调用Format,但是要指定你想要格式化的树的跨度,否则格式化程序会在[=17=上运行 ]只是 您传入的树,没有来自其父级的上下文。

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

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

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

            }
        }
    }";

如您所见,左边距和实际代码之间仍然有一个制表符。显然 Roslyn 格式化程序无法处理这种情况(诚然,这种情况并不常见)。

不过在与此不同的情况下,您可能对格式化程序感兴趣,这就是为什么我会接受凯文的回答。