TWT*_*TWT 2 c# roslyn roslyn-code-analysis
我正在使用以下代码来检索代码块中使用的所有符号。这包括声明和对符号的引用。不幸的是,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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我发现您的代码有几个问题。
第一个是一个细节,但是您说您正在寻找“使用”的符号。您是否认为将符号声明为使用符号的一种?如果没有,您可以摆脱model.GetDeclaredSymbol(node)。
第二个问题更为重要:您过于频繁地获得相同的符号。
以下面的语句为例:
SomeMethod();
Run Code Online (Sandbox Code Playgroud)
那是一个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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
它不会获得所有符号。例如,找不到用于运算符的符号。
这就是我要讲的第三点:您确实应该考虑要使用的符号。您真的需要所有符号吗?
即使答案是“是”,您也可以通过扭转上述逻辑来避免许多冗余查找。
例如:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我仅从上面的示例中过滤了ExpressionStatement和InvocationExpression。您可以安全地过滤掉更多的内容,但是我将其留给您练习。
| 归档时间: |
|
| 查看次数: |
1064 次 |
| 最近记录: |