internal static ConditionalStatementInfo Create(
     IfStatementSyntax ifStatement,
     bool walkDownParentheses = true,
     bool allowMissing        = false)
 {
     if (ifStatement?.IsParentKind(SyntaxKind.ElseClause) != false)
     {
         return(default);
Esempio n. 2
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);
        }
Esempio n. 3
0
        private static void AnalyzeElseClause(SyntaxNodeAnalysisContext context)
        {
            var elseClause = (ElseClauseSyntax)context.Node;

            StatementSyntax statement = elseClause.Statement;

            if (statement?.Kind() != SyntaxKind.Block)
            {
                return;
            }

            var block = (BlockSyntax)statement;

            if (block.Statements.Any())
            {
                return;
            }

            IfStatementSyntax topmostIf = elseClause.GetTopmostIf();

            if (topmostIf.IsParentKind(SyntaxKind.IfStatement))
            {
                var parentIf = (IfStatementSyntax)topmostIf.Parent;

                if (parentIf.Else != null)
                {
                    return;
                }
            }

            if (!elseClause.ElseKeyword.TrailingTrivia.IsEmptyOrWhitespace())
            {
                return;
            }

            SyntaxToken openBrace = block.OpenBraceToken;

            if (!openBrace.LeadingTrivia.IsEmptyOrWhitespace())
            {
                return;
            }

            if (!openBrace.TrailingTrivia.IsEmptyOrWhitespace())
            {
                return;
            }

            if (!block.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace())
            {
                return;
            }

            DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.RemoveEmptyElseClause, elseClause);
        }
        private static IfStatementSyntax GetUpdatedIfStatement(
            IsPatternExpressionSyntax updatedCondition,
            ImmutableArray <SyntaxTrivia> trivia,
            IfStatementSyntax originalIf,
            IfStatementSyntax currentIf)
        {
            var newIf = currentIf.ReplaceNode(currentIf.Condition, updatedCondition);

            newIf = originalIf.IsParentKind(SyntaxKind.ElseClause)
                ? newIf.ReplaceToken(newIf.CloseParenToken, newIf.CloseParenToken.WithTrailingTrivia(trivia))
                : newIf.WithPrependedLeadingTrivia(trivia);

            return(newIf.WithAdditionalAnnotations(Formatter.Annotation));
        }
Esempio n. 5
0
        private static void AnalyzeElseClause(SyntaxNodeAnalysisContext context)
        {
            var elseClause = (ElseClauseSyntax)context.Node;

            if (elseClause.Statement?.Kind() == SyntaxKind.Block)
            {
                IfStatementSyntax ifStatement = elseClause.GetTopmostIf();

                if (ifStatement.IsParentKind(SyntaxKind.Block))
                {
                    AnalyzeStatement(context, ifStatement, (BlockSyntax)elseClause.Statement);
                }
            }
        }
        private static void Analyze(SyntaxNodeAnalysisContext context, StatementSyntax statement, Func <SyntaxKind, bool> predicate)
        {
            if (statement.IsParentKind(SyntaxKind.Block))
            {
                var block = (BlockSyntax)statement.Parent;

                SyntaxNode parent = block.Parent;

                if (parent != null)
                {
                    SyntaxKind kind = parent.Kind();

                    if (predicate(kind))
                    {
                        if (IsRemovable(block, statement, kind))
                        {
                            ReportDiagnostic(context, statement);
                        }
                    }
                    else if (kind == SyntaxKind.ElseClause)
                    {
                        var elseClause = (ElseClauseSyntax)parent;

                        if (!elseClause.ContinuesWithIf())
                        {
                            IfStatementSyntax ifStatement = elseClause.GetTopmostIf();

                            if (ifStatement.IsParentKind(SyntaxKind.Block))
                            {
                                block = (BlockSyntax)ifStatement.Parent;

                                parent = block.Parent;

                                if (parent != null)
                                {
                                    kind = parent.Kind();

                                    if (predicate(kind) &&
                                        IsRemovable(block, ifStatement, kind))
                                    {
                                        ReportDiagnostic(context, statement);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Esempio n. 7
0
        public static IfStatementSyntax GetPreviousIf(IfStatementSyntax ifStatement)
        {
            if (ifStatement == null)
            {
                throw new ArgumentNullException(nameof(ifStatement));
            }

            if (ifStatement.IsParentKind(SyntaxKind.ElseClause) &&
                ifStatement.Parent.IsParentKind(SyntaxKind.IfStatement))
            {
                return((IfStatementSyntax)ifStatement.Parent.Parent);
            }

            return(null);
        }
        public static void ComputeRefactoring(RefactoringContext context, IfStatementSyntax ifStatement)
        {
            if (ifStatement.IsParentKind(SyntaxKind.ElseClause))
            {
                return;
            }

            if (ifStatement.Else == null)
            {
                return;
            }

            foreach (IfStatementOrElseClause ifOrElse in ifStatement.AsCascade())
            {
                StatementSyntax statement = ifOrElse.Statement;

                if (statement is BlockSyntax block)
                {
                    statement = block.Statements.LastOrDefault();
                }

                if (statement == null)
                {
                    return;
                }

                if (!statement.IsKind(
                        SyntaxKind.ReturnStatement,
                        SyntaxKind.ContinueStatement,
                        SyntaxKind.BreakStatement,
                        SyntaxKind.ThrowStatement))
                {
                    return;
                }
            }

            context.RegisterRefactoring(
                "Split if-else",
                cancellationToken => RefactorAsync(context.Document, ifStatement, cancellationToken),
                RefactoringIdentifiers.SplitIfElse);
        }
Esempio n. 9
0
        internal static SimpleIfElseInfo Create(
            IfStatementSyntax ifStatement,
            bool walkDownParentheses = true,
            bool allowMissing        = false)
        {
            if (ifStatement?.IsParentKind(SyntaxKind.ElseClause) != false)
            {
                return(Default);
            }

            StatementSyntax whenFalse = ifStatement.Else?.Statement;

            if (!Check(whenFalse, allowMissing))
            {
                return(Default);
            }

            if (whenFalse.IsKind(SyntaxKind.IfStatement))
            {
                return(Default);
            }

            StatementSyntax whenTrue = ifStatement.Statement;

            if (!Check(whenTrue, allowMissing))
            {
                return(Default);
            }

            ExpressionSyntax condition = WalkAndCheck(ifStatement.Condition, walkDownParentheses, allowMissing);

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

            return(new SimpleIfElseInfo(ifStatement, condition, whenTrue, whenFalse));
        }
        internal static void ComputeRefactoring(RefactoringContext context, IfStatementSyntax ifStatement)
        {
            SimpleIfStatementInfo simpleIf = SyntaxInfo.SimpleIfStatementInfo(ifStatement);

            if (simpleIf.Success)
            {
                if (simpleIf.Condition.IsKind(SyntaxKind.LogicalOrExpression))
                {
                    context.RegisterRefactoring(
                        "Split if",
                        ct => SplitSimpleIfAsync(context.Document, ifStatement, ct),
                        RefactoringDescriptors.SplitIf);
                }
            }
            else if (ifStatement.IsParentKind(SyntaxKind.ElseClause) &&
                     ifStatement.Else == null &&
                     ifStatement.Condition.IsKind(SyntaxKind.LogicalOrExpression))
            {
                context.RegisterRefactoring(
                    "Split if",
                    ct => SplitLastElseIfAsync(context.Document, ifStatement, ct),
                    RefactoringDescriptors.SplitIf);
            }
        }
Esempio n. 11
0
        private static ReduceIfNestingAnalysisResult AnalyzeCore(
            IfStatementSyntax ifStatement,
            SemanticModel semanticModel,
            SyntaxKind jumpKind,
            ReduceIfNestingOptions options,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement);

            if (!statementsInfo.Success)
            {
                return(Fail(ifStatement));
            }

            SyntaxNode node       = statementsInfo.Parent;
            SyntaxNode parent     = node.Parent;
            SyntaxKind parentKind = parent.Kind();

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            if (statementsInfo.IsParentSwitchSection ||
                parentKind == SyntaxKind.SwitchSection)
            {
                SyntaxNode switchSection = (statementsInfo.IsParentSwitchSection) ? node : parent;

                if (!options.AllowSwitchSection())
                {
                    return(Fail(switchSection));
                }

                if (ifStatement != statements.LastButOneOrDefault())
                {
                    return(Fail(switchSection));
                }

                if (!IsFixableJumpStatement(statements.Last(), ref jumpKind))
                {
                    return(Fail(switchSection));
                }

                if (!options.AllowNestedFix() &&
                    IsNestedFix(switchSection.Parent, semanticModel, options, cancellationToken))
                {
                    return(Fail(switchSection));
                }

                return(Success(jumpKind, switchSection));
            }

            if (parentKind.Is(
                    SyntaxKind.ForStatement,
                    SyntaxKind.ForEachStatement,
                    SyntaxKind.DoStatement,
                    SyntaxKind.WhileStatement))
            {
                if (!options.AllowLoop())
                {
                    return(Fail(parent));
                }

                StatementSyntax lastStatement = statements.Last();

                if (ifStatement == lastStatement)
                {
                    jumpKind = SyntaxKind.ContinueStatement;
                }
                else
                {
                    if (ifStatement != statements.LastButOneOrDefault())
                    {
                        return(Fail(parent));
                    }

                    if (!IsFixableJumpStatement(lastStatement, ref jumpKind))
                    {
                        return(Fail(parent));
                    }
                }

                if (!options.AllowNestedFix() &&
                    IsNestedFix(parent.Parent, semanticModel, options, cancellationToken))
                {
                    return(Fail(parent));
                }

                return(Success(jumpKind, parent));
            }

            if (!IsFixable(ifStatement, statements, ref jumpKind))
            {
                return(Fail(node));
            }

            switch (parentKind)
            {
            case SyntaxKind.ConstructorDeclaration:
            case SyntaxKind.DestructorDeclaration:
            case SyntaxKind.SetAccessorDeclaration:
            case SyntaxKind.AddAccessorDeclaration:
            case SyntaxKind.RemoveAccessorDeclaration:
            {
                if (jumpKind == SyntaxKind.None)
                {
                    jumpKind = SyntaxKind.ReturnStatement;
                }
                else if (jumpKind != SyntaxKind.ReturnStatement)
                {
                    return(Fail(parent));
                }

                return(Success(jumpKind, parent));
            }

            case SyntaxKind.OperatorDeclaration:
            case SyntaxKind.ConversionOperatorDeclaration:
            case SyntaxKind.GetAccessorDeclaration:
            {
                if (jumpKind == SyntaxKind.None)
                {
                    return(Fail(parent));
                }

                return(Success(jumpKind, parent));
            }

            case SyntaxKind.MethodDeclaration:
            {
                var methodDeclaration = (MethodDeclarationSyntax)parent;

                if (jumpKind != SyntaxKind.None)
                {
                    return(Success(jumpKind, parent));
                }

                if (methodDeclaration.ReturnsVoid())
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (methodDeclaration.Modifiers.Contains(SyntaxKind.AsyncKeyword) &&
                    semanticModel
                    .GetDeclaredSymbol(methodDeclaration, cancellationToken)?
                    .ReturnType
                    .HasMetadataName(MetadataNames.System_Threading_Tasks_Task) == true)
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (semanticModel
                    .GetDeclaredSymbol(methodDeclaration, cancellationToken)?
                    .ReturnType
                    .OriginalDefinition
                    .IsIEnumerableOrIEnumerableOfT() == true &&
                    methodDeclaration.ContainsYield())
                {
                    return(Success(SyntaxKind.YieldBreakStatement, parent));
                }

                break;
            }

            case SyntaxKind.LocalFunctionStatement:
            {
                var localFunction = (LocalFunctionStatementSyntax)parent;

                if (jumpKind != SyntaxKind.None)
                {
                    return(Success(jumpKind, parent));
                }

                if (localFunction.ReturnsVoid())
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (localFunction.Modifiers.Contains(SyntaxKind.AsyncKeyword) &&
                    semanticModel.GetDeclaredSymbol(localFunction, cancellationToken)?
                    .ReturnType
                    .HasMetadataName(MetadataNames.System_Threading_Tasks_Task) == true)
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (semanticModel.GetDeclaredSymbol(localFunction, cancellationToken)?
                    .ReturnType
                    .OriginalDefinition
                    .IsIEnumerableOrIEnumerableOfT() == true &&
                    localFunction.ContainsYield())
                {
                    return(Success(SyntaxKind.YieldBreakStatement, parent));
                }

                break;
            }

            case SyntaxKind.AnonymousMethodExpression:
            case SyntaxKind.SimpleLambdaExpression:
            case SyntaxKind.ParenthesizedLambdaExpression:
            {
                var anonymousFunction = (AnonymousFunctionExpressionSyntax)parent;

                if (jumpKind != SyntaxKind.None)
                {
                    return(Success(jumpKind, parent));
                }

                if (!(semanticModel.GetSymbol(anonymousFunction, cancellationToken) is IMethodSymbol methodSymbol))
                {
                    return(Fail(parent));
                }

                if (methodSymbol.ReturnsVoid)
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                if (anonymousFunction.AsyncKeyword.Kind() == SyntaxKind.AsyncKeyword &&
                    methodSymbol.ReturnType.HasMetadataName(MetadataNames.System_Threading_Tasks_Task))
                {
                    return(Success(SyntaxKind.ReturnStatement, parent));
                }

                break;
            }

            case SyntaxKind.IfStatement:
            {
                ifStatement = (IfStatementSyntax)parent;

                if (ifStatement.IsParentKind(SyntaxKind.ElseClause))
                {
                    if (ifStatement.Else != null)
                    {
                        return(Fail(parent));
                    }

                    if (!options.AllowIfInsideIfElse())
                    {
                        return(Fail(parent));
                    }

                    return(AnalyzeCore(ifStatement.GetTopmostIf(), semanticModel, jumpKind, options, cancellationToken));
                }
                else
                {
                    if (!IsFixable(ifStatement))
                    {
                        return(Fail(parent));
                    }

                    if (!options.AllowNestedFix())
                    {
                        return(Fail(parent));
                    }

                    return(AnalyzeCore(ifStatement, semanticModel, jumpKind, options, cancellationToken));
                }
            }

            case SyntaxKind.ElseClause:
            {
                if (!options.AllowIfInsideIfElse())
                {
                    return(Fail(parent));
                }

                var elseClause = (ElseClauseSyntax)parent;

                return(AnalyzeCore(elseClause.GetTopmostIf(), semanticModel, jumpKind, options, cancellationToken));
            }
            }

            return(Fail(parent));
        }