코드에 몇 가지 문제가 있습니다.
첫 번째 부분은 세부 사항이지만 약간 "사용하는"기호를 찾고 있다고합니다. 당신은 을 상징을 일종의 로 표기한다고 생각하십니까? 기호를 사용하고 있습니까? 그렇지 않은 경우 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;
}
}
}
I 위의 예에서와 만 ExpressionStatement
InvocationExpression
을 여과 하였다. 당신이 안전하게 걸러 낼 수있는 것들이 더 많이 있지만, 나는 그것을 당신을위한 운동으로 남겨 둡니다.
예. 모든 노드에 대해 GetSymbolInfo를 호출하고 있지만 필요는 없는지 의심 스럽습니다. 예를 들어, using using System.Collections.Generic;과 같은 선언을 사용하면 System 및 System.Collections 네임 스페이스에 대한 심볼이 실제로 필요합니까? 그래서 당신이 필요로하는 상징에 대해 생각하기 시작하십시오. –