private static bool IsFixableIfElseInsideWhile( IfStatementSyntax ifStatement, ElseClauseSyntax elseClause) { if (elseClause.SingleNonBlockStatementOrDefault()?.Kind() != SyntaxKind.BreakStatement) return false; SyntaxNode parent = ifStatement.Parent; if (parent is BlockSyntax block) { if (block.Statements.Count != 1) return false; parent = block.Parent; } if (!(parent is WhileStatementSyntax whileStatement)) return false; if (whileStatement.SpanContainsDirectives()) return false; if (whileStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression) return false; return true; }
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 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()); }