我怎样才能访问Roslyn的退货商品?

时间:2016-01-28 17:37:23

标签: c# compiler-warnings roslyn

在我们开发自定义独立代码分析以帮助开发人员根据VS中的最佳实践编写C#代码时,我们正在使用Roslyn及其功能。

我们的一个要求有点棘手,我们需要解析和编译一个有下面概念问题的方法:

var myVariable = SomeExpression...; 
return myVariable; 

这意味着如果定义了一个变量,然后立即返回并且再也没有使用过,[GCop] [1]应警告开发人员并说变量声明是不必要的。

 protected override void Analyze(SyntaxNodeAnalysisContext context)
    {
        NodeToAnalyze = context.Node;

        var varDeclareSyntax = (LocalDeclarationStatementSyntax)NodeToAnalyze;
        if (varDeclareSyntax == null) return;

        var variableDeclare = varDeclareSyntax.ChildNodes().OfType<VariableDeclarationSyntax>().FirstOrDefault();
        if (variableDeclare == null) return;

        var varDeclarator = variableDeclare.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault();
        if (varDeclarator == null) return;

        var identifierToken = varDeclarator.Identifier.Text;


        var method = varDeclarator.GetSingleAncestor<MethodDeclarationSyntax>();

        var varDeclaratorIndex = method.DescendantNodes().OfType<CSharpSyntaxNode>().IndexOf(varDeclarator);
  /// ??????? TO DO :

现在我们可以访问node =&gt; (var item = 10;) 问题是我们如何能够准确访问下一行 return item;

enter image description here

我找到了myVariable语法节点及其值,但我不知道如何能够找到返回的 Identider

2 个答案:

答案 0 :(得分:2)

LocalDeclarationStatement包含在一个更大的语法节点中,并且是ReturnStatementSyntax.的兄弟。你的分析真的不应该从LocalDeclarationStatement开始 - 从BlockSyntax或其他东西开始然后寻找声明和从那里返回。

尝试这种方法的另一种方法是首先找到ReturnStatementSyntax ,一旦你看到它返回一个简单变量,你就可以调用SemanticModel.GetSymbolInfo()来查找符号,然后从该符号转到定义它的语法。从那里你可以看到它们是否是并排的。

答案 1 :(得分:0)

希望完成......这是我的代码

 protected override void Analyze(SyntaxNodeAnalysisContext context)
        {
            NodeToAnalyze = context.Node;

        var varDeclareSyntax = (LocalDeclarationStatementSyntax)NodeToAnalyze;
        if (varDeclareSyntax == null) return;

        var variableDeclare = varDeclareSyntax.ChildNodes().OfType<VariableDeclarationSyntax>().FirstOrDefault();
        if (variableDeclare == null) return;

        var varDeclarator = variableDeclare.ChildNodes().OfType<VariableDeclaratorSyntax>().FirstOrDefault();
        if (varDeclarator == null) return;

        //var identifierToken = varDeclarator.Identifier.Text; //  <- here we find [item] in ( var item=expression; )

        var method = varDeclarator.GetSingleAncestor<MethodDeclarationSyntax>();

        var varDeclaratorIndex = method.DescendantNodes().OfType<CSharpSyntaxNode>().IndexOf(varDeclarator);

        var allNodes = method.DescendantNodes().OfType<CSharpSyntaxNode>().Select((node, index) => new Node
        {
            Index = index,
            Syntax = node,
            Location = node.GetLocation(),
            Kind = node.Kind(),
            Ancestors = node.Ancestors()
        }).ToArray();

        var maxIndex = allNodes.Where(it => it.Ancestors.Any(x => x == varDeclarator)).Max(it => it.Index.Value);

        if (maxIndex >= allNodes.Length) return;

        var nextReturn = allNodes[maxIndex + 1];

        if (nextReturn.Kind != SyntaxKind.ReturnStatement) return;

        var @return = nextReturn.Syntax as ReturnStatementSyntax;

        if ((@return.Expression as IdentifierNameSyntax)?.Identifier.ValueText == varDeclarator.Identifier.ValueText)
        {
            ReportDiagnostic(context, varDeclareSyntax);
        }
    }

    protected override RuleDescription GetDescription()
    {
        return new RuleDescription
        {
            ID = "176",
            Category = Category.Design,
            Message = "Variable declaration is unnecessary due to it used only for return statement"
        };
    }

    private class Node : NodeDefinition
    {
        public IEnumerable<SyntaxNode> Ancestors { get; set; }
        public SyntaxNode Syntax { get; set; }
        public SyntaxKind Kind { get; set; }
    }