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

C# 格式化方法签名会丢失缩进,c#,roslyn,C#,Roslyn,我正在创建一个代码修复程序,它将检测到的方法的访问修饰符public。实现非常简单:删除所有现有的访问修饰符,并在前面添加public。之后,我替换节点并返回解决方案 但是,这将导致一个类似于以下内容的修改器列表:publicvirtual void Method()。在相互粘贴的修饰符之上,代码行的缩进错误。看起来是这样的: [TestClass] public class MyClass { [TestMethod] p

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

但是,这将导致一个类似于以下内容的修改器列表:
publicvirtual void Method()
。在相互粘贴的修饰符之上,代码行的缩进错误。看起来是这样的:

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

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

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

            }
        }
    }";
因此,作为一种解决方案,我改为格式化代码。使用

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);
}
私有任务MakePublicAsync(文档文档、SyntaxNode根、MethodDeclarationSyntax方法)
{
var removableModifiers=new[]
{
SyntaxFactory.Token(SyntaxKind.InternalKeyword),
SyntaxFactory.Token(SyntaxKind.ProtectedKeyword),
SyntaxFactory.Token(SyntaxKind.PrivateKeyword)
};
var modifierList=新的SyntaxTokenList()
.Add(SyntaxFactory.Token(SyntaxKind.PublicKeyword))
.AddRange(method.Modifiers.Where(x=>!removableModifiers.Select(y=>y.RawKind).Contains(x.RawKind));
var newMethod=带修饰符的方法(修饰符列表);
var formattedMethod=Formatter.Format(newMethod,newMethod.Modifiers.Span,document.Project.Solution.Workspace,document.Project.Solution.Workspace.Options);
var newRoot=root.ReplaceNode(方法,formattedMethod.WithLeadingTrivia(方法.GetLeadingTrivia());
var newDocument=document.WithSyntaxRoot(newRoot);
返回Task.FromResult(newDocument.Project.Solution);
}

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


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

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

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

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

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

            }
        }
    }";
var-original=@”
使用制度;
使用系统文本;
命名空间控制台应用程序1
{
类MyClass
{   
void方法(可为空的myVar=5)
{
}
}
}";
正如您所看到的,在左边距和实际代码之间仍然有一个选项卡。显然,Roslyn格式化程序无法处理这种情况(不可否认,这种情况并不常见)


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

我正要发布我的解决方案:如果我将琐事预先添加到
SyntaxNode
中,我从
SyntaxFactory.Token(SyntaxKind.PublicKeyword)
收到的消息,我所有的测试都会正常。您认为格式化程序批注解决方案比此更可取吗?是的,通常我建议只使用批注,然后它将匹配用户设置,并与其他更改一起格式化。我应该在哪里应用此批注?当我在方法级别执行此操作时,方法本身已格式化,但整个方法缩进严重。我希望避免格式化整个文档,因为每次使用代码修复程序时,这都会让人很恼火。您应该能够在添加/更改的代码上添加它。如果这产生了一个严重缩进的方法,您是否可以用一些复制代码在上提出问题?