@@ -2147,8 +2147,23 @@ namespace ts {
21472147 export function preProcessFile ( sourceText : string , readImportFiles = true , detectJavaScriptImports = false ) : PreProcessedFileInfo {
21482148 const referencedFiles : FileReference [ ] = [ ] ;
21492149 const importedFiles : FileReference [ ] = [ ] ;
2150- let ambientExternalModules : string [ ] ;
2150+ let ambientExternalModules : { ref : FileReference , depth : number } [ ] ;
21512151 let isNoDefaultLib = false ;
2152+ let braceNesting = 0 ;
2153+ // assume that text represent an external module if it contains at least one top level import/export
2154+ // ambient modules that are found inside external modules are interpreted as module augmentations
2155+ let externalModule = false ;
2156+
2157+ function nextToken ( ) {
2158+ const token = scanner . scan ( ) ;
2159+ if ( token === SyntaxKind . OpenBraceToken ) {
2160+ braceNesting ++ ;
2161+ }
2162+ else if ( token === SyntaxKind . CloseBraceToken ) {
2163+ braceNesting -- ;
2164+ }
2165+ return token ;
2166+ }
21522167
21532168 function processTripleSlashDirectives ( ) : void {
21542169 const commentRanges = getLeadingCommentRanges ( sourceText , 0 ) ;
@@ -2165,21 +2180,33 @@ namespace ts {
21652180 } ) ;
21662181 }
21672182
2183+ function getFileReference ( ) {
2184+ const file = scanner . getTokenValue ( ) ;
2185+ const pos = scanner . getTokenPos ( ) ;
2186+ return {
2187+ fileName : file ,
2188+ pos : pos ,
2189+ end : pos + file . length
2190+ } ;
2191+ }
2192+
21682193 function recordAmbientExternalModule ( ) : void {
21692194 if ( ! ambientExternalModules ) {
21702195 ambientExternalModules = [ ] ;
21712196 }
2172- ambientExternalModules . push ( scanner . getTokenValue ( ) ) ;
2197+ ambientExternalModules . push ( { ref : getFileReference ( ) , depth : braceNesting } ) ;
21732198 }
21742199
21752200 function recordModuleName ( ) {
2176- const importPath = scanner . getTokenValue ( ) ;
2177- const pos = scanner . getTokenPos ( ) ;
2178- importedFiles . push ( {
2179- fileName : importPath ,
2180- pos : pos ,
2181- end : pos + importPath . length
2182- } ) ;
2201+ importedFiles . push ( getFileReference ( ) ) ;
2202+
2203+ markAsExternalModuleIfTopLevel ( ) ;
2204+ }
2205+
2206+ function markAsExternalModuleIfTopLevel ( ) {
2207+ if ( braceNesting === 0 ) {
2208+ externalModule = true ;
2209+ }
21832210 }
21842211
21852212 /**
@@ -2189,9 +2216,9 @@ namespace ts {
21892216 let token = scanner . getToken ( ) ;
21902217 if ( token === SyntaxKind . DeclareKeyword ) {
21912218 // declare module "mod"
2192- token = scanner . scan ( ) ;
2219+ token = nextToken ( ) ;
21932220 if ( token === SyntaxKind . ModuleKeyword ) {
2194- token = scanner . scan ( ) ;
2221+ token = nextToken ( ) ;
21952222 if ( token === SyntaxKind . StringLiteral ) {
21962223 recordAmbientExternalModule ( ) ;
21972224 }
@@ -2208,17 +2235,18 @@ namespace ts {
22082235 function tryConsumeImport ( ) : boolean {
22092236 let token = scanner . getToken ( ) ;
22102237 if ( token === SyntaxKind . ImportKeyword ) {
2211- token = scanner . scan ( ) ;
2238+
2239+ token = nextToken ( ) ;
22122240 if ( token === SyntaxKind . StringLiteral ) {
22132241 // import "mod";
22142242 recordModuleName ( ) ;
22152243 return true ;
22162244 }
22172245 else {
22182246 if ( token === SyntaxKind . Identifier || isKeyword ( token ) ) {
2219- token = scanner . scan ( ) ;
2247+ token = nextToken ( ) ;
22202248 if ( token === SyntaxKind . FromKeyword ) {
2221- token = scanner . scan ( ) ;
2249+ token = nextToken ( ) ;
22222250 if ( token === SyntaxKind . StringLiteral ) {
22232251 // import d from "mod";
22242252 recordModuleName ( ) ;
@@ -2232,7 +2260,7 @@ namespace ts {
22322260 }
22332261 else if ( token === SyntaxKind . CommaToken ) {
22342262 // consume comma and keep going
2235- token = scanner . scan ( ) ;
2263+ token = nextToken ( ) ;
22362264 }
22372265 else {
22382266 // unknown syntax
@@ -2241,17 +2269,17 @@ namespace ts {
22412269 }
22422270
22432271 if ( token === SyntaxKind . OpenBraceToken ) {
2244- token = scanner . scan ( ) ;
2272+ token = nextToken ( ) ;
22452273 // consume "{ a as B, c, d as D}" clauses
22462274 // make sure that it stops on EOF
22472275 while ( token !== SyntaxKind . CloseBraceToken && token !== SyntaxKind . EndOfFileToken ) {
2248- token = scanner . scan ( ) ;
2276+ token = nextToken ( ) ;
22492277 }
22502278
22512279 if ( token === SyntaxKind . CloseBraceToken ) {
2252- token = scanner . scan ( ) ;
2280+ token = nextToken ( ) ;
22532281 if ( token === SyntaxKind . FromKeyword ) {
2254- token = scanner . scan ( ) ;
2282+ token = nextToken ( ) ;
22552283 if ( token === SyntaxKind . StringLiteral ) {
22562284 // import {a as A} from "mod";
22572285 // import d, {a, b as B} from "mod"
@@ -2261,13 +2289,13 @@ namespace ts {
22612289 }
22622290 }
22632291 else if ( token === SyntaxKind . AsteriskToken ) {
2264- token = scanner . scan ( ) ;
2292+ token = nextToken ( ) ;
22652293 if ( token === SyntaxKind . AsKeyword ) {
2266- token = scanner . scan ( ) ;
2294+ token = nextToken ( ) ;
22672295 if ( token === SyntaxKind . Identifier || isKeyword ( token ) ) {
2268- token = scanner . scan ( ) ;
2296+ token = nextToken ( ) ;
22692297 if ( token === SyntaxKind . FromKeyword ) {
2270- token = scanner . scan ( ) ;
2298+ token = nextToken ( ) ;
22712299 if ( token === SyntaxKind . StringLiteral ) {
22722300 // import * as NS from "mod"
22732301 // import d, * as NS from "mod"
@@ -2288,19 +2316,20 @@ namespace ts {
22882316 function tryConsumeExport ( ) : boolean {
22892317 let token = scanner . getToken ( ) ;
22902318 if ( token === SyntaxKind . ExportKeyword ) {
2291- token = scanner . scan ( ) ;
2319+ markAsExternalModuleIfTopLevel ( ) ;
2320+ token = nextToken ( ) ;
22922321 if ( token === SyntaxKind . OpenBraceToken ) {
2293- token = scanner . scan ( ) ;
2322+ token = nextToken ( ) ;
22942323 // consume "{ a as B, c, d as D}" clauses
22952324 // make sure it stops on EOF
22962325 while ( token !== SyntaxKind . CloseBraceToken && token !== SyntaxKind . EndOfFileToken ) {
2297- token = scanner . scan ( ) ;
2326+ token = nextToken ( ) ;
22982327 }
22992328
23002329 if ( token === SyntaxKind . CloseBraceToken ) {
2301- token = scanner . scan ( ) ;
2330+ token = nextToken ( ) ;
23022331 if ( token === SyntaxKind . FromKeyword ) {
2303- token = scanner . scan ( ) ;
2332+ token = nextToken ( ) ;
23042333 if ( token === SyntaxKind . StringLiteral ) {
23052334 // export {a as A} from "mod";
23062335 // export {a, b as B} from "mod"
@@ -2310,19 +2339,19 @@ namespace ts {
23102339 }
23112340 }
23122341 else if ( token === SyntaxKind . AsteriskToken ) {
2313- token = scanner . scan ( ) ;
2342+ token = nextToken ( ) ;
23142343 if ( token === SyntaxKind . FromKeyword ) {
2315- token = scanner . scan ( ) ;
2344+ token = nextToken ( ) ;
23162345 if ( token === SyntaxKind . StringLiteral ) {
23172346 // export * from "mod"
23182347 recordModuleName ( ) ;
23192348 }
23202349 }
23212350 }
23222351 else if ( token === SyntaxKind . ImportKeyword ) {
2323- token = scanner . scan ( ) ;
2352+ token = nextToken ( ) ;
23242353 if ( token === SyntaxKind . Identifier || isKeyword ( token ) ) {
2325- token = scanner . scan ( ) ;
2354+ token = nextToken ( ) ;
23262355 if ( token === SyntaxKind . EqualsToken ) {
23272356 if ( tryConsumeRequireCall ( /*skipCurrentToken*/ true ) ) {
23282357 return true ;
@@ -2338,11 +2367,11 @@ namespace ts {
23382367 }
23392368
23402369 function tryConsumeRequireCall ( skipCurrentToken : boolean ) : boolean {
2341- let token = skipCurrentToken ? scanner . scan ( ) : scanner . getToken ( ) ;
2370+ let token = skipCurrentToken ? nextToken ( ) : scanner . getToken ( ) ;
23422371 if ( token === SyntaxKind . RequireKeyword ) {
2343- token = scanner . scan ( ) ;
2372+ token = nextToken ( ) ;
23442373 if ( token === SyntaxKind . OpenParenToken ) {
2345- token = scanner . scan ( ) ;
2374+ token = nextToken ( ) ;
23462375 if ( token === SyntaxKind . StringLiteral ) {
23472376 // require("mod");
23482377 recordModuleName ( ) ;
@@ -2356,17 +2385,17 @@ namespace ts {
23562385 function tryConsumeDefine ( ) : boolean {
23572386 let token = scanner . getToken ( ) ;
23582387 if ( token === SyntaxKind . Identifier && scanner . getTokenValue ( ) === "define" ) {
2359- token = scanner . scan ( ) ;
2388+ token = nextToken ( ) ;
23602389 if ( token !== SyntaxKind . OpenParenToken ) {
23612390 return true ;
23622391 }
23632392
2364- token = scanner . scan ( ) ;
2393+ token = nextToken ( ) ;
23652394 if ( token === SyntaxKind . StringLiteral ) {
23662395 // looks like define ("modname", ... - skip string literal and comma
2367- token = scanner . scan ( ) ;
2396+ token = nextToken ( ) ;
23682397 if ( token === SyntaxKind . CommaToken ) {
2369- token = scanner . scan ( ) ;
2398+ token = nextToken ( ) ;
23702399 }
23712400 else {
23722401 // unexpected token
@@ -2380,7 +2409,7 @@ namespace ts {
23802409 }
23812410
23822411 // skip open bracket
2383- token = scanner . scan ( ) ;
2412+ token = nextToken ( ) ;
23842413 let i = 0 ;
23852414 // scan until ']' or EOF
23862415 while ( token !== SyntaxKind . CloseBracketToken && token !== SyntaxKind . EndOfFileToken ) {
@@ -2390,7 +2419,7 @@ namespace ts {
23902419 i ++ ;
23912420 }
23922421
2393- token = scanner . scan ( ) ;
2422+ token = nextToken ( ) ;
23942423 }
23952424 return true ;
23962425
@@ -2400,7 +2429,7 @@ namespace ts {
24002429
24012430 function processImports ( ) : void {
24022431 scanner . setText ( sourceText ) ;
2403- scanner . scan ( ) ;
2432+ nextToken ( ) ;
24042433 // Look for:
24052434 // import "mod";
24062435 // import d from "mod"
@@ -2427,7 +2456,7 @@ namespace ts {
24272456 continue ;
24282457 }
24292458 else {
2430- scanner . scan ( ) ;
2459+ nextToken ( ) ;
24312460 }
24322461 }
24332462
@@ -2438,7 +2467,34 @@ namespace ts {
24382467 processImports ( ) ;
24392468 }
24402469 processTripleSlashDirectives ( ) ;
2441- return { referencedFiles, importedFiles, isLibFile : isNoDefaultLib , ambientExternalModules } ;
2470+ if ( externalModule ) {
2471+ // for external modules module all nested ambient modules are augmentations
2472+ if ( ambientExternalModules ) {
2473+ // move all detected ambient modules to imported files since they need to be resolved
2474+ for ( const decl of ambientExternalModules ) {
2475+ importedFiles . push ( decl . ref ) ;
2476+ }
2477+ }
2478+ return { referencedFiles, importedFiles, isLibFile : isNoDefaultLib , ambientExternalModules : undefined } ;
2479+ }
2480+ else {
2481+ // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0
2482+ let ambientModuleNames : string [ ] ;
2483+ if ( ambientExternalModules ) {
2484+ for ( const decl of ambientExternalModules ) {
2485+ if ( decl . depth === 0 ) {
2486+ if ( ! ambientModuleNames ) {
2487+ ambientModuleNames = [ ] ;
2488+ }
2489+ ambientModuleNames . push ( decl . ref . fileName ) ;
2490+ }
2491+ else {
2492+ importedFiles . push ( decl . ref ) ;
2493+ }
2494+ }
2495+ }
2496+ return { referencedFiles, importedFiles, isLibFile : isNoDefaultLib , ambientExternalModules : ambientModuleNames } ;
2497+ }
24422498 }
24432499
24442500 /// Helpers
0 commit comments