Szukaj…


Utwórz obszar roboczy z projektu MSBuild

Najpierw uzyskaj nuget Microsoft.CodeAnalysis.CSharp.Workspaces zanim przejdziesz dalej.

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

Aby załadować istniejący kod do obszaru roboczego, skompiluj i zgłoś błędy. Następnie kod zostanie umieszczony w pamięci. Odtąd dostępna będzie zarówno strona składniowa, jak i semantyczna.

Drzewo składniowe

Drzewo składni to niezmienna struktura danych reprezentująca program jako drzewo nazw, poleceń i znaczników (jak wcześniej skonfigurowano w edytorze).

Załóżmy na przykład, że instancja Microsoft.CodeAnalysis.Compilation nazwie compilation została skonfigurowana. Istnieje wiele sposobów wyświetlania nazw wszystkich zmiennych zadeklarowanych w załadowanym kodzie. Aby zrobić to naiwnie, weź wszystkie elementy składni w każdym dokumencie (metoda DescendantNodes ) i użyj Linq, aby wybrać węzły opisujące deklarację zmiennej:

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

Każdy typ konstrukcji C # z odpowiednim typem będzie istniał w drzewie składni. Aby szybko znaleźć określone typy, użyj okna Syntax Visualizer z Visual Studio. Spowoduje to zinterpretowanie bieżącego otwartego dokumentu jako drzewa składniowego Roslyn.

Model semantyczny

Model semantyczny oferuje głębszy poziom interpretacji i wglądu w kod w porównaniu z drzewem składni. Tam, gdzie drzewa składniowe mogą podawać nazwy zmiennych, modele semantyczne podają także typ i wszystkie odwołania. Drzewa składniowe zauważają wywołania metod, ale modele semantyczne podają odniesienia do dokładnej lokalizacji, w której deklarowana jest metoda (po zastosowaniu rozwiązania przeciążenia).

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)"
            }
        }
    }
}

Spowoduje to wyświetlenie listy zmiennych lokalnych przy użyciu drzewa składni. Następnie konsultuje się z modelem semantycznym, aby uzyskać pełną nazwę typu i znaleźć wszystkie odwołania do każdej zmiennej.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow