Exemplo n.º 1
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var diagnostic     = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var syntax         = root.FindNode(diagnosticSpan);

            var conditional = syntax as ConditionalExpressionSyntax;

            if (conditional != null)
            {
                context.RegisterCodeFix(
                    CodeAction.Create(
                        Title,
                        c =>
                {
                    var condition = TernaryOperatorPointless.RemoveParentheses(conditional.Condition);
                    var whenTrue  = TernaryOperatorPointless.RemoveParentheses(conditional.WhenTrue);
                    var whenFalse = TernaryOperatorPointless.RemoveParentheses(conditional.WhenFalse);

                    ExpressionSyntax compared;
                    bool comparedIsNullInTrue;
                    ConditionalSimplification.TryGetComparedVariable(condition, out compared, out comparedIsNullInTrue);

                    var newRoot = root.ReplaceNode(conditional, GetNullCoalescing(whenTrue, whenFalse, compared)
                                                   .WithTriviaFrom(conditional))
                                  .WithAdditionalAnnotations(Formatter.Annotation);
                    return(Task.FromResult(context.Document.WithSyntaxRoot(newRoot)));
                }),
                    context.Diagnostics);
            }

            var ifStatement = syntax as IfStatementSyntax;

            if (ifStatement != null)
            {
                context.RegisterCodeFix(
                    CodeAction.Create(
                        Title,
                        c =>
                {
                    var whenTrue  = ConditionalSimplification.ExtractSingleStatement(ifStatement.Statement);
                    var whenFalse = ConditionalSimplification.ExtractSingleStatement(ifStatement.Else.Statement);

                    ExpressionSyntax compared;
                    bool comparedIsNullInTrue;
                    ConditionalSimplification.TryGetComparedVariable(ifStatement.Condition, out compared, out comparedIsNullInTrue);

                    var isNullCoalescing = bool.Parse(diagnostic.Properties[ConditionalSimplification.IsNullCoalescingKey]);

                    var newRoot = root.ReplaceNode(ifStatement,
                                                   GetSimplified(whenTrue, whenFalse, ifStatement.Condition, compared, isNullCoalescing)
                                                   .WithTriviaFrom(ifStatement))
                                  .WithAdditionalAnnotations(Formatter.Annotation);
                    return(Task.FromResult(context.Document.WithSyntaxRoot(newRoot)));
                }),
                    context.Diagnostics);
            }
        }
        private bool CanBeSimplified(StatementSyntax statement1, StatementSyntax statement2,
                                     ExpressionSyntax compared, bool comparedIsNullInTrue, SemanticModel semanticModel, out bool isNullCoalescing)
        {
            isNullCoalescing = false;
            var return1 = statement1 as ReturnStatementSyntax;
            var return2 = statement2 as ReturnStatementSyntax;

            if (return1 != null && return2 != null)
            {
                var retExpr1 = TernaryOperatorPointless.RemoveParentheses(return1.Expression);
                var retExpr2 = TernaryOperatorPointless.RemoveParentheses(return2.Expression);

                if (compared != null && CanBeNullCoalescing(retExpr1, retExpr2, compared, comparedIsNullInTrue, semanticModel))
                {
                    isNullCoalescing = true;
                }

                return(true);
            }

            var expressionStatement1 = statement1 as ExpressionStatementSyntax;
            var expressionStatement2 = statement2 as ExpressionStatementSyntax;

            if (expressionStatement1 == null || expressionStatement2 == null)
            {
                return(false);
            }

            var expression1 = TernaryOperatorPointless.RemoveParentheses(expressionStatement1.Expression);
            var expression2 = TernaryOperatorPointless.RemoveParentheses(expressionStatement2.Expression);

            if (AreCandidateAssignments(expression1, expression2, compared, comparedIsNullInTrue, semanticModel, out isNullCoalescing))
            {
                return(true);
            }

            if (compared != null && CanBeNullCoalescing(expression1, expression2, compared, comparedIsNullInTrue, semanticModel))
            {
                isNullCoalescing = true;
                return(true);
            }

            if (AreCandidateInvocations(expression1, expression2, semanticModel, null, false))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 3
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            var diagnostic     = context.Diagnostics.First();
            var diagnosticSpan = diagnostic.Location.SourceSpan;
            var conditional    = root.FindNode(diagnosticSpan) as ConditionalExpressionSyntax;

            context.RegisterCodeFix(
                CodeAction.Create(
                    Title,
                    c =>
            {
                var newRoot = root.ReplaceNode(conditional, TernaryOperatorPointless.RemoveParentheses(conditional.WhenTrue))
                              .WithAdditionalAnnotations(Formatter.Annotation);
                return(Task.FromResult(context.Document.WithSyntaxRoot(newRoot)));
            }),
                context.Diagnostics);
        }
Exemplo n.º 4
0
        private StatementSyntax GetSimplified(StatementSyntax statement1, StatementSyntax statement2,
                                              ExpressionSyntax condition, ExpressionSyntax compared, bool isNullCoalescing)
        {
            var return1 = statement1 as ReturnStatementSyntax;
            var return2 = statement2 as ReturnStatementSyntax;

            if (return1 != null && return2 != null)
            {
                var retExpr1 = TernaryOperatorPointless.RemoveParentheses(return1.Expression);
                var retExpr2 = TernaryOperatorPointless.RemoveParentheses(return2.Expression);

                if (isNullCoalescing)
                {
                    var nullCoalescing = GetNullCoalescing(retExpr1, retExpr2, compared);
                    return(SyntaxFactory.ReturnStatement(nullCoalescing));
                }

                return
                    (SyntaxFactory.ReturnStatement(
                         SyntaxFactory.ConditionalExpression(
                             condition,
                             return1.Expression,
                             return2.Expression)));
            }

            var expressionStatement1 = statement1 as ExpressionStatementSyntax;
            var expressionStatement2 = statement2 as ExpressionStatementSyntax;

            var expression1 = TernaryOperatorPointless.RemoveParentheses(expressionStatement1.Expression);
            var expression2 = TernaryOperatorPointless.RemoveParentheses(expressionStatement2.Expression);

            var assignment = GetSimplifiedAssignment(expression1, expression2, condition, compared, isNullCoalescing);

            if (assignment != null)
            {
                return(SyntaxFactory.ExpressionStatement(assignment));
            }

            return(SyntaxFactory.ExpressionStatement(
                       GetSimplificationFromInvocations(expression1, expression2, condition, compared, isNullCoalescing)));
        }
        public override void Initialize(AnalysisContext context)
        {
            context.RegisterSyntaxNodeActionInNonGenerated(
                c =>
            {
                var conditional = (ConditionalExpressionSyntax)c.Node;

                var condition = TernaryOperatorPointless.RemoveParentheses(conditional.Condition);
                var whenTrue  = TernaryOperatorPointless.RemoveParentheses(conditional.WhenTrue);
                var whenFalse = TernaryOperatorPointless.RemoveParentheses(conditional.WhenFalse);

                if (EquivalenceChecker.AreEquivalent(whenTrue, whenFalse))
                {
                    return;
                }

                ExpressionSyntax compared;
                bool comparedIsNullInTrue;
                if (!TryGetComparedVariable(condition, out compared, out comparedIsNullInTrue) ||
                    !ExpressionCanBeNull(compared, c.SemanticModel))
                {
                    return;
                }

                if (CanBeNullCoalescing(whenTrue, whenFalse, compared, comparedIsNullInTrue, c.SemanticModel))
                {
                    c.ReportDiagnostic(Diagnostic.Create(Rule, conditional.GetLocation(), "??"));
                }
            },
                SyntaxKind.ConditionalExpression);

            context.RegisterSyntaxNodeActionInNonGenerated(
                c =>
            {
                var ifStatement = (IfStatementSyntax)c.Node;
                if (ifStatement.Else == null ||
                    ifStatement.Parent is ElseClauseSyntax)
                {
                    return;
                }

                var whenTrue  = ExtractSingleStatement(ifStatement.Statement);
                var whenFalse = ExtractSingleStatement(ifStatement.Else.Statement);

                if (whenTrue == null ||
                    whenFalse == null ||
                    EquivalenceChecker.AreEquivalent(whenTrue, whenFalse))
                {
                    return;
                }

                ExpressionSyntax compared;
                bool comparedIsNullInTrue;
                var possiblyTernary =
                    TryGetComparedVariable(ifStatement.Condition, out compared, out comparedIsNullInTrue) &&
                    ExpressionCanBeNull(compared, c.SemanticModel);

                bool isNullCoalescing;
                if (CanBeSimplified(whenTrue, whenFalse,
                                    possiblyTernary ? compared : null,
                                    comparedIsNullInTrue,
                                    c.SemanticModel, out isNullCoalescing))
                {
                    c.ReportDiagnostic(Diagnostic.Create(Rule, ifStatement.IfKeyword.GetLocation(),
                                                         ImmutableDictionary <string, string> .Empty.Add(IsNullCoalescingKey, isNullCoalescing.ToString()),
                                                         isNullCoalescing ? "??" : "?:"));
                }
            },
                SyntaxKind.IfStatement);
        }