给出MethodDeclarationSyntax
的列表,我想收集可传递调用此方法的解决方案中的所有方法。
我一直在使用以下代码:
var methods = new Stack<MethodDeclarationSyntax>();
... // fill methods with original method to start from
var visited = new HashSet<MethodDeclarationSyntax>();
while (methods.Count > 0)
{
var method = methods.Pop();
if (!visited.Add(method))
{
continue;
}
var methodSymbol = (await solution.GetDocument(method.SyntaxTree).GetSemanticModelAsync()).GetDeclaredSymbol(method);
foreach (var referencer in await SymbolFinder.FindCallersAsync(methodSymbol, solution))
{
var callingMethod = (MethodDeclarationSyntax) referencer.CallingSymbol.DeclaringSyntaxReferences[0].GetSyntax();
methods.Push(callingMethod);
}
}
问题在于MethodDeclarationSyntax
似乎不是一个单例,因此此循环永远运行,一次又一次地访问相同的方法。
在字典/哈希集中唯一标识MethodDeclarationSyntax
的正确方法是什么?
编辑1)
作为一种解决方法,我正在使用以下MethodDeclarationSyntaxComparer
初始化我的HashSet
,但是它看起来非常脆弱:
private class MethodDeclarationSyntaxComparer: IEqualityComparer<MethodDeclarationSyntax>
{
public bool Equals(MethodDeclarationSyntax x, MethodDeclarationSyntax y)
{
var xloc = x.GetLocation();
var yloc = y.GetLocation();
return xloc.SourceTree.FilePath == yloc.SourceTree.FilePath &&
xloc.SourceSpan == yloc.SourceSpan;
}
public int GetHashCode(MethodDeclarationSyntax obj)
{
var loc = obj.GetLocation();
return (loc.SourceTree.FilePath.GetHashCode() * 307) ^ loc.SourceSpan.GetHashCode();
}
}
答案 0 :(得分:1)
我想知道是否在这里使用SyntaxNode
是正确的方法。
由于您已经在使用SymbolFinder
并且正在使用语义模型,所以正确的方法也许是实际使用ISymbol
而不是SyntaxNode
。 / p>
ISymbol
已包含您正在使用的SyntaxReference
,因此:
var methods = new Stack<IMethodSymbol>();
... // fill methods with original method to start from
... // convert methods to symbols via semanticModel.GetDeclaredSymbol (node);
var visited = new HashSet<IMethodSymbol>();
while (methods.Count > 0)
{
var method = methods.Pop();
if (!visited.Add(method))
{
continue;
}
foreach (var referencer in await SymbolFinder.FindCallersAsync(method, solution))
{
var callingMethod = (MethodDeclarationSyntax) referencer.CallingSymbol.DeclaringSyntaxReferences[0].GetSyntax();
methods.Push(callingMethod);
}
}
您可以将访问的哈希集设为Dictionary<IMethodSymbol, IEnumerable<Location>>
,并合并所有位置,从而从该结果中重构语法。