private static async Task <Document> InvertIfElseAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); ElseClauseSyntax elseClause = ifStatement.Else; StatementSyntax whenTrue = ifStatement.Statement; StatementSyntax whenFalse = elseClause.Statement; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); IfStatementSyntax newIfStatement = ifStatement.Update( ifKeyword: ifStatement.IfKeyword, openParenToken: ifStatement.OpenParenToken, condition: SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(ifStatement.Condition, semanticModel, cancellationToken), closeParenToken: ifStatement.CloseParenToken, statement: whenFalse.WithTriviaFrom(whenTrue), @else: elseClause.WithStatement(whenTrue.WithTriviaFrom(whenFalse))); newIfStatement = newIfStatement.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(ifStatement, newIfStatement, cancellationToken).ConfigureAwait(false)); }
private static async Task <Document> UseExceptionFilterAsync( Document document, IfStatementSyntax ifStatement, CancellationToken cancellationToken) { ElseClauseSyntax elseClause = ifStatement.Else; var catchClause = (CatchClauseSyntax)ifStatement.Parent.Parent; SyntaxList <StatementSyntax> statements = catchClause.Block.Statements; ExpressionSyntax filterExpression = ifStatement.Condition; SyntaxList <StatementSyntax> newStatements; if (ifStatement.Statement.SingleNonBlockStatementOrDefault() is ThrowStatementSyntax throwStatement && throwStatement.Expression == null) { if (elseClause != null) { newStatements = ReplaceStatement(elseClause.Statement); } else { newStatements = statements.RemoveAt(0); } SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); filterExpression = SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(filterExpression, semanticModel, cancellationToken); }
private static async Task <ExpressionSyntax> CreateNewNodeAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken) { ExpressionSyntax left = binaryExpression.Left; ExpressionSyntax right = binaryExpression.Right; SyntaxTriviaList trivia = binaryExpression .DescendantTrivia(TextSpan.FromBounds(left.Span.End, right.SpanStart)) .ToSyntaxTriviaList() .EmptyIfWhitespace(); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); if (CSharpFacts.IsBooleanLiteralExpression(left.Kind())) { SyntaxTriviaList leadingTrivia = binaryExpression.GetLeadingTrivia().AddRange(trivia); if (right.IsKind(SyntaxKind.LogicalNotExpression)) { var logicalNot = (PrefixUnaryExpressionSyntax)right; ExpressionSyntax operand = logicalNot.Operand; if (semanticModel.GetTypeInfo(operand, cancellationToken).ConvertedType.IsNullableOf(SpecialType.System_Boolean)) { return(binaryExpression .WithLeft(SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(left, semanticModel, cancellationToken)) .WithRight(operand.WithTriviaFrom(right))); } } return(SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(right, semanticModel, cancellationToken) .WithLeadingTrivia(leadingTrivia)); } else if (CSharpFacts.IsBooleanLiteralExpression(right.Kind())) { SyntaxTriviaList trailingTrivia = trivia.AddRange(binaryExpression.GetTrailingTrivia()); if (left.IsKind(SyntaxKind.LogicalNotExpression)) { var logicalNot = (PrefixUnaryExpressionSyntax)left; ExpressionSyntax operand = logicalNot.Operand; if (semanticModel.GetTypeInfo(operand, cancellationToken).ConvertedType.IsNullableOf(SpecialType.System_Boolean)) { return(binaryExpression .WithLeft(operand.WithTriviaFrom(left)) .WithRight(SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(right, semanticModel, cancellationToken))); } } return(SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(left, semanticModel, cancellationToken) .WithTrailingTrivia(trailingTrivia)); } throw new InvalidOperationException(); }
private static ExpressionSyntax GetBooleanExpression( ExpressionSyntax condition, ExpressionSyntax expression1, ExpressionSyntax expression2, Document document, SemanticModel semanticModel, CancellationToken cancellationToken = default) { switch (expression1.Kind()) { case SyntaxKind.TrueLiteralExpression: { switch (expression2.Kind()) { case SyntaxKind.TrueLiteralExpression: return(expression2); case SyntaxKind.FalseLiteralExpression: return(condition); default: return(LogicalOrExpression(condition, expression2)); } } case SyntaxKind.FalseLiteralExpression: { switch (expression2.Kind()) { case SyntaxKind.TrueLiteralExpression: return(SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(condition, semanticModel, cancellationToken)); case SyntaxKind.FalseLiteralExpression: return(expression2); default: return(LogicalAndExpression(SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(condition, semanticModel, cancellationToken), expression2)); } } default: { switch (expression2.Kind()) { case SyntaxKind.TrueLiteralExpression: return(LogicalOrExpression(SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(condition, semanticModel, cancellationToken), expression1)); case SyntaxKind.FalseLiteralExpression: return(LogicalAndExpression(condition, expression1)); default: throw new InvalidOperationException(); } } }
private static async Task <Document> RefactorAsync( Document document, ExpressionSyntax expression, CancellationToken cancellationToken) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax newNode = SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(expression, semanticModel, cancellationToken); return(await document.ReplaceNodeAsync(expression, newNode, cancellationToken).ConfigureAwait(false)); }
private static Task <Document> IfToReturnWithExpressionAsync( Document document, IfToReturnWithExpressionAnalysis analysis, CancellationToken cancellationToken = default) { ExpressionSyntax expression = analysis.Expression; if (analysis.Invert) { expression = SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(expression, analysis.SemanticModel, cancellationToken); } StatementSyntax statement; if (analysis.IsYield) { statement = YieldReturnStatement(expression); } else { statement = ReturnStatement(expression); } IfStatementSyntax ifStatement = analysis.IfStatement; if (ifStatement.IsSimpleIf()) { StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement); SyntaxList <StatementSyntax> statements = statementsInfo.Statements; int index = statements.IndexOf(ifStatement); StatementSyntax newNode = statement .WithLeadingTrivia(ifStatement.GetLeadingTrivia()) .WithTrailingTrivia(statements[index + 1].GetTrailingTrivia()) .WithFormatterAnnotation(); SyntaxList <StatementSyntax> newStatements = statements .RemoveAt(index) .ReplaceAt(index, newNode); return(document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken)); } else { StatementSyntax newNode = statement .WithTriviaFrom(ifStatement) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(ifStatement, newNode, cancellationToken)); } }
public static async Task <Document> RefactorAsync( Document document, BinaryExpressionSyntax binaryExpression, CancellationToken cancellationToken = default) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ExpressionSyntax newNode = SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(binaryExpression, semanticModel, cancellationToken); newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(binaryExpression, newNode, cancellationToken).ConfigureAwait(false)); }
public static async Task <Document> RefactorAsync( Document document, ConditionalExpressionSyntax conditionalExpression, CancellationToken cancellationToken = default) { SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); ConditionalExpressionSyntax newNode = conditionalExpression.Update( condition: SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(conditionalExpression.Condition, semanticModel, cancellationToken), questionToken: conditionalExpression.QuestionToken, whenTrue: conditionalExpression.WhenFalse.WithTriviaFrom(conditionalExpression.WhenTrue), colonToken: conditionalExpression.ColonToken, whenFalse: conditionalExpression.WhenTrue.WithTriviaFrom(conditionalExpression.WhenFalse)); newNode = newNode.WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(conditionalExpression, newNode, cancellationToken).ConfigureAwait(false)); }
private static Task <Document> IfElseToAssignmentWithConditionAsync( Document document, IfElseToAssignmentWithConditionAnalysis analysis, CancellationToken cancellationToken = default) { ExpressionSyntax right = analysis.Right; if (analysis.Invert) { right = SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(right, analysis.SemanticModel, cancellationToken); } ExpressionStatementSyntax newNode = SimpleAssignmentStatement(analysis.Left.WithoutTrivia(), right.WithoutTrivia()) .WithTriviaFrom(analysis.IfStatement) .WithFormatterAnnotation(); return(document.ReplaceNodeAsync(analysis.IfStatement, newNode, cancellationToken)); }
public static async Task <Document> RefactorAsync( Document document, InvocationExpressionSyntax invocationExpression, string memberName, ExpressionSyntax expression, CancellationToken cancellationToken = default) { var memberAccessExpression = (MemberAccessExpressionSyntax)invocationExpression.Expression; MemberAccessExpressionSyntax newMemberAccessExpression = memberAccessExpression .WithName(SyntaxFactory.IdentifierName(memberName).WithTriviaFrom(memberAccessExpression.Name)); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); InvocationExpressionSyntax newNode = invocationExpression .ReplaceNode(expression, SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(expression, semanticModel, cancellationToken)) .WithExpression(newMemberAccessExpression); return(await document.ReplaceNodeAsync(invocationExpression, newNode, cancellationToken).ConfigureAwait(false)); }
public static async Task <Document> RefactorAsync( Document document, IfStatementSyntax ifStatement, SyntaxKind jumpKind, bool recursive, CancellationToken cancellationToken = default) { StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement); SyntaxNode node = statementsInfo.Parent; SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var rewriter = new ReduceIfStatementRewriter( jumpKind, recursive, SyntaxLogicalInverter.GetInstance(document), semanticModel, cancellationToken); SyntaxNode newNode = rewriter.Visit(node).WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(node, newNode, cancellationToken).ConfigureAwait(false)); }
public static async Task <Document> InvertIfAsync( Document document, IfStatementSyntax ifStatement, bool recursive = false, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); StatementSyntax statement = ifStatement.Statement; StatementListInfo statementsInfo = SyntaxInfo.StatementListInfo(ifStatement); SyntaxList <StatementSyntax> statements = statementsInfo.Statements; InvertIfAnalysis analysis = InvertIfAnalysis.Create(ifStatement, statement); int ifStatementIndex = statements.IndexOf(ifStatement); StatementSyntax lastStatement = analysis.LastStatement; int lastStatementIndex = statements.IndexOf(lastStatement); bool isLastStatementRedundant = IsLastStatementRedundant(); bool shouldUseElseClause = !CSharpFacts.IsJumpStatement(lastStatement.Kind()); SemanticModel semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); SyntaxList <StatementSyntax> newStatements = statements; if (!recursive) { Refactor(); } else { IfStatementSyntax lastIfStatement; InvertIfAnalysis a = analysis.AnalyzeNextStatement(); do { lastIfStatement = a.IfStatement; a = a.AnalyzeNextStatement(); }while (a.Success); int firstLastStatementIndex = lastStatementIndex; int index = statements.IndexOf(lastIfStatement); int firstIndex = ifStatementIndex; while (index >= firstIndex) { ifStatementIndex = index; ifStatement = (IfStatementSyntax)statements[ifStatementIndex]; statement = ifStatement.Statement; Refactor(); lastStatementIndex = firstLastStatementIndex + newStatements.Count - statements.Count; index--; } } return(await document.ReplaceStatementsAsync(statementsInfo, newStatements, cancellationToken).ConfigureAwait(false)); void Refactor() { cancellationToken.ThrowIfCancellationRequested(); SyntaxList <StatementSyntax> nextStatements = newStatements .Skip(ifStatementIndex + 1) .Take(lastStatementIndex - ifStatementIndex) .ToSyntaxList() .TrimTrivia(); BlockSyntax newStatement; SyntaxList <StatementSyntax> newNextStatements; if (statement is BlockSyntax block) { newStatement = block.WithStatements(nextStatements); newNextStatements = block.Statements; } else { newStatement = Block(nextStatements); newNextStatements = SingletonList(statement); } if (isLastStatementRedundant) { newNextStatements = newNextStatements.RemoveAt(newNextStatements.Count - 1); } ElseClauseSyntax elseClause = null; if (newNextStatements.Any() && shouldUseElseClause) { elseClause = ElseClause(Block(newNextStatements)); newNextStatements = default; } IfStatementSyntax newIfStatement = ifStatement.Update( ifKeyword: ifStatement.IfKeyword, openParenToken: ifStatement.OpenParenToken, condition: SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(ifStatement.Condition, semanticModel, cancellationToken), closeParenToken: ifStatement.CloseParenToken, statement: newStatement, @else: elseClause); newIfStatement = newIfStatement.WithFormatterAnnotation(); SyntaxList <StatementSyntax> newNodes = newNextStatements.Insert(0, newIfStatement); newStatements = newStatements.ReplaceRange(ifStatementIndex, lastStatementIndex - ifStatementIndex + 1, newNodes); } bool IsLastStatementRedundant() { StatementSyntax jumpStatement = analysis.JumpStatement; switch (jumpStatement.Kind()) { case SyntaxKind.ReturnStatement: { if (((ReturnStatementSyntax)jumpStatement).Expression == null && RemoveRedundantStatementAnalysis.IsFixable(lastStatement, SyntaxKind.ReturnStatement)) { return(true); } break; } case SyntaxKind.ContinueStatement: { if (RemoveRedundantStatementAnalysis.IsFixable(lastStatement, SyntaxKind.ContinueStatement)) { return(true); } break; } } return(false); } }
private static ExpressionSyntax GetNewNode(PrefixUnaryExpressionSyntax logicalNot, Document document) { ExpressionSyntax operand = logicalNot.Operand; ExpressionSyntax expression = operand.WalkDownParentheses(); switch (expression.Kind()) { case SyntaxKind.TrueLiteralExpression: case SyntaxKind.FalseLiteralExpression: { LiteralExpressionSyntax newNode = BooleanLiteralExpression(expression.Kind() == SyntaxKind.FalseLiteralExpression); newNode = newNode.WithTriviaFrom(expression); return(operand.ReplaceNode(expression, newNode)); } case SyntaxKind.LogicalNotExpression: { return(((PrefixUnaryExpressionSyntax)expression).Operand); } case SyntaxKind.EqualsExpression: case SyntaxKind.NotEqualsExpression: case SyntaxKind.LessThanExpression: case SyntaxKind.LessThanOrEqualExpression: case SyntaxKind.GreaterThanExpression: case SyntaxKind.GreaterThanOrEqualExpression: { BinaryExpressionSyntax newExpression = SyntaxLogicalInverter.GetInstance(document).InvertBinaryExpression((BinaryExpressionSyntax)expression); return(operand.ReplaceNode(expression, newExpression)); } case SyntaxKind.InvocationExpression: { var invocationExpression = (InvocationExpressionSyntax)expression; var memberAccessExpression = (MemberAccessExpressionSyntax)invocationExpression.Expression; ExpressionSyntax lambdaExpression = invocationExpression.ArgumentList.Arguments[0].Expression.WalkDownParentheses(); SingleParameterLambdaExpressionInfo lambdaInfo = SyntaxInfo.SingleParameterLambdaExpressionInfo(lambdaExpression); var logicalNot2 = (PrefixUnaryExpressionSyntax)SimplifyLogicalNegationAnalyzer.GetReturnExpression(lambdaInfo.Body).WalkDownParentheses(); InvocationExpressionSyntax newNode = invocationExpression.ReplaceNode(logicalNot2, logicalNot2.Operand.WithTriviaFrom(logicalNot2)); return(SyntaxRefactorings.ChangeInvokedMethodName(newNode, (memberAccessExpression.Name.Identifier.ValueText == "All") ? "Any" : "All")); } case SyntaxKind.IsPatternExpression: { var isPatternExpression = (IsPatternExpressionSyntax)expression; var pattern = (ConstantPatternSyntax)isPatternExpression.Pattern; UnaryPatternSyntax newPattern = NotPattern(pattern.WithoutTrivia()).WithTriviaFrom(pattern); return(isPatternExpression.WithPattern(newPattern) .PrependToLeadingTrivia(logicalNot.GetLeadingTrivia()) .AppendToTrailingTrivia(logicalNot.GetTrailingTrivia())); } } return(null); }
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 = SyntaxLogicalInverter.GetInstance(document).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 = SyntaxLogicalInverter.GetInstance(document).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.SimplifyIfInsideWhileOrDo) { var block = (BlockSyntax)ifStatement.Parent; SyntaxList <StatementSyntax> statements = block.Statements; BlockSyntax newBlock = block.WithStatements(statements.Remove(ifStatement)); ExpressionSyntax newCondition = SyntaxLogicalInverter.GetInstance(document).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 if (kind == SimplifyCodeBranchingKind.LastIfElseWithReturnOrContinueInsideIf) { IfStatementSyntax newIfStatement = ifStatement.Update( ifStatement.IfKeyword, ifStatement.OpenParenToken, SyntaxLogicalInverter.GetInstance(document).LogicallyInvert(condition, semanticModel, cancellationToken), ifStatement.CloseParenToken, elseClause.Statement, default(ElseClauseSyntax)) .WithFormatterAnnotation(); return(await document.ReplaceNodeAsync(ifStatement, newIfStatement, cancellationToken).ConfigureAwait(false)); } else { throw new InvalidOperationException(); } }