我看到你的代碼的幾個問題。
第一個是一個細節,但你說你正在尋找你「使用」的符號。您是否認爲宣稱符號是一種使用的符號?如果沒有,你可以擺脫model.GetDeclaredSymbol(node)
。
第二個問題更爲重要:您經常使用相同的符號。
採取例如以下語句:
SomeMethod();
這是一個ExpressionStatement
節點,withing它有一個InvocationExpression
,並在那裏有一個IdentifierName
。您在這三個節點上都打電話model.GetSymbolInfo(node)
。你應該尋找一種方法來避免這種情況。
如果您只在類型SimpleNameSyntax
(或其後代IdentifierNameSyntax
和GenericNameSyntax
)的節點上調用model.GetSymbolInfo(node)
,您將獲得很多符號。
喜歡的東西:
public static IEnumerable<ISymbol> GetAllSymbols(CSharpCompilation compilation, SyntaxNode root)
{
var noDuplicates = new HashSet<ISymbol>();
var model = compilation.GetSemanticModel(root.SyntaxTree);
foreach (var node in root.DescendantNodesAndSelf())
{
switch (node.Kind())
{
case SyntaxKind.IdentifierName:
case SyntaxKind.GenericName:
ISymbol symbol = model.GetSymbolInfo(node).Symbol;
if (symbol != null && noDuplicates.Add(symbol))
{
yield return symbol;
}
break;
}
}
}
它不會得到所有符號雖然。例如,運營商的符號不會被發現。
這使我想到了第三點:你真的應該考慮你以後的哪些符號。你真的需要所有符號?
即使答案是「是」,也可以通過轉換上述邏輯來避免多次冗餘查找的情況。
例如:
public static IEnumerable<ISymbol> GetAllSymbols(CSharpCompilation compilation, SyntaxNode root)
{
var noDuplicates = new HashSet<ISymbol>();
var model = compilation.GetSemanticModel(root.SyntaxTree);
foreach (var node in root.DescendantNodesAndSelf())
{
switch (node.Kind())
{
case SyntaxKind.ExpressionStatement:
case SyntaxKind.InvocationExpression:
break;
default:
ISymbol symbol = model.GetSymbolInfo(node).Symbol;
if (symbol != null)
{
if (noDuplicates.Add(symbol))
yield return symbol;
}
break;
}
}
}
在該套色我濾出只從上面的例子中的ExpressionStatement
和InvocationExpression
。還有更多的你可以安全地過濾出來,但是我把它作爲你的鍛鍊。
是的。你爲每個節點調用GetSymbolInfo,但我懷疑你需要這個。例如,當你有一個使用聲明,比如'using System.Collections.Generic;',你真的需要System和System.Collections命名空間的符號嗎?所以開始考慮你需要什麼符號。 –