2017-04-18 5 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 System.Collections.Generic;のような宣言を使用している場合、SystemとSystem.Collectionsの名前空間のシンボルが本当に必要ですか?だからあなたが必要とするシンボルについて考え始める。 –

答えて

0

コードにいくつかの問題があります。

最初のものは細部ですが、あなたが使用しているシンボルを探しているとします。 のシンボルをのシンボルの一種、を使用して宣言していますか?そうでない場合は、model.GetDeclaredSymbol(node)を取り除くことができます。

第2の問題は、もっと重要です。あなたは同じシンボルをあまりにも頻繁に使用しています。

例えば次の文を取る:

SomeMethod(); 

InvocationExpressionがあり、そこにIdentifierNameがあり、それをwithing、ExpressionStatementノードであること。これらのノードの3つすべてに対してmodel.GetSymbolInfo(node)を呼び出しています。それを避ける方法を探してください。

あなただけのタイプSimpleNameSyntaxのノード上model.GetSymbolInfo(node)(またはその子孫、IdentifierNameSyntaxGenericNameSyntax)と呼ばれる場合は、多くのシンボルになるだろう。

ような何か:

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は、上記の例からのみExpressionStatementInvocationExpressionを濾過しました。あなたが安全に除外できることはもっとたくさんありますが、私はそれをあなたのための運動として残しています。

関連する問題