Exemple #1
0
        public static void ComputeRefactoring(RefactoringContext context, IfStatementSyntax ifStatement)
        {
            ExpressionSyntax condition = ifStatement.Condition;

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

            StatementSyntax statement = ifStatement.Statement;

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

            Document document = context.Document;

            ElseClauseSyntax elseClause = ifStatement.Else;

            if (elseClause != null)
            {
                if (context.IsRefactoringEnabled(RefactoringIdentifiers.InvertIfElse))
                {
                    StatementSyntax elseStatement = elseClause.Statement;

                    if (elseStatement?.IsMissing == false &&
                        !elseStatement.IsKind(SyntaxKind.IfStatement))
                    {
                        context.RegisterRefactoring(
                            "Invert if-else",
                            ct => InvertIfElseAsync(document, ifStatement, ct),
                            RefactoringIdentifiers.InvertIfElse);
                    }
                }
            }
            else if (context.IsRefactoringEnabled(RefactoringIdentifiers.InvertIf) &&
                     ifStatement.IsTopmostIf())
            {
                InvertIfAnalysis analysis = InvertIfAnalysis.Create(ifStatement, statement);

                if (analysis.Success)
                {
                    context.RegisterRefactoring(
                        "Invert if",
                        ct => InvertIfAsync(document, ifStatement, recursive: false, ct),
                        RefactoringIdentifiers.InvertIf);

                    if (analysis.AnalyzeNextStatement().Success)
                    {
                        context.RegisterRefactoring(
                            "Invert if (recursively)",
                            ct => InvertIfAsync(document, ifStatement, recursive: true, ct),
                            RecursiveRefactoringIdentifier);
                    }
                }
            }
        }
Exemple #2
0
        public static async Task <Document> InvertIfAsync(
            Document document,
            IfStatementSyntax ifStatement,
            bool recursive = false,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            cancellationToken.ThrowIfCancellationRequested();

            StatementSyntax statement = ifStatement.Statement;

            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            InvertIfAnalysis analysis = InvertIfAnalysis.Create(ifStatement, statement);

            int ifStatementIndex = statements.IndexOf(ifStatement);

            StatementSyntax lastStatement = analysis.LastStatement;

            int lastStatementIndex = statements.IndexOf(lastStatement);

            bool isLastStatementRedundant = IsLastStatementRedundant();

            bool shouldUseElseClause = !CSharpFacts.IsJumpStatement(lastStatement.Kind());

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

            SyntaxList <StatementSyntax> newStatements = statements;

            if (!recursive)
            {
                Refactor();
            }
            else
            {
                IfStatementSyntax lastIfStatement;

                InvertIfAnalysis a = analysis.AnalyzeNextStatement();

                do
                {
                    lastIfStatement = a.IfStatement;

                    a = a.AnalyzeNextStatement();
                } while (a.Success);

                int firstLastStatementIndex = lastStatementIndex;

                int index = statements.IndexOf(lastIfStatement);

                int firstIndex = ifStatementIndex;

                while (index >= firstIndex)
                {
                    ifStatementIndex = index;
                    ifStatement      = (IfStatementSyntax)statements[ifStatementIndex];
                    statement        = ifStatement.Statement;
                    Refactor();
                    lastStatementIndex = firstLastStatementIndex + newStatements.Count - statements.Count;
                    lastStatement      = (statement is BlockSyntax block) ? block.Statements.Last() : statement;
                    index--;
                }
            }

            return(await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false));

            void Refactor()
            {
                cancellationToken.ThrowIfCancellationRequested();

                SyntaxList <StatementSyntax> nextStatements = newStatements
                                                              .Skip(ifStatementIndex + 1)
                                                              .Take(lastStatementIndex - ifStatementIndex)
                                                              .ToSyntaxList()
                                                              .TrimTrivia();

                BlockSyntax newStatement;
                SyntaxList <StatementSyntax> newNextStatements;

                if (statement is BlockSyntax block)
                {
                    newStatement      = block.WithStatements(nextStatements);
                    newNextStatements = block.Statements;
                }
                else
                {
                    newStatement      = Block(nextStatements);
                    newNextStatements = SingletonList(statement);
                }

                if (isLastStatementRedundant)
                {
                    newNextStatements = newNextStatements.RemoveAt(newNextStatements.Count - 1);
                }

                ElseClauseSyntax elseClause = null;

                if (newNextStatements.Any() &&
                    shouldUseElseClause)
                {
                    elseClause        = ElseClause(Block(newNextStatements));
                    newNextStatements = default;
                }

                IfStatementSyntax newIfStatement = ifStatement.Update(
                    ifKeyword: ifStatement.IfKeyword,
                    openParenToken: ifStatement.OpenParenToken,
                    condition: SyntaxInverter.LogicallyInvert(ifStatement.Condition, semanticModel, cancellationToken),
                    closeParenToken: ifStatement.CloseParenToken,
                    statement: newStatement,
                    @else: elseClause);

                newIfStatement = newIfStatement.WithFormatterAnnotation();

                SyntaxList <StatementSyntax> newNodes = newNextStatements.Insert(0, newIfStatement);

                newStatements = newStatements.ReplaceRange(ifStatementIndex, lastStatementIndex - ifStatementIndex + 1, newNodes);
            }

            bool IsLastStatementRedundant()
            {
                StatementSyntax jumpStatement = analysis.JumpStatement;

                switch (jumpStatement.Kind())
                {
                case SyntaxKind.ReturnStatement:
                {
                    if (((ReturnStatementSyntax)jumpStatement).Expression == null &&
                        RemoveRedundantStatementAnalysis.IsFixable(lastStatement, SyntaxKind.ReturnStatement))
                    {
                        return(true);
                    }

                    break;
                }

                case SyntaxKind.ContinueStatement:
                {
                    if (RemoveRedundantStatementAnalysis.IsFixable(lastStatement, SyntaxKind.ContinueStatement))
                    {
                        return(true);
                    }

                    break;
                }
                }

                return(false);
            }
        }