@@ -34,8 +34,8 @@ namespace ts {
34
34
/**
35
35
* Map from config file name to up-to-date status
36
36
*/
37
- projectStatus : FileMap < UpToDateStatus > ;
38
- diagnostics ?: FileMap < number > ; // TODO(shkamat): this should be really be diagnostics but thats for later time
37
+ projectStatus : ConfigFileMap < UpToDateStatus > ;
38
+ diagnostics ?: ConfigFileMap < number > ; // TODO(shkamat): this should be really be diagnostics but thats for later time
39
39
40
40
invalidateProject ( project : ResolvedConfigFileName , dependencyGraph : DependencyGraph | undefined ) : void ;
41
41
getNextInvalidatedProject ( ) : ResolvedConfigFileName | undefined ;
@@ -189,110 +189,96 @@ namespace ts {
189
189
}
190
190
}
191
191
192
- interface FileMap < T > {
193
- setValue ( fileName : string , value : T ) : void ;
194
- getValue ( fileName : string ) : T | never ;
195
- getValueOrUndefined ( fileName : string ) : T | undefined ;
196
- hasKey ( fileName : string ) : boolean ;
197
- removeKey ( fileName : string ) : void ;
198
- getKeys ( ) : string [ ] ;
192
+ interface FileMap < T , U extends string = string , V extends Path = Path > {
193
+ setValue ( fileName : U , value : T ) : void ;
194
+ getValue ( fileName : U ) : T | undefined ;
195
+ hasKey ( fileName : U ) : boolean ;
196
+ removeKey ( fileName : U ) : void ;
197
+ forEach ( action : ( value : T , key : V ) => void ) : void ;
199
198
getSize ( ) : number ;
200
199
}
201
200
201
+ type ResolvedConfigFilePath = ResolvedConfigFileName & Path ;
202
+ type ConfigFileMap < T > = FileMap < T , ResolvedConfigFileName , ResolvedConfigFilePath > ;
203
+ type ToResolvedConfigFilePath = ( fileName : ResolvedConfigFileName ) => ResolvedConfigFilePath ;
204
+ type ToPath = ( fileName : string ) => Path ;
205
+
202
206
/**
203
207
* A FileMap maintains a normalized-key to value relationship
204
208
*/
205
- function createFileMap < T > ( ) : FileMap < T > {
209
+ function createFileMap < T > ( toPath : ToResolvedConfigFilePath ) : ConfigFileMap < T > ;
210
+ function createFileMap < T , U extends string = string , V extends Path = Path > ( toPath : ToPath ) : FileMap < T , U , V > ;
211
+ function createFileMap < T , U extends string = string , V extends Path = Path > ( toPath : ( fileName : U ) => V ) : FileMap < T , U , V > {
206
212
// tslint:disable-next-line:no-null-keyword
207
213
const lookup = createMap < T > ( ) ;
208
214
209
215
return {
210
216
setValue,
211
217
getValue,
212
- getValueOrUndefined,
213
218
removeKey,
214
- getKeys ,
219
+ forEach ,
215
220
hasKey,
216
221
getSize
217
222
} ;
218
223
219
- function getKeys ( ) : string [ ] {
220
- return Object . keys ( lookup ) ;
221
- }
222
-
223
- function hasKey ( fileName : string ) {
224
- return lookup . has ( normalizePath ( fileName ) ) ;
224
+ function forEach ( action : ( value : T , key : V ) => void ) {
225
+ lookup . forEach ( action ) ;
225
226
}
226
227
227
- function removeKey ( fileName : string ) {
228
- lookup . delete ( normalizePath ( fileName ) ) ;
228
+ function hasKey ( fileName : U ) {
229
+ return lookup . has ( toPath ( fileName ) ) ;
229
230
}
230
231
231
- function setValue ( fileName : string , value : T ) {
232
- lookup . set ( normalizePath ( fileName ) , value ) ;
232
+ function removeKey ( fileName : U ) {
233
+ lookup . delete ( toPath ( fileName ) ) ;
233
234
}
234
235
235
- function getValue ( fileName : string ) : T | never {
236
- const f = normalizePath ( fileName ) ;
237
- if ( lookup . has ( f ) ) {
238
- return lookup . get ( f ) ! ;
239
- }
240
- else {
241
- throw new Error ( `No value corresponding to ${ fileName } exists in this map` ) ;
242
- }
236
+ function setValue ( fileName : U , value : T ) {
237
+ lookup . set ( toPath ( fileName ) , value ) ;
243
238
}
244
239
245
- function getValueOrUndefined ( fileName : string ) : T | undefined {
246
- const f = normalizePath ( fileName ) ;
247
- return lookup . get ( f ) ;
240
+ function getValue ( fileName : U ) : T | undefined {
241
+ return lookup . get ( toPath ( fileName ) ) ;
248
242
}
249
243
250
244
function getSize ( ) {
251
245
return lookup . size ;
252
246
}
253
247
}
254
248
255
- function createDependencyMapper ( ) {
256
- const childToParents = createFileMap < ResolvedConfigFileName [ ] > ( ) ;
257
- const parentToChildren = createFileMap < ResolvedConfigFileName [ ] > ( ) ;
258
- const allKeys = createFileMap < true > ( ) ;
249
+ function createDependencyMapper ( toPath : ToResolvedConfigFilePath ) {
250
+ const childToParents = createFileMap < ResolvedConfigFileName [ ] > ( toPath ) ;
251
+ const parentToChildren = createFileMap < ResolvedConfigFileName [ ] > ( toPath ) ;
259
252
260
253
function addReference ( childConfigFileName : ResolvedConfigFileName , parentConfigFileName : ResolvedConfigFileName ) : void {
261
254
addEntry ( childToParents , childConfigFileName , parentConfigFileName ) ;
262
255
addEntry ( parentToChildren , parentConfigFileName , childConfigFileName ) ;
263
256
}
264
257
265
258
function getReferencesTo ( parentConfigFileName : ResolvedConfigFileName ) : ResolvedConfigFileName [ ] {
266
- return parentToChildren . getValueOrUndefined ( parentConfigFileName ) || [ ] ;
259
+ return parentToChildren . getValue ( parentConfigFileName ) || [ ] ;
267
260
}
268
261
269
262
function getReferencesOf ( childConfigFileName : ResolvedConfigFileName ) : ResolvedConfigFileName [ ] {
270
- return childToParents . getValueOrUndefined ( childConfigFileName ) || [ ] ;
271
- }
272
-
273
- function getKeys ( ) : ReadonlyArray < ResolvedConfigFileName > {
274
- return allKeys . getKeys ( ) as ResolvedConfigFileName [ ] ;
263
+ return childToParents . getValue ( childConfigFileName ) || [ ] ;
275
264
}
276
265
277
266
function addEntry ( mapToAddTo : typeof childToParents | typeof parentToChildren , key : ResolvedConfigFileName , element : ResolvedConfigFileName ) {
278
267
key = normalizePath ( key ) as ResolvedConfigFileName ;
279
268
element = normalizePath ( element ) as ResolvedConfigFileName ;
280
- let arr = mapToAddTo . getValueOrUndefined ( key ) ;
269
+ let arr = mapToAddTo . getValue ( key ) ;
281
270
if ( arr === undefined ) {
282
271
mapToAddTo . setValue ( key , arr = [ ] ) ;
283
272
}
284
273
if ( arr . indexOf ( element ) < 0 ) {
285
274
arr . push ( element ) ;
286
275
}
287
- allKeys . setValue ( key , true ) ;
288
- allKeys . setValue ( element , true ) ;
289
276
}
290
277
291
278
return {
292
279
addReference,
293
280
getReferencesTo,
294
281
getReferencesOf,
295
- getKeys
296
282
} ;
297
283
}
298
284
@@ -355,16 +341,16 @@ namespace ts {
355
341
return opts . rootDir || getDirectoryPath ( configFileName ) ;
356
342
}
357
343
358
- function createConfigFileCache ( host : CompilerHost ) {
359
- const cache = createFileMap < ParsedCommandLine | "error" > ( ) ;
344
+ function createConfigFileCache ( host : CompilerHost , toPath : ToResolvedConfigFilePath ) {
345
+ const cache = createFileMap < ParsedCommandLine | "error" > ( toPath ) ;
360
346
const configParseHost = parseConfigHostFromCompilerHost ( host ) ;
361
347
362
348
function isParsedCommandLine ( value : ParsedCommandLine | "error" ) : value is ParsedCommandLine {
363
349
return ! ( value as "error" ) . length ;
364
350
}
365
351
366
352
function parseConfigFile ( configFilePath : ResolvedConfigFileName ) {
367
- const value = cache . getValueOrUndefined ( configFilePath ) ;
353
+ const value = cache . getValue ( configFilePath ) ;
368
354
if ( value ) {
369
355
return isParsedCommandLine ( value ) ? value : undefined ;
370
356
}
@@ -398,18 +384,18 @@ namespace ts {
398
384
return fileExtensionIs ( fileName , Extension . Dts ) ;
399
385
}
400
386
401
- export function createBuildContext ( options : BuildOptions ) : BuildContext {
387
+ export function createBuildContext ( options : BuildOptions , toPath : ToResolvedConfigFilePath ) : BuildContext {
402
388
const invalidatedProjectQueue = [ ] as ResolvedConfigFileName [ ] ;
403
389
let nextIndex = 0 ;
404
- const projectPendingBuild = createFileMap < true > ( ) ;
390
+ const projectPendingBuild = createFileMap < true > ( toPath ) ;
405
391
const missingRoots = createMap < true > ( ) ;
406
- const diagnostics = options . watch ? createFileMap < number > ( ) : undefined ;
392
+ const diagnostics = options . watch ? createFileMap < number > ( toPath ) : undefined ;
407
393
408
394
return {
409
395
options,
410
- projectStatus : createFileMap ( ) ,
396
+ projectStatus : createFileMap ( toPath ) ,
411
397
diagnostics,
412
- unchangedOutputs : createFileMap ( ) ,
398
+ unchangedOutputs : createFileMap ( toPath as ToPath ) ,
413
399
invalidateProject,
414
400
getNextInvalidatedProject,
415
401
hasPendingInvalidatedProjects,
@@ -513,8 +499,10 @@ namespace ts {
513
499
*/
514
500
export function createSolutionBuilder ( host : SolutionBuilderHost , rootNames : ReadonlyArray < string > , defaultOptions : BuildOptions ) {
515
501
const hostWithWatch = host as SolutionBuilderWithWatchHost ;
516
- const configFileCache = createConfigFileCache ( host ) ;
517
- let context = createBuildContext ( defaultOptions ) ;
502
+ const currentDirectory = host . getCurrentDirectory ( ) ;
503
+ const getCanonicalFileName = createGetCanonicalFileName ( host . useCaseSensitiveFileNames ( ) ) ;
504
+ const configFileCache = createConfigFileCache ( host , toPath ) ;
505
+ let context = createBuildContext ( defaultOptions , toPath ) ;
518
506
let timerToBuildInvalidatedProject : any ;
519
507
let reportFileChangeDetected = false ;
520
508
@@ -535,6 +523,12 @@ namespace ts {
535
523
startWatching
536
524
} ;
537
525
526
+ function toPath ( fileName : ResolvedConfigFileName ) : ResolvedConfigFilePath ;
527
+ function toPath ( fileName : string ) : Path ;
528
+ function toPath ( fileName : string ) {
529
+ return ts . toPath ( fileName , currentDirectory , getCanonicalFileName ) ;
530
+ }
531
+
538
532
function reportStatus ( message : DiagnosticMessage , ...args : string [ ] ) {
539
533
host . reportSolutionBuilderStatus ( createCompilerDiagnostic ( message , ...args ) ) ;
540
534
}
@@ -600,7 +594,7 @@ namespace ts {
600
594
}
601
595
602
596
function resetBuildContext ( opts = defaultOptions ) {
603
- context = createBuildContext ( opts ) ;
597
+ context = createBuildContext ( opts , toPath ) ;
604
598
}
605
599
606
600
function getUpToDateStatusOfFile ( configFileName : ResolvedConfigFileName ) : UpToDateStatus {
@@ -623,13 +617,13 @@ namespace ts {
623
617
return { type : UpToDateStatusType . Unbuildable , reason : "File deleted mid-build" } ;
624
618
}
625
619
626
- const prior = context . projectStatus . getValueOrUndefined ( project . options . configFilePath ! ) ;
620
+ const prior = context . projectStatus . getValue ( project . options . configFilePath as ResolvedConfigFilePath ) ;
627
621
if ( prior !== undefined ) {
628
622
return prior ;
629
623
}
630
624
631
625
const actual = getUpToDateStatusWorker ( project ) ;
632
- context . projectStatus . setValue ( project . options . configFilePath ! , actual ) ;
626
+ context . projectStatus . setValue ( project . options . configFilePath as ResolvedConfigFilePath , actual ) ;
633
627
return actual ;
634
628
}
635
629
@@ -700,7 +694,7 @@ namespace ts {
700
694
// had its file touched but not had its contents changed - this allows us
701
695
// to skip a downstream typecheck
702
696
if ( isDeclarationFile ( output ) ) {
703
- const unchangedTime = context . unchangedOutputs . getValueOrUndefined ( output ) ;
697
+ const unchangedTime = context . unchangedOutputs . getValue ( output ) ;
704
698
if ( unchangedTime !== undefined ) {
705
699
newestDeclarationFileContentChangedTime = newer ( unchangedTime , newestDeclarationFileContentChangedTime ) ;
706
700
}
@@ -845,9 +839,9 @@ namespace ts {
845
839
846
840
function reportErrorSummary ( ) {
847
841
if ( context . options . watch ) {
848
- let errorCount = 0 ;
849
- context . diagnostics ! . getKeys ( ) . forEach ( resolved => errorCount += context . diagnostics ! . getValue ( resolved ) ) ;
850
- reportWatchStatus ( errorCount === 1 ? Diagnostics . Found_1_error_Watching_for_file_changes : Diagnostics . Found_0_errors_Watching_for_file_changes , errorCount ) ;
842
+ let totalErrors = 0 ;
843
+ context . diagnostics ! . forEach ( singleProjectErrors => totalErrors += singleProjectErrors ) ;
844
+ reportWatchStatus ( totalErrors === 1 ? Diagnostics . Found_1_error_Watching_for_file_changes : Diagnostics . Found_0_errors_Watching_for_file_changes , totalErrors ) ;
851
845
}
852
846
}
853
847
@@ -881,7 +875,7 @@ namespace ts {
881
875
const permanentMarks : { [ path : string ] : true } = { } ;
882
876
const circularityReportStack : string [ ] = [ ] ;
883
877
const buildOrder : ResolvedConfigFileName [ ] = [ ] ;
884
- const graph = createDependencyMapper ( ) ;
878
+ const graph = createDependencyMapper ( toPath ) ;
885
879
886
880
let hadError = false ;
887
881
@@ -1061,7 +1055,7 @@ namespace ts {
1061
1055
host . setModifiedTime ( file , now ) ;
1062
1056
}
1063
1057
1064
- context . projectStatus . setValue ( proj . options . configFilePath ! , { type : UpToDateStatusType . UpToDate , newestDeclarationFileContentChangedTime : priorNewestUpdateTime } as UpToDateStatus ) ;
1058
+ context . projectStatus . setValue ( proj . options . configFilePath as ResolvedConfigFilePath , { type : UpToDateStatusType . UpToDate , newestDeclarationFileContentChangedTime : priorNewestUpdateTime } as UpToDateStatus ) ;
1065
1059
}
1066
1060
1067
1061
function getFilesToClean ( configFileNames : ReadonlyArray < ResolvedConfigFileName > ) : string [ ] | undefined {
0 commit comments