2017-04-18 7 views
0

다음 코드를 사용하여 코드 블록에서 사용되는 모든 기호를 검색하고 있습니다. 여기에는 선언 및 기호에 대한 참조가 포함됩니다. 불행히도 GetSymbolInfo 호출은 매우 느리며이 때문에이 메서드에 소요되는 총 시간이 길어질 수 있습니다. 이 속도를 높이는 방법이 있습니까?Roslyn - 모든 기호 찾기

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

예. 모든 노드에 대해 GetSymbolInfo를 호출하고 있지만 필요는 없는지 의심 스럽습니다. 예를 들어, using using System.Collections.Generic;과 같은 선언을 사용하면 System 및 System.Collections 네임 스페이스에 대한 심볼이 실제로 필요합니까? 그래서 당신이 필요로하는 상징에 대해 생각하기 시작하십시오. –

답변

0

코드에 몇 가지 문제가 있습니다.

첫 번째 부분은 세부 사항이지만 약간 "사용하는"기호를 찾고 있다고합니다. 당신은 상징을 일종의 로 표기한다고 생각하십니까? 기호를 사용하고 있습니까? 그렇지 않은 경우 model.GetDeclaredSymbol(node)을 제거 할 수 있습니다.

두 번째 문제는 훨씬 더 중요합니다. 동일한 기호를 너무 자주 사용하고 있습니다. 예를 들어

테이크 다음과 같은 성명 :

SomeMethod(); 

ExpressionStatement 노드가, 그것은 withing에하는 것은 InvocationExpression이 거기에 IdentifierName있다. 세 노드 모두에 model.GetSymbolInfo(node)을 호출합니다. 이를 피하는 방법을 찾아야합니다. 당신은 단지 유형 SimpleNameSyntax (또는 그 후손, IdentifierNameSyntaxGenericNameSyntax)의 노드에 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 위의 예에서와 만 ExpressionStatementInvocationExpression을 여과 하였다. 당신이 안전하게 걸러 낼 수있는 것들이 더 많이 있지만, 나는 그것을 당신을위한 운동으로 남겨 둡니다.