@@ -2331,11 +2331,13 @@ module ts {
2331
2331
}
2332
2332
}
2333
2333
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
+ } ) ;
2339
2341
2340
2342
return map ( keywords , getReferenceEntryFromNode ) ;
2341
2343
}
@@ -2352,109 +2354,85 @@ module ts {
2352
2354
forEach ( switchStatement . clauses , clause => {
2353
2355
pushKeywordIf ( keywords , clause . getFirstToken ( ) , SyntaxKind . CaseKeyword , SyntaxKind . DefaultKeyword ) ;
2354
2356
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
+ } ) ;
2361
2364
} ) ;
2362
2365
2363
2366
return map ( keywords , getReferenceEntryFromNode ) ;
2364
2367
}
2365
2368
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 ) {
2368
2373
switch ( owner . kind ) {
2369
2374
case SyntaxKind . ForStatement :
2370
2375
case SyntaxKind . ForInStatement :
2371
2376
case SyntaxKind . DoStatement :
2372
2377
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 )
2379
2379
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
+
2390
2382
}
2391
2383
}
2392
2384
2393
2385
return undefined ;
2394
2386
}
2395
2387
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 ;
2403
2392
2404
2393
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 ) ;
2428
2396
}
2429
-
2430
2397
// Do not cross function boundaries.
2431
- if ( ! isAnyFunction ( node ) ) {
2398
+ else if ( ! isAnyFunction ( node ) ) {
2432
2399
forEachChild ( node , aggregate ) ;
2433
2400
}
2434
-
2435
- // Restore the last state.
2436
- breakSearchType = prevBreakSearchType ;
2437
- continueSearchType = prevContinueSearchType ;
2438
2401
} ;
2439
2402
}
2440
2403
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 ) ;
2451
2406
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
+ }
2457
2433
}
2434
+
2435
+ return undefined ;
2458
2436
}
2459
2437
2460
2438
// returns true if 'node' is defined and has a matching 'kind'.
0 commit comments