Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        public static void AnalyzeConditionalExpression(SyntaxNodeAnalysisContext context, INamedTypeSymbol expressionType)
        {
            if (context.Node.SpanContainsDirectives())
            {
                return;
            }

            ConditionalExpressionInfo conditionalExpression;

            if (ConditionalExpressionInfo.TryCreate((ConditionalExpressionSyntax)context.Node, out conditionalExpression))
            {
                SemanticModel     semanticModel     = context.SemanticModel;
                CancellationToken cancellationToken = context.CancellationToken;

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

                    if (whenNotNull.IsKind(
                            SyntaxKind.SimpleMemberAccessExpression,
                            SyntaxKind.ElementAccessExpression,
                            SyntaxKind.ConditionalAccessExpression,
                            SyntaxKind.InvocationExpression) &&
                        semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken)?.IsReferenceTypeOrNullableType() == true &&
                        !ContainsOutArgumentWithLocal(whenNotNull, semanticModel, cancellationToken))
                    {
                        ExpressionSyntax expression = FindExpressionThatCanBeConditionallyAccessed(nullCheck.Expression, whenNotNull);

                        if (expression != null)
                        {
                            ExpressionSyntax whenNull = (nullCheck.IsCheckingNull)
                                ? conditionalExpression.WhenTrue
                                : conditionalExpression.WhenFalse;

                            ITypeSymbol typeSymbol = semanticModel.GetTypeSymbol(whenNotNull, cancellationToken);

                            if (semanticModel.IsDefaultValue(typeSymbol, whenNull, cancellationToken) &&
                                !conditionalExpression.Node.IsInExpressionTree(expressionType, semanticModel, cancellationToken))
                            {
                                context.ReportDiagnostic(
                                    DiagnosticDescriptors.UseConditionalAccessInsteadOfConditionalExpression,
                                    conditionalExpression.Node);
                            }
                        }
                    }
                }
            }
        }
        public static void Analyze(SyntaxNodeAnalysisContext context, ConditionalExpressionSyntax conditionalExpression)
        {
            if (context.Node.ContainsDiagnostics)
            {
                return;
            }

            if (context.Node.SpanContainsDirectives())
            {
                return;
            }

            ConditionalExpressionInfo info;

            if (ConditionalExpressionInfo.TryCreate(conditionalExpression, out info))
            {
                switch (info.WhenTrue.Kind())
                {
                case SyntaxKind.TrueLiteralExpression:
                {
                    if (info.WhenFalse.IsKind(SyntaxKind.FalseLiteralExpression))
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.SimplifyConditionalExpression, conditionalExpression);
                    }

                    break;
                }

                case SyntaxKind.FalseLiteralExpression:
                {
                    if (info.WhenFalse.IsKind(SyntaxKind.TrueLiteralExpression))
                    {
                        context.ReportDiagnostic(DiagnosticDescriptors.SimplifyConditionalExpression, conditionalExpression);
                    }

                    break;
                }
                }
            }
        }
Exemplo n.º 4
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);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 5
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));
        }