C# Language
Plate-forme de compilation .NET (Roslyn)
Recherche…
Créer un espace de travail à partir d'un projet MSBuild
Obtenez d'abord le nuget Microsoft.CodeAnalysis.CSharp.Workspaces
avant de continuer.
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);
}
Pour charger du code existant dans l'espace de travail, compilez et signalez les erreurs. Le code sera ensuite stocké dans la mémoire. De là, le côté syntaxique et le côté sémantique seront disponibles pour travailler avec.
Arbre de syntaxe
Un arbre de syntaxe est une structure de données immuable représentant le programme sous la forme d'une arborescence de noms, de commandes et de marques (comme précédemment configuré dans l'éditeur).
Par exemple, supposons qu'une instance Microsoft.CodeAnalysis.Compilation
nommée compilation
ait été configurée. Il existe plusieurs façons de répertorier les noms de chaque variable déclarée dans le code chargé. Pour ce faire, prenez tous les éléments de la syntaxe dans chaque document (la méthode DescendantNodes
) et utilisez Linq pour sélectionner les nœuds décrivant la déclaration de variable:
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);
}
}
Chaque type de construction C # avec un type correspondant existera dans l'arbre de syntaxe. Pour trouver rapidement des types spécifiques, utilisez la fenêtre Syntax Visualizer
de Visual Studio. Ceci interprétera le document ouvert actuel comme un arbre de syntaxe Roslyn.
Modèle sémantique
Un modèle sémantique offre un niveau plus élevé d'interprétation et de compréhension du code par rapport à un arbre de syntaxe. Lorsque les arbres de syntaxe peuvent indiquer les noms des variables, les modèles sémantiques indiquent également le type et toutes les références. Les arbres de syntaxe remarquent les appels de méthode, mais les modèles sémantiques donnent des références à l'emplacement précis de la méthode déclarée (après l'application d'une résolution de surcharge).
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)"
}
}
}
}
Cela génère une liste de variables locales à l'aide d'un arbre de syntaxe. Ensuite, il consulte le modèle sémantique pour obtenir le nom complet du type et trouver toutes les références de chaque variable.