我正在使用Roslyn生成大量代码(约60k行)。
当我使用Formatter.Format()
格式化空格时会出现问题。实际格式化时间过长(~60k lines in ~200s
)。
使用过的代码。
public string GenerateCode()
{
var workspace = new AdhocWorkspace();
OptionSet options = workspace.Options;
options = options.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInMethods, true);
options = options.WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInProperties, true);
CompilationUnitSyntax compilationUnit = CreateCompilationUnit();// this method builds the syntax tree.
SyntaxNode formattedNode = Formatter.Format(compilationUnit, workspace, options);
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
formattedNode.WriteTo(writer);
}
return sb.ToString();
}
我开始认识到,人类可读的格式不是必不可少的(仍然会很好)。我停止格式化代码,但生成的代码实际上无法编译。这是因为某些关键字没有必要的空白。例如" publicstaticclassMyClass"。
我尝试了Formatter
的不同选项,但没有一个是足够的。
然后我一直在寻找另一种选择" minimal"格式化。据我所知,没有。
最后,我设法通过在标识符本身中添加额外的空格来解决这个问题。
var className = "MyClass";
SyntaxFactory.ClassDeclaration(" " + className)
.AddModifiers(
// Using explicit identifier with extra whitespace
SF.Identifier(" public "),
SF.Identifier(" static "));
// Instead of the SyntaxKind enum
//SF.Token(SyntaxKind.PublicKeyword),
//SF.Token(SyntaxKind.StaticKeyword));
代码生成。
public string GenerateCode()
{
var workspace = new AdhocWorkspace();
CompilationUnitSyntax compilationUnit = CreateCompilationUnit(); // this method builds the syntax tree.
var sb = new StringBuilder();
using (var writer = new StringWriter(sb))
{
compilationUnit.WriteTo(writer);
}
return sb.ToString();
}
这样生成速度要快得多(~60k lines in ~2s
不是真正的行,因为它没有格式化,但代码量相同)。虽然这有效,但看起来有点像黑客。另一个解决方案可能是创建一个替代Formatter
,但这是我不想承担的任务。
有没有人想出更好的解决方案?有没有办法更有效地使用Formatter
?
注意:提供的时间测量包括构建语法树的时间和其他几个过程。在这两种情况下,格式化约为测量时间的98%。因此,仍然可以将它们用于比较。
答案 0 :(得分:1)
您正在寻找的“最小格式化程序”是.NormalizeWhitespace()
方法。
这不适合您希望人类维护的代码,但是我认为这不应该成为问题,因为您要处理的是60k行文件!