Reputation: 79
Does Roslyn provide a way to generate a syntax tree for an arbitrary valid type string or ITypeSymbol?
For example, System.Threading.Task
parses to a tree of
QualifiedName(
QualifiedName(
IdentifierName("System"),
IdentifierName("Threading")),
IdentifierName("Task"))
While System.Threading.Task<int>
parses to a tree of
QualifiedName(
QualifiedName(
IdentifierName("System"),
IdentifierName("Threading")),
GenericName(
Identifier("Task"))
.WithTypeArgumentList(
TypeArgumentList(
SingletonSeparatedList<TypeSyntax>(
PredefinedType(
Token(SyntaxKind.IntKeyword))))))
and finally System.Threading.Task<,>
parses to a tree of
QualifiedName(
QualifiedName(
IdentifierName("System"),
IdentifierName("Threading")),
GenericName(
Identifier("Task"))
.WithTypeArgumentList(
TypeArgumentList(
SeparatedList<TypeSyntax>(
new SyntaxNodeOrToken[]{
OmittedTypeArgument(),
Token(SyntaxKind.CommaToken),
OmittedTypeArgument()}))))
While I am in the process of writing a lightweight lexer for this use case, I wanted to know if this was provided by Roslyn already.
Update #1: Final variant to minimize parsing based on the approach described by Tamas:
public static async Task<TypeSyntax> CreateTypeSyntax(string typeName)
{
var options = new CSharpParseOptions(kind: SourceCodeKind.Script);
var parsedTree = CSharpSyntaxTree.ParseText($"typeof({typeName})", options);
var treeRoot = await parsedTree.GetRootAsync();
var typeNameNode = treeRoot.DescendantNodes().OfType<TypeSyntax>().FirstOrDefault();
return typeNameNode;
}
Upvotes: 2
Views: 902
Reputation: 6420
You can use CSharpSyntaxTree.ParseText
to generate a tree from any input. If you give it an input which you have control over, then you can get to the subtree that interests you. So for example now you want to have the syntax for a type. You can put together an input like:
@"class MyClass
{
TYPE_THAT_INTERESTS_ME field;
}"
Then get the tree of it, and navigate to the field, and get the TypeSyntax
from its VariableDeclarationSyntax
.
Upvotes: 1