@@ -31,6 +31,7 @@ namespace ts {
3131 let rootFileNames : string [ ] ;
3232 let dependencyMap : Map < string [ ] > ;
3333 let pathWeightMap : Map < number > ;
34+ let visitedBlocks : Block [ ] ;
3435
3536 interface Map < T > {
3637 [ index : string ] : T ;
@@ -57,12 +58,14 @@ namespace ts {
5758 sourceFiles = < any > program . getSourceFiles ( ) ;
5859 rootFileNames = < any > program . getRootFileNames ( ) ;
5960 checker = program . getTypeChecker ( ) ;
61+ visitedBlocks = [ ] ;
6062 buildDependencyMap ( ) ;
6163 let result = sortOnDependency ( ) ;
6264 sourceFiles = null ;
6365 rootFileNames = null ;
6466 checker = null ;
6567 dependencyMap = null ;
68+ visitedBlocks = null ;
6669 return result ;
6770 }
6871
@@ -314,7 +317,7 @@ namespace ts {
314317
315318 function visitDecorators ( decorators : NodeArray < Decorator > ) : void {
316319 for ( let decorator of decorators ) {
317- visitExpression ( decorator . expression ) ;
320+ visitCallExpression ( decorator . expression ) ;
318321 }
319322 }
320323
@@ -325,7 +328,8 @@ namespace ts {
325328 switch ( expression . kind ) {
326329 case SyntaxKind . NewExpression :
327330 case SyntaxKind . CallExpression :
328- visitCallExpression ( < CallExpression > expression ) ;
331+ visitCallArguments ( < CallExpression > expression ) ;
332+ visitCallExpression ( ( < CallExpression > expression ) . expression ) ;
329333 break ;
330334 case SyntaxKind . Identifier :
331335 checkDependencyAtLocation ( expression ) ;
@@ -367,13 +371,13 @@ namespace ts {
367371 visitExpression ( ( < TaggedTemplateExpression > expression ) . tag ) ;
368372 visitExpression ( ( < TaggedTemplateExpression > expression ) . template ) ;
369373 break ;
370- case ts . SyntaxKind . ConditionalExpression :
374+ case ts . SyntaxKind . ConditionalExpression :
371375 visitExpression ( ( < ts . ConditionalExpression > expression ) . condition ) ;
372376 visitExpression ( ( < ts . ConditionalExpression > expression ) . whenTrue ) ;
373377 visitExpression ( ( < ts . ConditionalExpression > expression ) . whenFalse ) ;
374378 break ;
375-
376- case ts . SyntaxKind . SpreadElement :
379+
380+ case ts . SyntaxKind . SpreadElement :
377381 visitExpression ( ( < SpreadElement > expression ) . expression ) ;
378382 break ;
379383 case ts . SyntaxKind . VoidExpression :
@@ -452,14 +456,16 @@ namespace ts {
452456 } ) ;
453457 }
454458
455- function visitCallExpression ( callExpression : CallExpression ) : void {
459+ function visitCallArguments ( callExpression : CallExpression ) : void {
456460 if ( callExpression . arguments ) {
457461 callExpression . arguments . forEach ( argument => {
458462 visitExpression ( argument ) ;
459463 } ) ;
460464 }
465+ }
461466
462- let expression = escapeParenthesized ( callExpression . expression ) ;
467+ function visitCallExpression ( expression : Expression ) : void {
468+ expression = escapeParenthesized ( expression ) ;
463469 visitExpression ( expression ) ;
464470 switch ( expression . kind ) {
465471 case SyntaxKind . FunctionExpression :
@@ -468,11 +474,60 @@ namespace ts {
468474 break ;
469475 case SyntaxKind . PropertyAccessExpression :
470476 case SyntaxKind . Identifier :
471- let callerFileName = getSourceFileOfNode ( callExpression ) . fileName ;
477+ let callerFileName = getSourceFileOfNode ( expression ) . fileName ;
472478 checkCallTarget ( callerFileName , expression ) ;
473479 break ;
480+ case SyntaxKind . CallExpression :
481+ visitReturnedFunction ( ( < CallExpression > expression ) . expression ) ;
482+ break ;
474483 }
484+ }
475485
486+ function visitReturnedFunction ( expression : Expression ) : Expression [ ] {
487+ expression = escapeParenthesized ( expression ) ;
488+ let returnExpressions : Expression [ ] = [ ] ;
489+ if ( expression . kind === SyntaxKind . CallExpression ) {
490+ let expressions = visitReturnedFunction ( ( < CallExpression > expression ) . expression ) ;
491+ for ( let returnExpression of expressions ) {
492+ let returns = visitReturnedFunction ( returnExpression ) ;
493+ returnExpressions = returnExpressions . concat ( returns ) ;
494+ }
495+ return returnExpressions ;
496+ }
497+
498+ let functionBlocks : Block [ ] = [ ] ;
499+ switch ( expression . kind ) {
500+ case SyntaxKind . FunctionExpression :
501+ functionBlocks . push ( ( < FunctionExpression > expression ) . body ) ;
502+ break ;
503+ case SyntaxKind . PropertyAccessExpression :
504+ case SyntaxKind . Identifier :
505+ let callerFileName = getSourceFileOfNode ( expression ) . fileName ;
506+ let declarations : Declaration [ ] = [ ] ;
507+ getForwardDeclarations ( expression , declarations , callerFileName ) ;
508+ for ( let declaration of declarations ) {
509+ let sourceFile = getSourceFileOfNode ( declaration ) ;
510+ if ( ! sourceFile || sourceFile . isDeclarationFile ) {
511+ continue ;
512+ }
513+ if ( declaration . kind === SyntaxKind . FunctionDeclaration ||
514+ declaration . kind === SyntaxKind . MethodDeclaration ) {
515+ functionBlocks . push ( ( < FunctionDeclaration > declaration ) . body ) ;
516+ }
517+ }
518+ break ;
519+ }
520+
521+ for ( let block of functionBlocks ) {
522+ for ( let statement of block . statements ) {
523+ if ( statement . kind === SyntaxKind . ReturnStatement ) {
524+ let returnExpression = ( < ReturnStatement > statement ) . expression ;
525+ returnExpressions . push ( returnExpression ) ;
526+ visitCallExpression ( returnExpression ) ;
527+ }
528+ }
529+ }
530+ return returnExpressions ;
476531 }
477532
478533 function escapeParenthesized ( expression : Expression ) : Expression {
@@ -488,7 +543,7 @@ namespace ts {
488543 for ( let declaration of declarations ) {
489544 let sourceFile = getSourceFileOfNode ( declaration ) ;
490545 if ( ! sourceFile || sourceFile . isDeclarationFile ) {
491- return ;
546+ continue ;
492547 }
493548 addDependency ( callerFileName , sourceFile . fileName ) ;
494549 if ( declaration . kind === SyntaxKind . FunctionDeclaration ||
@@ -568,13 +623,14 @@ namespace ts {
568623 }
569624
570625 function visitBlock ( block : Block ) : void {
571- if ( ! block || block . visitedBySorting ) {
626+ if ( ! block || visitedBlocks . indexOf ( block ) != - 1 ) {
572627 return ;
573628 }
574- block . visitedBySorting = true ;
629+ visitedBlocks . push ( block ) ;
575630 for ( let statement of block . statements ) {
576631 visitStatement ( statement ) ;
577632 }
633+ visitedBlocks . pop ( ) ;
578634 }
579635
580636 function visitVariableList ( variables : VariableDeclarationList ) {
0 commit comments