/// <summary>
        /// This strategy uses the names and needs the whole array of base types, not just one type in the base list.
        /// </summary>
        /// <param name="baseTypeInfo"></param>
        private List <BaseTypeReference> DiscriminateByName(IEnumerable <BaseTypeSyntax> simpleBaseTypes)
        {
            var baseTypes = new List <BaseTypeReference>();
            IEnumerable <SemanticUtilities.BaseTypeInfo> baseTypeInfos = SemanticUtilities.SeparateClassAndInterfacesBasedOnNames(simpleBaseTypes);

            foreach (var baseTypeInfo in baseTypeInfos)
            {
                // Semantic model passed for consistency, but here is actually null
                switch (baseTypeInfo.Kind)
                {
                case Roslyn.TypeKind.Class:
                    baseTypes.Add(this.CreateBaseTypeReferenceHelper(baseTypeInfo.Node, this.SemanticModel, Roslyn.TypeKind.Class));
                    break;

                case Roslyn.TypeKind.Interface:
                    baseTypes.Add(this.CreateBaseTypeReferenceHelper(baseTypeInfo.Node, this.SemanticModel, Roslyn.TypeKind.Interface));
                    break;

                default:
                    // Not recognized, skip it
                    continue;
                }
            }

            return(baseTypes);
        }
Exemple #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 (IsEquivalent(nullCheck.Expression, expression1))
                {
                    return(new IfElseToAssignmentWithCoalesceExpression(ifStatement, left, expression1, expression2));
                }
            }

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

                if (IsEquivalent(nullCheck.Expression, expression1))
                {
                    return(new IfElseToAssignmentWithCoalesceExpression(ifStatement, left, expression1, expression2));
                }
            }

            return(null);
        }
Exemple #3
0
        private static IfRefactoring CreateIfToReturnWithCoalesceExpression(
            IfStatementSyntax ifStatement,
            ExpressionSyntax expression1,
            ExpressionSyntax expression2,
            NullCheckExpression nullCheck,
            bool isYield,
            SemanticModel semanticModel,
            CancellationToken cancellationToken)
        {
            if (nullCheck.Kind == NullCheckKind.EqualsToNull ||
                nullCheck.Kind == NullCheckKind.NotEqualsToNull)
            {
                if (SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1, requireNotNull: true))
                {
                    return(IfToReturnWithCoalesceExpression.Create(ifStatement, expression1, expression2, isYield));
                }
            }

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

                if (SyntaxComparer.AreEquivalent(nullCheck.Expression, expression1, requireNotNull: true))
                {
                    return(IfToReturnWithCoalesceExpression.Create(ifStatement, expression1, expression2, isYield));
                }
            }

            return(null);
        }
Exemple #4
0
        public static async Task <Document> RefactorAsync(
            Document document,
            ConditionalExpressionSyntax conditionalExpressionSyntax,
            CancellationToken cancellationToken)
        {
            ConditionalExpressionInfo conditionalExpression;

            if (ConditionalExpressionInfo.TryCreate(conditionalExpressionSyntax, out conditionalExpression))
            {
                SemanticModel semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(false);

                NullCheckExpression nullCheck;
                if (NullCheckExpression.TryCreate(conditionalExpression.Condition, semanticModel, out nullCheck, cancellationToken))
                {
                    ExpressionSyntax whenNotNull = (nullCheck.IsCheckingNotNull)
                        ? conditionalExpression.WhenTrue
                        : conditionalExpression.WhenFalse;

                    ExpressionSyntax whenNull = (nullCheck.IsCheckingNull)
                        ? conditionalExpression.WhenTrue
                        : conditionalExpression.WhenFalse;

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

                    ExpressionSyntax newNode;

                    if (expression.Parent == whenNotNull &&
                        whenNotNull.IsKind(SyntaxKind.SimpleMemberAccessExpression) &&
                        SemanticUtilities.IsPropertyOfNullableOfT(whenNotNull, "Value", semanticModel, cancellationToken))
                    {
                        newNode = expression;
                    }
                    else
                    {
                        newNode = SyntaxFactory.ParseExpression(whenNotNull.ToString().Insert(expression.Span.End - whenNotNull.SpanStart, "?"));
                    }

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

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

                    return(await document.ReplaceNodeAsync(conditionalExpressionSyntax, newNode, cancellationToken).ConfigureAwait(false));
                }
            }

            Debug.Fail(conditionalExpressionSyntax.ToString());

            return(document);
        }
        private static bool IsPropertyOfNullableOfT(ExpressionSyntax expression, string name, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (expression?.IsKind(SyntaxKind.SimpleMemberAccessExpression) == true)
            {
                var memberAccessExpression = (MemberAccessExpressionSyntax)expression;

                SimpleNameSyntax simpleName = memberAccessExpression.Name;

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

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

            return(false);
        }
        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 (SemanticUtilities.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 &&
                            SemanticUtilities.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);
        }
        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 &&
                        SemanticUtilities.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 &&
                        SemanticUtilities.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);
        }