private static bool IsElseIfOrElseClauseEquivalent( ISyntaxFactsService syntaxFacts, IIfLikeStatementGenerator ifGenerator, SyntaxNode elseIfOrElseClause1, SyntaxNode elseIfOrElseClause2) { // Compare Else/ElseIf clauses for equality. var isIfStatement = ifGenerator.IsIfOrElseIf(elseIfOrElseClause1); if (isIfStatement != ifGenerator.IsIfOrElseIf(elseIfOrElseClause2)) { // If we have one Else and one ElseIf, they're not equal. return(false); } if (isIfStatement) { // If we have two ElseIf blocks, their conditions have to match. var condition1 = ifGenerator.GetCondition(elseIfOrElseClause1); var condition2 = ifGenerator.GetCondition(elseIfOrElseClause2); if (!syntaxFacts.AreEquivalent(condition1, condition2)) { return(false); } } var statements1 = WalkDownScopeBlocks(syntaxFacts, syntaxFacts.GetStatementContainerStatements(elseIfOrElseClause1)); var statements2 = WalkDownScopeBlocks(syntaxFacts, syntaxFacts.GetStatementContainerStatements(elseIfOrElseClause2)); return(statements1.SequenceEqual(statements2, syntaxFacts.AreEquivalent)); }
private static bool IsFirstStatementOfIfOrElseIf( ISyntaxFactsService syntaxFacts, IIfLikeStatementGenerator ifGenerator, SyntaxNode statement, out SyntaxNode ifOrElseIf) { // Check whether the statement is a first statement inside an if or else if. // If it's inside a block, it has to be the first statement of the block. // We can't assume that a statement will always be in a statement container, because an if statement // in top level code will be in a GlobalStatement. if (syntaxFacts.IsStatementContainer(statement.Parent)) { var statements = syntaxFacts.GetStatementContainerStatements(statement.Parent); if (statements.Count > 0 && statements[0] == statement) { var rootStatements = WalkUpScopeBlocks(syntaxFacts, statements); if (rootStatements.Count > 0 && ifGenerator.IsIfOrElseIf(rootStatements[0].Parent)) { ifOrElseIf = rootStatements[0].Parent; return(true); } } } ifOrElseIf = null; return(false); }
private static bool IsFirstStatementIfStatement( ISyntaxFactsService syntaxFacts, IIfLikeStatementGenerator ifGenerator, SyntaxNode ifOrElseIf, out SyntaxNode ifStatement) { // Check whether the first statement inside an if or else if is an if statement. // If the if statement is inside a block, it has to be the first statement of the block. // An if or else if should always be a statement container, but we'll do a defensive check anyway. Debug.Assert(syntaxFacts.IsStatementContainer(ifOrElseIf)); if (syntaxFacts.IsStatementContainer(ifOrElseIf)) { var rootStatements = syntaxFacts.GetStatementContainerStatements(ifOrElseIf); var statements = WalkDownScopeBlocks(syntaxFacts, rootStatements); if (statements.Count > 0 && ifGenerator.IsIfOrElseIf(statements[0])) { ifStatement = statements[0]; return(true); } } ifStatement = null; return(false); }
static SyntaxNode FindIfOrElseIf(TextSpan span, IIfLikeStatementGenerator ifGenerator, SyntaxNode root) { var innerMatch = root.FindNode(span, getInnermostNodeForTie: true); return(innerMatch?.FirstAncestorOrSelf <SyntaxNode>( node => ifGenerator.IsIfOrElseIf(node) && node.Span == span)); }
private static bool IsFirstStatementOfIfOrElseIf( ISyntaxFactsService syntaxFacts, IIfLikeStatementGenerator ifGenerator, SyntaxNode statement, out SyntaxNode ifOrElseIf) { // Check whether the statement is a first statement inside an if or else if. // If it's inside a block, it has to be the first statement of the block. // A statement should always be in a statement container, but we'll do a defensive check anyway so that // we don't crash if the helper is missing some cases or there's a new language feature it didn't account for. Debug.Assert(syntaxFacts.IsStatementContainer(statement.Parent)); if (syntaxFacts.IsStatementContainer(statement.Parent)) { var statements = syntaxFacts.GetStatementContainerStatements(statement.Parent); if (statements.Count > 0 && statements[0] == statement) { var rootStatements = WalkUpScopeBlocks(syntaxFacts, statements); if (rootStatements.Count > 0 && ifGenerator.IsIfOrElseIf(rootStatements[0].Parent)) { ifOrElseIf = rootStatements[0].Parent; return(true); } } } ifOrElseIf = null; return(false); }
private static async Task <bool> CanStatementsBeMergedAsync( Document document, ISyntaxFactsService syntaxFacts, IBlockFactsService blockFacts, IIfLikeStatementGenerator ifGenerator, SyntaxNode firstStatement, SyntaxNode secondStatement, CancellationToken cancellationToken) { // We don't support cases where the previous if statement has any else-if or else clauses. In order for that // to be mergable, the control flow would have to quit from inside every branch, which is getting a little complex. if (!ifGenerator.IsIfOrElseIf(firstStatement) || ifGenerator.GetElseIfAndElseClauses(firstStatement).Length > 0) { return(false); } if (!ifGenerator.IsIfOrElseIf(secondStatement)) { return(false); } if (!ContainEquivalentStatements(syntaxFacts, blockFacts, firstStatement, secondStatement, out var insideStatements)) { return(false); } if (insideStatements.Count == 0) { // Even though there are no statements inside, we still can't merge these into one statement // because it would change the semantics from always evaluating the second condition to short-circuiting. return(false); } else { // There are statements inside. We can merge these into one statement if // control flow can't reach the end of these statements (otherwise, it would change from running // the second 'if' in the case that both conditions are true to only running the statements once). // 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); } }