public static Task <Document> RefactorAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken)
        {
            var statement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault();

            SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(statement);

            int             insertIndex  = invocationInfo.Expression.Span.End - statement.FullSpan.Start;
            StatementSyntax newStatement = SyntaxFactory.ParseStatement(statement.ToFullString().Insert(insertIndex, "?"));

            IEnumerable <SyntaxTrivia> leading = ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, statement.SpanStart));

            newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia()))
                ? newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia())
                : newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia().Concat(leading));

            IEnumerable <SyntaxTrivia> trailing = ifStatement.DescendantTrivia(TextSpan.FromBounds(statement.Span.End, ifStatement.Span.End));

            newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia()))
                ? newStatement.WithTrailingTrivia(ifStatement.GetTrailingTrivia())
                : newStatement.WithTrailingTrivia(trailing.Concat(ifStatement.GetTrailingTrivia()));

            return(document.ReplaceNodeAsync(ifStatement, newStatement, cancellationToken));
        }
        private static bool IsFixableIfInsideWhileOrDo(IfStatementSyntax ifStatement)
        {
            SyntaxNode parent = ifStatement.Parent;

            if (parent.Kind() != SyntaxKind.Block)
                return false;

            if (ifStatement.SingleNonBlockStatementOrDefault()?.Kind() != SyntaxKind.BreakStatement)
                return false;

            var block = (BlockSyntax)parent;

            SyntaxList<StatementSyntax> statements = block.Statements;

            int count = statements.Count;

            if (count == 1)
                return false;

            int index = statements.IndexOf(ifStatement);

            if (index != 0
                && index != count - 1)
            {
                return false;
            }

            parent = block.Parent;

            SyntaxKind kind = parent.Kind();

            if (kind == SyntaxKind.WhileStatement)
            {
                var whileStatement = (WhileStatementSyntax)parent;

                if (whileStatement.SpanContainsDirectives())
                    return false;

                if (whileStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression)
                    return false;
            }
            else if (kind == SyntaxKind.DoStatement)
            {
                var doStatement = (DoStatementSyntax)parent;

                if (doStatement.SpanContainsDirectives())
                    return false;

                if (doStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression)
                    return false;
            }
            else
            {
                return false;
            }

            return true;
        }
Exemple #3
0
        internal static SimplifyCodeBranchingKind?GetKind(IfStatementSyntax ifStatement, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            ExpressionSyntax condition = ifStatement.Condition?.WalkDownParentheses();

            if (condition?.IsMissing != false)
            {
                return(null);
            }

            StatementSyntax ifStatementStatement = ifStatement.Statement;

            if (ifStatementStatement == null)
            {
                return(null);
            }

            ElseClauseSyntax elseClause = ifStatement.Else;

            if (elseClause != null)
            {
                if (IsFixableIfElseInsideWhile(ifStatement, elseClause))
                {
                    return(SimplifyCodeBranchingKind.IfElseInsideWhile);
                }
                else
                {
                    var ifStatementBlock = ifStatementStatement as BlockSyntax;

                    if (ifStatementBlock?.Statements.Any() == false &&
                        ifStatementBlock.OpenBraceToken.TrailingTrivia.IsEmptyOrWhitespace() &&
                        ifStatementBlock.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace() &&
                        IsFixableIfElseWithEmptyIf(ifStatement, elseClause))
                    {
                        return(SimplifyCodeBranchingKind.IfElseWithEmptyIf);
                    }
                    else if (IsFixableIfElseWithReturnOrContinueInsideIf(ifStatement, elseClause))
                    {
                        return(SimplifyCodeBranchingKind.LastIfElseWithReturnOrContinueInsideIf);
                    }
                }
            }
            else if (IsFixableSimpleIfInsideWhileOrDo(ifStatement, semanticModel, cancellationToken))
            {
                return(SimplifyCodeBranchingKind.SimplifyIfInsideWhileOrDo);
            }
            else if (!ifStatement.IsParentKind(SyntaxKind.ElseClause) &&
                     (ifStatement.SingleNonBlockStatementOrDefault() is DoStatementSyntax doStatement) &&
                     CSharpFactory.AreEquivalent(condition, doStatement.Condition?.WalkDownParentheses()))
            {
                return(SimplifyCodeBranchingKind.SimpleIfContainingOnlyDo);
            }

            return(null);
        }
Exemple #4
0
        public static async Task <Document> RefactorAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken)
        {
            var statement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault();

            StatementSyntax newStatement = statement;

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.NotEqualsToNull);

            SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(statement);

            ExpressionSyntax expression = invocationInfo.Expression;

            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            if (semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken).IsNullableType())
            {
                var memberAccess = (MemberAccessExpressionSyntax)invocationInfo.Expression;

                newStatement = statement.ReplaceNode(memberAccess, memberAccess.Expression.WithTrailingTrivia(memberAccess.GetTrailingTrivia()));

                expression = memberAccess.Expression;
            }

            int insertIndex = expression.Span.End - statement.FullSpan.Start;

            newStatement = SyntaxFactory.ParseStatement(newStatement.ToFullString().Insert(insertIndex, "?"));

            IEnumerable <SyntaxTrivia> leading = ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, statement.SpanStart));

            newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia()))
                ? newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia())
                : newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia().Concat(leading));

            IEnumerable <SyntaxTrivia> trailing = ifStatement.DescendantTrivia(TextSpan.FromBounds(statement.Span.End, ifStatement.Span.End));

            newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia()))
                ? newStatement.WithTrailingTrivia(ifStatement.GetTrailingTrivia())
                : newStatement.WithTrailingTrivia(trailing.Concat(ifStatement.GetTrailingTrivia()));

            return(await document.ReplaceNodeAsync(ifStatement, newStatement, cancellationToken).ConfigureAwait(false));
        }
        private static Task <Document> RefactorAsync(
            Document document,
            StatementSyntax statement,
            IfStatementSyntax ifStatement,
            int statementIndex,
            StatementListInfo statementsInfo,
            ExpressionSyntax expression,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            var expressionStatement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault();

            var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression;

            BinaryExpressionSyntax newNode = CreateCoalesceExpression(
                expression.WithoutTrailingTrivia(),
                assignment.Right.WithTrailingTrivia(expression.GetTrailingTrivia()),
                semanticModel.GetTypeSymbol(assignment.Left, cancellationToken),
                statement.SpanStart,
                semanticModel);

            StatementSyntax newStatement = statement.ReplaceNode(expression, newNode);

            IEnumerable <SyntaxTrivia> trivia = statementsInfo.Parent.DescendantTrivia(TextSpan.FromBounds(statement.Span.End, ifStatement.Span.End));

            if (!trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia()))
            {
                newStatement = newStatement.WithTrailingTrivia(trivia);
                newStatement = newStatement.AppendToTrailingTrivia(ifStatement.GetTrailingTrivia());
            }
            else
            {
                newStatement = newStatement.WithTrailingTrivia(ifStatement.GetTrailingTrivia());
            }

            SyntaxList <StatementSyntax> newStatements = statementsInfo.Statements
                                                         .Remove(ifStatement)
                                                         .ReplaceAt(statementIndex, newStatement);

            return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken));
        }
Exemple #6
0
        private static ImmutableArray <IfAnalysis> Analyze(
            IfStatementSyntax ifStatement,
            ReturnStatementSyntax returnStatement,
            IfAnalysisOptions options,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax condition = ifStatement.Condition?.WalkDownParentheses();

            if (condition?.IsMissing != false)
            {
                return(Empty);
            }

            StatementSyntax statement = ifStatement.SingleNonBlockStatementOrDefault();

            if (statement?.IsKind(SyntaxKind.ReturnStatement) != true)
            {
                return(Empty);
            }

            if (!options.CheckSpanDirectives(ifStatement, TextSpan.FromBounds(ifStatement.SpanStart, returnStatement.Span.End)))
            {
                return(Empty);
            }

            return(Analyze(
                       ifStatement,
                       condition,
                       ((ReturnStatementSyntax)statement).Expression?.WalkDownParentheses(),
                       returnStatement.Expression?.WalkDownParentheses(),
                       options,
                       isYield: false,
                       semanticModel: semanticModel,
                       cancellationToken: cancellationToken));
        }
        private static bool IsFixableSimpleIfInsideWhileOrDo(
            IfStatementSyntax ifStatement,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            SyntaxNode parent = ifStatement.Parent;

            if (parent.Kind() != SyntaxKind.Block)
            {
                return(false);
            }

            if (ifStatement.SingleNonBlockStatementOrDefault()?.Kind() != SyntaxKind.BreakStatement)
            {
                return(false);
            }

            var block = (BlockSyntax)parent;

            SyntaxList <StatementSyntax> statements = block.Statements;

            int count = statements.Count;

            if (count == 1)
            {
                return(false);
            }

            int index = statements.IndexOf(ifStatement);

            if (index != 0 &&
                index != count - 1)
            {
                return(false);
            }

            parent = block.Parent;

            SyntaxKind kind = parent.Kind();

            if (kind == SyntaxKind.WhileStatement)
            {
                var whileStatement = (WhileStatementSyntax)parent;

                if (whileStatement.SpanContainsDirectives())
                {
                    return(false);
                }

                if (whileStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression)
                {
                    return(false);
                }

                if (index == count - 1 &&
                    ContainsLocalDefinedInLoopBody(
                        ifStatement.Condition,
                        TextSpan.FromBounds(block.SpanStart, ifStatement.SpanStart),
                        semanticModel,
                        cancellationToken))
                {
                    return(false);
                }

                return(true);
            }
            else if (kind == SyntaxKind.DoStatement)
            {
                var doStatement = (DoStatementSyntax)parent;

                if (doStatement.SpanContainsDirectives())
                {
                    return(false);
                }

                if (doStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression)
                {
                    return(false);
                }

                if (index == count - 1 &&
                    ContainsLocalDefinedInLoopBody(
                        ifStatement.Condition,
                        TextSpan.FromBounds(block.SpanStart, ifStatement.SpanStart),
                        semanticModel,
                        cancellationToken))
                {
                    return(false);
                }

                return(true);
            }

            return(false);
        }
Exemple #8
0
        public static Task <Document> RefactorAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken = default)
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            int index = statements.IndexOf(ifStatement);

            StatementSyntax expressionStatement = (ExpressionStatementSyntax)statements[index + 1];

            SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo((ExpressionStatementSyntax)expressionStatement);

            ExpressionSyntax expression = invocationInfo.Expression;

            SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo((ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault());

            BinaryExpressionSyntax coalesceExpression = CSharpFactory.CoalesceExpression(expression.WithoutTrivia(), ParenthesizedExpression(assignmentInfo.AssignmentExpression));

            ParenthesizedExpressionSyntax newExpression = ParenthesizedExpression(coalesceExpression)
                                                          .WithTriviaFrom(expression);

            StatementSyntax newExpressionStatement = expressionStatement.ReplaceNode(expression, newExpression);

            IEnumerable <SyntaxTrivia> trivia = statementsInfo.Parent.DescendantTrivia(TextSpan.FromBounds(ifStatement.FullSpan.Start, expressionStatement.FullSpan.Start));

            if (trivia.Any(f => !f.IsWhitespaceOrEndOfLineTrivia()))
            {
                newExpressionStatement = newExpressionStatement.PrependToLeadingTrivia(trivia);
            }

            SyntaxList <StatementSyntax> newStatements = statements
                                                         .Replace(expressionStatement, newExpressionStatement)
                                                         .RemoveAt(index);

            return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken));
        }
Exemple #9
0
        public static ImmutableArray <IfAnalysis> Analyze(
            IfStatementSyntax ifStatement,
            IfAnalysisOptions options,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (!ifStatement.IsTopmostIf())
            {
                return(Empty);
            }

            ExpressionSyntax condition = ifStatement.Condition?.WalkDownParentheses();

            if (condition == null)
            {
                return(Empty);
            }

            ElseClauseSyntax elseClause = ifStatement.Else;

            if (elseClause != null)
            {
                if (!options.CheckSpanDirectives(ifStatement))
                {
                    return(Empty);
                }

                StatementSyntax statement1 = ifStatement.SingleNonBlockStatementOrDefault();

                if (statement1 == null)
                {
                    return(Empty);
                }

                SyntaxKind kind1 = statement1.Kind();

                if (kind1.Is(
                        SyntaxKind.ExpressionStatement,
                        SyntaxKind.ReturnStatement,
                        SyntaxKind.YieldReturnStatement))
                {
                    StatementSyntax statement2 = elseClause.SingleNonBlockStatementOrDefault();

                    if (statement2?.Kind() == kind1)
                    {
                        switch (kind1)
                        {
                        case SyntaxKind.ExpressionStatement:
                        {
                            return(Analyze(
                                       ifStatement,
                                       condition,
                                       (ExpressionStatementSyntax)statement1,
                                       (ExpressionStatementSyntax)statement2,
                                       options,
                                       semanticModel,
                                       cancellationToken));
                        }

                        case SyntaxKind.ReturnStatement:
                        {
                            return(Analyze(
                                       ifStatement,
                                       condition,
                                       ((ReturnStatementSyntax)statement1).Expression?.WalkDownParentheses(),
                                       ((ReturnStatementSyntax)statement2).Expression?.WalkDownParentheses(),
                                       options,
                                       isYield: false,
                                       semanticModel: semanticModel,
                                       cancellationToken: cancellationToken));
                        }

                        case SyntaxKind.YieldReturnStatement:
                        {
                            return(Analyze(
                                       ifStatement,
                                       condition,
                                       ((YieldStatementSyntax)statement1).Expression?.WalkDownParentheses(),
                                       ((YieldStatementSyntax)statement2).Expression?.WalkDownParentheses(),
                                       options,
                                       isYield: true,
                                       semanticModel: semanticModel,
                                       cancellationToken: cancellationToken));
                        }
                        }
                    }
                }
            }
            else if (ifStatement.NextStatement() is ReturnStatementSyntax returnStatement)
            {
                return(Analyze(ifStatement, returnStatement, options, semanticModel, cancellationToken));
            }

            return(Empty);
        }
Exemple #10
0
        private static async Task <Document> RefactorAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            ExpressionSyntax condition = ifStatement.Condition;

            ElseClauseSyntax elseClause = ifStatement.Else;

            SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            SimplifyCodeBranchingKind kind = SimplifyCodeBranchingAnalyzer.GetKind(ifStatement, semanticModel, cancellationToken).Value;

            if (kind == SimplifyCodeBranchingKind.IfElseWithEmptyIf)
            {
                ExpressionSyntax newCondition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken);

                StatementSyntax statement = elseClause.Statement;

                if (statement is IfStatementSyntax nestedIf)
                {
                    newCondition = LogicalAndExpression(newCondition.Parenthesize(), nestedIf.Condition.Parenthesize());

                    statement = nestedIf.Statement;
                }

                IfStatementSyntax newIfStatement = ifStatement.Update(
                    ifStatement.IfKeyword,
                    ifStatement.OpenParenToken,
                    newCondition,
                    ifStatement.CloseParenToken,
                    statement,
                    default(ElseClauseSyntax));

                newIfStatement = newIfStatement.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(ifStatement, newIfStatement, cancellationToken).ConfigureAwait(false));
            }
            else if (kind == SimplifyCodeBranchingKind.IfElseInsideWhile)
            {
                bool elseContainsBreak = elseClause.SingleNonBlockStatementOrDefault()?.Kind() == SyntaxKind.BreakStatement;

                SyntaxList <StatementSyntax> statements;

                if (elseContainsBreak)
                {
                    statements = (ifStatement.Statement is BlockSyntax block2)
                        ? block2.Statements
                        : SingletonList(ifStatement.Statement);
                }
                else
                {
                    statements = (elseClause.Statement is BlockSyntax block2)
                        ? block2.Statements
                        : SingletonList(elseClause.Statement);
                }

                WhileStatementSyntax whileStatement;

                if (ifStatement.Parent is BlockSyntax block)
                {
                    whileStatement = (WhileStatementSyntax)block.Parent;

                    block = block.WithStatements(block.Statements.ReplaceRange(ifStatement, statements));
                }
                else
                {
                    whileStatement = (WhileStatementSyntax)ifStatement.Parent;

                    block = Block(statements);
                }

                if (!elseContainsBreak)
                {
                    condition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken);
                }

                WhileStatementSyntax newWhileStatement = whileStatement.Update(
                    whileStatement.WhileKeyword,
                    whileStatement.OpenParenToken,
                    condition,
                    whileStatement.CloseParenToken,
                    block);

                newWhileStatement = newWhileStatement.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(whileStatement, newWhileStatement, cancellationToken).ConfigureAwait(false));
            }
            else if (kind == SimplifyCodeBranchingKind.SimplifIfInsideWhileOrDo)
            {
                var block = (BlockSyntax)ifStatement.Parent;

                SyntaxList <StatementSyntax> statements = block.Statements;

                BlockSyntax newBlock = block.WithStatements(statements.Remove(ifStatement));

                ExpressionSyntax newCondition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken);

                SyntaxNode newNode;

                switch (block.Parent)
                {
                case WhileStatementSyntax whileStatement:
                {
                    if (statements.IsFirst(ifStatement))
                    {
                        newNode = whileStatement.Update(
                            whileStatement.WhileKeyword,
                            whileStatement.OpenParenToken,
                            newCondition,
                            whileStatement.CloseParenToken,
                            newBlock);
                    }
                    else
                    {
                        newNode = DoStatement(
                            Token(whileStatement.WhileKeyword.LeadingTrivia, SyntaxKind.DoKeyword, whileStatement.CloseParenToken.TrailingTrivia),
                            newBlock.WithoutTrailingTrivia(),
                            Token(SyntaxKind.WhileKeyword),
                            OpenParenToken(),
                            newCondition,
                            CloseParenToken(),
                            SemicolonToken().WithTrailingTrivia(newBlock.GetTrailingTrivia()));
                    }

                    break;
                }

                case DoStatementSyntax doStatement:
                {
                    if (statements.IsLast(ifStatement))
                    {
                        newNode = doStatement.Update(
                            doStatement.DoKeyword,
                            newBlock,
                            doStatement.WhileKeyword,
                            doStatement.OpenParenToken,
                            newCondition,
                            doStatement.CloseParenToken,
                            doStatement.SemicolonToken);
                    }
                    else
                    {
                        newNode = WhileStatement(
                            Token(doStatement.DoKeyword.LeadingTrivia, SyntaxKind.WhileKeyword, SyntaxTriviaList.Empty),
                            OpenParenToken(),
                            newCondition,
                            Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, doStatement.DoKeyword.TrailingTrivia),
                            newBlock.WithTrailingTrivia(doStatement.GetTrailingTrivia()));
                    }

                    break;
                }

                default:
                {
                    throw new InvalidOperationException();
                }
                }

                newNode = newNode.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(block.Parent, newNode, cancellationToken).ConfigureAwait(false));
            }
            else if (kind == SimplifyCodeBranchingKind.SimpleIfContainingOnlyDo)
            {
                StatementSyntax statement = ifStatement.SingleNonBlockStatementOrDefault();

                var doStatement = (DoStatementSyntax)statement;

                WhileStatementSyntax whileStatement = WhileStatement(
                    Token(ifStatement.GetLeadingTrivia(), SyntaxKind.WhileKeyword, SyntaxTriviaList.Empty),
                    OpenParenToken(),
                    doStatement.Condition,
                    Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, doStatement.DoKeyword.TrailingTrivia),
                    doStatement.Statement.WithTrailingTrivia(ifStatement.GetTrailingTrivia()));

                whileStatement = whileStatement.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(ifStatement, whileStatement, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                throw new InvalidOperationException();
            }
        }
Exemple #11
0
        private static async Task <Document> RefactorAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax condition = ifStatement.Condition;

            ElseClauseSyntax elseClause = ifStatement.Else;

            if ((ifStatement.Statement as BlockSyntax)?.Statements.Any() == false)
            {
                SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                ExpressionSyntax newCondition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken);

                StatementSyntax statement = elseClause.Statement;

                if (statement is IfStatementSyntax nestedIf)
                {
                    newCondition = LogicalAndExpression(newCondition.Parenthesize(), nestedIf.Condition.Parenthesize());

                    statement = nestedIf.Statement;
                }

                cancellationToken.ThrowIfCancellationRequested();

                IfStatementSyntax newNode = ifStatement.Update(
                    ifStatement.IfKeyword,
                    ifStatement.OpenParenToken,
                    newCondition,
                    ifStatement.CloseParenToken,
                    statement,
                    default(ElseClauseSyntax));

                newNode = newNode.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(ifStatement, newNode, cancellationToken).ConfigureAwait(false));
            }
            else if (elseClause != null)
            {
                WhileStatementSyntax whileStatement;

                if (ifStatement.Parent is BlockSyntax block)
                {
                    whileStatement = (WhileStatementSyntax)block.Parent;
                }
                else
                {
                    block          = Block();
                    whileStatement = (WhileStatementSyntax)ifStatement.Parent;
                }

                cancellationToken.ThrowIfCancellationRequested();

                BlockSyntax newBlock = (ifStatement.Statement is BlockSyntax ifBlock)
                    ? block.WithStatements(ifBlock.Statements)
                    : block.WithStatements(SingletonList(ifStatement.Statement));

                SyntaxNode newNode = whileStatement.Update(
                    whileStatement.WhileKeyword,
                    whileStatement.OpenParenToken,
                    ifStatement.Condition,
                    whileStatement.CloseParenToken,
                    newBlock);

                newNode = newNode.WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(whileStatement, newNode, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                StatementSyntax statement = ifStatement.SingleNonBlockStatementOrDefault();

                if (statement.Kind() == SyntaxKind.BreakStatement)
                {
                    var block = (BlockSyntax)ifStatement.Parent;

                    SyntaxList <StatementSyntax> statements = block.Statements;

                    BlockSyntax newBlock = block.WithStatements(statements.Remove(ifStatement));

                    SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

                    ExpressionSyntax newCondition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken);

                    SyntaxNode newNode = block.Parent;

                    switch (block.Parent)
                    {
                    case WhileStatementSyntax whileStatement:
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (statements.IsFirst(ifStatement))
                        {
                            newNode = whileStatement.Update(
                                whileStatement.WhileKeyword,
                                whileStatement.OpenParenToken,
                                newCondition,
                                whileStatement.CloseParenToken,
                                newBlock);
                        }
                        else
                        {
                            newNode = DoStatement(
                                Token(whileStatement.WhileKeyword.LeadingTrivia, SyntaxKind.DoKeyword, whileStatement.CloseParenToken.TrailingTrivia),
                                newBlock.WithoutTrailingTrivia(),
                                Token(SyntaxKind.WhileKeyword),
                                OpenParenToken(),
                                newCondition,
                                CloseParenToken(),
                                SemicolonToken().WithTrailingTrivia(newBlock.GetTrailingTrivia()));
                        }

                        break;
                    }

                    case DoStatementSyntax doStatement:
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        if (statements.IsLast(ifStatement))
                        {
                            newNode = doStatement.Update(
                                doStatement.DoKeyword,
                                newBlock,
                                doStatement.WhileKeyword,
                                doStatement.OpenParenToken,
                                newCondition,
                                doStatement.CloseParenToken,
                                doStatement.SemicolonToken);
                        }
                        else
                        {
                            newNode = WhileStatement(
                                Token(doStatement.DoKeyword.LeadingTrivia, SyntaxKind.WhileKeyword, SyntaxTriviaList.Empty),
                                OpenParenToken(),
                                newCondition,
                                Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, doStatement.DoKeyword.TrailingTrivia),
                                newBlock.WithTrailingTrivia(doStatement.GetTrailingTrivia()));
                        }

                        break;
                    }

                    default:
                    {
                        Debug.Fail(block.Parent.Kind().ToString());
                        break;
                    }
                    }

                    newNode = newNode.WithFormatterAnnotation();

                    return(await document.ReplaceNodeAsync(block.Parent, newNode, cancellationToken).ConfigureAwait(false));
                }
                else if (statement.Kind() == SyntaxKind.DoStatement)
                {
                    var doStatement = (DoStatementSyntax)statement;

                    WhileStatementSyntax whileStatement = WhileStatement(
                        Token(ifStatement.GetLeadingTrivia(), SyntaxKind.WhileKeyword, SyntaxTriviaList.Empty),
                        OpenParenToken(),
                        doStatement.Condition,
                        Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, doStatement.DoKeyword.TrailingTrivia),
                        doStatement.Statement.WithTrailingTrivia(ifStatement.GetTrailingTrivia()));

                    whileStatement = whileStatement.WithFormatterAnnotation();

                    return(await document.ReplaceNodeAsync(ifStatement, whileStatement, cancellationToken).ConfigureAwait(false));
                }
            }

            throw new InvalidOperationException();
        }
Exemple #12
0
        public static Task <Document> InlineLazyInitializationAsync(
            Document document,
            IfStatementSyntax ifStatement,
            CancellationToken cancellationToken = default)
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            var assignmentStatement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault();

            SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(assignmentStatement, walkDownParentheses: false);

            ExpressionSyntax right = assignmentInfo.Right;

            int index = statementsInfo.IndexOf(ifStatement);

            var expressionStatement2 = (ExpressionStatementSyntax)statementsInfo[index + 1];

            SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(expressionStatement2);

            ExpressionSyntax expression = invocationInfo.Expression;

            var newLeading = new List <SyntaxTrivia>(ifStatement.GetLeadingTrivia());

            ExpressionSyntax coalesceExpression;

            if (document.SupportsLanguageFeature(CSharpLanguageFeature.NullCoalescingAssignmentOperator))
            {
                AddTrivia(ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, right.SpanStart)).ToSyntaxTriviaList());

                coalesceExpression = CoalesceAssignmentExpression(expression.WithoutTrivia(), right.WithoutTrivia());
            }
            else
            {
                AddTrivia(ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, assignmentInfo.AssignmentExpression.SpanStart)).ToSyntaxTriviaList());

                coalesceExpression = CoalesceExpression(expression.WithoutTrivia(), ParenthesizedExpression(assignmentInfo.AssignmentExpression.WithoutTrivia()));
            }

            AddTrivia(ifStatement.DescendantTrivia(TextSpan.FromBounds(right.Span.End, ifStatement.Span.End)).ToSyntaxTriviaList());
            AddTrivia(ifStatement.GetTrailingTrivia());
            AddTrivia(expressionStatement2.GetLeadingTrivia());

            ParenthesizedExpressionSyntax newExpression = ParenthesizedExpression(coalesceExpression)
                                                          .WithLeadingTrivia(newLeading)
                                                          .WithTrailingTrivia(expression.GetTrailingTrivia());

            StatementSyntax newExpressionStatement = expressionStatement2.ReplaceNode(expression, newExpression);

            StatementListInfo newStatements = statementsInfo
                                              .Replace(expressionStatement2, newExpressionStatement)
                                              .RemoveAt(index);

            return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken));

            void AddTrivia(SyntaxTriviaList trivia)
            {
                if (!trivia.IsEmptyOrWhitespace())
                {
                    newLeading.AddRange(trivia);
                }
            }
        }
Exemple #13
0
        private static bool IsFixableIfElseWithReturnOrContinueInsideIf(IfStatementSyntax ifStatement, ElseClauseSyntax elseClause)
        {
            if (elseClause.Statement?.IsKind(SyntaxKind.IfStatement) != false)
            {
                return(false);
            }

            IfStatementSyntax topmostIf = ifStatement.GetTopmostIf();

            if (!(topmostIf.Parent is BlockSyntax block))
            {
                return(false);
            }

            if (!block.Statements.IsLast(topmostIf, ignoreLocalFunctions: true))
            {
                return(false);
            }

            switch (block.Parent.Kind())
            {
            case SyntaxKind.MethodDeclaration:
            case SyntaxKind.LocalFunctionStatement:
            case SyntaxKind.ConstructorDeclaration:
            case SyntaxKind.DestructorDeclaration:
            case SyntaxKind.AddAccessorDeclaration:
            case SyntaxKind.RemoveAccessorDeclaration:
            case SyntaxKind.SetAccessorDeclaration:
            {
                //void M()
                //{
                //    if (x)
                //    {
                //        return;
                //    }
                //    else
                //    {
                //        M();
                //    }

                return(ifStatement.SingleNonBlockStatementOrDefault() is ReturnStatementSyntax returnStatement &&
                       returnStatement.Expression == null);
            }

            case SyntaxKind.ForEachStatement:
            case SyntaxKind.ForEachVariableStatement:
            case SyntaxKind.ForStatement:
            case SyntaxKind.WhileStatement:
            {
                //while (x)
                //{
                //    if (y)
                //    {
                //        continue;
                //    }
                //    else
                //    {
                //        M();
                //    }
                //}

                return(ifStatement.SingleNonBlockStatementOrDefault().IsKind(SyntaxKind.ContinueStatement));
            }
            }

            return(false);
        }
Exemple #14
0
        private static ImmutableArray <IfAnalysis> Analyze(
            ExpressionStatementSyntax expressionStatement,
            IfStatementSyntax ifStatement,
            IfAnalysisOptions options,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            SimpleAssignmentStatementInfo assignment = SyntaxInfo.SimpleAssignmentStatementInfo(expressionStatement);

            if (!assignment.Success)
            {
                return(Empty);
            }

            ElseClauseSyntax elseClause = ifStatement.Else;

            if (elseClause?.Statement?.IsKind(SyntaxKind.IfStatement) != false)
            {
                return(Empty);
            }

            SimpleAssignmentStatementInfo assignment1 = SyntaxInfo.SimpleAssignmentStatementInfo(ifStatement.SingleNonBlockStatementOrDefault());

            if (!assignment1.Success)
            {
                return(Empty);
            }

            SimpleAssignmentStatementInfo assignment2 = SyntaxInfo.SimpleAssignmentStatementInfo(elseClause.SingleNonBlockStatementOrDefault());

            if (!assignment2.Success)
            {
                return(Empty);
            }

            if (!AreEquivalent(assignment1.Left, assignment2.Left, assignment.Left))
            {
                return(Empty);
            }

            if (!options.CheckSpanDirectives(ifStatement.Parent, TextSpan.FromBounds(expressionStatement.SpanStart, ifStatement.Span.End)))
            {
                return(Empty);
            }

            if (IsNullLiteralConvertedToNullableOfT(assignment1.Right, semanticModel, cancellationToken) ||
                IsNullLiteralConvertedToNullableOfT(assignment2.Right, semanticModel, cancellationToken))
            {
                return(Empty);
            }

            return(new AssignmentAndIfElseToAssignmentWithConditionalExpressionAnalysis(expressionStatement, assignment.Right, ifStatement, assignment1.Right, assignment2.Right, semanticModel).ToImmutableArray());
        }
Exemple #15
0
        private static ImmutableArray <IfAnalysis> Analyze(
            LocalDeclarationStatementSyntax localDeclarationStatement,
            IfStatementSyntax ifStatement,
            IfAnalysisOptions options,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            VariableDeclaratorSyntax declarator = localDeclarationStatement
                                                  .Declaration?
                                                  .Variables
                                                  .SingleOrDefault(shouldThrow: false);

            if (declarator == null)
            {
                return(Empty);
            }

            ElseClauseSyntax elseClause = ifStatement.Else;

            if (elseClause?.Statement?.IsKind(SyntaxKind.IfStatement) != false)
            {
                return(Empty);
            }

            SimpleAssignmentStatementInfo assignment1 = SyntaxInfo.SimpleAssignmentStatementInfo(ifStatement.SingleNonBlockStatementOrDefault());

            if (!assignment1.Success)
            {
                return(Empty);
            }

            SimpleAssignmentStatementInfo assignment2 = SyntaxInfo.SimpleAssignmentStatementInfo(elseClause.SingleNonBlockStatementOrDefault());

            if (!assignment2.Success)
            {
                return(Empty);
            }

            if (assignment1.Left.Kind() != SyntaxKind.IdentifierName)
            {
                return(Empty);
            }

            if (assignment2.Left.Kind() != SyntaxKind.IdentifierName)
            {
                return(Empty);
            }

            string identifier1 = ((IdentifierNameSyntax)assignment1.Left).Identifier.ValueText;
            string identifier2 = ((IdentifierNameSyntax)assignment2.Left).Identifier.ValueText;

            if (!string.Equals(identifier1, identifier2, StringComparison.Ordinal))
            {
                return(Empty);
            }

            if (!string.Equals(identifier1, declarator.Identifier.ValueText, StringComparison.Ordinal))
            {
                return(Empty);
            }

            if (!options.CheckSpanDirectives(ifStatement.Parent, TextSpan.FromBounds(localDeclarationStatement.SpanStart, ifStatement.Span.End)))
            {
                return(Empty);
            }

            if (IsNullLiteralConvertedToNullableOfT(assignment1.Right, semanticModel, cancellationToken) ||
                IsNullLiteralConvertedToNullableOfT(assignment2.Right, semanticModel, cancellationToken))
            {
                return(Empty);
            }

            return(new LocalDeclarationAndIfElseToAssignmentWithConditionalExpressionAnalysis(localDeclarationStatement, ifStatement, assignment1.Right, assignment2.Right, semanticModel).ToImmutableArray());
        }