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); } } } }