2012-06-29 9 views
13

que puedo conseguir una lista de la solución de todas las llamadas a un método particuliar utilizando el siguiente código:Obtención de los argumentos del método 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"); 
      } 
     } 
    } 
} 

Pero esto me da una lista de ReferencedSymbol. Aunque esto me da el número de archivo y línea desde el que se llama al método, también me gustaría obtener los argumentos específicos con los que se llama al método. ¿Cómo puedo convertir lo que tengo u obtener la misma información con Roslyn? (observe que primero cargo la solución con el método Solution.Load y luego recorro para descubrir dónde se define/declara el método (createCommandList)).

Respuesta

0

Puede buscar el árbol de sintaxis de la referencia en la ubicación de origen específica para encontrar el nodo que está buscando. Tendrá que usar una llamada como DescendentNodes desde el nodo raíz del árbol y probablemente necesite solicitar el tipo de nodo específico del idioma que está buscando. Una vez que tienes el nodo en el árbol de referencia, puedes usar el modelo semántico de ese árbol para contarte otra información sobre los argumentos.

2

Ya estás usando Roslyn aquí. Cuando tenga un referenceSymbol, puede obtener la sintaxis de declaración de métodos y luego mirar hacia abajo en el árbol para obtener la lista de parámetros.

he insertado una variable arguments que utiliza su 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 

Al realizar una salida de depuración, a continuación, puede utilizar esa lista de argumentos para obtener los nombres.

Mi solución requiere obtener el First() del DeclaringSyntaxNodes, que no me gusta mucho pero no puedo encontrar otra forma de llegar a los Nodos Descendientes del Árbol de Sintaxis.

0

He descubierto otra forma de obtener la lista de parámetros de un método que también podría funcionar para otros.

Decir que tengo el siguiente método que tiene dos parámetros:

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

Entonces usted consigue sus nodos como desee. Por ejemplo, esto me da una lista de métodos públicos:

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

Entonces puede iterar a través de la lista de métodos para llegar a ParameterList propiedad del método que se expone a realizar esta operación muy fácil. Al final de este bucle la lista parameters sostendrá los nombres de cada parámetro en el método (en el ejemplo del método Debug anteriormente que llevará a cabo los valores enabled y show como se esperaba):

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); 
    } 
} 
Cuestiones relacionadas