2016-04-22 3 views
1

Предлагает ли Roslyn способ генерации дерева синтаксиса для произвольной допустимой строки типа или ITypeSymbol?Создание дерева синтаксиса из строки типа/ITypeSymbol в Roslyn

Например, System.Threading.Task разбирает к дереву

QualifiedName(
    QualifiedName(
     IdentifierName("System"), 
     IdentifierName("Threading")), 
    IdentifierName("Task")) 

В то время как System.Threading.Task<int> разбирает к дереву

QualifiedName(
    QualifiedName(
     IdentifierName("System"), 
     IdentifierName("Threading")), 
    GenericName(
     Identifier("Task")) 
    .WithTypeArgumentList(
     TypeArgumentList(
      SingletonSeparatedList<TypeSyntax>(
       PredefinedType(
        Token(SyntaxKind.IntKeyword)))))) 

и, наконец, System.Threading.Task<,> разбирает к дереву

QualifiedName(
    QualifiedName(
     IdentifierName("System"), 
     IdentifierName("Threading")), 
    GenericName(
     Identifier("Task")) 
    .WithTypeArgumentList(
     TypeArgumentList(
      SeparatedList<TypeSyntax>(
       new SyntaxNodeOrToken[]{ 
        OmittedTypeArgument(), 
        Token(SyntaxKind.CommaToken), 
        OmittedTypeArgument()})))) 

While Я нахожусь в процессе написания легкого лексера f или этот прецедент, я хотел знать, было ли это уже предоставлено Рослином.

Update # 1: Окончательный вариант, чтобы минимизировать разборе на основе подхода, описанного Тамас:

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; 
} 

ответ

1

Вы можете использовать CSharpSyntaxTree.ParseText для создания дерева с любого входа. Если вы дадите ему вход, который вы контролируете, вы можете перейти к интересующему вас поддереву. Так, например, теперь вы хотите иметь синтаксис для типа. Вы можете соединить вход как:

@"class MyClass 
{ 
    TYPE_THAT_INTERESTS_ME field; 
}" 

Тогда получите дерево его, и перейдите к полю, и получить TypeSyntax от его VariableDeclarationSyntax.

+0

Этот подход с узлом typeof() выглядит так, как будто он соответствует счету. – ThatRA

+0

Вам нужно дать Roslyn полную программу на C#, или вы можете дать ей просто фрагмент? (например, могу ли я разобрать «a + b * c» сам по себе? Могу ли я проанализировать допустимую подстроку языка: «else x + 2;»? Какой API вызывает? –

+0

Я не думаю, что есть API для обработки произвольных В результате возникает ошибка восстановления в синтаксическом анализаторе, но это не означает, что он будет предоставлять допустимое дерево вывода для всего. Возможно, даже невозможно однозначно вернуть дерево для ввода. Рассмотрим 'x +', что не является допустимое выражение и может быть частью 'x + 2' или' x ++ '. Возможно, вам захочется проверить http://roslynquoter.azurewebsites.net/ и посмотреть на пару вводов, которые он производит. – Tamas