public static Task <Document> RefactorAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken) { var statement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault(); SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(statement); int insertIndex = invocationInfo.Expression.Span.End - statement.FullSpan.Start; StatementSyntax newStatement = SyntaxFactory.ParseStatement(statement.ToFullString().Insert(insertIndex, "?")); IEnumerable <SyntaxTrivia> leading = ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, statement.SpanStart)); newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia())) ? newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia()) : newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia().Concat(leading)); IEnumerable <SyntaxTrivia> trailing = ifStatement.DescendantTrivia(TextSpan.FromBounds(statement.Span.End, ifStatement.Span.End)); newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia())) ? newStatement.WithTrailingTrivia(ifStatement.GetTrailingTrivia()) : newStatement.WithTrailingTrivia(trailing.Concat(ifStatement.GetTrailingTrivia())); return(document.ReplaceNodeAsync(ifStatement, newStatement, cancellationToken)); }
private static bool IsFixableIfInsideWhileOrDo(IfStatementSyntax ifStatement) { SyntaxNode parent = ifStatement.Parent; if (parent.Kind() != SyntaxKind.Block) return false; if (ifStatement.SingleNonBlockStatementOrDefault()?.Kind() != SyntaxKind.BreakStatement) return false; var block = (BlockSyntax)parent; SyntaxList<StatementSyntax> statements = block.Statements; int count = statements.Count; if (count == 1) return false; int index = statements.IndexOf(ifStatement); if (index != 0 && index != count - 1) { return false; } parent = block.Parent; SyntaxKind kind = parent.Kind(); if (kind == SyntaxKind.WhileStatement) { var whileStatement = (WhileStatementSyntax)parent; if (whileStatement.SpanContainsDirectives()) return false; if (whileStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression) return false; } else if (kind == SyntaxKind.DoStatement) { var doStatement = (DoStatementSyntax)parent; if (doStatement.SpanContainsDirectives()) return false; if (doStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression) return false; } else { return false; } return true; }
internal static SimplifyCodeBranchingKind?GetKind(IfStatementSyntax ifStatement, SemanticModel semanticModel, CancellationToken cancellationToken) { ExpressionSyntax condition = ifStatement.Condition?.WalkDownParentheses(); if (condition?.IsMissing != false) { return(null); } StatementSyntax ifStatementStatement = ifStatement.Statement; if (ifStatementStatement == null) { return(null); } ElseClauseSyntax elseClause = ifStatement.Else; if (elseClause != null) { if (IsFixableIfElseInsideWhile(ifStatement, elseClause)) { return(SimplifyCodeBranchingKind.IfElseInsideWhile); } else { var ifStatementBlock = ifStatementStatement as BlockSyntax; if (ifStatementBlock?.Statements.Any() == false && ifStatementBlock.OpenBraceToken.TrailingTrivia.IsEmptyOrWhitespace() && ifStatementBlock.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace() && IsFixableIfElseWithEmptyIf(ifStatement, elseClause)) { return(SimplifyCodeBranchingKind.IfElseWithEmptyIf); } else if (IsFixableIfElseWithReturnOrContinueInsideIf(ifStatement, elseClause)) { return(SimplifyCodeBranchingKind.LastIfElseWithReturnOrContinueInsideIf); } } } else if (IsFixableSimpleIfInsideWhileOrDo(ifStatement, semanticModel, cancellationToken)) { return(SimplifyCodeBranchingKind.SimplifyIfInsideWhileOrDo); } else if (!ifStatement.IsParentKind(SyntaxKind.ElseClause) && (ifStatement.SingleNonBlockStatementOrDefault() is DoStatementSyntax doStatement) && CSharpFactory.AreEquivalent(condition, doStatement.Condition?.WalkDownParentheses())) { return(SimplifyCodeBranchingKind.SimpleIfContainingOnlyDo); } return(null); }
public static async Task <Document> RefactorAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken) { var statement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault(); StatementSyntax newStatement = statement; NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.NotEqualsToNull); SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(statement); ExpressionSyntax expression = invocationInfo.Expression; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (semanticModel.GetTypeSymbol(nullCheck.Expression, cancellationToken).IsNullableType()) { var memberAccess = (MemberAccessExpressionSyntax)invocationInfo.Expression; newStatement = statement.ReplaceNode(memberAccess, memberAccess.Expression.WithTrailingTrivia(memberAccess.GetTrailingTrivia())); expression = memberAccess.Expression; } int insertIndex = expression.Span.End - statement.FullSpan.Start; newStatement = SyntaxFactory.ParseStatement(newStatement.ToFullString().Insert(insertIndex, "?")); IEnumerable <SyntaxTrivia> leading = ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, statement.SpanStart)); newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia())) ? newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia()) : newStatement.WithLeadingTrivia(ifStatement.GetLeadingTrivia().Concat(leading)); IEnumerable <SyntaxTrivia> trailing = ifStatement.DescendantTrivia(TextSpan.FromBounds(statement.Span.End, ifStatement.Span.End)); newStatement = (leading.All(f => f.IsWhitespaceOrEndOfLineTrivia())) ? newStatement.WithTrailingTrivia(ifStatement.GetTrailingTrivia()) : newStatement.WithTrailingTrivia(trailing.Concat(ifStatement.GetTrailingTrivia())); return(await document.ReplaceNodeAsync(ifStatement, newStatement, cancellationToken).ConfigureAwait(false)); }
private static Task <Document> RefactorAsync( Document document, StatementSyntax statement, IfStatementSyntax ifStatement, int statementIndex, StatementListInfo statementsInfo, ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken) { var expressionStatement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault(); var assignment = (AssignmentExpressionSyntax)expressionStatement.Expression; BinaryExpressionSyntax newNode = CreateCoalesceExpression( expression.WithoutTrailingTrivia(), assignment.Right.WithTrailingTrivia(expression.GetTrailingTrivia()), semanticModel.GetTypeSymbol(assignment.Left, cancellationToken), statement.SpanStart, semanticModel); StatementSyntax newStatement = statement.ReplaceNode(expression, newNode); IEnumerable <SyntaxTrivia> trivia = statementsInfo.Parent.DescendantTrivia(TextSpan.FromBounds(statement.Span.End, ifStatement.Span.End)); if (!trivia.All(f => f.IsWhitespaceOrEndOfLineTrivia())) { newStatement = newStatement.WithTrailingTrivia(trivia); newStatement = newStatement.AppendToTrailingTrivia(ifStatement.GetTrailingTrivia()); } else { newStatement = newStatement.WithTrailingTrivia(ifStatement.GetTrailingTrivia()); } SyntaxList <StatementSyntax> newStatements = statementsInfo.Statements .Remove(ifStatement) .ReplaceAt(statementIndex, newStatement); return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken)); }
private static ImmutableArray <IfAnalysis> Analyze( IfStatementSyntax ifStatement, ReturnStatementSyntax returnStatement, IfAnalysisOptions options, SemanticModel semanticModel, CancellationToken cancellationToken) { ExpressionSyntax condition = ifStatement.Condition?.WalkDownParentheses(); if (condition?.IsMissing != false) { return(Empty); } StatementSyntax statement = ifStatement.SingleNonBlockStatementOrDefault(); if (statement?.IsKind(SyntaxKind.ReturnStatement) != true) { return(Empty); } if (!options.CheckSpanDirectives(ifStatement, TextSpan.FromBounds(ifStatement.SpanStart, returnStatement.Span.End))) { return(Empty); } return(Analyze( ifStatement, condition, ((ReturnStatementSyntax)statement).Expression?.WalkDownParentheses(), returnStatement.Expression?.WalkDownParentheses(), options, isYield: false, semanticModel: semanticModel, cancellationToken: cancellationToken)); }
private static bool IsFixableSimpleIfInsideWhileOrDo( IfStatementSyntax ifStatement, SemanticModel semanticModel, CancellationToken cancellationToken) { SyntaxNode parent = ifStatement.Parent; if (parent.Kind() != SyntaxKind.Block) { return(false); } if (ifStatement.SingleNonBlockStatementOrDefault()?.Kind() != SyntaxKind.BreakStatement) { return(false); } var block = (BlockSyntax)parent; SyntaxList <StatementSyntax> statements = block.Statements; int count = statements.Count; if (count == 1) { return(false); } int index = statements.IndexOf(ifStatement); if (index != 0 && index != count - 1) { return(false); } parent = block.Parent; SyntaxKind kind = parent.Kind(); if (kind == SyntaxKind.WhileStatement) { var whileStatement = (WhileStatementSyntax)parent; if (whileStatement.SpanContainsDirectives()) { return(false); } if (whileStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression) { return(false); } if (index == count - 1 && ContainsLocalDefinedInLoopBody( ifStatement.Condition, TextSpan.FromBounds(block.SpanStart, ifStatement.SpanStart), semanticModel, cancellationToken)) { return(false); } return(true); } else if (kind == SyntaxKind.DoStatement) { var doStatement = (DoStatementSyntax)parent; if (doStatement.SpanContainsDirectives()) { return(false); } if (doStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression) { return(false); } if (index == count - 1 && ContainsLocalDefinedInLoopBody( ifStatement.Condition, TextSpan.FromBounds(block.SpanStart, ifStatement.SpanStart), semanticModel, cancellationToken)) { return(false); } return(true); } return(false); }
public static Task <Document> RefactorAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken = default) { StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement); SyntaxList <StatementSyntax> statements = statementsInfo.Statements; int index = statements.IndexOf(ifStatement); StatementSyntax expressionStatement = (ExpressionStatementSyntax)statements[index + 1]; SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo((ExpressionStatementSyntax)expressionStatement); ExpressionSyntax expression = invocationInfo.Expression; SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo((ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault()); BinaryExpressionSyntax coalesceExpression = CSharpFactory.CoalesceExpression(expression.WithoutTrivia(), ParenthesizedExpression(assignmentInfo.AssignmentExpression)); ParenthesizedExpressionSyntax newExpression = ParenthesizedExpression(coalesceExpression) .WithTriviaFrom(expression); StatementSyntax newExpressionStatement = expressionStatement.ReplaceNode(expression, newExpression); IEnumerable <SyntaxTrivia> trivia = statementsInfo.Parent.DescendantTrivia(TextSpan.FromBounds(ifStatement.FullSpan.Start, expressionStatement.FullSpan.Start)); if (trivia.Any(f => !f.IsWhitespaceOrEndOfLineTrivia())) { newExpressionStatement = newExpressionStatement.PrependToLeadingTrivia(trivia); } SyntaxList <StatementSyntax> newStatements = statements .Replace(expressionStatement, newExpressionStatement) .RemoveAt(index); return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken)); }
public static ImmutableArray <IfAnalysis> Analyze( IfStatementSyntax ifStatement, IfAnalysisOptions options, SemanticModel semanticModel, CancellationToken cancellationToken = default(CancellationToken)) { if (!ifStatement.IsTopmostIf()) { return(Empty); } ExpressionSyntax condition = ifStatement.Condition?.WalkDownParentheses(); if (condition == null) { return(Empty); } ElseClauseSyntax elseClause = ifStatement.Else; if (elseClause != null) { if (!options.CheckSpanDirectives(ifStatement)) { return(Empty); } StatementSyntax statement1 = ifStatement.SingleNonBlockStatementOrDefault(); if (statement1 == null) { return(Empty); } SyntaxKind kind1 = statement1.Kind(); if (kind1.Is( SyntaxKind.ExpressionStatement, SyntaxKind.ReturnStatement, SyntaxKind.YieldReturnStatement)) { StatementSyntax statement2 = elseClause.SingleNonBlockStatementOrDefault(); if (statement2?.Kind() == kind1) { switch (kind1) { case SyntaxKind.ExpressionStatement: { return(Analyze( ifStatement, condition, (ExpressionStatementSyntax)statement1, (ExpressionStatementSyntax)statement2, options, semanticModel, cancellationToken)); } case SyntaxKind.ReturnStatement: { return(Analyze( ifStatement, condition, ((ReturnStatementSyntax)statement1).Expression?.WalkDownParentheses(), ((ReturnStatementSyntax)statement2).Expression?.WalkDownParentheses(), options, isYield: false, semanticModel: semanticModel, cancellationToken: cancellationToken)); } case SyntaxKind.YieldReturnStatement: { return(Analyze( ifStatement, condition, ((YieldStatementSyntax)statement1).Expression?.WalkDownParentheses(), ((YieldStatementSyntax)statement2).Expression?.WalkDownParentheses(), options, isYield: true, semanticModel: semanticModel, cancellationToken: cancellationToken)); } } } } } else if (ifStatement.NextStatement() is ReturnStatementSyntax returnStatement) { return(Analyze(ifStatement, returnStatement, options, semanticModel, cancellationToken)); } return(Empty); }
private static async Task <Document> RefactorAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); ExpressionSyntax condition = ifStatement.Condition; ElseClauseSyntax elseClause = ifStatement.Else; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); SimplifyCodeBranchingKind kind = SimplifyCodeBranchingAnalyzer.GetKind(ifStatement, semanticModel, cancellationToken).Value; if (kind == SimplifyCodeBranchingKind.IfElseWithEmptyIf) { ExpressionSyntax newCondition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken); StatementSyntax statement = elseClause.Statement; if (statement is IfStatementSyntax nestedIf) { newCondition = LogicalAndExpression(newCondition.Parenthesize(), nestedIf.Condition.Parenthesize()); statement = nestedIf.Statement; } IfStatementSyntax newIfStatement = ifStatement.Update( ifStatement.IfKeyword, ifStatement.OpenParenToken, newCondition, ifStatement.CloseParenToken, statement, default(ElseClauseSyntax)); newIfStatement = newIfStatement.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(ifStatement, newIfStatement, cancellationToken).ConfigureAwait(false)); } else if (kind == SimplifyCodeBranchingKind.IfElseInsideWhile) { bool elseContainsBreak = elseClause.SingleNonBlockStatementOrDefault()?.Kind() == SyntaxKind.BreakStatement; SyntaxList <StatementSyntax> statements; if (elseContainsBreak) { statements = (ifStatement.Statement is BlockSyntax block2) ? block2.Statements : SingletonList(ifStatement.Statement); } else { statements = (elseClause.Statement is BlockSyntax block2) ? block2.Statements : SingletonList(elseClause.Statement); } WhileStatementSyntax whileStatement; if (ifStatement.Parent is BlockSyntax block) { whileStatement = (WhileStatementSyntax)block.Parent; block = block.WithStatements(block.Statements.ReplaceRange(ifStatement, statements)); } else { whileStatement = (WhileStatementSyntax)ifStatement.Parent; block = Block(statements); } if (!elseContainsBreak) { condition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken); } WhileStatementSyntax newWhileStatement = whileStatement.Update( whileStatement.WhileKeyword, whileStatement.OpenParenToken, condition, whileStatement.CloseParenToken, block); newWhileStatement = newWhileStatement.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(whileStatement, newWhileStatement, cancellationToken).ConfigureAwait(false)); } else if (kind == SimplifyCodeBranchingKind.SimplifIfInsideWhileOrDo) { var block = (BlockSyntax)ifStatement.Parent; SyntaxList <StatementSyntax> statements = block.Statements; BlockSyntax newBlock = block.WithStatements(statements.Remove(ifStatement)); ExpressionSyntax newCondition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken); SyntaxNode newNode; switch (block.Parent) { case WhileStatementSyntax whileStatement: { if (statements.IsFirst(ifStatement)) { newNode = whileStatement.Update( whileStatement.WhileKeyword, whileStatement.OpenParenToken, newCondition, whileStatement.CloseParenToken, newBlock); } else { newNode = DoStatement( Token(whileStatement.WhileKeyword.LeadingTrivia, SyntaxKind.DoKeyword, whileStatement.CloseParenToken.TrailingTrivia), newBlock.WithoutTrailingTrivia(), Token(SyntaxKind.WhileKeyword), OpenParenToken(), newCondition, CloseParenToken(), SemicolonToken().WithTrailingTrivia(newBlock.GetTrailingTrivia())); } break; } case DoStatementSyntax doStatement: { if (statements.IsLast(ifStatement)) { newNode = doStatement.Update( doStatement.DoKeyword, newBlock, doStatement.WhileKeyword, doStatement.OpenParenToken, newCondition, doStatement.CloseParenToken, doStatement.SemicolonToken); } else { newNode = WhileStatement( Token(doStatement.DoKeyword.LeadingTrivia, SyntaxKind.WhileKeyword, SyntaxTriviaList.Empty), OpenParenToken(), newCondition, Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, doStatement.DoKeyword.TrailingTrivia), newBlock.WithTrailingTrivia(doStatement.GetTrailingTrivia())); } break; } default: { throw new InvalidOperationException(); } } newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(block.Parent, newNode, cancellationToken).ConfigureAwait(false)); } else if (kind == SimplifyCodeBranchingKind.SimpleIfContainingOnlyDo) { StatementSyntax statement = ifStatement.SingleNonBlockStatementOrDefault(); var doStatement = (DoStatementSyntax)statement; WhileStatementSyntax whileStatement = WhileStatement( Token(ifStatement.GetLeadingTrivia(), SyntaxKind.WhileKeyword, SyntaxTriviaList.Empty), OpenParenToken(), doStatement.Condition, Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, doStatement.DoKeyword.TrailingTrivia), doStatement.Statement.WithTrailingTrivia(ifStatement.GetTrailingTrivia())); whileStatement = whileStatement.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(ifStatement, whileStatement, cancellationToken).ConfigureAwait(false)); } else { throw new InvalidOperationException(); } }
private static async Task <Document> RefactorAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken) { ExpressionSyntax condition = ifStatement.Condition; ElseClauseSyntax elseClause = ifStatement.Else; if ((ifStatement.Statement as BlockSyntax)?.Statements.Any() == false) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax newCondition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken); StatementSyntax statement = elseClause.Statement; if (statement is IfStatementSyntax nestedIf) { newCondition = LogicalAndExpression(newCondition.Parenthesize(), nestedIf.Condition.Parenthesize()); statement = nestedIf.Statement; } cancellationToken.ThrowIfCancellationRequested(); IfStatementSyntax newNode = ifStatement.Update( ifStatement.IfKeyword, ifStatement.OpenParenToken, newCondition, ifStatement.CloseParenToken, statement, default(ElseClauseSyntax)); newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(ifStatement, newNode, cancellationToken).ConfigureAwait(false)); } else if (elseClause != null) { WhileStatementSyntax whileStatement; if (ifStatement.Parent is BlockSyntax block) { whileStatement = (WhileStatementSyntax)block.Parent; } else { block = Block(); whileStatement = (WhileStatementSyntax)ifStatement.Parent; } cancellationToken.ThrowIfCancellationRequested(); BlockSyntax newBlock = (ifStatement.Statement is BlockSyntax ifBlock) ? block.WithStatements(ifBlock.Statements) : block.WithStatements(SingletonList(ifStatement.Statement)); SyntaxNode newNode = whileStatement.Update( whileStatement.WhileKeyword, whileStatement.OpenParenToken, ifStatement.Condition, whileStatement.CloseParenToken, newBlock); newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(whileStatement, newNode, cancellationToken).ConfigureAwait(false)); } else { StatementSyntax statement = ifStatement.SingleNonBlockStatementOrDefault(); if (statement.Kind() == SyntaxKind.BreakStatement) { var block = (BlockSyntax)ifStatement.Parent; SyntaxList <StatementSyntax> statements = block.Statements; BlockSyntax newBlock = block.WithStatements(statements.Remove(ifStatement)); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax newCondition = SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken); SyntaxNode newNode = block.Parent; switch (block.Parent) { case WhileStatementSyntax whileStatement: { cancellationToken.ThrowIfCancellationRequested(); if (statements.IsFirst(ifStatement)) { newNode = whileStatement.Update( whileStatement.WhileKeyword, whileStatement.OpenParenToken, newCondition, whileStatement.CloseParenToken, newBlock); } else { newNode = DoStatement( Token(whileStatement.WhileKeyword.LeadingTrivia, SyntaxKind.DoKeyword, whileStatement.CloseParenToken.TrailingTrivia), newBlock.WithoutTrailingTrivia(), Token(SyntaxKind.WhileKeyword), OpenParenToken(), newCondition, CloseParenToken(), SemicolonToken().WithTrailingTrivia(newBlock.GetTrailingTrivia())); } break; } case DoStatementSyntax doStatement: { cancellationToken.ThrowIfCancellationRequested(); if (statements.IsLast(ifStatement)) { newNode = doStatement.Update( doStatement.DoKeyword, newBlock, doStatement.WhileKeyword, doStatement.OpenParenToken, newCondition, doStatement.CloseParenToken, doStatement.SemicolonToken); } else { newNode = WhileStatement( Token(doStatement.DoKeyword.LeadingTrivia, SyntaxKind.WhileKeyword, SyntaxTriviaList.Empty), OpenParenToken(), newCondition, Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, doStatement.DoKeyword.TrailingTrivia), newBlock.WithTrailingTrivia(doStatement.GetTrailingTrivia())); } break; } default: { Debug.Fail(block.Parent.Kind().ToString()); break; } } newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(block.Parent, newNode, cancellationToken).ConfigureAwait(false)); } else if (statement.Kind() == SyntaxKind.DoStatement) { var doStatement = (DoStatementSyntax)statement; WhileStatementSyntax whileStatement = WhileStatement( Token(ifStatement.GetLeadingTrivia(), SyntaxKind.WhileKeyword, SyntaxTriviaList.Empty), OpenParenToken(), doStatement.Condition, Token(SyntaxTriviaList.Empty, SyntaxKind.CloseParenToken, doStatement.DoKeyword.TrailingTrivia), doStatement.Statement.WithTrailingTrivia(ifStatement.GetTrailingTrivia())); whileStatement = whileStatement.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(ifStatement, whileStatement, cancellationToken).ConfigureAwait(false)); } } throw new InvalidOperationException(); }
public static Task <Document> InlineLazyInitializationAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken = default) { StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement); var assignmentStatement = (ExpressionStatementSyntax)ifStatement.SingleNonBlockStatementOrDefault(); SimpleAssignmentStatementInfo assignmentInfo = SyntaxInfo.SimpleAssignmentStatementInfo(assignmentStatement, walkDownParentheses: false); ExpressionSyntax right = assignmentInfo.Right; int index = statementsInfo.IndexOf(ifStatement); var expressionStatement2 = (ExpressionStatementSyntax)statementsInfo[index + 1]; SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(expressionStatement2); ExpressionSyntax expression = invocationInfo.Expression; var newLeading = new List <SyntaxTrivia>(ifStatement.GetLeadingTrivia()); ExpressionSyntax coalesceExpression; if (document.SupportsLanguageFeature(CSharpLanguageFeature.NullCoalescingAssignmentOperator)) { AddTrivia(ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, right.SpanStart)).ToSyntaxTriviaList()); coalesceExpression = CoalesceAssignmentExpression(expression.WithoutTrivia(), right.WithoutTrivia()); } else { AddTrivia(ifStatement.DescendantTrivia(TextSpan.FromBounds(ifStatement.SpanStart, assignmentInfo.AssignmentExpression.SpanStart)).ToSyntaxTriviaList()); coalesceExpression = CoalesceExpression(expression.WithoutTrivia(), ParenthesizedExpression(assignmentInfo.AssignmentExpression.WithoutTrivia())); } AddTrivia(ifStatement.DescendantTrivia(TextSpan.FromBounds(right.Span.End, ifStatement.Span.End)).ToSyntaxTriviaList()); AddTrivia(ifStatement.GetTrailingTrivia()); AddTrivia(expressionStatement2.GetLeadingTrivia()); ParenthesizedExpressionSyntax newExpression = ParenthesizedExpression(coalesceExpression) .WithLeadingTrivia(newLeading) .WithTrailingTrivia(expression.GetTrailingTrivia()); StatementSyntax newExpressionStatement = expressionStatement2.ReplaceNode(expression, newExpression); StatementListInfo newStatements = statementsInfo .Replace(expressionStatement2, newExpressionStatement) .RemoveAt(index); return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken)); void AddTrivia(SyntaxTriviaList trivia) { if (!trivia.IsEmptyOrWhitespace()) { newLeading.AddRange(trivia); } } }
private static bool IsFixableIfElseWithReturnOrContinueInsideIf(IfStatementSyntax ifStatement, ElseClauseSyntax elseClause) { if (elseClause.Statement?.IsKind(SyntaxKind.IfStatement) != false) { return(false); } IfStatementSyntax topmostIf = ifStatement.GetTopmostIf(); if (!(topmostIf.Parent is BlockSyntax block)) { return(false); } if (!block.Statements.IsLast(topmostIf, ignoreLocalFunctions: true)) { return(false); } switch (block.Parent.Kind()) { case SyntaxKind.MethodDeclaration: case SyntaxKind.LocalFunctionStatement: case SyntaxKind.ConstructorDeclaration: case SyntaxKind.DestructorDeclaration: case SyntaxKind.AddAccessorDeclaration: case SyntaxKind.RemoveAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: { //void M() //{ // if (x) // { // return; // } // else // { // M(); // } return(ifStatement.SingleNonBlockStatementOrDefault() is ReturnStatementSyntax returnStatement && returnStatement.Expression == null); } case SyntaxKind.ForEachStatement: case SyntaxKind.ForEachVariableStatement: case SyntaxKind.ForStatement: case SyntaxKind.WhileStatement: { //while (x) //{ // if (y) // { // continue; // } // else // { // M(); // } //} return(ifStatement.SingleNonBlockStatementOrDefault().IsKind(SyntaxKind.ContinueStatement)); } } return(false); }
private static ImmutableArray <IfAnalysis> Analyze( ExpressionStatementSyntax expressionStatement, IfStatementSyntax ifStatement, IfAnalysisOptions options, SemanticModel semanticModel, CancellationToken cancellationToken) { SimpleAssignmentStatementInfo assignment = SyntaxInfo.SimpleAssignmentStatementInfo(expressionStatement); if (!assignment.Success) { return(Empty); } ElseClauseSyntax elseClause = ifStatement.Else; if (elseClause?.Statement?.IsKind(SyntaxKind.IfStatement) != false) { return(Empty); } SimpleAssignmentStatementInfo assignment1 = SyntaxInfo.SimpleAssignmentStatementInfo(ifStatement.SingleNonBlockStatementOrDefault()); if (!assignment1.Success) { return(Empty); } SimpleAssignmentStatementInfo assignment2 = SyntaxInfo.SimpleAssignmentStatementInfo(elseClause.SingleNonBlockStatementOrDefault()); if (!assignment2.Success) { return(Empty); } if (!AreEquivalent(assignment1.Left, assignment2.Left, assignment.Left)) { return(Empty); } if (!options.CheckSpanDirectives(ifStatement.Parent, TextSpan.FromBounds(expressionStatement.SpanStart, ifStatement.Span.End))) { return(Empty); } if (IsNullLiteralConvertedToNullableOfT(assignment1.Right, semanticModel, cancellationToken) || IsNullLiteralConvertedToNullableOfT(assignment2.Right, semanticModel, cancellationToken)) { return(Empty); } return(new AssignmentAndIfElseToAssignmentWithConditionalExpressionAnalysis(expressionStatement, assignment.Right, ifStatement, assignment1.Right, assignment2.Right, semanticModel).ToImmutableArray()); }
private static ImmutableArray <IfAnalysis> Analyze( LocalDeclarationStatementSyntax localDeclarationStatement, IfStatementSyntax ifStatement, IfAnalysisOptions options, SemanticModel semanticModel, CancellationToken cancellationToken) { VariableDeclaratorSyntax declarator = localDeclarationStatement .Declaration? .Variables .SingleOrDefault(shouldThrow: false); if (declarator == null) { return(Empty); } ElseClauseSyntax elseClause = ifStatement.Else; if (elseClause?.Statement?.IsKind(SyntaxKind.IfStatement) != false) { return(Empty); } SimpleAssignmentStatementInfo assignment1 = SyntaxInfo.SimpleAssignmentStatementInfo(ifStatement.SingleNonBlockStatementOrDefault()); if (!assignment1.Success) { return(Empty); } SimpleAssignmentStatementInfo assignment2 = SyntaxInfo.SimpleAssignmentStatementInfo(elseClause.SingleNonBlockStatementOrDefault()); if (!assignment2.Success) { return(Empty); } if (assignment1.Left.Kind() != SyntaxKind.IdentifierName) { return(Empty); } if (assignment2.Left.Kind() != SyntaxKind.IdentifierName) { return(Empty); } string identifier1 = ((IdentifierNameSyntax)assignment1.Left).Identifier.ValueText; string identifier2 = ((IdentifierNameSyntax)assignment2.Left).Identifier.ValueText; if (!string.Equals(identifier1, identifier2, StringComparison.Ordinal)) { return(Empty); } if (!string.Equals(identifier1, declarator.Identifier.ValueText, StringComparison.Ordinal)) { return(Empty); } if (!options.CheckSpanDirectives(ifStatement.Parent, TextSpan.FromBounds(localDeclarationStatement.SpanStart, ifStatement.Span.End))) { return(Empty); } if (IsNullLiteralConvertedToNullableOfT(assignment1.Right, semanticModel, cancellationToken) || IsNullLiteralConvertedToNullableOfT(assignment2.Right, semanticModel, cancellationToken)) { return(Empty); } return(new LocalDeclarationAndIfElseToAssignmentWithConditionalExpressionAnalysis(localDeclarationStatement, ifStatement, assignment1.Right, assignment2.Right, semanticModel).ToImmutableArray()); }