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 中所见。
另外两个也添加此功能的插件包括:
- CSharpFixFormat for Visual Studio Code
- AStyle 看起来可用于 VS 2017 专业版及更高版本
@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();
}
我正在使用 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 中所见。
另外两个也添加此功能的插件包括:
- CSharpFixFormat for Visual Studio Code
- AStyle 看起来可用于 VS 2017 专业版及更高版本
@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();
}