2017-05-24 49 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); 
相关问题