I'm using CSharpSyntaxTree.ParseText
to create a syntax tree from an arbitrary block of code; I'd like to be able to wrap or encapsulate either that SyntaxTree
or its UnitCompilationRoot
in a region. I'm aware of the Quoter website that allows you to see how any arbitrary code could be written using the Roslyn API, but the way it breaks down the code into its raw components doesn't help with the use-case of adding a region to a SyntaxTree
or UnitCompilationRoot
.
// Create syntax tree from template
var str = @"public class Foo { }"
var syntaxTree = CSharpSyntaxTree.ParseText(str);
// Add Region
// ????
Regions are represented by Roslyn as special kind of SyntaxTrivia
.
So for the purpose of wrapping block of code into region you may get target SyntaxNode
and replace it's leading and trailing trivia with regions trivia.
The following code demonstrates how this can be done:
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));
}
To perform more complex operations you may use CSharpSyntaxRewriter class. Some examples of using that class may be found at here.