コードにいくつかの問題があります。
最初のものは細部ですが、あなたが使用しているシンボルを探しているとします。 はのシンボルをのシンボルの一種、を使用して宣言していますか?そうでない場合は、model.GetDeclaredSymbol(node)
を取り除くことができます。
第2の問題は、もっと重要です。あなたは同じシンボルをあまりにも頻繁に使用しています。
例えば次の文を取る:
SomeMethod();
InvocationExpression
があり、そこにIdentifierName
があり、それをwithing、ExpressionStatement
ノードであること。これらのノードの3つすべてに対してmodel.GetSymbolInfo(node)
を呼び出しています。それを避ける方法を探してください。
あなただけのタイプSimpleNameSyntax
のノード上model.GetSymbolInfo(node)
(またはその子孫、IdentifierNameSyntax
とGenericNameSyntax
)と呼ばれる場合は、多くのシンボルになるだろう。
ような何か:
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;
}
}
}
それはしかしすべてシンボルを取得しないでしょう。たとえば、演算子のシンボルが見つかりません。
それは私の3番目のポイントにつながります。本当にあなたは後になっているシンボルを考慮する必要があります。あなたは本当にすべてシンボルが必要ですか?
答えが「はい」であっても、上記のロジックを回すことで、冗長検索の多くのケースを避けることができます。例えば
:ケーシング本で
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;
}
}
}
Iは、上記の例からのみExpressionStatement
とInvocationExpression
を濾過しました。あなたが安全に除外できることはもっとたくさんありますが、私はそれをあなたのための運動として残しています。
はい。すべてのノードでGetSymbolInfoを呼び出していますが、必要があるかどうかは疑問です。例えば、using System.Collections.Generic;のような宣言を使用している場合、SystemとSystem.Collectionsの名前空間のシンボルが本当に必要ですか?だからあなたが必要とするシンボルについて考え始める。 –