2012-06-29 116 views
13

獲取方法的參數,我可以使用下面的代碼到particuliar方法的所有調用的解決方案中獲得的列表:與羅斯林

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"); 
      } 
     } 
    } 
} 

但是這給了我的ReferencedSymbol列表。雖然這給了我調用該方法的文件和行號,但我還想獲取調用方法的特定參數。我怎樣才能將我擁有的信息或與Roslyn獲取相同的信息? (請注意,我首先使用Solution.Load方法加載解決方案,然後循環查找方法的定義/聲明位置(createCommandList))。

回答

0

您可以搜索它所在的特定源位置處的引用的語法樹,以查找您正在查找的節點。您需要在樹的根節點中使用類似DescendentNodes的調用,並且您可能需要請求您正在查找的特定於語言的節點類型。一旦在參照樹中有節點,就可以使用該樹的語義模型來告訴你有關參數的其他信息。

2

您已經在這裏使用Roslyn。當你有一個referenceSymbol時,你可以得到方法聲明語法,然後往下查看樹來獲取參數列表。

我插入使用您referenceSymbol一個arguments變量:

// 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 

當您執行調試輸出,可以再使用的參數該列表以獲得名稱。

我的解決方案需要獲得DeclaringSyntaxNodesFirst(),我不太喜歡它,但無法找到另一種方法來獲取語法樹的後代節點。

0

我發現了另一種從可能適用於其他方法的方法獲取參數列表的方法。

說我有下面的方法有兩個參數:

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

然後你得到你的節點按照自己的喜好。例如,這給我的公共方法列表:

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

然後我就可以通過方法該列表進行迭代,以獲得在該方法的這暴露,使這個操作很容易ParameterList財產。通過該循環的結束清單parameters將持有的每個參數的名稱在方法(在Debug方法的上述示例中,將保存的值enabledshow如預期):

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