roslynДерево синтаксиса

Вступление

Одной из основных частей компилятора Roslyn является API синтаксиса. Он предоставляет деревья синтаксиса, используемые компиляторами для понимания программ Visual Basic и C #.

замечания

  • Дерево синтаксиса представляет собой дерево разбора в контексте компилятора Roslyn.

Получение корня дерева синтаксиса из документа.

Если у вас уже есть доступ к вашему классу Document из рабочей области (с помощью Workspaces ), вам легко получить доступ к корню вашего дерева синтаксиса.

 Document document = ... // Get document from workspace or other source 

 var syntaxRoot = await document.GetSyntaxRootAsync();

Перемещение дерева синтаксиса с помощью LINQ

Вы можете легко перемещаться по дереву синтаксиса с помощью LINQ. Например, легко получить все узлы ClassDeclarationSyntax (объявленные классы), которые имеют имя, начинающееся с буквы A :

var allClassesWithNameStartingWithA = syntaxRoot.DescendantNodes()
    .OfType<ClassDeclarationSyntax>()
    .Where(x => x.Identifier.ToString().StartsWith("A"));

Или получить все классы, которые имеют атрибуты:

var allClassesWithAttriutes = syntaxRoot.DescendantNodes()
    .OfType<ClassDeclarationSyntax>()
    .Where(x => x.AttributeLists.Any(y => y.Attributes.Any()));

Перемещение дерева синтаксиса с помощью CSharpSyntaxWalker

Класс CSharpSyntaxWalker представляет собой нестандартную реализацию шаблона Visitor, который мы можем использовать для перемещения нашего дерева синтаксиса. Вот простой пример Синтаксического Уолкера, который собирает все struct -s, у которых есть имя, начиная с буквы A :

public class StructCollector : CSharpSyntaxWalker
{
    public StructCollector()
    {
        this.Structs = new List<StructDeclarationSyntax>();
    }

    public IList<StructDeclarationSyntax> Structs { get; }

    public override void VisitStructDeclaration(StructDeclarationSyntax node)
    {
        if (node.Identifier.ToString().StartsWith("A"))
        {
            this.Structs.Add(node);
        }
    }
}

Мы можем использовать наш SyntaxWalker следующим образом:

var structCollector = new StructCollector();
structCollector.Visit(syntaxRoot); // Or any other syntax node
Console.WriteLine($"The number of structs that have a name starting with the letter 'A' is {structCollector.Structs.Count}");