【发布时间】:2018-02-27 21:39:11
【问题描述】:
我正在使用 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 的不同选项,但没有一个是足够的。
然后我正在寻找一种替代的“最小”格式化程序。据我所知,没有。
最后,我设法通过在标识符本身中添加额外的空格来解决这个问题。
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 不是真正的行,因为它没有格式化,但它是相同数量的代码)。虽然这可行,但它似乎有点 hacky。另一种解决方案可能是创建一个替代Formatter,但这是我不想承担的任务。
有人想出更好的解决方案吗?有什么方法可以更有效地使用Formatter?
注意:提供的时间测量包括构建语法树的时间和其他几个过程。在这两种情况下,格式化大约是测量时间的 98%。所以还是可以拿来比较的。
【问题讨论】:
-
Roslyn is open source。您是否考虑过分析代码以找出为什么格式化程序很慢?这可能是某种病态的分配模式,可以进行简单的修复。在那种情况下,每个人都会赢(而不是你为这种情况编写专用的格式化程序)。当然,它不必那么简单,但你至少有足够的背景材料来打开一个问题。
标签: c# .net code-generation roslyn