2017-04-18 33 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)

第二個問題更爲重要:您經常使用相同的符號。

採取例如以下語句:

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; 
     } 
    } 
} 

在該套色我濾出只從上面的例子中的ExpressionStatementInvocationExpression。還有更多的你可以安全地過濾出來,但是我把它作爲你的鍛鍊。

相關問題