2017-05-24 46 views
1

我正在嘗試編寫分析器,我需要使用Roslyn查找對字段所做的所有分配。Roslyn查找對字段所做的所有分配

private async static Task<bool> VariableDoesNotMutate(SyntaxNodeAnalysisContext context, VariableDeclaratorSyntax firstVariable) 
{ 
    var variableSymbol = context.SemanticModel.GetDeclaredSymbol(firstVariable); 
    var references = await SymbolFinder.FindReferencesAsync(variableSymbol, context.GetSolution()); 

    foreach (var reference in references) 
    { 
     //How do I check for assignment? 
    } 

    //need to filter by assignments 
    return references.Count() > 1; 
} 

我聽說使用symbolFinder是正確的,但我不知道如何做到這一點。
符號查找器需要一個解決方案,我只能通過黑客訪問,所以我假設有另一種方法來做到這一點。

問題:

  1. 當我試圖找到只返回一個聲明我沒有找到任何其他引用我如何可以解決此一變量的所有引用?

  2. 一旦我有一個參考如何確定它是否是一項任務?

+1

你可能錯了'Solution'例如搜索。 – SLaks

+0

@SLaks如何使用查找所有賦值給符號,當分析器沒有公共方法來找到解決方案? –

+0

由於性能原因,您不能/不應該那樣做。 – SLaks

回答

0

我最初找不到任何參考文獻,因爲我的文檔不是正確的解決方案。分析器不能爲您提供一種方法來獲得解決方案,並且@SLaks認爲性能原因不應該這樣做:

獲取解決方案您需要反映到AnalyzerOptions中我已經寫了一個答案如何這樣做here

但是,如果您需要,您可以執行此操作獲取解決方案中的等效符號並解決此問題。這是潛在的危險

static async Task<ISymbol> GetEquivalentSymbol(SyntaxNodeAnalysisContext context, FieldDeclarationSyntax field, CancellationToken cancellationToken) 
{ 
    var solution = context.GetSolution(); 
    var classDeclaration = field.Ancestors().OfType<ClassDeclarationSyntax>().FirstOrDefault(); 
    var namespaceDeclaration = field.Ancestors().OfType<NamespaceDeclarationSyntax>().FirstOrDefault(); 

    var className = classDeclaration?.Identifier.ValueText; 

    var initialVariable = field.Declaration.Variables.FirstOrDefault(); 

    foreach (var project in solution.Projects) 
    { 
     foreach (var document in project.Documents) 
     { 
      var semanticModel = await document.GetSemanticModelAsync(cancellationToken); 
      var root = await document.GetSyntaxRootAsync(cancellationToken); 
      if (null != namespaceDeclaration) 
      { 
       var namespaceNode = root.DescendantNodes().OfType<NamespaceDeclarationSyntax>() 
        .FirstOrDefault(node => node.Name.ToString() == namespaceDeclaration.Name.ToString()); 
       if (null == namespaceNode) 
       { 
        continue; 
       } 
      } 

      var classNode = root.DescendantNodes() 
       .OfType<ClassDeclarationSyntax>() 
       .FirstOrDefault(node => node.Identifier.ValueText == className); 

      var desiredField = classNode?.DescendantNodes().OfType<FieldDeclarationSyntax>() 
       .FirstOrDefault(x => x.Declaration.Variables.First().Identifier.ValueText == initialVariable.Identifier.ValueText); 

      if (desiredField == null) 
      { 
       continue; 
      } 

      var symbol = semanticModel.GetDeclaredSymbol(desiredField.Declaration.Variables.FirstOrDefault()); 
      return symbol; 
     } 
    } 

    return null; 
} 

然後你就可以得到引用,像這樣:

var equivalentSymbol = await GetEquivalentSymbol(context, field, cancellationToken); 

var references = await SymbolFinder.FindReferencesAsync(equivalentSymbol, context.GetSolution(), cancellationToken); 
相關問題