private static bool CanBeMergedWithParent( ISyntaxFactsService syntaxFacts, IIfLikeStatementGenerator ifGenerator, SyntaxNode ifOrElseIf, out SyntaxNode parentIfOrElseIf) { return(ifGenerator.IsElseIfClause(ifOrElseIf, out parentIfOrElseIf) && ContainEquivalentStatements(syntaxFacts, ifOrElseIf, parentIfOrElseIf, out _)); }
private static async Task <bool> CanBeSeparateStatementsAsync( Document document, ISyntaxFactsService syntaxFacts, IIfLikeStatementGenerator ifGenerator, SyntaxNode ifOrElseIf, CancellationToken cancellationToken ) { // In order to make separate statements, ifOrElseIf must be an if statement, not an else-if clause. if (ifGenerator.IsElseIfClause(ifOrElseIf, out _)) { return(false); } // If there is an else clause, we *could* in theory separate these and move the current else clause to the second // statement, but we won't. It would break the else-if chain in an odd way. We'll insert an else-if instead. if (ifGenerator.GetElseIfAndElseClauses(ifOrElseIf).Length > 0) { return(false); } var insideStatements = syntaxFacts.GetStatementContainerStatements(ifOrElseIf); if (insideStatements.Count == 0) { // Even though there are no statements inside, we still can't split this into separate statements // because it would change the semantics from short-circuiting to always evaluating the second condition, // breaking code like 'if (a == null || a.InstanceMethod())'. return(false); } else { // There are statements inside. We can split this into separate statements and leave out the 'else' if // control flow can't reach the end of these statements (otherwise, it would continue to the second 'if' // and in the case that both conditions are true, run the same statements twice). // This will typically look like a single return, break, continue or a throw statement. var semanticModel = await document .GetSemanticModelAsync(cancellationToken) .ConfigureAwait(false); var controlFlow = semanticModel.AnalyzeControlFlow( insideStatements[0], insideStatements[insideStatements.Count - 1] ); return(!controlFlow.EndPointIsReachable); } }