2017-08-25 2 views
0

J'essaie de créer un analyseur de code qui vérifie les instructions d'utilisation complètes. Ce lien a été incroyablement utile, et la base de ma solution (How can I get the fully qualified namespace from a using directive in Roslyn?) mais je rencontre un problème lorsque j'essaie d'accéder à l'emplacement du symbole pour la directive using. Mon code ressemble à ceci:Erreur de métadonnées d'espace de noms entièrement qualifiée avec Roslyn

private static void AnalyzeModel(SemanticModelAnalysisContext semanticModelAnalysisContext) 
    { 
     var semanticModel = semanticModelAnalysisContext.SemanticModel; 
     var root = semanticModel.SyntaxTree.GetRoot(); 

     // compare each using statement's name with its fully qualified name 
     foreach (var usingDirective in root.DescendantNodes().OfType<UsingDirectiveSyntax>()) 
     { 
      var symbol = semanticModel.GetSymbolInfo(usingDirective.Name).Symbol; 
      var fullyQualifiedName = symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); 

      if (fullyQualifiedName.Contains(GlobalTag)) 
      { 
       fullyQualifiedName = fullyQualifiedName.Substring(GlobalTag.Length); 
      } 

      if (usingDirective.Name.ToString() != fullyQualifiedName) 
      { 
       // for each name that is not fully qualified, produce a diagnostic. 
       var diagnostic = Diagnostic.Create(Rule, symbol.Locations[0], symbol.Name); 
       semanticModelAnalysisContext.ReportDiagnostic(diagnostic); 
      } 
     } 
    } 

Le problème est le symbol.Locations[0] contient uniquement les éléments dans les métadonnées, et non des éléments dans la source. Cela conduit à l'erreur suivante:

Assert.IsTrue failed. Test base does not currently handle diagnostics in metadata locations.

Ma source dans mes tests unitaires ressemble à ceci:

private const string incorrectSourceCode = @" namespace System { using IO; using Threading; }";

Pourquoi n'y a aucun élément dans symbol.Locations qui sont la source? Y at-il un autre endroit où je peux obtenir cet emplacement? J'ai essayé d'utiliser symbol.ContainingSymbol.Locations[0] ou symbol.ContainingNamespace.Locations[0], mais ceux-ci ne se réfèrent pas à l'utilisation spécifique d'utilisation qui m'intéresse. J'ai étiré mes cheveux au cours de ces heures, et une certaine clarté serait très grandement appréciée.

Merci d'avance!

Répondre

2

Symbol contient MetadateLocation, donc si vous voulez voir SourceLocation juste le récupérer de la SyntaxNode appropriée:

var diagnostic = Diagnostic.Create(Rule, usingDirective.Name.GetLocation(), symbol.Name) 

au lieu de

var diagnostic = Diagnostic.Create(Rule, symbol.Locations[0], symbol.Name) 
+0

Cette solution a fonctionné comme un charme. Merci beaucoup de partager vos connaissances, vous êtes une âme aimable. :) – CynicalPassion63