web-dev-qa-db-fra.com

Trouver toutes les références à une méthode avec Roslyn

Je cherche à analyser un groupe de fichiers .cs pour voir lesquels appellent la propriété Value d'un Nullable<T> (recherche de toutes les références). Par exemple, cela correspondrait à:

class Program
{
    static void Main()
    {
        int? nullable = 123;
        int value = nullable.Value;
    }
}

J'ai découvert Roslyn et regardé certains des échantillons, mais beaucoup d'entre eux sont obsolètes et l'API est énorme. Comment pourrais-je procéder?

Je suis bloqué après avoir analysé l'arbre de syntaxe. Voici ce que j'ai jusqu'à présent:

public static void Analyze(string sourceCode)
{
    var tree = CSharpSyntaxTree.ParseText(sourceCode);

    tree./* ??? What goes here? */
}
19
James Ko

Vous recherchez probablement la classe SymbolFinder et en particulier la méthode FindAllReferences .

Il semble que vous ayez du mal à vous familiariser avec Roslyn. J'ai une série de billets de blog pour aider les gens à se familiariser avec Roslyn appelés Learn Roslyn Now .

Comme @SLaks le mentionne, vous allez avoir besoin d'accéder au modèle sémantique que je couvre dans Partie 7: Introduction au modèle sémantique

Voici un exemple qui vous montre comment l'API peut être utilisée. Si vous le pouvez, j'utiliserais MSBuildWorkspace et chargerais le projet à partir du disque au lieu de le créer dans un AdHocWorkspace comme celui-ci.

var mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var ws = new AdhocWorkspace();
//Create new solution
var solId = SolutionId.CreateNewId();
var solutionInfo = SolutionInfo.Create(solId, VersionStamp.Create());
//Create new project
var project = ws.AddProject("Sample", "C#");
project = project.AddMetadataReference(mscorlib);
//Add project to workspace
ws.TryApplyChanges(project.Solution);
string text = @"
class C
{
    void M()
    {
        M();
        M();
    }
}";
var sourceText = SourceText.From(text);
//Create new document
var doc = ws.AddDocument(project.Id, "NewDoc", sourceText);
//Get the semantic model
var model = doc.GetSemanticModelAsync().Result;
//Get the syntax node for the first invocation to M()
var methodInvocation = doc.GetSyntaxRootAsync().Result.DescendantNodes().OfType<InvocationExpressionSyntax>().First();
var methodSymbol = model.GetSymbolInfo(methodInvocation).Symbol;
//Finds all references to M()
var referencesToM = SymbolFinder.FindReferencesAsync(methodSymbol,  doc.Project.Solution).Result;
43
JoshVarty

Un journal de problèmes et d'éventuelles corrections, j'avais obligé Roslyn à travailler avec VS2017:

La raison des projets VS2017 vides devient visible lorsque l'événement MSBuildWorkspace WorkspaceFailed est connecté.

La première série d'échecs a été:

MSB0001: Erreur interne MSBuild: saisissez les informations pour Microsoft.Build.Utilities.ToolLocationHelper dans le cache de la liste blanche en tant que Microsoft.Build.Utilities.ToolLocationHelper, Microsoft.Build.Utilities.Core, Version = 15.1.0.0, Culture = neutre, PublicKeyToken = b03f5f7f11d50a3a mais le type n'a pas pu être chargé. inopinément nul])

Ce problème a été résolu en installant les packages NuGet Microsoft.Build.Locator 1.1.2 et Microsoft.Build.Utilities.Core 15.9.20

La deuxième série d'échecs a été:

Msbuild a échoué lors du traitement du fichier 'C:\Users ... vbproj' avec le message: C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets: (1491, 5): La tâche "Microsoft.Build.Tasks.AssignProjectConfiguration" n'a pas pu être chargée à partir de l'assembly Microsoft.Build.Tasks.Core, Version = 15.1.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a. Impossible de charger le fichier ou l'assembly "Microsoft.Build.Tasks.Core, Version = 15.1.0.0, Culture = neutral, PublicKeyToken = b03f5f7f11d50a3a" ou l'une de ses dépendances. Le système ne peut pas trouver le fichier spécifié. Confirmez que la déclaration est correcte, que l'assembly et toutes ses dépendances sont disponibles et que la tâche contient une classe publique qui implémente Microsoft.Build.Framework.ITask.])

Ce problème a été résolu en ajoutant NuGet Microsoft.Build.Tasks.Core 15.9.20

La troisième série d'échecs était: === Msbuild a échoué lors du traitement du fichier 'C:\Users ... vbproj' avec le message: C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets: (1657, 5): la tâche "GetReferenceNearestTargetFrameworkTask" n'a pas pu être instanciée à partir de l'assembly "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.Build.Tasks.dll ". Veuillez vérifier que l'assembly de tâche a été créé à l'aide de la même version de l'assembly Microsoft.Build.Framework que celle installée sur votre ordinateur et que votre application hôte ne manque pas de redirection de liaison pour Microsoft.Build.Framework. Impossible de convertir un objet de type 'NuGet.Build.Tasks.GetReferenceNearestTargetFrameworkTask' en type 'Microsoft.Build.Framework.ITask'.])

Notez que Microsoft.Build.Framework.dll du projet = 15.1.0.0 mais le message mentionne "MSBuild\15.0\Bin"

Ajout à app.config - corrigé! cf entrez la description du lien ici Je peux maintenant charger des projets à partir des solutions VS2017

  <!-- vvv Roslyn manual fixup https://github.com/Microsoft/msbuild/issues/2369 -->
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build.Utilities.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <dependentAssembly>
    <assemblyIdentity name="Microsoft.Build.Tasks.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-15.1.0.0" newVersion="15.1.0.0" />
  </dependentAssembly>
  <!-- ^^^ Roslyn manual fixup https://github.com/Microsoft/msbuild/issues/2369 -->
1
brewmanz