Поиск…


Создание рабочей области из проекта MSBuild

Прежде чем продолжить, сначала запустите Microsoft.CodeAnalysis.CSharp.Workspaces nuget.

var workspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
var project = await workspace.OpenProjectAsync(projectFilePath);
var compilation = await project.GetCompilationAsync();

foreach (var diagnostic in compilation.GetDiagnostics()
    .Where(d => d.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Error))
{
    Console.WriteLine(diagnostic);
}

Чтобы загрузить существующий код в рабочую область, выполните компиляцию и отправьте сообщение об ошибках. После этого код будет находиться в памяти. Отсюда и синтаксическая, и семантическая стороны будут доступны для работы.

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

Дерево синтаксиса - это неизменяемая структура данных, представляющая программу как дерево имен, команд и меток (как ранее было настроено в редакторе).

Например, предположим, что экземпляр Microsoft.CodeAnalysis.Compilation именем compilation был настроен. Существует несколько способов перечислить имена каждой переменной, объявленной в загруженном коде. Чтобы сделать это наивно, возьмите все фрагменты синтаксиса в каждом документе (метод DescendantNodes ) и используйте Linq для выбора узлов, описывающих объявление переменных:

foreach (var syntaxTree in compilation.SyntaxTrees)
{
    var root = await syntaxTree.GetRootAsync();
    var declaredIdentifiers = root.DescendantNodes()
        .Where(an => an is VariableDeclaratorSyntax)
        .Cast<VariableDeclaratorSyntax>()
        .Select(vd => vd.Identifier);

    foreach (var di in declaredIdentifiers)
    {
        Console.WriteLine(di);
    }
}

Каждый тип конструкции C # с соответствующим типом будет существовать в дереве синтаксиса. Чтобы быстро найти определенные типы, используйте окно Syntax Visualizer Visual Studio Visual Studio. Это будет интерпретировать текущий открытый документ как синтаксическое дерево Roslyn.

Семантическая модель

Семантическая модель предлагает более глубокий уровень интерпретации и понимания кода по сравнению с деревом синтаксиса. Если деревья синтаксиса могут указывать имена переменных, семантические модели также дают тип и все ссылки. Деревья синтаксиса замечают вызовы методов, но семантические модели дают ссылки на точное местоположение, объявленное методом (после применения разрешения перегрузки).

var workspace = Microsoft.CodeAnalysis.MSBuild.MSBuildWorkspace.Create();
var sln = await workspace.OpenSolutionAsync(solutionFilePath);
var project = sln.Projects.First();
var compilation = await project.GetCompilationAsync();

foreach (var syntaxTree in compilation.SyntaxTrees)
{
    var root = await syntaxTree.GetRootAsync();

    var declaredIdentifiers = root.DescendantNodes()
        .Where(an => an is VariableDeclaratorSyntax)
        .Cast<VariableDeclaratorSyntax>();

    foreach (var di in declaredIdentifiers)
    {
        Console.WriteLine(di.Identifier);
        // => "root"

        var variableSymbol = compilation
            .GetSemanticModel(syntaxTree)
            .GetDeclaredSymbol(di) as ILocalSymbol;

        Console.WriteLine(variableSymbol.Type);
        // => "Microsoft.CodeAnalysis.SyntaxNode"

        var references = await SymbolFinder.FindReferencesAsync(variableSymbol, sln);
        foreach (var reference in references)
        {
            foreach (var loc in reference.Locations)
            {
                Console.WriteLine(loc.Location.SourceSpan);
                // => "[1375..1379)"
            }
        }
    }
}

Это выводит список локальных переменных, используя дерево синтаксиса. Затем он консультируется с семантической моделью, чтобы получить полное имя типа и найти все ссылки каждой переменной.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow