如何使用 Roslyn 在区域或评论中包装 SyntaxTree 或 UnitCompilationRoot?

How can I wrap a SyntaxTree or UnitCompilationRoot in a region or comment using Roslyn?

我正在使用 CSharpSyntaxTree.ParseText 从任意代码块创建语法树;我希望能够将 SyntaxTree 或其 UnitCompilationRoot 包装或封装在一个区域中。我知道 Quoter 网站允许您查看如何使用 Roslyn API 编写任意代码,但是它将代码分解为原始组件的方式对用例没有帮助将区域添加到 SyntaxTreeUnitCompilationRoot.

使用任意代码的示例

// Create syntax tree from template
var str = @"public class Foo { }"
var syntaxTree = CSharpSyntaxTree.ParseText(str);

// Add Region
// ????

区域由 Roslyn 表示为特殊类型的 SyntaxTrivia。 因此,为了将代码块包装到区域中,您可以获取目标 SyntaxNode 并将它的前导和尾随琐事替换为区域琐事。 以下代码演示了如何完成此操作:

public static T AddRegion<T>(this T node, string regionName) where T : SyntaxNode
{
    return node
        // inserts #region RegionName before node
        .WithLeadingTrivia(node.GetLeadingTrivia().Insert(0, GetRegionLeadingTrivia(regionName)))
        // inserts #endregion after node
        .WithTrailingTrivia(node.GetTrailingTrivia().Add(GetRegionTrailingTrivia()));
}

public static SyntaxTrivia GetRegionLeadingTrivia(string regionName)
{
    return SyntaxFactory.Trivia(
        SyntaxFactory
            .RegionDirectiveTrivia(true)
            .WithEndOfDirectiveToken(
                SyntaxFactory.Token(
                    SyntaxFactory.TriviaList(SyntaxFactory.PreprocessingMessage(regionName)),
                    SyntaxKind.EndOfDirectiveToken,
                    SyntaxFactory.TriviaList())));
}

public static SyntaxTrivia GetRegionTrailingTrivia()
{
    return SyntaxFactory.Trivia(SyntaxFactory.EndRegionDirectiveTrivia(true));
}

要执行更复杂的操作,您可以使用 CSharpSyntaxRewriter class. Some examples of using that class may be found at here