コード例 #1
0
        private static ExpressionSyntax GetNullableOfTValueProperty(ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (expression.Kind() != SyntaxKind.SimpleMemberAccessExpression)
            {
                return(null);
            }

            var memberAccessExpression = (MemberAccessExpressionSyntax)expression;

            if (!(memberAccessExpression.Name is IdentifierNameSyntax identifierName))
            {
                return(null);
            }

            if (!string.Equals(identifierName.Identifier.ValueText, "Value", StringComparison.Ordinal))
            {
                return(null);
            }

            if (!SyntaxUtility.IsPropertyOfNullableOfT(expression, "Value", semanticModel, cancellationToken))
            {
                return(null);
            }

            return(memberAccessExpression.Expression);
        }
コード例 #2
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);
        }
コード例 #3
0
 private static bool IsPropertyOfNullableOfT(
     ExpressionSyntax expression,
     string name,
     SemanticModel semanticModel,
     CancellationToken cancellationToken)
 {
     return(expression?.Kind() == SyntaxKind.IdentifierName &&
            string.Equals(((IdentifierNameSyntax)expression).Identifier.ValueText, name, StringComparison.Ordinal) &&
            SyntaxUtility.IsPropertyOfNullableOfT(expression, name, semanticModel, cancellationToken));
 }
コード例 #4
0
        private static bool IsPropertyOfNullableOfT(ExpressionSyntax expression, string name, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (expression?.Kind() == SyntaxKind.SimpleMemberAccessExpression)
            {
                var memberAccessExpression = (MemberAccessExpressionSyntax)expression;

                SimpleNameSyntax simpleName = memberAccessExpression.Name;

                if (simpleName?.Kind() == SyntaxKind.IdentifierName)
                {
                    var identifierName = (IdentifierNameSyntax)simpleName;

                    return(string.Equals(identifierName.Identifier.ValueText, name, StringComparison.Ordinal) &&
                           SyntaxUtility.IsPropertyOfNullableOfT(expression, name, semanticModel, cancellationToken));
                }
            }

            return(false);
        }
コード例 #5
0
        private static void AnalyzeLogicalAndExpression(SyntaxNodeAnalysisContext context)
        {
            var logicalAnd = (BinaryExpressionSyntax)context.Node;

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

            BinaryExpressionInfo logicalAndInfo = SyntaxInfo.BinaryExpressionInfo(logicalAnd);

            if (!logicalAndInfo.Success)
            {
                return;
            }

            NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(
                logicalAndInfo.Left,
                context.SemanticModel,
                NullCheckStyles.NotEqualsToNull | NullCheckStyles.HasValue,
                cancellationToken: context.CancellationToken);

            if (!nullCheck.Success)
            {
                return;
            }

            ExpressionSyntax right = logicalAndInfo.Right;

            switch (right.Kind())
            {
            case SyntaxKind.LogicalNotExpression:
            {
                var logicalNot = (PrefixUnaryExpressionSyntax)right;

                Analyze(nullCheck.Expression, logicalNot.Operand?.WalkDownParentheses(), null);
                break;
            }

            case SyntaxKind.EqualsExpression:
            case SyntaxKind.LessThanExpression:
            case SyntaxKind.LessThanOrEqualExpression:
            case SyntaxKind.GreaterThanExpression:
            case SyntaxKind.GreaterThanOrEqualExpression:
            {
                BinaryExpressionInfo binaryExpressionInfo = SyntaxInfo.BinaryExpressionInfo((BinaryExpressionSyntax)right);

                if (!binaryExpressionInfo.Success)
                {
                    break;
                }

                ExpressionSyntax left = binaryExpressionInfo.Left;

                Analyze(nullCheck.Expression, left, binaryExpressionInfo.Right);
                break;
            }

            case SyntaxKind.SimpleMemberAccessExpression:
            {
                AnalyzeSimpleMemberAccessExpression(nullCheck.Expression, (MemberAccessExpressionSyntax)right, null);
                break;
            }
            }

            void Analyze(ExpressionSyntax expression1, ExpressionSyntax expression2, ExpressionSyntax expression3)
            {
                if (expression2.IsKind(SyntaxKind.SimpleMemberAccessExpression))
                {
                    AnalyzeSimpleMemberAccessExpression(expression1, (MemberAccessExpressionSyntax)expression2, expression3);
                }
            }

            void AnalyzeSimpleMemberAccessExpression(ExpressionSyntax expression, MemberAccessExpressionSyntax memberAccessExpression, ExpressionSyntax expression3)
            {
                if (memberAccessExpression.Name is not IdentifierNameSyntax identifierName ||
                    !string.Equals(identifierName.Identifier.ValueText, "Value", StringComparison.Ordinal))
                {
                    return;
                }

                if (!SyntaxUtility.IsPropertyOfNullableOfT(memberAccessExpression, "Value", context.SemanticModel, context.CancellationToken))
                {
                    return;
                }

                if (!AreEquivalent(expression, memberAccessExpression.Expression))
                {
                    return;
                }

                if (expression3 != null)
                {
                    switch (expression3.Kind())
                    {
                    case SyntaxKind.NumericLiteralExpression:
                    case SyntaxKind.StringLiteralExpression:
                    case SyntaxKind.CharacterLiteralExpression:
                    case SyntaxKind.TrueLiteralExpression:
                    case SyntaxKind.FalseLiteralExpression:
                    {
                        break;
                    }

                    case SyntaxKind.NullLiteralExpression:
                    case SyntaxKind.DefaultLiteralExpression:
                    {
                        return;
                    }

                    default:
                    {
                        if (context.SemanticModel.GetTypeSymbol(expression3, context.CancellationToken).IsNullableType())
                        {
                            return;
                        }

                        break;
                    }
                    }
                }

                DiagnosticHelpers.ReportDiagnostic(context, DiagnosticRules.UnnecessaryNullCheck, logicalAnd);
            }
        }
コード例 #6
0
        public static bool TryCreate(
            SyntaxNode node,
            SemanticModel semanticModel,
            out NullCheckExpression result,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            if (node != null)
            {
                var expression = node as ExpressionSyntax;

                if (expression != null)
                {
                    expression = expression.WalkDownParentheses();

                    SyntaxKind kind = expression.Kind();

                    switch (kind)
                    {
                    case SyntaxKind.EqualsExpression:
                    case SyntaxKind.NotEqualsExpression:
                    {
                        var binaryExpression = (BinaryExpressionSyntax)expression;

                        ExpressionSyntax left  = binaryExpression.Left?.WalkDownParentheses();
                        ExpressionSyntax right = binaryExpression.Right?.WalkDownParentheses();

                        return(TryCreate(binaryExpression, kind, left, right, semanticModel, cancellationToken, out result) ||
                               TryCreate(binaryExpression, kind, right, left, semanticModel, cancellationToken, out result));
                    }

                    case SyntaxKind.SimpleMemberAccessExpression:
                    {
                        if (SyntaxUtility.IsPropertyOfNullableOfT(expression, "HasValue", semanticModel, cancellationToken))
                        {
                            var memberAccessExpression = (MemberAccessExpressionSyntax)expression;

                            result = new NullCheckExpression(expression, memberAccessExpression.Expression, NullCheckKind.HasValue);
                            return(true);
                        }

                        break;
                    }

                    case SyntaxKind.LogicalNotExpression:
                    {
                        var logicalNotExpression = (PrefixUnaryExpressionSyntax)expression;

                        ExpressionSyntax operand = logicalNotExpression.Operand?.WalkDownParentheses();

                        if (operand?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true &&
                            SyntaxUtility.IsPropertyOfNullableOfT(operand, "HasValue", semanticModel, cancellationToken))
                        {
                            var memberAccessExpression = (MemberAccessExpressionSyntax)operand;

                            result = new NullCheckExpression(expression, memberAccessExpression.Expression, NullCheckKind.NotHasValue);
                            return(true);
                        }

                        break;
                    }
                    }
                }
            }

            result = default(NullCheckExpression);
            return(false);
        }
コード例 #7
0
        private static bool TryCreate(
            BinaryExpressionSyntax binaryExpression,
            SyntaxKind kind,
            ExpressionSyntax expression1,
            ExpressionSyntax expression2,
            SemanticModel semanticModel,
            CancellationToken cancellationToken,
            out NullCheckExpression result)
        {
            if (expression1 != null &&
                expression2 != null)
            {
                switch (expression1.Kind())
                {
                case SyntaxKind.NullLiteralExpression:
                {
                    result = new NullCheckExpression(
                        binaryExpression,
                        expression2,
                        (kind == SyntaxKind.EqualsExpression) ? NullCheckKind.EqualsToNull : NullCheckKind.NotEqualsToNull);

                    return(true);
                }

                case SyntaxKind.TrueLiteralExpression:
                {
                    if (expression2?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true &&
                        SyntaxUtility.IsPropertyOfNullableOfT(expression2, "HasValue", semanticModel, cancellationToken))
                    {
                        result = new NullCheckExpression(
                            binaryExpression,
                            ((MemberAccessExpressionSyntax)expression2).Expression,
                            (kind == SyntaxKind.EqualsExpression) ? NullCheckKind.HasValue : NullCheckKind.NotHasValue);

                        return(true);
                    }

                    break;
                }

                case SyntaxKind.FalseLiteralExpression:
                {
                    if (expression2?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true &&
                        SyntaxUtility.IsPropertyOfNullableOfT(expression2, "HasValue", semanticModel, cancellationToken))
                    {
                        result = new NullCheckExpression(
                            binaryExpression,
                            ((MemberAccessExpressionSyntax)expression2).Expression,
                            (kind == SyntaxKind.EqualsExpression) ? NullCheckKind.NotHasValue : NullCheckKind.HasValue);

                        return(true);
                    }

                    break;
                }
                }
            }

            result = default(NullCheckExpression);
            return(false);
        }
コード例 #8
0
        private static IdentifierNameSyntax GetIdentifierName(
            ExpressionSyntax expression,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (expression == null)
            {
                return(null);
            }

            if (expression is IdentifierNameSyntax identifierName)
            {
                return(identifierName);
            }

            if (expression.Kind() != SyntaxKind.SimpleMemberAccessExpression)
            {
                return(null);
            }

            var memberAccess = (MemberAccessExpressionSyntax)expression;

            ExpressionSyntax expression2 = memberAccess.Expression;

            switch (expression2?.Kind())
            {
            case SyntaxKind.SimpleMemberAccessExpression:
            {
                var memberAccess2 = (MemberAccessExpressionSyntax)expression2;

                if (memberAccess2.Expression?.Kind() != SyntaxKind.ThisExpression)
                {
                    return(null);
                }

                if (!SyntaxUtility.IsPropertyOfNullableOfT(memberAccess.Name as IdentifierNameSyntax, "Value", semanticModel, cancellationToken))
                {
                    return(null);
                }

                return(memberAccess2.Name as IdentifierNameSyntax);
            }

            case SyntaxKind.ThisExpression:
            {
                return(memberAccess.Name as IdentifierNameSyntax);
            }

            case SyntaxKind.IdentifierName:
            {
                if (!SyntaxUtility.IsPropertyOfNullableOfT(memberAccess.Name as IdentifierNameSyntax, "Value", semanticModel, cancellationToken))
                {
                    return(null);
                }

                return((IdentifierNameSyntax)expression2);
            }
            }

            return(null);
        }