@@ -93,12 +93,14 @@ namespace ts {
9393 signature : string ;
9494 }
9595
96- export function createBuilder (
97- getCanonicalFileName : ( fileName : string ) => string ,
98- getEmitOutput : ( program : Program , sourceFile : SourceFile , emitOnlyDtsFiles : boolean , isDetailed : boolean ) => EmitOutput | EmitOutputDetailed ,
99- computeHash : ( data : string ) => string ,
100- shouldEmitFile : ( sourceFile : SourceFile ) => boolean
101- ) : Builder {
96+ export interface BuilderOptions {
97+ getCanonicalFileName : ( fileName : string ) => string ;
98+ getEmitOutput : ( program : Program , sourceFile : SourceFile , emitOnlyDtsFiles : boolean , isDetailed : boolean ) => EmitOutput | EmitOutputDetailed ;
99+ computeHash : ( data : string ) => string ;
100+ shouldEmitFile : ( sourceFile : SourceFile ) => boolean ;
101+ }
102+
103+ export function createBuilder ( options : BuilderOptions ) : Builder {
102104 let isModuleEmit : boolean | undefined ;
103105 const fileInfos = createMap < FileInfo > ( ) ;
104106 const semanticDiagnosticsPerFile = createMap < ReadonlyArray < Diagnostic > > ( ) ;
@@ -181,7 +183,7 @@ namespace ts {
181183 ensureProgramGraph ( program ) ;
182184
183185 const sourceFile = program . getSourceFile ( path ) ;
184- const singleFileResult = sourceFile && shouldEmitFile ( sourceFile ) ? [ sourceFile . fileName ] : [ ] ;
186+ const singleFileResult = sourceFile && options . shouldEmitFile ( sourceFile ) ? [ sourceFile . fileName ] : [ ] ;
185187 const info = fileInfos . get ( path ) ;
186188 if ( ! info || ! updateShapeSignature ( program , sourceFile , info ) ) {
187189 return singleFileResult ;
@@ -197,7 +199,7 @@ namespace ts {
197199 return { outputFiles : [ ] , emitSkipped : true } ;
198200 }
199201
200- return getEmitOutput ( program , program . getSourceFileByPath ( path ) , /*emitOnlyDtsFiles*/ false , /*isDetailed*/ false ) ;
202+ return options . getEmitOutput ( program , program . getSourceFileByPath ( path ) , /*emitOnlyDtsFiles*/ false , /*isDetailed*/ false ) ;
201203 }
202204
203205 function enumerateChangedFilesSet (
@@ -220,21 +222,21 @@ namespace ts {
220222 onChangedFile : ( fileName : string , path : Path ) => void ,
221223 onEmitOutput : ( emitOutput : EmitOutputDetailed , sourceFile : SourceFile ) => void
222224 ) {
223- const seenFiles = createMap < SourceFile > ( ) ;
225+ const seenFiles = createMap < true > ( ) ;
224226 enumerateChangedFilesSet ( program , onChangedFile , ( fileName , sourceFile ) => {
225227 if ( ! seenFiles . has ( fileName ) ) {
226- seenFiles . set ( fileName , sourceFile ) ;
228+ seenFiles . set ( fileName , true ) ;
227229 if ( sourceFile ) {
228230 // Any affected file shouldnt have the cached diagnostics
229231 semanticDiagnosticsPerFile . delete ( sourceFile . path ) ;
230232
231- const emitOutput = getEmitOutput ( program , sourceFile , emitOnlyDtsFiles , /*isDetailed*/ true ) as EmitOutputDetailed ;
233+ const emitOutput = options . getEmitOutput ( program , sourceFile , emitOnlyDtsFiles , /*isDetailed*/ true ) as EmitOutputDetailed ;
232234 onEmitOutput ( emitOutput , sourceFile ) ;
233235
234236 // mark all the emitted source files as seen
235237 if ( emitOutput . emittedSourceFiles ) {
236238 for ( const file of emitOutput . emittedSourceFiles ) {
237- seenFiles . set ( file . fileName , file ) ;
239+ seenFiles . set ( file . fileName , true ) ;
238240 }
239241 }
240242 }
@@ -309,13 +311,13 @@ namespace ts {
309311 const prevSignature = info . signature ;
310312 let latestSignature : string ;
311313 if ( sourceFile . isDeclarationFile ) {
312- latestSignature = computeHash ( sourceFile . text ) ;
314+ latestSignature = options . computeHash ( sourceFile . text ) ;
313315 info . signature = latestSignature ;
314316 }
315317 else {
316- const emitOutput = getEmitOutput ( program , sourceFile , /*emitOnlyDtsFiles*/ true , /*isDetailed*/ false ) ;
318+ const emitOutput = options . getEmitOutput ( program , sourceFile , /*emitOnlyDtsFiles*/ true , /*isDetailed*/ false ) ;
317319 if ( emitOutput . outputFiles && emitOutput . outputFiles . length > 0 ) {
318- latestSignature = computeHash ( emitOutput . outputFiles [ 0 ] . text ) ;
320+ latestSignature = options . computeHash ( emitOutput . outputFiles [ 0 ] . text ) ;
319321 info . signature = latestSignature ;
320322 }
321323 else {
@@ -352,7 +354,7 @@ namespace ts {
352354 // Handle triple slash references
353355 if ( sourceFile . referencedFiles && sourceFile . referencedFiles . length > 0 ) {
354356 for ( const referencedFile of sourceFile . referencedFiles ) {
355- const referencedPath = toPath ( referencedFile . fileName , sourceFileDirectory , getCanonicalFileName ) ;
357+ const referencedPath = toPath ( referencedFile . fileName , sourceFileDirectory , options . getCanonicalFileName ) ;
356358 addReferencedFile ( referencedPath ) ;
357359 }
358360 }
@@ -365,7 +367,7 @@ namespace ts {
365367 }
366368
367369 const fileName = resolvedTypeReferenceDirective . resolvedFileName ;
368- const typeFilePath = toPath ( fileName , sourceFileDirectory , getCanonicalFileName ) ;
370+ const typeFilePath = toPath ( fileName , sourceFileDirectory , options . getCanonicalFileName ) ;
369371 addReferencedFile ( typeFilePath ) ;
370372 } ) ;
371373 }
@@ -381,18 +383,26 @@ namespace ts {
381383 }
382384
383385 /**
384- * Gets all the emittable files from the program
386+ * Gets all the emittable files from the program.
387+ * @param firstSourceFile This one will be emitted first. See https://github.com/Microsoft/TypeScript/issues/16888
385388 */
386- function getAllEmittableFiles ( program : Program ) {
389+ function getAllEmittableFiles ( program : Program , firstSourceFile : SourceFile ) : string [ ] {
387390 const defaultLibraryFileName = getDefaultLibFileName ( program . getCompilerOptions ( ) ) ;
388391 const sourceFiles = program . getSourceFiles ( ) ;
389392 const result : string [ ] = [ ] ;
393+ add ( firstSourceFile ) ;
390394 for ( const sourceFile of sourceFiles ) {
391- if ( getBaseFileName ( sourceFile . fileName ) !== defaultLibraryFileName && shouldEmitFile ( sourceFile ) ) {
392- result . push ( sourceFile . fileName ) ;
395+ if ( sourceFile !== firstSourceFile ) {
396+ add ( sourceFile ) ;
393397 }
394398 }
395399 return result ;
400+
401+ function add ( sourceFile : SourceFile ) : void {
402+ if ( getBaseFileName ( sourceFile . fileName ) !== defaultLibraryFileName && options . shouldEmitFile ( sourceFile ) ) {
403+ result . push ( sourceFile . fileName ) ;
404+ }
405+ }
396406 }
397407
398408 function getNonModuleEmitHandler ( ) : EmitHandler {
@@ -404,14 +414,14 @@ namespace ts {
404414 getFilesAffectedByUpdatedShape
405415 } ;
406416
407- function getFilesAffectedByUpdatedShape ( program : Program , _sourceFile : SourceFile , singleFileResult : string [ ] ) : string [ ] {
417+ function getFilesAffectedByUpdatedShape ( program : Program , sourceFile : SourceFile , singleFileResult : string [ ] ) : string [ ] {
408418 const options = program . getCompilerOptions ( ) ;
409419 // If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project,
410420 // so returning the file itself is good enough.
411421 if ( options && ( options . out || options . outFile ) ) {
412422 return singleFileResult ;
413423 }
414- return getAllEmittableFiles ( program ) ;
424+ return getAllEmittableFiles ( program , sourceFile ) ;
415425 }
416426 }
417427
@@ -484,11 +494,11 @@ namespace ts {
484494
485495 function getFilesAffectedByUpdatedShape ( program : Program , sourceFile : SourceFile , singleFileResult : string [ ] ) : string [ ] {
486496 if ( ! isExternalModule ( sourceFile ) && ! containsOnlyAmbientModules ( sourceFile ) ) {
487- return getAllEmittableFiles ( program ) ;
497+ return getAllEmittableFiles ( program , sourceFile ) ;
488498 }
489499
490- const options = program . getCompilerOptions ( ) ;
491- if ( options && ( options . isolatedModules || options . out || options . outFile ) ) {
500+ const compilerOptions = program . getCompilerOptions ( ) ;
501+ if ( compilerOptions && ( compilerOptions . isolatedModules || compilerOptions . out || compilerOptions . outFile ) ) {
492502 return singleFileResult ;
493503 }
494504
@@ -498,7 +508,7 @@ namespace ts {
498508
499509 const seenFileNamesMap = createMap < string > ( ) ;
500510 const setSeenFileName = ( path : Path , sourceFile : SourceFile ) => {
501- seenFileNamesMap . set ( path , sourceFile && shouldEmitFile ( sourceFile ) ? sourceFile . fileName : undefined ) ;
511+ seenFileNamesMap . set ( path , sourceFile && options . shouldEmitFile ( sourceFile ) ? sourceFile . fileName : undefined ) ;
502512 } ;
503513
504514 // Start with the paths this file was referenced by
0 commit comments