C# Language
.NET Compiler Platform (Roslyn)
Ricerca…
Crea spazio di lavoro dal progetto MSBuild
Prima di continuare, ottenere prima il nuget Microsoft.CodeAnalysis.CSharp.Workspaces
.
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);
}
Per caricare il codice esistente nello spazio di lavoro, compilare e segnalare errori. Successivamente il codice sarà localizzato in memoria. Da qui, saranno disponibili sia il lato sintattico che quello semantico con cui lavorare.
Albero della sintassi
Un Syntax Tree è una struttura di dati immutabile che rappresenta il programma come un albero di nomi, comandi e segni (come precedentemente configurato nell'editor).
Ad esempio, si supponga che sia stata configurata un'istanza Microsoft.CodeAnalysis.Compilation
denominata compilation
. Esistono diversi modi per elencare i nomi di ogni variabile dichiarata nel codice caricato. Per farlo in modo ingenuo, prendi tutti i pezzi di sintassi in ogni documento (il metodo DescendantNodes
) e usa Linq per selezionare i nodi che descrivono la dichiarazione delle variabili:
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);
}
}
Nell'edificio della sintassi esisteranno tutti i tipi di costrutti C # con un tipo corrispondente. Per trovare rapidamente tipi specifici, utilizzare la finestra Syntax Visualizer
di Visual Studio. Questo interpreterà il documento aperto corrente come un albero di sintassi di Roslyn.
Modello semantico
Un modello semantico offre un livello più profondo di interpretazione e intuizione del codice rispetto a un albero di sintassi. Laddove gli alberi di sintassi possono indicare i nomi delle variabili, i modelli semantici forniscono anche il tipo e tutti i riferimenti. Le chiamate del metodo di avviso degli alberi di sintassi, ma i modelli semantici forniscono riferimenti alla posizione precisa in cui è stato dichiarato il metodo (dopo che è stata applicata la risoluzione di sovraccarico).
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)"
}
}
}
}
Questo produce un elenco di variabili locali usando un albero di sintassi. Quindi consulta il modello semantico per ottenere il nome completo del tipo e trova tutti i riferimenti di ogni variabile.