我使用以下代码检索代码块中使用的所有符号。这包括声明和符号引用。 不幸的是,GetSymbolInfo调用非常慢,因此这个方法花费的总时间可能很长。有没有办法加快速度呢?
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())
{
ISymbol symbol = model.GetDeclaredSymbol(node) ??
model.GetSymbolInfo(node).Symbol;
if (symbol != null)
{
if (noDuplicates.Add(symbol))
yield return symbol;
}
}
}
答案 0 :(得分:4)
我发现您的代码存在一些问题。
第一个是一个细节,但你说你正在寻找你“使用”的符号。您是否认为使用符号将符号声明为?如果没有,你可以摆脱model.GetDeclaredSymbol(node)
。
第二个问题更为重要:你经常得到相同的符号。
以下面的陈述为例:
SomeMethod();
这是一个ExpressionStatement
节点,其中有一个InvocationExpression
,其中有一个IdentifierName
。您在所有这三个节点上调用model.GetSymbolInfo(node)
。你应该寻找一种避免这种情况的方法。
如果您只在类型model.GetSymbolInfo(node)
(或其后代,SimpleNameSyntax
和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;
}
}
}
但它不会获得所有符号。例如,找不到运算符的符号。
这让我想到了第三点:你真的应该考虑你追求的符号。你真的需要所有符号吗?
即使答案是“是”,通过改变上述逻辑,你可以避免许多冗余查找的情况。
例如:
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
。还有更多你可以安全地过滤掉,但我把它作为练习留给你。