Roslyn Formatter.Format()花费的时间太长

时间:2017-09-19 07:41:47

标签: c# .net code-generation roslyn

我正在使用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%。因此,仍然可以将它们用于比较。

1 个答案:

答案 0 :(得分:1)

您正在寻找的“最小格式化程序”是.NormalizeWhitespace()方法。

这不适合您希望人类维护的代码,但是我认为这不应该成为问题,因为您要处理的是60k行文件!