2012-06-29 24 views
13

posso ottenere una lista dalla soluzione di tutte le chiamate a un metodo particuliar utilizzando il seguente codice:Come argomenti del metodo con Roslyn

var createCommandList = new List<MethodSymbol>(); 
INamedTypeSymbol interfaceSymbol = 
    (from p 
    in solution.Projects 
    select p.GetCompilation().GetTypeByMetadataName(
     "BuySeasons.BsiServices.DataResource.IBsiDataConnection") 
    ).FirstOrDefault(); 
foreach (ISymbol symbol in interfaceSymbol.GetMembers("CreateCommand")) 
{ 
    if (symbol.Kind == CommonSymbolKind.Method 
     && symbol is MethodSymbol) 
    { 
     createCommandList.Add(symbol as MethodSymbol); 
    } 
} 
foreach (MethodSymbol methodSymbol in createCommandList) 
{ 
    foreach (ReferencedSymbol referenceSymbol 
     in methodSymbol.FindReferences(solution)) 
    { 
     foreach (ReferenceLocation referenceLocation 
      in from l 
       in referenceSymbol.Locations 
       orderby l.Document.FilePath 
       select l) 
     { 
      if (referenceLocation.Location.GetLineSpan(false) 
        .StartLinePosition.Line == 
       referenceLocation.Location.GetLineSpan(false) 
        .EndLinePosition.Line) 
      { 
       Debug.WriteLine("{0} {1} at {2} {3}/{4} - {5}", 
        methodSymbol.Name, 
        "(" + String.Join(",", 
         (from p 
         in methodSymbol.Parameters 
         select p.Type.Name + " " + p.Name).ToArray() 
         ) + ")", 
       Path.GetFileName(referenceLocation.Location.GetLineSpan(false) 
        .Path), 
       referenceLocation.Location.GetLineSpan(false) 
        .StartLinePosition.Line, 
       referenceLocation.Location.GetLineSpan(false) 
        .StartLinePosition.Character, 
       referenceLocation.Location.GetLineSpan(false) 
        .EndLinePosition.Character)); 
      } 
      else 
      { 
       throw new ApplicationException("Call spans multiple lines"); 
      } 
     } 
    } 
} 

Ma questo mi dà un elenco di ReferencedSymbol. Anche se questo mi dà il numero di file e di riga che il metodo è chiamato da vorrei anche ottenere gli argomenti specifici con cui viene chiamato il metodo. Come posso convertire quello che ho o ottenere le stesse informazioni con Roslyn? (Notare che prima carico la soluzione con il metodo Solution.Load e quindi faccio il loop per scoprire dove il metodo è definito/dichiarato (createCommandList)).

risposta

0

È possibile cercare l'albero di sintassi del riferimento nella posizione di origine specifica in cui si trova per trovare il nodo che si sta cercando. Dovrai utilizzare una chiamata come DescendentNodes dal nodo radice dell'albero e probabilmente dovrai richiedere il tipo di nodo specifico per la lingua che stai cercando. Una volta che hai il nodo nella struttura di riferimento, puoi usare il modello semantico di quell'albero per dirti altre informazioni sugli argomenti.

2

Stai già utilizzando Roslyn qui. Quando hai un referenceSymbol, puoi ottenere la sintassi della dichiarazione dei metodi e poi guardare in basso nell'albero per ottenere l'elenco dei parametri.

ho inserito una variabile arguments che utilizza il referenceSymbol:

// Snip start 
foreach (MethodSymbol methodSymbol in createCommandList) 
{ 
    foreach (ReferencedSymbol referenceSymbol 
     in methodSymbol.FindReferences(solution)) 
    { 
     var arguments = referenceSymbol.Definition.DeclaringSyntaxNodes.First() 
      .DescendantNodes().OfType<ParameterSyntax>().ToList(); 

     foreach (ReferenceLocation referenceLocation in 
      from l 
      in referenceSymbol.Locations 
      orderby l.Document.FilePath 
      select l) 
     { 
// Snip end 

Quando si esegue un output di debug, è possibile quindi utilizzare tale elenco di argomenti per ottenere i nomi.

La mia soluzione richiede di ottenere il First() del DeclaringSyntaxNodes, che non mi piace molto ma non riesco a trovare un altro modo per ottenere i nodi discendenti dell'albero Syntax.

0

Ho scoperto un altro modo per ottenere l'elenco dei parametri da un metodo che potrebbe funzionare anche per gli altri.

Dire che ho il seguente metodo che ha due parametri:

public string DebugPage(string enabled, string show){ 
    //do stuff 
} 

poi si arriva nodi tuttavia si desidera. Per esempio, questo mi dà un elenco dei metodi pubblici:

IEnumerable<MethodDeclarationSyntax> methods = from m in root.DescendantNodes().OfType<MethodDeclarationSyntax>() where m.Modifiers.ToString().Contains("public") select m; 

allora posso scorrere quella lista di metodi per arrivare alla proprietà del metodo di ParameterList che è esposto per rendere questa operazione molto semplice. Alla fine di questo ciclo lista parameters conterrà i nomi di ciascun parametro nel metodo (nell'esempio del metodo Debug soprastante contenere i valori enabled e show come previsto):

var parameters = new List<string>(); 

foreach (var method in methods) 
{ 
    foreach (var n in method.ParameterList.Parameters) 
    { 
    var parameterName = n.Identifier.Text; 
    parameters.Add(parameterName); 
    } 
} 
Problemi correlati