roslyn 为 region 和 endregion 添加 space

roslyn add space for region and endregion

我正在使用 roslyn 修改 c# 代码,除了与代码不对齐的区域外,其他都有效。缺少前面的空格。

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ClearWebProject
{
    public class ConvertRoslyn
    {
        public void Read(string file)
        {
            var text = @"
using System;

public partial class Class1
{
}
public class Class2
{
    #region toto
    int test = 2;
    #endregion
}
public class Class3
{
}
";

            var tree = CSharpSyntaxTree.ParseText(text);
            var root = (CompilationUnitSyntax)tree.GetRoot();
            var result = string.Empty;

            if (!root.ChildNodes().OfType<NamespaceDeclarationSyntax>().Any())
            {
                ClassDeclarationSyntax aspClass = null;
                List<MemberDeclarationSyntax> otherMembers = new List<MemberDeclarationSyntax>();
                foreach (var classe in root.ChildNodes().OfType<MemberDeclarationSyntax>())
                {
                    if(aspClass == null && classe.Modifiers.Any(p=> p.RawKind == (int)SyntaxKind.PartialKeyword))
                    {
                        aspClass = classe as ClassDeclarationSyntax;
                    }
                    else
                    {
                        otherMembers.Add(classe);
                    }
                }

                if(otherMembers.Any())
                {
                    var beginRegion = SyntaxFactory.Trivia(SyntaxFactory.RegionDirectiveTrivia(true)
                        .WithTrailingTrivia(new[] { SyntaxFactory.Space, 
                            SyntaxFactory.PreprocessingMessage("Classes internes") }));
                    var endRegion = SyntaxFactory.Trivia(SyntaxFactory.EndRegionDirectiveTrivia(true));
                    //SyntaxFactory.SyntaxTrivia(SyntaxKind.WhitespaceTrivia,"  ")
                    otherMembers[0] = otherMembers[0].WithLeadingTrivia(beginRegion);
                    result = SyntaxFactory.CompilationUnit()
                    .WithUsings(root.Usings)
                    .AddMembers(SyntaxFactory.NamespaceDeclaration(SyntaxFactory.IdentifierName("TestNamespace"))
                        .AddMembers(aspClass
                                .AddMembers(otherMembers.ToArray())
                                .WithCloseBraceToken(SyntaxFactory.Token(SyntaxKind.CloseBraceToken)
                                    .WithLeadingTrivia(endRegion)))
                        ).NormalizeWhitespace().ToFullString();
                }
                else
                {
                    result = SyntaxFactory.CompilationUnit()
                    .WithUsings(root.Usings)
                    .AddMembers(SyntaxFactory.NamespaceDeclaration(SyntaxFactory.IdentifierName("TestNamespace"))
                        .AddMembers(aspClass)
                        ).NormalizeWhitespace().ToFullString();
                }


                Console.WriteLine(result);
            }
        }
    }
}

这就是我得到的。 如您所见,现有区域(如我创建的区域)从第

行开始
using System;

namespace TestNamespace
{
    public partial class Class1
    {
#region Classes internes
        public class Class2
        {
#region toto
            int test = 2;
#endregion
        }

        public class Class3
        {
        }
#endregion
    }
}

我想要这个

using System;

namespace TestNamespace
{
    public partial class Class1
    {
        #region Classes internes
        public class Class2
        {
            #region toto
            int test = 2;
            #endregion
        }

        public class Class3
        {
        }
        #endregion
    }
}

区域指令相对于代码缩进

它已被报告为 Roslyn 的 GitHub 存储库 here 上的一个问题,但它至今仍处于开放状态。就我而言,似乎没有办法单独通过 Visual Studio 来做到这一点。

您可以使用 ReSharper 之类的插件来强制缩进预处理器指令,如之前 link 中所见。

另外两个也添加此功能的插件包括:

@Codehack 感谢您对 roslyn 的这种不可能性的回应。

我刚刚编写了一个函数来缩进区域指令。对我来说,其他预编译指令应该在行的开头,而不是区域!

    public string IndentRegion(string codeCsharp)
    {
        using var strReader = new StringReader(codeCsharp);
        using var strWriter = new StringWriter();
        
        string line = null;
        var spaceCountAtStart = 0;
        var regions = new Stack<int>();
        while ((line = strReader.ReadLine()) != null) 
        {
            if(line.StartsWith("#region"))
            {
                var sb = new StringBuilder();
                sb.Append(' ', spaceCountAtStart);
                regions.Push(spaceCountAtStart);
                strWriter.WriteLine($"{sb}{line}");
            }
            else if (line.StartsWith("#endregion"))
            {
                var sb = new StringBuilder();
                sb.Append(' ', regions.Pop());
                strWriter.WriteLine($"{sb}{line}");
            }
            else
            {
                if (!string.IsNullOrEmpty(line))
                {
                    strWriter.WriteLine(line);
                    spaceCountAtStart = line.TakeWhile(Char.IsWhiteSpace).Count();
                    var firstChar = line.ElementAtOrDefault(spaceCountAtStart);
                    if (firstChar == '{')
                    {
                        spaceCountAtStart += 4;
                    }
                }
            }
        }

        return strWriter.ToString();
    }