Ejemplo n.º 1
0
        private static Task <Document> RemoveUnnecessaryConditionalAccessAsync(
            Document document,
            ConditionalAccessExpressionSyntax conditionalAccess,
            CancellationToken cancellationToken)
        {
            SyntaxNode equalsExpression = conditionalAccess.WalkUpParentheses().Parent;

            ExpressionSyntax newExpression = conditionalAccess
                                             .RemoveOperatorToken()
                                             .WithLeadingTrivia(equalsExpression.GetLeadingTrivia())
                                             .WithTrailingTrivia(equalsExpression.GetTrailingTrivia())
                                             .WithFormatterAnnotation();

            return(document.ReplaceNodeAsync(equalsExpression, newExpression, cancellationToken));
        }
        public static async Task <Document> RefactorAsync(
            Document document,
            ConditionalAccessExpressionSyntax conditionalAccess,
            CancellationToken cancellationToken)
        {
            ExpressionSyntax expression = conditionalAccess.Expression;

            SemanticModel semanticModel = await document.GetSemanticModelAsync().ConfigureAwait(false);

            int position = conditionalAccess.SpanStart;

            string localName = NameGenerator.Default.EnsureUniqueLocalName(DefaultNames.Variable, semanticModel, position);

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

            TypeSyntax type = (typeSymbol?.SupportsExplicitDeclaration() == true)
                ? typeSymbol.ToMinimalTypeSyntax(semanticModel, position)
                : VarType();

            LocalDeclarationStatementSyntax localStatement = LocalDeclarationStatement(
                type,
                Identifier(localName).WithRenameAnnotation(),
                expression);

            InvocationExpressionSyntax newExpression = CreateTaskFromResultExpression(conditionalAccess, semanticModel, cancellationToken);

            IfStatementSyntax ifStatement = IfStatement(
                CSharpSnippets.NotEqualsToNull(IdentifierName(localName)),
                Block(ReturnStatement(conditionalAccess.RemoveOperatorToken())),
                ElseClause(Block(ReturnStatement(newExpression))));

            SyntaxList <StatementSyntax> statements = List(new StatementSyntax[] { localStatement, ifStatement });

            SyntaxNode parent = conditionalAccess.Parent;

            if (parent is ReturnStatementSyntax returnStatement)
            {
                statements = statements.WithTriviaFrom(returnStatement);

                if (returnStatement.IsEmbedded())
                {
                    return(await document.ReplaceNodeAsync(returnStatement, Block(statements), cancellationToken).ConfigureAwait(false));
                }
                else
                {
                    return(await document.ReplaceNodeAsync(returnStatement, statements, cancellationToken).ConfigureAwait(false));
                }
            }
            else if (parent is SimpleLambdaExpressionSyntax simpleLambda)
            {
                SimpleLambdaExpressionSyntax newNode = simpleLambda
                                                       .WithBody(Block(statements))
                                                       .WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(simpleLambda, newNode, cancellationToken).ConfigureAwait(false));
            }
            else if (parent is ParenthesizedLambdaExpressionSyntax parenthesizedLambda)
            {
                ParenthesizedLambdaExpressionSyntax newNode = parenthesizedLambda
                                                              .WithBody(Block(statements))
                                                              .WithFormatterAnnotation();

                return(await document.ReplaceNodeAsync(parenthesizedLambda, newNode, cancellationToken).ConfigureAwait(false));
            }
            else
            {
                var arrowExpressionClause = (ArrowExpressionClauseSyntax)parent;

                SyntaxNode node = arrowExpressionClause.Parent;

                SyntaxNode newNode = CreateNewNode(node).WithFormatterAnnotation();

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

            SyntaxNode CreateNewNode(SyntaxNode node)
            {
                switch (node)
                {
                case MethodDeclarationSyntax methodDeclaration:
                {
                    return(methodDeclaration
                           .WithExpressionBody(null)
                           .WithBody(Block(statements)));
                }

                case LocalFunctionStatementSyntax localFunction:
                {
                    return(localFunction
                           .WithExpressionBody(null)
                           .WithBody(Block(statements)));
                }

                case PropertyDeclarationSyntax propertyDeclaration:
                {
                    return(propertyDeclaration
                           .WithExpressionBody(null)
                           .WithSemicolonToken(default(SyntaxToken))
                           .WithAccessorList(AccessorList(GetAccessorDeclaration(Block(statements)))));
                }

                case IndexerDeclarationSyntax indexerDeclaration:
                {
                    return(indexerDeclaration
                           .WithExpressionBody(null)
                           .WithSemicolonToken(default(SyntaxToken))
                           .WithAccessorList(AccessorList(GetAccessorDeclaration(Block(statements)))));
                }

                case AccessorDeclarationSyntax accessorDeclaration:
                {
                    return(accessorDeclaration
                           .WithExpressionBody(null)
                           .WithSemicolonToken(default(SyntaxToken))
                           .WithBody(Block(statements)));
                }

                default:
                {
                    Debug.Fail(node.Kind().ToString());
                    return(node);
                }
                }
            }
        }