Exemple #1
0
 private static bool AreEquivalent(StatementSyntax statement, StatementSyntax statement2)
 {
     return(statement.Kind() == statement2.Kind() &&
            SyntaxComparer.AreEquivalent(statement, statement2) &&
            statement.DescendantTrivia().All(f => f.IsWhitespaceOrEndOfLineTrivia()) &&
            statement2.DescendantTrivia().All(f => f.IsWhitespaceOrEndOfLineTrivia()));
 }
        public static bool CanRefactor(AssignmentExpressionSyntax assignment)
        {
            if (assignment == null)
            {
                throw new ArgumentNullException(nameof(assignment));
            }

            if (assignment.IsKind(SyntaxKind.SimpleAssignmentExpression))
            {
                ExpressionSyntax left  = assignment.Left;
                ExpressionSyntax right = assignment.Right;

                if (left?.IsMissing == false &&
                    right?.IsMissing == false &&
                    !assignment.IsParentKind(SyntaxKind.ObjectInitializerExpression) &&
                    right.SupportsCompoundAssignment())
                {
                    var binaryExpression         = (BinaryExpressionSyntax)right;
                    ExpressionSyntax binaryLeft  = binaryExpression.Left;
                    ExpressionSyntax binaryRight = binaryExpression.Right;

                    return(binaryLeft?.IsMissing == false &&
                           binaryRight?.IsMissing == false &&
                           SyntaxComparer.AreEquivalent(left, binaryLeft) &&
                           (assignment
                            .DescendantTrivia(assignment.Span)
                            .All(f => f.IsWhitespaceOrEndOfLineTrivia())));
                }
            }

            return(false);
        }
Exemple #3
0
        private static IfRefactoring CreateIfToAssignmentWithWithCoalesceExpression(
            IfStatementSyntax ifStatement,
            ExpressionSyntax left,
            ExpressionSyntax expression1,
            ExpressionSyntax expression2,
            NullCheckExpression nullCheck,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (nullCheck.Kind == NullCheckKind.EqualsToNull ||
                nullCheck.Kind == NullCheckKind.NotEqualsToNull)
            {
                if (SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1, requireNotNull: true))
                {
                    return(new IfElseToAssignmentWithCoalesceExpression(ifStatement, left, expression1, expression2));
                }
            }

            if (expression1.IsKind(SyntaxKind.SimpleMemberAccessExpression) &&
                SyntaxUtility.IsPropertyOfNullableOfT(expression1, "Value", semanticModel, cancellationToken))
            {
                expression1 = ((MemberAccessExpressionSyntax)expression1).Expression;

                if (SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1, requireNotNull: true))
                {
                    return(new IfElseToAssignmentWithCoalesceExpression(ifStatement, left, expression1, expression2));
                }
            }

            return(null);
        }
        private static IfRefactoring CreateIfToReturnStatement(
            IfStatementSyntax ifStatement,
            ExpressionSyntax expression1,
            ExpressionSyntax expression2,
            NullCheckExpressionInfo nullCheck,
            IfAnalysisOptions options,
            bool isYield,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if ((nullCheck.Kind & NullCheckKind.ComparisonToNull) != 0 &&
                SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1))
            {
                return(CreateIfToReturnStatement(ifStatement, expression1, expression2, options, isYield, isNullable: false));
            }

            expression1 = GetNullableOfTValueProperty(expression1, semanticModel, cancellationToken);

            if (SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1))
            {
                return(CreateIfToReturnStatement(ifStatement, expression1, expression2, options, isYield, isNullable: true));
            }

            return(null);
        }
Exemple #5
0
        internal static ExpressionSyntax FindExpressionThatCanBeConditionallyAccessed(ExpressionSyntax expressionToFind, ExpressionSyntax expression)
        {
            if (expression.IsKind(SyntaxKind.LogicalNotExpression))
            {
                expression = ((PrefixUnaryExpressionSyntax)expression).Operand;
            }

            SyntaxKind kind = expressionToFind.Kind();

            SyntaxToken firstToken = expression.GetFirstToken();

            int start = firstToken.SpanStart;

            SyntaxNode node = firstToken.Parent;

            while (node?.SpanStart == start)
            {
                if (kind == node.Kind() &&
                    node.IsParentKind(SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.ElementAccessExpression) &&
                    SyntaxComparer.AreEquivalent(expressionToFind, node))
                {
                    return((ExpressionSyntax)node);
                }

                node = node.Parent;
            }

            return(null);
        }
Exemple #6
0
        private static ImmutableArray <IfRefactoring> Analyze(
            ExpressionStatementSyntax expressionStatement,
            IfStatementSyntax ifStatement,
            IfAnalysisOptions options)
        {
            SimpleAssignmentStatement assignment;

            if (SimpleAssignmentStatement.TryCreate(expressionStatement, out assignment))
            {
                ElseClauseSyntax elseClause = ifStatement.Else;

                if (elseClause?.Statement?.IsKind(SyntaxKind.IfStatement) == false)
                {
                    SimpleAssignmentStatement assignment1;
                    if (SimpleAssignmentStatement.TryCreate(ifStatement.GetSingleStatementOrDefault(), out assignment1))
                    {
                        SimpleAssignmentStatement assignment2;
                        if (SimpleAssignmentStatement.TryCreate(elseClause.GetSingleStatementOrDefault(), out assignment2) &&
                            SyntaxComparer.AreEquivalent(assignment1.Left, assignment2.Left, assignment.Left) &&
                            options.CheckSpanDirectives(ifStatement.Parent, TextSpan.FromBounds(expressionStatement.SpanStart, ifStatement.Span.End)))
                        {
                            return(new AssignmentAndIfElseToAssignmentWithConditionalExpression(expressionStatement, assignment.Right, ifStatement, assignment1.Right, assignment2.Right).ToImmutableArray());
                        }
                    }
                }
            }

            return(ImmutableArray <IfRefactoring> .Empty);
        }
        private static bool NullCheckExists(ExpressionSyntax expression, StatementSyntax statement)
        {
            StatementsInfo statementsInfo = SyntaxInfo.StatementsInfo(statement);

            if (!statementsInfo.Success)
            {
                return(false);
            }

            SyntaxList <StatementSyntax> statements = statementsInfo.Statements;

            int index = statements.IndexOf(statement);

            if (index >= statements.Count - 1)
            {
                return(false);
            }

            StatementSyntax nextStatement = statements[index + 1];

            if (!(nextStatement is IfStatementSyntax ifStatement))
            {
                return(false);
            }

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

            if (!nullCheck.Success)
            {
                return(false);
            }

            return(SyntaxComparer.AreEquivalent(expression, nullCheck.Expression));
        }
Exemple #8
0
        private static bool CanRefactor(
            ExpressionStatementSyntax expressionStatement,
            IfStatementSyntax ifStatement,
            ExpressionSyntax expression,
            SyntaxNode parent)
        {
            ExpressionSyntax expression2 = expressionStatement.Expression;

            if (expression2?.IsKind(SyntaxKind.SimpleAssignmentExpression) == true)
            {
                var assignment = (AssignmentExpressionSyntax)expression2;

                ExpressionSyntax left = assignment.Left;

                if (left?.IsMissing == false)
                {
                    ExpressionSyntax right = assignment.Right;

                    return(right?.IsMissing == false &&
                           SyntaxComparer.AreEquivalent(expression, left) &&
                           !parent.ContainsDirectives(TextSpan.FromBounds(right.Span.End, ifStatement.Span.Start)));
                }
            }

            return(false);
        }
Exemple #9
0
        private static ImmutableArray<IfRefactoring> Analyze(
            ExpressionStatementSyntax expressionStatement,
            IfStatementSyntax ifStatement,
            IfAnalysisOptions options)
        {
            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.GetSingleStatementOrDefault());

            if (!assignment1.Success)
                return Empty;

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

            if (!assignment2.Success)
                return Empty;

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

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

            return new AssignmentAndIfElseToAssignmentWithConditionalExpression(expressionStatement, assignment.Right, ifStatement, assignment1.Right, assignment2.Right).ToImmutableArray();
        }
Exemple #10
0
        public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
        {
            var ifStatement = (IfStatementSyntax)context.Node;

            if (ifStatement.IsSimpleIf() &&
                !ifStatement.ContainsDiagnostics)
            {
                SyntaxList <StatementSyntax> statements;
                if (ifStatement.TryGetContainingList(out statements) &&
                    !IsPartOfLazyInitialization(ifStatement, statements))
                {
                    EqualsToNullExpression equalsToNull;
                    if (EqualsToNullExpression.TryCreate(ifStatement.Condition, out equalsToNull))
                    {
                        SimpleAssignmentStatement assignment;
                        if (SimpleAssignmentStatement.TryCreate(ifStatement.GetSingleStatementOrDefault(), out assignment) &&
                            SyntaxComparer.AreEquivalent(assignment.Left, equalsToNull.Left) &&
                            assignment.Right.IsSingleLine() &&
                            !ifStatement.SpanContainsDirectives())
                        {
                            int index = statements.IndexOf(ifStatement);

                            if (index > 0)
                            {
                                StatementSyntax previousStatement = statements[index - 1];

                                if (!previousStatement.ContainsDiagnostics &&
                                    CanRefactor(previousStatement, ifStatement, equalsToNull.Left, ifStatement.Parent))
                                {
                                    context.ReportDiagnostic(DiagnosticDescriptors.UseCoalesceExpression, previousStatement);
                                }
                            }

                            if (index < statements.Count - 1)
                            {
                                StatementSyntax nextStatement = statements[index + 1];

                                if (!nextStatement.ContainsDiagnostics)
                                {
                                    MemberInvocationStatement memberInvocation;
                                    if (MemberInvocationStatement.TryCreate(nextStatement, out memberInvocation) &&
                                        SyntaxComparer.AreEquivalent(equalsToNull.Left, memberInvocation.Expression) &&
                                        !ifStatement.Parent.ContainsDirectives(TextSpan.FromBounds(ifStatement.SpanStart, nextStatement.Span.End)))
                                    {
                                        context.ReportDiagnostic(DiagnosticDescriptors.InlineLazyInitialization, ifStatement);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #11
0
        private static bool CanRefactor(
            BinaryExpressionSyntax left,
            BinaryExpressionSyntax right,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (left.Right.IsKind(SyntaxKind.NullLiteralExpression))
            {
                ExpressionSyntax rightLeft = right.Left;

                ExpressionSyntax expression = left.Left;

                if (SyntaxComparer.AreEquivalent(expression, rightLeft))
                {
                    if (right.IsKind(SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression) &&
                        SymbolEquals(expression, rightLeft, semanticModel, cancellationToken) &&
                        CSharpUtility.IsEmptyString(right.Right, semanticModel, cancellationToken))
                    {
                        return(true);
                    }
                }
                else if (rightLeft.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    var memberAccess = (MemberAccessExpressionSyntax)rightLeft;

                    if (string.Equals(memberAccess.Name.Identifier.ValueText, "Length", StringComparison.Ordinal) &&
                        right.Right.IsNumericLiteralExpression("0"))
                    {
                        ISymbol symbol = semanticModel.GetSymbol(memberAccess, cancellationToken);

                        if (symbol?.IsProperty() == true)
                        {
                            var propertySymbol = (IPropertySymbol)symbol;
                            if (!propertySymbol.IsIndexer &&
                                propertySymbol.IsPublic() &&
                                !propertySymbol.IsStatic &&
                                propertySymbol.Type.IsInt() &&
                                propertySymbol.ContainingType?.IsString() == true &&
                                string.Equals(propertySymbol.Name, "Length", StringComparison.Ordinal) &&
                                SyntaxComparer.AreEquivalent(expression, memberAccess.Expression) &&
                                SymbolEquals(expression, memberAccess.Expression, semanticModel, cancellationToken))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
        public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
        {
            var ifStatement = (IfStatementSyntax)context.Node;

            if (ifStatement.IsSimpleIf() &&
                !ifStatement.ContainsDiagnostics &&
                ifStatement.TryGetContainingList(out SyntaxList <StatementSyntax> statements) &&
                !IsPartOfLazyInitialization(ifStatement, statements))
            {
                NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, semanticModel: context.SemanticModel, cancellationToken: context.CancellationToken);
                if (nullCheck.Success)
                {
                    SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(ifStatement.GetSingleStatementOrDefault());
                    if (assignmentInfo.Success &&
                        SyntaxComparer.AreEquivalent(assignmentInfo.Left, nullCheck.Expression) &&
                        assignmentInfo.Right.IsSingleLine() &&
                        !ifStatement.SpanContainsDirectives())
                    {
                        int index = statements.IndexOf(ifStatement);

                        if (index > 0)
                        {
                            StatementSyntax previousStatement = statements[index - 1];

                            if (!previousStatement.ContainsDiagnostics &&
                                CanRefactor(previousStatement, ifStatement, nullCheck.Expression, ifStatement.Parent))
                            {
                                context.ReportDiagnostic(DiagnosticDescriptors.UseCoalesceExpression, previousStatement);
                            }
                        }

                        if (index < statements.Count - 1)
                        {
                            StatementSyntax nextStatement = statements[index + 1];

                            if (!nextStatement.ContainsDiagnostics)
                            {
                                MemberInvocationStatementInfo invocationInfo = SyntaxInfo.MemberInvocationStatementInfo(nextStatement);
                                if (invocationInfo.Success &&
                                    SyntaxComparer.AreEquivalent(nullCheck.Expression, invocationInfo.Expression) &&
                                    !ifStatement.Parent.ContainsDirectives(TextSpan.FromBounds(ifStatement.SpanStart, nextStatement.Span.End)))
                                {
                                    context.ReportDiagnostic(DiagnosticDescriptors.InlineLazyInitialization, ifStatement);
                                }
                            }
                        }
                    }
                }
            }
        }
 private static void Analyze(
     SyntaxNodeAnalysisContext context,
     BinaryExpressionSyntax logicalAnd,
     ExpressionSyntax expression1,
     ExpressionSyntax expression2)
 {
     if (IsPropertyOfNullableOfT(expression2, "Value", context.SemanticModel, context.CancellationToken) &&
         SyntaxComparer.AreEquivalent(
             ((MemberAccessExpressionSyntax)expression1).Expression,
             ((MemberAccessExpressionSyntax)expression2).Expression,
             requireNotNull: true))
     {
         context.ReportDiagnostic(DiagnosticDescriptors.SimplifyBooleanExpression, logicalAnd);
     }
 }
Exemple #14
0
        public static bool CanRefactor(
            IfStatementSyntax ifStatement,
            SemanticModel semanticModel,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (ifStatement.IsTopmostIf())
            {
                ElseClauseSyntax elseClause = ifStatement.Else;

                if (elseClause != null)
                {
                    ExpressionSyntax condition = ifStatement.Condition;

                    if (condition != null)
                    {
                        ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(condition, cancellationToken);

                        if (typeSymbol?.IsBoolean() == true)
                        {
                            AssignmentExpressionSyntax trueExpression = GetSimpleAssignmentExpression(ifStatement.GetSingleStatementOrDefault());

                            ExpressionSyntax trueRight = trueExpression?.Right;

                            if (trueRight?.Kind().IsBooleanLiteralExpression() == true)
                            {
                                AssignmentExpressionSyntax falseExpression = GetSimpleAssignmentExpression(elseClause.GetSingleStatementOrDefault());

                                ExpressionSyntax falseRight = falseExpression?.Right;

                                if (falseRight?.Kind().IsBooleanLiteralExpression() == true)
                                {
                                    var trueBooleanLiteral  = (LiteralExpressionSyntax)trueRight;
                                    var falseBooleanLiteral = (LiteralExpressionSyntax)falseRight;

                                    if (trueBooleanLiteral.IsKind(SyntaxKind.TrueLiteralExpression) != falseBooleanLiteral.IsKind(SyntaxKind.TrueLiteralExpression) &&
                                        SyntaxComparer.AreEquivalent(trueExpression.Left, falseExpression.Left, requireNotNull: true))
                                    {
                                        return(true);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
        private static bool AreStatementsEquivalent(List <StatementSyntax> first, List <StatementSyntax> second)
        {
            if (first.Count == second.Count)
            {
                for (int i = 0; i < first.Count; i++)
                {
                    if (!SyntaxComparer.AreEquivalent(first[i], second[i]))
                    {
                        return(false);
                    }
                }

                return(true);
            }

            return(false);
        }
Exemple #16
0
        private static bool NullCheckExists(ExpressionSyntax expression, StatementSyntax statement)
        {
            if (!statement.IsEmbedded())
            {
                StatementContainer container;
                if (StatementContainer.TryCreate(statement, out container))
                {
                    SyntaxList <StatementSyntax> statements = container.Statements;

                    int index = statements.IndexOf(statement);

                    if (index < statements.Count - 1)
                    {
                        StatementSyntax nextStatement = statements[index + 1];

                        if (nextStatement.IsKind(SyntaxKind.IfStatement))
                        {
                            var ifStatement = (IfStatementSyntax)nextStatement;

                            ExpressionSyntax condition = ifStatement.Condition;

                            if (condition?.IsKind(SyntaxKind.NotEqualsExpression) == true)
                            {
                                var notEqualsExpression = (BinaryExpressionSyntax)condition;

                                ExpressionSyntax left = notEqualsExpression.Left;

                                if (SyntaxComparer.AreEquivalent(left, expression, requireNotNull: true))
                                {
                                    ExpressionSyntax right = notEqualsExpression.Right;

                                    if (right?.IsKind(SyntaxKind.NullLiteralExpression) == true)
                                    {
                                        return(true);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
Exemple #17
0
        public static void AnalyzeSimpleAssignmentExpression(SyntaxNodeAnalysisContext context)
        {
            if (context.Node.SpanContainsDirectives())
            {
                return;
            }

            var assignment = (AssignmentExpressionSyntax)context.Node;

            if (!assignment.IsParentKind(SyntaxKind.ObjectInitializerExpression))
            {
                ExpressionSyntax left  = assignment.Left;
                ExpressionSyntax right = assignment.Right;

                if (left?.IsMissing == false &&
                    right?.IsKind(SyntaxKind.AddExpression, SyntaxKind.SubtractExpression) == true)
                {
                    var binaryExpression = (BinaryExpressionSyntax)right;

                    ExpressionSyntax binaryLeft  = binaryExpression.Left;
                    ExpressionSyntax binaryRight = binaryExpression.Right;

                    if (binaryLeft?.IsMissing == false &&
                        binaryRight?.IsNumericLiteralExpression("1") == true)
                    {
                        ITypeSymbol typeSymbol = context.SemanticModel.GetTypeSymbol(left, context.CancellationToken);

                        if (typeSymbol?.SupportsPrefixOrPostfixUnaryOperator() == true &&
                            SyntaxComparer.AreEquivalent(left, binaryLeft))
                        {
                            string operatorText = GetOperatorText(assignment);

                            ReportDiagnostic(context, assignment, operatorText);

                            context.ReportToken(DiagnosticDescriptors.UsePostfixUnaryOperatorInsteadOfAssignmentFadeOut, assignment.OperatorToken, operatorText);
                            context.ReportNode(DiagnosticDescriptors.UsePostfixUnaryOperatorInsteadOfAssignmentFadeOut, binaryLeft, operatorText);
                            context.ReportNode(DiagnosticDescriptors.UsePostfixUnaryOperatorInsteadOfAssignmentFadeOut, binaryRight, operatorText);
                        }
                    }
                }
            }
        }
        public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context, INamedTypeSymbol expressionType)
        {
            var ifStatement = (IfStatementSyntax)context.Node;

            if (ifStatement.IsSimpleIf() &&
                !ifStatement.ContainsDiagnostics)
            {
                NotEqualsToNullExpression notEqualsToNull;
                if (NotEqualsToNullExpression.TryCreate(ifStatement.Condition, out notEqualsToNull))
                {
                    MemberInvocationStatement memberInvocation;
                    if (MemberInvocationStatement.TryCreate(ifStatement.GetSingleStatementOrDefault(), out memberInvocation) &&
                        SyntaxComparer.AreEquivalent(notEqualsToNull.Left, memberInvocation.Expression) &&
                        !ifStatement.IsInExpressionTree(expressionType, context.SemanticModel, context.CancellationToken) &&
                        !ifStatement.SpanContainsDirectives())
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.UseConditionalAccess, ifStatement);
                    }
                }
            }
        }
Exemple #19
0
        public static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context, INamedTypeSymbol expressionType)
        {
            var ifStatement = (IfStatementSyntax)context.Node;

            if (ifStatement.IsSimpleIf() &&
                !ifStatement.ContainsDiagnostics)
            {
                NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, allowedKinds: NullCheckKind.NotEqualsToNull);
                if (nullCheck.Success)
                {
                    MemberInvocationStatementInfo invocationInfo = SyntaxInfo.MemberInvocationStatementInfo(ifStatement.GetSingleStatementOrDefault());
                    if (invocationInfo.Success &&
                        SyntaxComparer.AreEquivalent(nullCheck.Expression, invocationInfo.Expression) &&
                        !ifStatement.IsInExpressionTree(expressionType, context.SemanticModel, context.CancellationToken) &&
                        !ifStatement.SpanContainsDirectives())
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.UseConditionalAccess, ifStatement);
                    }
                }
            }
        }
Exemple #20
0
        public static void AnalyzeLogicalOrExpression(SyntaxNodeAnalysisContext context)
        {
            SyntaxNode node = context.Node;

            if (node.ContainsDiagnostics)
            {
                return;
            }

            if (node.SpanContainsDirectives())
            {
                return;
            }

            var logicalOr = (BinaryExpressionSyntax)context.Node;

            ExpressionSyntax left = logicalOr.Left.WalkDownParentheses();

            ExpressionSyntax right = logicalOr.Right.WalkDownParentheses();

            if (left.IsKind(SyntaxKind.LogicalAndExpression) &&
                right.IsKind(SyntaxKind.LogicalAndExpression))
            {
                ExpressionPair expressions = GetExpressionPair((BinaryExpressionSyntax)left);

                if (expressions.IsValid)
                {
                    ExpressionPair expressions2 = GetExpressionPair((BinaryExpressionSyntax)right);

                    if (expressions2.IsValid &&
                        (expressions.Expression.Kind() == expressions2.NegatedExpression.Kind() &&
                         expressions.NegatedExpression.Kind() == expressions2.Expression.Kind() &&
                         SyntaxComparer.AreEquivalent(expressions.Expression, expressions2.NegatedExpression) &&
                         SyntaxComparer.AreEquivalent(expressions.NegatedExpression, expressions2.Expression)))
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.UseExclusiveOrOperator, logicalOr);
                    }
                }
            }
        }
Exemple #21
0
        public static void ComputeRefactorings(RefactoringContext context, StatementContainerSelection selectedStatements)
        {
            using (IEnumerator <StatementSyntax> en = selectedStatements.GetEnumerator())
            {
                if (en.MoveNext() &&
                    en.Current.IsKind(SyntaxKind.ExpressionStatement))
                {
                    var statement = (ExpressionStatementSyntax)en.Current;

                    if (statement.Expression?.IsKind(SyntaxKind.SimpleAssignmentExpression) == true &&
                        en.MoveNext() &&
                        en.Current.IsKind(SyntaxKind.ReturnStatement))
                    {
                        var returnStatement = (ReturnStatementSyntax)en.Current;

                        if (returnStatement.Expression != null &&
                            !en.MoveNext())
                        {
                            var assignment = (AssignmentExpressionSyntax)statement.Expression;

                            if (assignment.Left?.IsMissing == false &&
                                assignment.Right?.IsMissing == false &&
                                SyntaxComparer.AreEquivalent(assignment.Left, returnStatement.Expression))
                            {
                                context.RegisterRefactoring(
                                    "Merge statements",
                                    cancellationToken =>
                                {
                                    return(RefactorAsync(
                                               context.Document,
                                               statement,
                                               returnStatement,
                                               cancellationToken));
                                });
                            }
                        }
                    }
                }
            }
        }
        private static bool IsFixableEqualsExpression(
            BinaryExpressionSyntax equalsExpression,
            ExpressionSyntax switchExpression,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax left = equalsExpression.Left?.WalkDownParentheses();

            if (IsFixableSwitchExpression(left, semanticModel, cancellationToken))
            {
                ExpressionSyntax right = equalsExpression.Right?.WalkDownParentheses();

                if (IsFixableSwitchExpression(right, semanticModel, cancellationToken) &&
                    semanticModel.GetConstantValue(right).HasValue)
                {
                    return(switchExpression == null ||
                           SyntaxComparer.AreEquivalent(left, switchExpression));
                }
            }

            return(false);
        }
        private static bool IsFixable(
            StatementSyntax statement,
            ExpressionSyntax expression,
            INamedTypeSymbol stringBuilderSymbol,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (statement.IsKind(SyntaxKind.ExpressionStatement) &&
                !statement.SpanOrLeadingTriviaContainsDirectives())
            {
                var expressionStatement = (ExpressionStatementSyntax)statement;

                MemberInvocationExpression memberInvocation;

                return(MemberInvocationExpression.TryCreate(expressionStatement.Expression, out memberInvocation) &&
                       IsFixable(memberInvocation, stringBuilderSymbol, semanticModel, cancellationToken) &&
                       SyntaxComparer.AreEquivalent(
                           expression,
                           GetFirstInvocationInMethodChain(memberInvocation, stringBuilderSymbol, semanticModel, cancellationToken).Expression,
                           requireNotNull: true));
            }

            return(false);
        }
Exemple #24
0
        public static async Task <Document> RefactorAsync(
            Document document,
            ConditionalExpressionSyntax conditionalExpression,
            CancellationToken cancellationToken)
        {
            SemanticModel semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(false);

            ConditionalExpressionInfo.TryCreate(conditionalExpression, out ConditionalExpressionInfo conditionalExpressionInfo);

            NullCheckExpression.TryCreate(conditionalExpressionInfo.Condition, semanticModel, out NullCheckExpression nullCheck, cancellationToken);

            ExpressionSyntax whenNotNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenTrue : conditionalExpressionInfo.WhenFalse;

            ExpressionSyntax whenNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenFalse : conditionalExpressionInfo.WhenTrue;

            ExpressionSyntax expression = UseConditionalAccessRefactoring.FindExpressionThatCanBeConditionallyAccessed(nullCheck.Expression, whenNotNull);

            bool coalesce = false;

            ExpressionSyntax newNode = null;

            if (SyntaxComparer.AreEquivalent(nullCheck.Expression, whenNotNull))
            {
                newNode  = nullCheck.Expression;
                coalesce = true;
            }
            else if (semanticModel
                     .GetTypeSymbol(nullCheck.Expression, cancellationToken)
                     .IsConstructedFrom(SpecialType.System_Nullable_T))
            {
                if (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    var memberAccessExpression = (MemberAccessExpressionSyntax)expression.Parent;

                    if (!memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) &&
                        (memberAccessExpression.Name as IdentifierNameSyntax)?.Identifier.ValueText == "Value")
                    {
                        if (memberAccessExpression == whenNotNull)
                        {
                            newNode  = nullCheck.Expression;
                            coalesce = true;
                        }
                        else
                        {
                            newNode = ParseExpression($"{expression}?{whenNotNull.ToString().Substring(memberAccessExpression.Span.End - whenNotNull.SpanStart)}");
                        }
                    }
                }
            }

            if (newNode == null)
            {
                newNode = ParseExpression(whenNotNull.ToString().Insert(expression.Span.End - whenNotNull.SpanStart, "?"));
            }

            if (coalesce || !semanticModel.GetTypeSymbol(whenNotNull, cancellationToken).IsReferenceType)
            {
                newNode = CoalesceExpression(newNode.Parenthesize(), whenNull.Parenthesize());
            }

            newNode = newNode
                      .WithTriviaFrom(conditionalExpression)
                      .Parenthesize();

            return(await document.ReplaceNodeAsync(conditionalExpression, newNode, cancellationToken).ConfigureAwait(false));
        }
Exemple #25
0
        public static void AnalyzeUsingStatement(SyntaxNodeAnalysisContext context)
        {
            var usingStatement = (UsingStatementSyntax)context.Node;

            StatementSyntax statement = usingStatement.Statement;

            if (statement?.IsKind(SyntaxKind.Block) == true)
            {
                var block = (BlockSyntax)statement;

                StatementSyntax lastStatement = block.Statements.LastOrDefault();

                if (lastStatement?.IsKind(SyntaxKind.ExpressionStatement) == true)
                {
                    var expressionStatement = (ExpressionStatementSyntax)lastStatement;

                    ExpressionSyntax expression = expressionStatement.Expression;

                    if (expression?.IsKind(SyntaxKind.InvocationExpression) == true)
                    {
                        var invocation = (InvocationExpressionSyntax)expression;

                        ExpressionSyntax invocationExpression = invocation.Expression;

                        if (invocationExpression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true)
                        {
                            var memberAccess = (MemberAccessExpressionSyntax)invocationExpression;

                            if (invocation.ArgumentList?.Arguments.Count == 0)
                            {
                                string methodName = memberAccess.Name?.Identifier.ValueText;

                                if (methodName == "Dispose" || methodName == "Close")
                                {
                                    ExpressionSyntax memberAccessExpression = memberAccess.Expression;

                                    if (memberAccessExpression != null)
                                    {
                                        ExpressionSyntax usingExpression = usingStatement.Expression;

                                        if (usingExpression != null)
                                        {
                                            if (SyntaxComparer.AreEquivalent(memberAccessExpression, usingExpression))
                                            {
                                                ReportDiagnostic(context, expressionStatement, methodName);
                                            }
                                        }
                                        else if (memberAccessExpression.IsKind(SyntaxKind.IdentifierName))
                                        {
                                            VariableDeclarationSyntax usingDeclaration = usingStatement.Declaration;

                                            if (usingDeclaration != null)
                                            {
                                                var identifierName = (IdentifierNameSyntax)memberAccessExpression;

                                                string name = identifierName.Identifier.ValueText;

                                                VariableDeclaratorSyntax declarator = usingDeclaration.Variables.LastOrDefault();

                                                if (declarator != null &&
                                                    declarator.Identifier.ValueText == name)
                                                {
                                                    ISymbol symbol = context.SemanticModel.GetDeclaredSymbol(declarator, context.CancellationToken);

                                                    if (symbol?.Equals(context.SemanticModel.GetSymbol(identifierName, context.CancellationToken)) == true)
                                                    {
                                                        ReportDiagnostic(context, expressionStatement, methodName);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        private static ImmutableArray <IfRefactoring> Analyze(
            IfStatementSyntax ifStatement,
            ExpressionSyntax condition,
            ExpressionStatementSyntax expressionStatement1,
            ExpressionStatementSyntax expressionStatement2,
            IfAnalysisOptions options,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            SimpleAssignmentStatementInfo assignment1 = SyntaxInfo.SimpleAssignmentStatementInfo(expressionStatement1);

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

            SimpleAssignmentStatementInfo assignment2 = SyntaxInfo.SimpleAssignmentStatementInfo(expressionStatement2);

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

            ExpressionSyntax left1  = assignment1.Left;
            ExpressionSyntax left2  = assignment2.Left;
            ExpressionSyntax right1 = assignment1.Right;
            ExpressionSyntax right2 = assignment2.Right;

            if (!SyntaxComparer.AreEquivalent(left1, left2))
            {
                return(Empty);
            }

            if (options.UseCoalesceExpression ||
                options.UseExpression)
            {
                SyntaxKind kind1 = right1.Kind();
                SyntaxKind kind2 = right2.Kind();

                if (kind1.IsBooleanLiteralExpression() &&
                    kind2.IsBooleanLiteralExpression() &&
                    kind1 != kind2)
                {
                    if (options.UseExpression)
                    {
                        return(new IfElseToAssignmentWithCondition(ifStatement, left1, condition, negate: kind1 == SyntaxKind.FalseLiteralExpression).ToImmutableArray());
                    }

                    return(Empty);
                }

                NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(condition, semanticModel: semanticModel, cancellationToken: cancellationToken);

                if (nullCheck.Success)
                {
                    IfRefactoring refactoring = CreateIfToAssignment(
                        ifStatement,
                        left1,
                        (nullCheck.IsCheckingNull) ? right2 : right1,
                        (nullCheck.IsCheckingNull) ? right1 : right2,
                        nullCheck,
                        options,
                        semanticModel,
                        cancellationToken);

                    if (refactoring != null)
                    {
                        return(refactoring.ToImmutableArray());
                    }
                }
            }

            if (options.UseConditionalExpression)
            {
                return(new IfElseToAssignmentWithConditionalExpression(ifStatement, left1, right1, right2).ToImmutableArray());
            }

            return(Empty);
        }
Exemple #27
0
        private static ImmutableArray <IfRefactoring> Analyze(
            IfStatementSyntax ifStatement,
            ExpressionSyntax condition,
            ExpressionStatementSyntax expressionStatement1,
            ExpressionStatementSyntax expressionStatement2,
            SemanticModel semanticModel,
            CancellationToken cancellationToken,
            IfAnalysisOptions options)
        {
            ExpressionSyntax expression1 = expressionStatement1.Expression;

            if (IsSimpleAssignment(expression1))
            {
                ExpressionSyntax expression2 = expressionStatement2.Expression;

                if (IsSimpleAssignment(expression2))
                {
                    var assignment1 = (AssignmentExpressionSyntax)expression1;
                    var assignment2 = (AssignmentExpressionSyntax)expression2;

                    ExpressionSyntax left1  = assignment1.Left;
                    ExpressionSyntax right1 = assignment1.Right;

                    if (left1?.IsMissing == false &&
                        right1?.IsMissing == false)
                    {
                        ExpressionSyntax left2  = assignment2.Left;
                        ExpressionSyntax right2 = assignment2.Right;

                        if (left2?.IsMissing == false &&
                            right2?.IsMissing == false &&
                            SyntaxComparer.AreEquivalent(left1, left2))
                        {
                            if (options.UseCoalesceExpression)
                            {
                                NullCheckExpression nullCheck;
                                if (NullCheckExpression.TryCreate(condition, semanticModel, out nullCheck, cancellationToken))
                                {
                                    IfRefactoring refactoring = CreateIfToAssignmentWithWithCoalesceExpression(
                                        ifStatement,
                                        left1,
                                        (nullCheck.IsCheckingNull) ? right2 : right1,
                                        (nullCheck.IsCheckingNull) ? right1 : right2,
                                        nullCheck,
                                        semanticModel,
                                        cancellationToken);

                                    if (refactoring != null)
                                    {
                                        return(refactoring.ToImmutableArray());
                                    }
                                }
                            }

                            if (options.UseConditionalExpression)
                            {
                                return(new IfElseToAssignmentWithConditionalExpression(ifStatement, left1, right1, right2).ToImmutableArray());
                            }
                        }
                    }
                }
            }

            return(ImmutableArray <IfRefactoring> .Empty);
        }
Exemple #28
0
        public static void AnalyzeConditionalExpression(SyntaxNodeAnalysisContext context)
        {
            if (context.Node.SpanContainsDirectives())
            {
                return;
            }

            var conditionalExpression = (ConditionalExpressionSyntax)context.Node;

            if (!ConditionalExpressionInfo.TryCreate(conditionalExpression, out ConditionalExpressionInfo conditionalExpressionInfo))
            {
                return;
            }

            SemanticModel     semanticModel     = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            if (!NullCheckExpression.TryCreate(conditionalExpressionInfo.Condition, semanticModel, out NullCheckExpression nullCheck, cancellationToken))
            {
                return;
            }

            ExpressionSyntax whenNotNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenTrue : conditionalExpressionInfo.WhenFalse;

            ExpressionSyntax whenNull = (nullCheck.IsCheckingNotNull) ? conditionalExpressionInfo.WhenFalse : conditionalExpressionInfo.WhenTrue;

            if (SyntaxComparer.AreEquivalent(nullCheck.Expression, whenNotNull))
            {
                if (semanticModel
                    .GetTypeSymbol(nullCheck.Expression, cancellationToken)?
                    .IsReferenceTypeOrNullableType() == true)
                {
                    context.ReportDiagnostic(
                        DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression,
                        conditionalExpression);
                }
            }
            else if (whenNotNull.IsKind(
                         SyntaxKind.SimpleMemberAccessExpression,
                         SyntaxKind.ElementAccessExpression,
                         SyntaxKind.ConditionalAccessExpression,
                         SyntaxKind.InvocationExpression))
            {
                ExpressionSyntax expression = UseConditionalAccessRefactoring.FindExpressionThatCanBeConditionallyAccessed(nullCheck.Expression, whenNotNull);

                if (expression == null)
                {
                    return;
                }

                ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken);

                if (typeSymbol == null)
                {
                    return;
                }

                if (typeSymbol.IsReferenceType)
                {
                    Analyze(context, conditionalExpressionInfo, whenNull, whenNotNull, semanticModel, cancellationToken);
                }
                else if (typeSymbol.IsConstructedFrom(SpecialType.System_Nullable_T))
                {
                    if (expression.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
                    {
                        var memberAccessExpression = (MemberAccessExpressionSyntax)expression.Parent;

                        if (!memberAccessExpression.IsParentKind(SyntaxKind.InvocationExpression) &&
                            (memberAccessExpression.Name as IdentifierNameSyntax)?.Identifier.ValueText == "Value")
                        {
                            if (memberAccessExpression == whenNotNull)
                            {
                                context.ReportDiagnostic(
                                    DiagnosticDescriptors.UseCoalesceExpressionInsteadOfConditionalExpression,
                                    conditionalExpression);
                            }
                            else
                            {
                                Analyze(context, conditionalExpressionInfo, whenNull, whenNotNull, semanticModel, cancellationToken);
                            }
                        }
                    }
                }
            }
        }
        private static BinaryExpressionPart GetRedundantPart(
            ExpressionSyntax left,
            ExpressionSyntax right,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            SyntaxKind leftKind  = left.Kind();
            SyntaxKind rightKind = right.Kind();

            switch (leftKind)
            {
            case SyntaxKind.ObjectCreationExpression:
            case SyntaxKind.AnonymousObjectCreationExpression:
            case SyntaxKind.ArrayCreationExpression:
            case SyntaxKind.ImplicitArrayCreationExpression:
            case SyntaxKind.InterpolatedStringExpression:
            case SyntaxKind.ThisExpression:
            case SyntaxKind.StringLiteralExpression:
            case SyntaxKind.TypeOfExpression:
                return(BinaryExpressionPart.Right);

            case SyntaxKind.NullLiteralExpression:
                return(BinaryExpressionPart.Left);

            case SyntaxKind.DefaultExpression:
            {
                if (IsDefaultOfReferenceType((DefaultExpressionSyntax)left, semanticModel, cancellationToken))
                {
                    return(BinaryExpressionPart.Left);
                }

                break;
            }
            }

            Optional <object> optional = semanticModel.GetConstantValue(left, cancellationToken);

            if (optional.HasValue)
            {
                object value = optional.Value;

                if (value != null)
                {
                    return(BinaryExpressionPart.Right);
                }
                else
                {
                    return(BinaryExpressionPart.Left);
                }
            }

            ITypeSymbol leftSymbol = semanticModel.GetTypeSymbol(left, cancellationToken);

            if (leftSymbol?.IsErrorType() == false &&
                leftSymbol.IsValueType &&
                !leftSymbol.IsConstructedFrom(SpecialType.System_Nullable_T))
            {
                return(BinaryExpressionPart.Right);
            }

            switch (rightKind)
            {
            case SyntaxKind.NullLiteralExpression:
                return(BinaryExpressionPart.Right);

            case SyntaxKind.DefaultExpression:
            {
                if (IsDefaultOfReferenceType((DefaultExpressionSyntax)right, semanticModel, cancellationToken))
                {
                    return(BinaryExpressionPart.Right);
                }

                break;
            }
            }

            if (leftKind == rightKind &&
                SyntaxComparer.AreEquivalent(left, right))
            {
                return(BinaryExpressionPart.Right);
            }

            return(BinaryExpressionPart.None);
        }