@@ -205,13 +205,15 @@ namespace ts {
205205 }
206206
207207 export function getPreEmitDiagnostics ( program : Program , sourceFile ?: SourceFile , cancellationToken ?: CancellationToken ) : Diagnostic [ ] {
208- let diagnostics = program . getOptionsDiagnostics ( cancellationToken ) . concat (
209- program . getSyntacticDiagnostics ( sourceFile , cancellationToken ) ,
210- program . getGlobalDiagnostics ( cancellationToken ) ,
211- program . getSemanticDiagnostics ( sourceFile , cancellationToken ) ) ;
208+ const diagnostics = [
209+ ...program . getOptionsDiagnostics ( cancellationToken ) ,
210+ ...program . getSyntacticDiagnostics ( sourceFile , cancellationToken ) ,
211+ ...program . getGlobalDiagnostics ( cancellationToken ) ,
212+ ...program . getSemanticDiagnostics ( sourceFile , cancellationToken )
213+ ] ;
212214
213215 if ( program . getCompilerOptions ( ) . declaration ) {
214- diagnostics = diagnostics . concat ( program . getDeclarationDiagnostics ( sourceFile , cancellationToken ) ) ;
216+ addRange ( diagnostics , program . getDeclarationDiagnostics ( sourceFile , cancellationToken ) ) ;
215217 }
216218
217219 return sortAndDeduplicateDiagnostics ( diagnostics ) ;
@@ -223,7 +225,7 @@ namespace ts {
223225 getNewLine ( ) : string ;
224226 }
225227
226- export function formatDiagnostics ( diagnostics : Diagnostic [ ] , host : FormatDiagnosticsHost ) : string {
228+ export function formatDiagnostics ( diagnostics : ReadonlyArray < Diagnostic > , host : FormatDiagnosticsHost ) : string {
227229 let output = "" ;
228230
229231 for ( const diagnostic of diagnostics ) {
@@ -399,7 +401,7 @@ namespace ts {
399401 * @param oldProgram - Reuses an old program structure.
400402 * @returns A 'Program' object.
401403 */
402- export function createProgram ( rootNames : string [ ] , options : CompilerOptions , host ?: CompilerHost , oldProgram ?: Program ) : Program {
404+ export function createProgram ( rootNames : ReadonlyArray < string > , options : CompilerOptions , host ?: CompilerHost , oldProgram ?: Program ) : Program {
403405 let program : Program ;
404406 let files : SourceFile [ ] = [ ] ;
405407 let commonSourceDirectory : string ;
@@ -888,7 +890,7 @@ namespace ts {
888890 for ( const { oldFile : oldSourceFile , newFile : newSourceFile } of modifiedSourceFiles ) {
889891 const newSourceFilePath = getNormalizedAbsolutePath ( newSourceFile . fileName , currentDirectory ) ;
890892 if ( resolveModuleNamesWorker ) {
891- const moduleNames = map ( concatenate ( newSourceFile . imports , newSourceFile . moduleAugmentations ) , getTextOfLiteral ) ;
893+ const moduleNames = getModuleNames ( newSourceFile ) ;
892894 const oldProgramState = { program : oldProgram , file : oldSourceFile , modifiedFilePaths } ;
893895 const resolutions = resolveModuleNamesReusingOldState ( moduleNames , newSourceFilePath , newSourceFile , oldProgramState ) ;
894896 // ensure that module resolution results are still correct
@@ -996,7 +998,7 @@ namespace ts {
996998 }
997999
9981000 function emitWorker ( program : Program , sourceFile : SourceFile , writeFileCallback : WriteFileCallback , cancellationToken : CancellationToken , emitOnlyDtsFiles ?: boolean , customTransformers ?: CustomTransformers ) : EmitResult {
999- let declarationDiagnostics : Diagnostic [ ] = [ ] ;
1001+ let declarationDiagnostics : ReadonlyArray < Diagnostic > = [ ] ;
10001002
10011003 if ( options . noEmit ) {
10021004 return { diagnostics : declarationDiagnostics , sourceMaps : undefined , emittedFiles : undefined , emitSkipped : true } ;
@@ -1006,10 +1008,12 @@ namespace ts {
10061008 // immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
10071009 // get any preEmit diagnostics, not just the ones
10081010 if ( options . noEmitOnError ) {
1009- const diagnostics = program . getOptionsDiagnostics ( cancellationToken ) . concat (
1010- program . getSyntacticDiagnostics ( sourceFile , cancellationToken ) ,
1011- program . getGlobalDiagnostics ( cancellationToken ) ,
1012- program . getSemanticDiagnostics ( sourceFile , cancellationToken ) ) ;
1011+ const diagnostics = [
1012+ ...program . getOptionsDiagnostics ( cancellationToken ) ,
1013+ ...program . getSyntacticDiagnostics ( sourceFile , cancellationToken ) ,
1014+ ...program . getGlobalDiagnostics ( cancellationToken ) ,
1015+ ...program . getSemanticDiagnostics ( sourceFile , cancellationToken )
1016+ ] ;
10131017
10141018 if ( diagnostics . length === 0 && program . getCompilerOptions ( ) . declaration ) {
10151019 declarationDiagnostics = program . getDeclarationDiagnostics ( /*sourceFile*/ undefined , cancellationToken ) ;
@@ -1060,8 +1064,8 @@ namespace ts {
10601064
10611065 function getDiagnosticsHelper (
10621066 sourceFile : SourceFile ,
1063- getDiagnostics : ( sourceFile : SourceFile , cancellationToken : CancellationToken ) => Diagnostic [ ] ,
1064- cancellationToken : CancellationToken ) : Diagnostic [ ] {
1067+ getDiagnostics : ( sourceFile : SourceFile , cancellationToken : CancellationToken ) => ReadonlyArray < Diagnostic > ,
1068+ cancellationToken : CancellationToken ) : ReadonlyArray < Diagnostic > {
10651069 if ( sourceFile ) {
10661070 return getDiagnostics ( sourceFile , cancellationToken ) ;
10671071 }
@@ -1073,15 +1077,15 @@ namespace ts {
10731077 } ) ) ;
10741078 }
10751079
1076- function getSyntacticDiagnostics ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : Diagnostic [ ] {
1080+ function getSyntacticDiagnostics ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : ReadonlyArray < Diagnostic > {
10771081 return getDiagnosticsHelper ( sourceFile , getSyntacticDiagnosticsForFile , cancellationToken ) ;
10781082 }
10791083
1080- function getSemanticDiagnostics ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : Diagnostic [ ] {
1084+ function getSemanticDiagnostics ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : ReadonlyArray < Diagnostic > {
10811085 return getDiagnosticsHelper ( sourceFile , getSemanticDiagnosticsForFile , cancellationToken ) ;
10821086 }
10831087
1084- function getDeclarationDiagnostics ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : Diagnostic [ ] {
1088+ function getDeclarationDiagnostics ( sourceFile : SourceFile , cancellationToken : CancellationToken ) : ReadonlyArray < Diagnostic > {
10851089 const options = program . getCompilerOptions ( ) ;
10861090 // collect diagnostics from the program only once if either no source file was specified or out/outFile is set (bundled emit)
10871091 if ( ! sourceFile || options . out || options . outFile ) {
@@ -1092,7 +1096,7 @@ namespace ts {
10921096 }
10931097 }
10941098
1095- function getSyntacticDiagnosticsForFile ( sourceFile : SourceFile ) : Diagnostic [ ] {
1099+ function getSyntacticDiagnosticsForFile ( sourceFile : SourceFile ) : ReadonlyArray < Diagnostic > {
10961100 // For JavaScript files, we report semantic errors for using TypeScript-only
10971101 // constructs from within a JavaScript file as syntactic errors.
10981102 if ( isSourceFileJavaScript ( sourceFile ) ) {
@@ -1430,12 +1434,10 @@ namespace ts {
14301434 return a . fileName === b . fileName ;
14311435 }
14321436
1433- function moduleNameIsEqualTo ( a : LiteralExpression , b : LiteralExpression ) : boolean {
1434- return a . text === b . text ;
1435- }
1436-
1437- function getTextOfLiteral ( literal : LiteralExpression ) : string {
1438- return literal . text ;
1437+ function moduleNameIsEqualTo ( a : StringLiteral | Identifier , b : StringLiteral | Identifier ) : boolean {
1438+ return a . kind === SyntaxKind . StringLiteral
1439+ ? b . kind === SyntaxKind . StringLiteral && a . text === b . text
1440+ : b . kind === SyntaxKind . Identifier && a . escapedText === b . escapedText ;
14391441 }
14401442
14411443 function collectExternalModuleReferences ( file : SourceFile ) : void {
@@ -1448,7 +1450,7 @@ namespace ts {
14481450
14491451 // file.imports may not be undefined if there exists dynamic import
14501452 let imports : StringLiteral [ ] ;
1451- let moduleAugmentations : StringLiteral [ ] ;
1453+ let moduleAugmentations : Array < StringLiteral | Identifier > ;
14521454 let ambientModules : string [ ] ;
14531455
14541456 // If we are importing helpers, we need to add a synthetic reference to resolve the
@@ -1477,7 +1479,7 @@ namespace ts {
14771479
14781480 return ;
14791481
1480- function collectModuleReferences ( node : Node , inAmbientModule : boolean ) : void {
1482+ function collectModuleReferences ( node : Statement , inAmbientModule : boolean ) : void {
14811483 switch ( node . kind ) {
14821484 case SyntaxKind . ImportDeclaration :
14831485 case SyntaxKind . ImportEqualsDeclaration :
@@ -1499,8 +1501,8 @@ namespace ts {
14991501 break ;
15001502 case SyntaxKind . ModuleDeclaration :
15011503 if ( isAmbientModule ( < ModuleDeclaration > node ) && ( inAmbientModule || hasModifier ( node , ModifierFlags . Ambient ) || file . isDeclarationFile ) ) {
1502- const moduleName = < StringLiteral > ( < ModuleDeclaration > node ) . name ; // TODO: GH#17347
1503- const nameText = ts . getTextOfIdentifierOrLiteral ( moduleName ) ;
1504+ const moduleName = ( < ModuleDeclaration > node ) . name ;
1505+ const nameText = getTextOfIdentifierOrLiteral ( moduleName ) ;
15041506 // Ambient module declarations can be interpreted as augmentations for some existing external modules.
15051507 // This will happen in two cases:
15061508 // - if current file is external module then module augmentation is a ambient module declaration defined in the top level scope
@@ -1817,8 +1819,7 @@ namespace ts {
18171819 collectExternalModuleReferences ( file ) ;
18181820 if ( file . imports . length || file . moduleAugmentations . length ) {
18191821 // Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
1820- const nonGlobalAugmentation = filter ( file . moduleAugmentations , ( moduleAugmentation ) => moduleAugmentation . kind === SyntaxKind . StringLiteral ) ;
1821- const moduleNames = map ( concatenate ( file . imports , nonGlobalAugmentation ) , getTextOfLiteral ) ;
1822+ const moduleNames = getModuleNames ( file ) ;
18221823 const oldProgramState = { program : oldProgram , file, modifiedFilePaths } ;
18231824 const resolutions = resolveModuleNamesReusingOldState ( moduleNames , getNormalizedAbsolutePath ( file . fileName , currentDirectory ) , file , oldProgramState ) ;
18241825 Debug . assert ( resolutions . length === moduleNames . length ) ;
@@ -2229,4 +2230,15 @@ namespace ts {
22292230 Debug . assert ( names . every ( name => name !== undefined ) , "A name is undefined." , ( ) => JSON . stringify ( names ) ) ;
22302231 return names ;
22312232 }
2233+
2234+ function getModuleNames ( { imports, moduleAugmentations } : SourceFile ) : string [ ] {
2235+ const res = imports . map ( i => i . text ) ;
2236+ for ( const aug of moduleAugmentations ) {
2237+ if ( aug . kind === SyntaxKind . StringLiteral ) {
2238+ res . push ( aug . text ) ;
2239+ }
2240+ // Do nothing if it's an Identifier; we don't need to do module resolution for `declare global`.
2241+ }
2242+ return res ;
2243+ }
22322244}
0 commit comments