2015-09-15 6 views
6

Zazwyczaj nazwy przestrzeni nazw w rozwiązaniu C# są takie, że pasują do domyślnego obszaru nazw dla projektu oraz nazwy wszystkich podkatalogów dla pliku zawierającego.Czy analizator może sprawdzić, czy przestrzenie nazw są zgodne z lokalizacją pliku?

Na przykład, plik o nazwie Haddock.cs jest w katalogu o nazwie Fish i domyślnej przestrzeni nazw (w pierwszej zakładce właściwości projektu w VS) jest Lakes następnie plik powinien zawierać coś jak

The StyleCop analyzers Projekt zawiera ładną regułę, która sprawdza, czy nazwa klasy pasuje do nazwy pliku.

Czy istnieje sposób na napisanie reguły, która weryfikuje, czy nazwa przestrzeni nazw jest poprawna?

Odpowiedz

5

Dostęp do ścieżki pliku można uzyskać od SyntaxTreeAction przy użyciu Tree.FilePath off of SyntaxTreeContext.

Po uzyskaniu ścieżki można następnie przeanalizować i porównać ją z nazwą wszystkich nazw węzłów NamesSpaceDeclarationSyntax w drzewie.

Niestety, nie sądzę, że istnieje sposób, aby uzyskać dostęp do domyślnej przestrzeni nazw dla projektu w tym czasie.

Oto krótka próbka, którą zrzuciłem, która robi to, co może. Przetwarzanie/porównywanie ścieżki do przestrzeni nazw jest prymitywne i prawdopodobnie istnieje lepszy sposób na zrobienie tego, ale to powinno zacząć.

public override void Initialize(AnalysisContext context) 
{ 
    context.RegisterCompilationStartAction((compilationSyntax) => 
    { 
     compilationSyntax.RegisterSyntaxTreeAction((syntaxTreeContext) => 
     { 
      var semModel = compilationSyntax.Compilation.GetSemanticModel(syntaxTreeContext.Tree); 
      var filePath = syntaxTreeContext.Tree.FilePath; 

      if (filePath == null) 
       return; 

      var namespaceNodes = syntaxTreeContext.Tree.GetRoot().DescendantNodes().OfType<NamespaceDeclarationSyntax>(); 
      var parentDirectory = System.IO.Path.GetDirectoryName(filePath); 

      // This will only work on windows and is not very robust. 
      var parentDirectoryWithDots = parentDirectory.Replace("\\", ".").ToLower(); 

      foreach (var ns in namespaceNodes) 
      { 
       var symbolInfo = semModel.GetDeclaredSymbol(ns) as INamespaceSymbol; 
       var name = symbolInfo.ToDisplayString(); 

       if (!parentDirectoryWithDots.EndsWith(name.ToLower().Trim())) 
       { 
        syntaxTreeContext.ReportDiagnostic(Diagnostic.Create(
         Rule, ns.Name.GetLocation(), parentDirectoryWithDots)); 
       } 
      } 
     }); 
    }); 
} 
+1

To nie sprawdzi zagnieżdżonych deklaracji 'namespace'. – SLaks

+0

@SLaks Nice catch, naprawiony. –

+1

To wciąż jest złe; 'ns.Name' nie zawiera zewnętrznych bloków. – SLaks