给出一个列表,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);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是MethodDeclarationSyntax看起来不是单身,所以这个循环永远在运行,一次又一次地访问相同的方法.
MethodDeclarationSyntax在Dictionary/Hashset中唯一标识a的正确方法是什么?
编辑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();
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道使用SyntaxNode这里是否是正确的方法。
既然您已经在使用SymbolFinder并且正在使用语义模型,也许正确的方法是实际使用ISymbols,而不是SyntaxNodes。
ISymbol已经包含SyntaxReference您正在使用的 s,因此:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将访问的哈希集放入Dictionary<IMethodSymbol, IEnumerable<Location>>,并连接所有位置,从而根据该结果重建语法。