我怎样才能访问 Roslyn 中的 return 项?

How can I have access to return item in Roslyn?

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

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

var myVariable = SomeExpression...; 
return myVariable; 

这意味着如果定义了一个变量,然后立即return编辑并且不再使用,[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 :

现在我们可以访问节点 => (var item = 10;) 问题是我们如何才能准确访问下一行 return item;

我找到了 myVariable Syntax 节点及其值,但我不知道如何找到 return Identider excatly

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

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

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

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