private static bool ContainsAwaitExpression(SyntaxNode node)
        {
            RemoveRedundantAsyncAwaitWalker walker = RemoveRedundantAsyncAwaitWalkerCache.GetInstance(node.Span, stopOnFirstAwaitExpression: true);

            walker.Visit(node);

            bool result = walker.AwaitExpressions.Count == 1;

            RemoveRedundantAsyncAwaitWalkerCache.Free(walker);

            return(result);
        }
        private static void Analyze(SyntaxNodeAnalysisContext context, SyntaxNode node, SyntaxToken asyncKeyword, BlockSyntax body)
        {
            SyntaxList <StatementSyntax> statements = body.Statements;

            StatementSyntax statement = statements.LastOrDefault(f => !f.IsKind(SyntaxKind.LocalFunctionStatement));

            if (statement == null)
            {
                return;
            }

            switch (statement.Kind())
            {
            case SyntaxKind.ReturnStatement:
            {
                var returnStatement = (ReturnStatementSyntax)statement;

                AwaitExpressionSyntax awaitExpression = GetAwaitExpression(returnStatement);

                if (awaitExpression == null)
                {
                    return;
                }

                RemoveRedundantAsyncAwaitWalker walker = VisitStatements();

                HashSet <AwaitExpressionSyntax> awaitExpressions = walker.AwaitExpressions;

                if (awaitExpressions.Count == 1)
                {
                    if (VerifyTypes(node, awaitExpression, context.SemanticModel, context.CancellationToken))
                    {
                        ReportDiagnostic(context, asyncKeyword, awaitExpression);
                    }
                }
                else if (awaitExpressions.Count > 1)
                {
                    StatementSyntax prevStatement = statements[statements.IndexOf(returnStatement) - 1];

                    switch (prevStatement.Kind())
                    {
                    case SyntaxKind.IfStatement:
                    {
                        if (VerifyIfStatement((IfStatementSyntax)prevStatement, awaitExpressions.Count - 1, endsWithElse: false) &&
                            VerifyTypes(node, awaitExpressions, context.SemanticModel, context.CancellationToken))
                        {
                            ReportDiagnostic(context, asyncKeyword, awaitExpressions);
                        }

                        break;
                    }

                    case SyntaxKind.SwitchStatement:
                    {
                        if (VerifySwitchStatement((SwitchStatementSyntax)prevStatement, awaitExpressions.Count - 1, containsDefaultSection: false) &&
                            VerifyTypes(node, awaitExpressions, context.SemanticModel, context.CancellationToken))
                        {
                            ReportDiagnostic(context, asyncKeyword, awaitExpressions);
                        }

                        break;
                    }
                    }
                }

                RemoveRedundantAsyncAwaitWalkerCache.Free(walker);
                break;
            }

            case SyntaxKind.IfStatement:
            {
                RemoveRedundantAsyncAwaitWalker walker = VisitStatements();

                HashSet <AwaitExpressionSyntax> awaitExpressions = walker.AwaitExpressions;

                if (awaitExpressions.Count > 0 &&
                    VerifyIfStatement((IfStatementSyntax)statement, awaitExpressions.Count, endsWithElse: true) &&
                    VerifyTypes(node, awaitExpressions, context.SemanticModel, context.CancellationToken))
                {
                    ReportDiagnostic(context, asyncKeyword, awaitExpressions);
                }

                RemoveRedundantAsyncAwaitWalkerCache.Free(walker);
                break;
            }

            case SyntaxKind.SwitchStatement:
            {
                RemoveRedundantAsyncAwaitWalker walker = VisitStatements();

                HashSet <AwaitExpressionSyntax> awaitExpressions = walker.AwaitExpressions;

                if (awaitExpressions.Count > 0 &&
                    VerifySwitchStatement((SwitchStatementSyntax)statement, awaitExpressions.Count, containsDefaultSection: true) &&
                    VerifyTypes(node, awaitExpressions, context.SemanticModel, context.CancellationToken))
                {
                    ReportDiagnostic(context, asyncKeyword, awaitExpressions);
                }

                RemoveRedundantAsyncAwaitWalkerCache.Free(walker);
                break;
            }
            }

            RemoveRedundantAsyncAwaitWalker VisitStatements()
            {
                RemoveRedundantAsyncAwaitWalker walker = RemoveRedundantAsyncAwaitWalkerCache.GetInstance();

                foreach (StatementSyntax s in statements)
                {
                    walker.Visit(s);

                    if (walker.ShouldStop)
                    {
                        return(walker);
                    }

                    if (s == statement)
                    {
                        return(walker);
                    }
                }

                return(walker);
            }
        }