@@ -971,7 +971,7 @@ namespace ts {
971971
972972 // check imports and module augmentations
973973 collectExternalModuleReferences ( newSourceFile ) ;
974- if ( ! arrayIsEqualTo ( oldSourceFile . imports , newSourceFile . imports , moduleNameIsEqualTo ) ) {
974+ if ( ! arrayIsEqualTo ( oldSourceFile . imports , newSourceFile . imports , importHasSameModuleName ) ) {
975975 // imports has changed
976976 oldProgram . structureIsReused = StructureIsReused . SafeModules ;
977977 }
@@ -1574,6 +1574,10 @@ namespace ts {
15741574 return a . fileName === b . fileName ;
15751575 }
15761576
1577+ function importHasSameModuleName ( a : AnyValidImportOrReExport , b : AnyValidImportOrReExport ) : boolean {
1578+ return moduleSpecifierFromImport ( a ) . text === moduleSpecifierFromImport ( b ) . text ;
1579+ }
1580+
15771581 function moduleNameIsEqualTo ( a : StringLiteral | Identifier , b : StringLiteral | Identifier ) : boolean {
15781582 return a . kind === SyntaxKind . StringLiteral
15791583 ? b . kind === SyntaxKind . StringLiteral && a . text === b . text
@@ -1589,7 +1593,7 @@ namespace ts {
15891593 const isExternalModuleFile = isExternalModule ( file ) ;
15901594
15911595 // file.imports may not be undefined if there exists dynamic import
1592- let imports : StringLiteral [ ] ;
1596+ let imports : AnyValidImportOrReExport [ ] | undefined ;
15931597 let moduleAugmentations : ( StringLiteral | Identifier ) [ ] ;
15941598 let ambientModules : string [ ] ;
15951599
@@ -1599,12 +1603,11 @@ namespace ts {
15991603 && ( options . isolatedModules || isExternalModuleFile )
16001604 && ! file . isDeclarationFile ) {
16011605 // synthesize 'import "tslib"' declaration
1602- const externalHelpersModuleReference = createLiteral ( externalHelpersModuleNameText ) ;
1603- const importDecl = createImportDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined , /*importClause*/ undefined ) ;
1606+ const importDecl = createImportDeclaration ( /*decorators*/ undefined , /*modifiers*/ undefined , /*importClause*/ undefined , createLiteral ( externalHelpersModuleNameText ) ) ;
16041607 addEmitFlags ( importDecl , EmitFlags . NeverApplyImportHelper ) ;
1605- externalHelpersModuleReference . parent = importDecl ;
1608+ importDecl . moduleSpecifier . parent = importDecl ;
16061609 importDecl . parent = file ;
1607- imports = [ externalHelpersModuleReference ] ;
1610+ imports = [ importDecl as ImportDeclaration & { moduleSpecifier : StringLiteral } ] ;
16081611 }
16091612
16101613 for ( const node of file . statements ) {
@@ -1621,66 +1624,55 @@ namespace ts {
16211624 return ;
16221625
16231626 function collectModuleReferences ( node : Statement , inAmbientModule : boolean ) : void {
1624- switch ( node . kind ) {
1625- case SyntaxKind . ImportDeclaration :
1626- case SyntaxKind . ImportEqualsDeclaration :
1627- case SyntaxKind . ExportDeclaration :
1628- const moduleNameExpr = getExternalModuleName ( node ) ;
1629- if ( ! moduleNameExpr || ! isStringLiteral ( moduleNameExpr ) ) {
1630- break ;
1631- }
1632- if ( ! moduleNameExpr . text ) {
1633- break ;
1634- }
1635-
1636- // TypeScript 1.0 spec (April 2014): 12.1.6
1637- // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules
1638- // only through top - level external module names. Relative external module names are not permitted.
1639- if ( ! inAmbientModule || ! isExternalModuleNameRelative ( moduleNameExpr . text ) ) {
1640- ( imports || ( imports = [ ] ) ) . push ( moduleNameExpr ) ;
1627+ if ( isAnyImportOrReExport ( node ) ) {
1628+ const moduleNameExpr = getExternalModuleName ( node ) ;
1629+ // TypeScript 1.0 spec (April 2014): 12.1.6
1630+ // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference other external modules
1631+ // only through top - level external module names. Relative external module names are not permitted.
1632+ if ( moduleNameExpr && isStringLiteral ( moduleNameExpr ) && moduleNameExpr . text && ( ! inAmbientModule || ! isExternalModuleNameRelative ( moduleNameExpr . text ) ) ) {
1633+ imports = append ( imports , node as AnyValidImportOrReExport ) ;
1634+ }
1635+ }
1636+ else if ( isModuleDeclaration ( node ) ) {
1637+ if ( isAmbientModule ( node ) && ( inAmbientModule || hasModifier ( node , ModifierFlags . Ambient ) || file . isDeclarationFile ) ) {
1638+ const nameText = getTextOfIdentifierOrLiteral ( node . name ) ;
1639+ // Ambient module declarations can be interpreted as augmentations for some existing external modules.
1640+ // This will happen in two cases:
1641+ // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope
1642+ // - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name
1643+ // immediately nested in top level ambient module declaration .
1644+ if ( isExternalModuleFile || ( inAmbientModule && ! isExternalModuleNameRelative ( nameText ) ) ) {
1645+ ( moduleAugmentations || ( moduleAugmentations = [ ] ) ) . push ( node . name ) ;
16411646 }
1642- break ;
1643- case SyntaxKind . ModuleDeclaration :
1644- if ( isAmbientModule ( < ModuleDeclaration > node ) && ( inAmbientModule || hasModifier ( node , ModifierFlags . Ambient ) || file . isDeclarationFile ) ) {
1645- const moduleName = ( < ModuleDeclaration > node ) . name ;
1646- const nameText = getTextOfIdentifierOrLiteral ( moduleName ) ;
1647- // Ambient module declarations can be interpreted as augmentations for some existing external modules.
1648- // This will happen in two cases:
1649- // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope
1650- // - if current file is not external module then module augmentation is an ambient module declaration with non-relative module name
1651- // immediately nested in top level ambient module declaration .
1652- if ( isExternalModuleFile || ( inAmbientModule && ! isExternalModuleNameRelative ( nameText ) ) ) {
1653- ( moduleAugmentations || ( moduleAugmentations = [ ] ) ) . push ( moduleName ) ;
1647+ else if ( ! inAmbientModule ) {
1648+ if ( file . isDeclarationFile ) {
1649+ // for global .d.ts files record name of ambient module
1650+ ( ambientModules || ( ambientModules = [ ] ) ) . push ( nameText ) ;
16541651 }
1655- else if ( ! inAmbientModule ) {
1656- if ( file . isDeclarationFile ) {
1657- // for global .d.ts files record name of ambient module
1658- ( ambientModules || ( ambientModules = [ ] ) ) . push ( nameText ) ;
1659- }
1660- // An AmbientExternalModuleDeclaration declares an external module.
1661- // This type of declaration is permitted only in the global module.
1662- // The StringLiteral must specify a top - level external module name.
1663- // Relative external module names are not permitted
1664-
1665- // NOTE: body of ambient module is always a module block, if it exists
1666- const body = < ModuleBlock > ( < ModuleDeclaration > node ) . body ;
1667- if ( body ) {
1668- for ( const statement of body . statements ) {
1669- collectModuleReferences ( statement , /*inAmbientModule*/ true ) ;
1670- }
1652+ // An AmbientExternalModuleDeclaration declares an external module.
1653+ // This type of declaration is permitted only in the global module.
1654+ // The StringLiteral must specify a top - level external module name.
1655+ // Relative external module names are not permitted
1656+
1657+ // NOTE: body of ambient module is always a module block, if it exists
1658+ const body = < ModuleBlock > ( < ModuleDeclaration > node ) . body ;
1659+ if ( body ) {
1660+ for ( const statement of body . statements ) {
1661+ collectModuleReferences ( statement , /*inAmbientModule*/ true ) ;
16711662 }
16721663 }
16731664 }
1665+ }
16741666 }
16751667 }
16761668
16771669 function collectDynamicImportOrRequireCalls ( node : Node ) : void {
16781670 if ( isRequireCall ( node , /*checkArgumentIsStringLiteral*/ true ) ) {
1679- ( imports || ( imports = [ ] ) ) . push ( < StringLiteral > ( < CallExpression > node ) . arguments [ 0 ] ) ;
1671+ imports = append ( imports , node ) ;
16801672 }
16811673 // we have to check the argument list has length of 1. We will still have to process these even though we have parsing error.
16821674 else if ( isImportCall ( node ) && node . arguments . length === 1 && node . arguments [ 0 ] . kind === SyntaxKind . StringLiteral ) {
1683- ( imports || ( imports = [ ] ) ) . push ( < StringLiteral > ( < CallExpression > node ) . arguments [ 0 ] ) ;
1675+ imports = append ( imports , node as CallExpression as RequireOrImportCall ) ;
16841676 }
16851677 else {
16861678 forEachChild ( node , collectDynamicImportOrRequireCalls ) ;
@@ -2426,7 +2418,7 @@ namespace ts {
24262418 }
24272419
24282420 function getModuleNames ( { imports, moduleAugmentations } : SourceFile ) : string [ ] {
2429- const res = imports . map ( i => i . text ) ;
2421+ const res = imports . map ( i => moduleSpecifierFromImport ( i ) . text ) ;
24302422 for ( const aug of moduleAugmentations ) {
24312423 if ( aug . kind === SyntaxKind . StringLiteral ) {
24322424 res . push ( aug . text ) ;
0 commit comments