Skip to content

Commit efed1f9

Browse files
Simplified ownership code for continue/break statements.
1 parent dae3487 commit efed1f9

File tree

1 file changed

+58
-80
lines changed

1 file changed

+58
-80
lines changed

src/services/services.ts

Lines changed: 58 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -2331,11 +2331,13 @@ module ts {
23312331
}
23322332
}
23332333

2334-
aggregateBreakAndContinueKeywords(/* owner */ loopNode,
2335-
/* startPoint */ loopNode.statement,
2336-
/* breakSearchType */ BreakContinueSearchType.All,
2337-
/* continueSearchType */ BreakContinueSearchType.All,
2338-
/* keywordAccumulator */ keywords);
2334+
var breaksAndContinues = aggregateAllBreakAndContinueStatements(loopNode.statement);
2335+
2336+
forEach(breaksAndContinues, statement => {
2337+
if (ownsBreakOrContinueStatement(loopNode, statement)) {
2338+
pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword);
2339+
}
2340+
});
23392341

23402342
return map(keywords, getReferenceEntryFromNode);
23412343
}
@@ -2352,109 +2354,85 @@ module ts {
23522354
forEach(switchStatement.clauses, clause => {
23532355
pushKeywordIf(keywords, clause.getFirstToken(), SyntaxKind.CaseKeyword, SyntaxKind.DefaultKeyword);
23542356

2355-
// For each clause, aggregate each of the analogous 'break' statements.
2356-
aggregateBreakAndContinueKeywords(/* owner */ switchStatement,
2357-
/* startPoint */ clause,
2358-
/* breakSearchType */ BreakContinueSearchType.All,
2359-
/* continueSearchType */ BreakContinueSearchType.None,
2360-
/* keywordAccumulator */ keywords);
2357+
var breaksAndContinues = aggregateAllBreakAndContinueStatements(clause);
2358+
2359+
forEach(breaksAndContinues, statement => {
2360+
if (ownsBreakOrContinueStatement(switchStatement, statement)) {
2361+
pushKeywordIf(keywords, statement.getFirstToken(), SyntaxKind.BreakKeyword);
2362+
}
2363+
});
23612364
});
23622365

23632366
return map(keywords, getReferenceEntryFromNode);
23642367
}
23652368

2366-
function getBreakOrContinueStatementOccurences(breakOrContinueStatement: BreakOrContinueStatement): ReferenceEntry[] {
2367-
for (var owner = node.parent; owner; owner = owner.parent) {
2369+
function getBreakOrContinueStatementOccurences(breakOrContinueStatement: BreakOrContinueStatement): ReferenceEntry[]{
2370+
var owner = getBreakOrContinueOwner(breakOrContinueStatement);
2371+
2372+
if (owner) {
23682373
switch (owner.kind) {
23692374
case SyntaxKind.ForStatement:
23702375
case SyntaxKind.ForInStatement:
23712376
case SyntaxKind.DoStatement:
23722377
case SyntaxKind.WhileStatement:
2373-
// The iteration statement is the owner if the break/continue statement is either unlabeled,
2374-
// or if the break/continue statement's label corresponds to one of the loop's labels.
2375-
if (!breakOrContinueStatement.label || isLabeledBy(owner, breakOrContinueStatement.label.text)) {
2376-
return getLoopBreakContinueOccurrences(<IterationStatement>owner)
2377-
}
2378-
break;
2378+
return getLoopBreakContinueOccurrences(<IterationStatement>owner)
23792379
case SyntaxKind.SwitchStatement:
2380-
// A switch statement can only be the owner of an break statement.
2381-
if (breakOrContinueStatement.kind === SyntaxKind.BreakStatement && (!breakOrContinueStatement.label || isLabeledBy(owner, breakOrContinueStatement.label.text))) {
2382-
return getSwitchCaseDefaultOccurrences(<SwitchStatement>owner);
2383-
}
2384-
break;
2385-
default:
2386-
if (isAnyFunction(owner)) {
2387-
return undefined;
2388-
}
2389-
break;
2380+
return getSwitchCaseDefaultOccurrences(<SwitchStatement>owner);
2381+
23902382
}
23912383
}
23922384

23932385
return undefined;
23942386
}
23952387

2396-
function aggregateBreakAndContinueKeywords(owner: Node,
2397-
startPoint: Node,
2398-
breakSearchType: BreakContinueSearchType,
2399-
continueSearchType: BreakContinueSearchType,
2400-
keywordAccumulator: Node[]): void {
2401-
2402-
return aggregate(startPoint);
2388+
function aggregateAllBreakAndContinueStatements(node: Node): BreakOrContinueStatement[] {
2389+
var statementAccumulator: BreakOrContinueStatement[] = []
2390+
aggregate(node);
2391+
return statementAccumulator;
24032392

24042393
function aggregate(node: Node): void {
2405-
// Remember the statuses of the flags before diving into the next node.
2406-
var prevBreakSearchType = breakSearchType;
2407-
var prevContinueSearchType = continueSearchType;
2408-
2409-
switch (node.kind) {
2410-
case SyntaxKind.BreakStatement:
2411-
case SyntaxKind.ContinueStatement:
2412-
if (ownsBreakOrContinue(owner, <BreakOrContinueStatement>node, breakSearchType, continueSearchType)) {
2413-
pushKeywordIf(keywordAccumulator, node.getFirstToken(), SyntaxKind.BreakKeyword, SyntaxKind.ContinueKeyword);
2414-
}
2415-
break;
2416-
2417-
case SyntaxKind.ForStatement:
2418-
case SyntaxKind.ForInStatement:
2419-
case SyntaxKind.DoStatement:
2420-
case SyntaxKind.WhileStatement:
2421-
// Inner loops take ownership of unlabeled 'continue' statements.
2422-
continueSearchType &= ~BreakContinueSearchType.Unlabeled;
2423-
// Fall through
2424-
case SyntaxKind.SwitchStatement:
2425-
// Inner loops & 'switch' statements take ownership of unlabeled 'break' statements.
2426-
breakSearchType &= ~BreakContinueSearchType.Unlabeled;
2427-
break;
2394+
if (node.kind === SyntaxKind.BreakStatement || node.kind === SyntaxKind.ContinueStatement) {
2395+
statementAccumulator.push(node);
24282396
}
2429-
24302397
// Do not cross function boundaries.
2431-
if (!isAnyFunction(node)) {
2398+
else if (!isAnyFunction(node)) {
24322399
forEachChild(node, aggregate);
24332400
}
2434-
2435-
// Restore the last state.
2436-
breakSearchType = prevBreakSearchType;
2437-
continueSearchType = prevContinueSearchType;
24382401
};
24392402
}
24402403

2441-
// Note: 'statement' must be a descendant of 'root'.
2442-
// Reasonable logic for restricting traversal prior to arriving at the
2443-
// 'statement' node is beyond the scope of this function.
2444-
function ownsBreakOrContinue(owner: Node,
2445-
statement: BreakOrContinueStatement,
2446-
breakSearchType: BreakContinueSearchType,
2447-
continueSearchType: BreakContinueSearchType): boolean {
2448-
var searchType = statement.kind === SyntaxKind.BreakStatement ?
2449-
breakSearchType :
2450-
continueSearchType;
2404+
function ownsBreakOrContinueStatement(owner: Node, statement: BreakOrContinueStatement): boolean {
2405+
var actualOwner = getBreakOrContinueOwner(statement);
24512406

2452-
if (statement.label && (searchType & BreakContinueSearchType.Labeled)) {
2453-
return isLabeledBy(owner, statement.label.text);
2454-
}
2455-
else {
2456-
return !!(searchType & BreakContinueSearchType.Unlabeled);
2407+
return actualOwner && actualOwner === owner;
2408+
}
2409+
2410+
function getBreakOrContinueOwner(statement: BreakOrContinueStatement): Node {
2411+
for (var node = statement.parent; node; node = node.parent) {
2412+
switch (node.kind) {
2413+
case SyntaxKind.SwitchStatement:
2414+
if (statement.kind === SyntaxKind.ContinueStatement) {
2415+
continue;
2416+
}
2417+
// Fall through.
2418+
case SyntaxKind.ForStatement:
2419+
case SyntaxKind.ForInStatement:
2420+
case SyntaxKind.WhileStatement:
2421+
case SyntaxKind.DoStatement:
2422+
if (!statement.label || isLabeledBy(node, statement.label.text)) {
2423+
return node;
2424+
}
2425+
break;
2426+
default:
2427+
// Don't cross function boundaries.
2428+
if (isAnyFunction(node)) {
2429+
return undefined;
2430+
}
2431+
break;
2432+
}
24572433
}
2434+
2435+
return undefined;
24582436
}
24592437

24602438
// returns true if 'node' is defined and has a matching 'kind'.

0 commit comments

Comments
 (0)