2015-08-03 10 views
7

W jaki sposób uzyskujesz dostęp do ścieżki pliku do projektu/rozwiązania kompilowanego wewnątrz analizatora kodów Roslyn? Muszę zweryfikować kod względem niektórych plików spec przechowywanych względem kodu. Rzeczy, które nie działają:Jak uzyskać ścieżkę rozwiązania w analizatorze kodu .NET

SyntaxTreeAnalysisContext.Tree.FilePath 
Assembly.GetExecutingAssembly().Location 
AppDomain.CurrentDomain.BaseDirectory 
Environment.CurrentDirectory 
Path.GetFullPath(relativePath) 
+0

Roslyn Analizatory istnieje poniżej warstwy obszaru roboczego; rozwiązanie może faktycznie nie istnieć. – SLaks

+0

Więc jest to niemożliwe z definicji? –

+0

Jeśli będziesz bardzo się starał, prawdopodobnie sprawisz, że będzie działał tylko w VS (spróbuj uzyskać SComponentModel od globalnego providera serwisów, a następnie przechwyć Roslyn VisualStudioWorkspace). Jednak będzie to kruche i nie zadziała w ogóle poza VS. – SLaks

Odpowiedz

3

Analizatory istnieć poniżej poziomu Workspace (są uruchamiane bezpośrednio przez kompilator), więc rozwiązanie nie może istnieć.

Ze skomplikowanych powodów nie są one tworzone przez MEF, więc nie ma łatwego sposobu na uzyskanie dostępu do niego, nawet jeśli istnieje.

Od wewnątrz VS można znaleźć globalnego dostawcę usług (np ServiceProvider.GlobalProvider), a następnie uzyskać SComponentModel (korzeń własnego MEF wykresie VS) i chwycić Roslyn za VisualStudioWorkspace z tego. Uważaj, że jest to dość kruche podejście i nie będzie działać wcale poza VS.

Nawet w ramach VS, będzie to dziwne sposoby analizowania w panelach podglądu, plikach dodatkowych i innych kontekstach, które nie są częścią rozwiązania globalnego.

0

Oto inne podejście, które działa bez VS; również kruche, ale z różnych powodów. :)

Znajdź csproj na poziomie pliku, wyszukując w górę hierarchię folderów zaczynając od ścieżki pliku źródłowego drzewa składni aktualnej.

Oczywiście nie zadziała w pewnych okolicznościach (jeśli plik źródłowy znajduje się poza poddrzewem folderu csproj, np. Połączone pliki lub są inne nieaktualne pliki csproj itp.) Jedyne bezpieczeństwo net Mogłabym myśleć o sprawdzeniu, czy znaleziony csproj jest rzeczywiście dla tej samej nazwy zespołu, do której odnosi się aktualna nazwa SemanticModel.Compilation.AssemblyName, więc nie skończymy z csprojem jakiegoś innego losowego projektu.

Oto kod, zobacz metodę zwaną FindProjectFile: https://nsdepcop.codeplex.com/SourceControl/changeset/view/75896#VS2015/source/NsDepCop.VisualStudioIntegration/ProjectAnalyzerRepository.cs

2

to nie jest możliwe, aby uzyskać roztwór z analizatora lub utrwalacza bez refleksji.

Użyj ustawienia additional files, aby zapisać ustawienia.

W projekcie:

<ItemGroup> 
    <AdditionalFiles Include="MyConfig.config" /> 
</ItemGroup> 

W analizatorze:

private const string ConfigFileName = "MyConfig.config"; 

private static string LoadConfig(ImmutableArray<AdditionalText> additionalFiles, CancellationToken cancellationToken) 
{ 
    var file = additionalFiles.SingleOrDefault(f => string.Compare(Path.GetFileName(f.Path), ConfigFileName, StringComparison.OrdinalIgnoreCase) == 0); 
    if (file == null) 
    { 
     return null; 
    } 

    var fileText = file.GetText(cancellationToken); 

    using (var stream = new MemoryStream()) 
    { 
     using (StreamWriter writer = new StreamWriter(stream, Encoding.UTF8, 1024, true)) 
     { 
      fileText.Write(writer, cancellationToken); 
     } 

     stream.Position = 0; 

     using (var reader = new StreamReader(stream)) 
     { 
      return reader.ReadToEnd(); 
     } 
    } 
} 

private static void HandleCompilationStart(CompilationStartAnalysisContext context) 
{ 
    var config = LoadConfig(context.Options.AdditionalFiles, context.CancellationToken); 
} 
+1

WorkspaceAnalyzerOptions jest wewnętrzna, jak to zrobić. –

+0

Masz rację, nie jest to możliwe. Edytowałem odpowiedź. –

+0

Dzięki za odpowiedź w ten sposób początkowo znalazłem sposób, aby to zrobić przez polowanie. Opublikuję odpowiedź w nieco –

0

ja wymyśliliśmy sposób, aby to zrobić poprzez odbicie, mam tylko przetestowane w środowisku Windows.

public static class RoslynExtensions 
{ 
    public static Solution GetSolution(this SyntaxNodeAnalysisContext context) 
    { 
     var workspace = context.Options.GetPrivatePropertyValue<object>("Workspace"); 
     return workspace.GetPrivatePropertyValue<Solution>("CurrentSolution"); 
    } 

    public static T GetPrivatePropertyValue<T>(this object obj, string propName) 
    { 
     if (obj == null) 
     { 
      throw new ArgumentNullException(nameof(obj)); 
     } 

     var pi = obj.GetType().GetRuntimeProperty(propName); 

     if (pi == null) 
     { 
      throw new ArgumentOutOfRangeException(nameof(propName), $"Property {propName} was not found in Type {obj.GetType().FullName}"); 
     } 

     return (T)pi.GetValue(obj, null); 
    } 
} 

wywołany z analizatorem tak:

public override void Initialize(AnalysisContext context) 
{ 
    context.RegisterSyntaxNodeAction(AnalyzeConstDeclaration, SyntaxKind.FieldDeclaration); 
} 

public static void AnalyzeConstDeclaration(SyntaxNodeAnalysisContext context) 
{ 
    var solution = context.GetSolution(); 
} 
+0

Ktoś chce wyjaśnić –

Powiązane problemy