@@ -1341,7 +1341,12 @@ namespace ts {
1341
1341
/**
1342
1342
* Reads the config file, reports errors if any and exits if the config file cannot be found
1343
1343
*/
1344
- export function getParsedCommandLineOfConfigFile ( configFileName : string , optionsToExtend : CompilerOptions , host : ParseConfigFileHost ) : ParsedCommandLine | undefined {
1344
+ export function getParsedCommandLineOfConfigFile (
1345
+ configFileName : string ,
1346
+ optionsToExtend : CompilerOptions ,
1347
+ host : ParseConfigFileHost ,
1348
+ /*@internal */ extendedConfigCache ?: Map < ExtendedConfigCacheEntry >
1349
+ ) : ParsedCommandLine | undefined {
1345
1350
let configFileText : string | undefined ;
1346
1351
try {
1347
1352
configFileText = host . readFile ( configFileName ) ;
@@ -1362,7 +1367,16 @@ namespace ts {
1362
1367
result . path = toPath ( configFileName , cwd , createGetCanonicalFileName ( host . useCaseSensitiveFileNames ) ) ;
1363
1368
result . resolvedPath = result . path ;
1364
1369
result . originalFileName = result . fileName ;
1365
- return parseJsonSourceFileConfigFileContent ( result , host , getNormalizedAbsolutePath ( getDirectoryPath ( configFileName ) , cwd ) , optionsToExtend , getNormalizedAbsolutePath ( configFileName , cwd ) ) ;
1370
+ return parseJsonSourceFileConfigFileContent (
1371
+ result ,
1372
+ host ,
1373
+ getNormalizedAbsolutePath ( getDirectoryPath ( configFileName ) , cwd ) ,
1374
+ optionsToExtend ,
1375
+ getNormalizedAbsolutePath ( configFileName , cwd ) ,
1376
+ /*resolutionStack*/ undefined ,
1377
+ /*extraFileExtension*/ undefined ,
1378
+ extendedConfigCache
1379
+ ) ;
1366
1380
}
1367
1381
1368
1382
/**
@@ -1976,8 +1990,8 @@ namespace ts {
1976
1990
* @param basePath A root directory to resolve relative path entries in the config
1977
1991
* file to. e.g. outDir
1978
1992
*/
1979
- export function parseJsonSourceFileConfigFileContent ( sourceFile : TsConfigSourceFile , host : ParseConfigHost , basePath : string , existingOptions ?: CompilerOptions , configFileName ?: string , resolutionStack ?: Path [ ] , extraFileExtensions ?: ReadonlyArray < FileExtensionInfo > ) : ParsedCommandLine {
1980
- return parseJsonConfigFileContentWorker ( /*json*/ undefined , sourceFile , host , basePath , existingOptions , configFileName , resolutionStack , extraFileExtensions ) ;
1993
+ export function parseJsonSourceFileConfigFileContent ( sourceFile : TsConfigSourceFile , host : ParseConfigHost , basePath : string , existingOptions ?: CompilerOptions , configFileName ?: string , resolutionStack ?: Path [ ] , extraFileExtensions ?: ReadonlyArray < FileExtensionInfo > , /* @internal */ extendedConfigCache ?: Map < ExtendedConfigCacheEntry > ) : ParsedCommandLine {
1994
+ return parseJsonConfigFileContentWorker ( /*json*/ undefined , sourceFile , host , basePath , existingOptions , configFileName , resolutionStack , extraFileExtensions , extendedConfigCache ) ;
1981
1995
}
1982
1996
1983
1997
/*@internal */
@@ -2016,11 +2030,12 @@ namespace ts {
2016
2030
configFileName ?: string ,
2017
2031
resolutionStack : Path [ ] = [ ] ,
2018
2032
extraFileExtensions : ReadonlyArray < FileExtensionInfo > = [ ] ,
2033
+ extendedConfigCache ?: Map < ExtendedConfigCacheEntry >
2019
2034
) : ParsedCommandLine {
2020
2035
Debug . assert ( ( json === undefined && sourceFile !== undefined ) || ( json !== undefined && sourceFile === undefined ) ) ;
2021
2036
const errors : Diagnostic [ ] = [ ] ;
2022
2037
2023
- const parsedConfig = parseConfig ( json , sourceFile , host , basePath , configFileName , resolutionStack , errors ) ;
2038
+ const parsedConfig = parseConfig ( json , sourceFile , host , basePath , configFileName , resolutionStack , errors , extendedConfigCache ) ;
2024
2039
const { raw } = parsedConfig ;
2025
2040
const options = extend ( existingOptions , parsedConfig . options || { } ) ;
2026
2041
options . configFilePath = configFileName && normalizeSlashes ( configFileName ) ;
@@ -2187,13 +2202,14 @@ namespace ts {
2187
2202
* It does *not* resolve the included files.
2188
2203
*/
2189
2204
function parseConfig (
2190
- json : any ,
2191
- sourceFile : TsConfigSourceFile | undefined ,
2192
- host : ParseConfigHost ,
2193
- basePath : string ,
2194
- configFileName : string | undefined ,
2195
- resolutionStack : string [ ] ,
2196
- errors : Push < Diagnostic > ,
2205
+ json : any ,
2206
+ sourceFile : TsConfigSourceFile | undefined ,
2207
+ host : ParseConfigHost ,
2208
+ basePath : string ,
2209
+ configFileName : string | undefined ,
2210
+ resolutionStack : string [ ] ,
2211
+ errors : Push < Diagnostic > ,
2212
+ extendedConfigCache ?: Map < ExtendedConfigCacheEntry >
2197
2213
) : ParsedTsconfig {
2198
2214
basePath = normalizeSlashes ( basePath ) ;
2199
2215
const resolvedPath = getNormalizedAbsolutePath ( configFileName || "" , basePath ) ;
@@ -2210,7 +2226,7 @@ namespace ts {
2210
2226
if ( ownConfig . extendedConfigPath ) {
2211
2227
// copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios.
2212
2228
resolutionStack = resolutionStack . concat ( [ resolvedPath ] ) ;
2213
- const extendedConfig = getExtendedConfig ( sourceFile , ownConfig . extendedConfigPath , host , basePath , resolutionStack , errors ) ;
2229
+ const extendedConfig = getExtendedConfig ( sourceFile , ownConfig . extendedConfigPath , host , basePath , resolutionStack , errors , extendedConfigCache ) ;
2214
2230
if ( extendedConfig && isSuccessfulParsedTsconfig ( extendedConfig ) ) {
2215
2231
const baseRaw = extendedConfig . raw ;
2216
2232
const raw = ownConfig . raw ;
@@ -2354,47 +2370,67 @@ namespace ts {
2354
2370
return undefined ;
2355
2371
}
2356
2372
2373
+ /*@internal */
2374
+ export interface ExtendedConfigCacheEntry {
2375
+ extendedResult : TsConfigSourceFile ;
2376
+ extendedConfig : ParsedTsconfig | undefined ;
2377
+ }
2378
+
2357
2379
function getExtendedConfig (
2358
2380
sourceFile : TsConfigSourceFile | undefined ,
2359
2381
extendedConfigPath : string ,
2360
2382
host : ParseConfigHost ,
2361
2383
basePath : string ,
2362
2384
resolutionStack : string [ ] ,
2363
2385
errors : Push < Diagnostic > ,
2386
+ extendedConfigCache ?: Map < ExtendedConfigCacheEntry >
2364
2387
) : ParsedTsconfig | undefined {
2365
- const extendedResult = readJsonConfigFile ( extendedConfigPath , path => host . readFile ( path ) ) ;
2388
+ const path = host . useCaseSensitiveFileNames ? extendedConfigPath : toLowerCase ( extendedConfigPath ) ;
2389
+ let value : ExtendedConfigCacheEntry | undefined ;
2390
+ let extendedResult : TsConfigSourceFile ;
2391
+ let extendedConfig : ParsedTsconfig | undefined ;
2392
+ if ( extendedConfigCache && ( value = extendedConfigCache . get ( path ) ) ) {
2393
+ ( { extendedResult, extendedConfig } = value ) ;
2394
+ }
2395
+ else {
2396
+ extendedResult = readJsonConfigFile ( extendedConfigPath , path => host . readFile ( path ) ) ;
2397
+ if ( ! extendedResult . parseDiagnostics . length ) {
2398
+ const extendedDirname = getDirectoryPath ( extendedConfigPath ) ;
2399
+ extendedConfig = parseConfig ( /*json*/ undefined , extendedResult , host , extendedDirname ,
2400
+ getBaseFileName ( extendedConfigPath ) , resolutionStack , errors , extendedConfigCache ) ;
2401
+
2402
+
2403
+ if ( isSuccessfulParsedTsconfig ( extendedConfig ) ) {
2404
+ // Update the paths to reflect base path
2405
+ const relativeDifference = convertToRelativePath ( extendedDirname , basePath , identity ) ;
2406
+ const updatePath = ( path : string ) => isRootedDiskPath ( path ) ? path : combinePaths ( relativeDifference , path ) ;
2407
+ const mapPropertiesInRawIfNotUndefined = ( propertyName : string ) => {
2408
+ if ( raw [ propertyName ] ) {
2409
+ raw [ propertyName ] = map ( raw [ propertyName ] , updatePath ) ;
2410
+ }
2411
+ } ;
2412
+
2413
+ const { raw } = extendedConfig ;
2414
+ mapPropertiesInRawIfNotUndefined ( "include" ) ;
2415
+ mapPropertiesInRawIfNotUndefined ( "exclude" ) ;
2416
+ mapPropertiesInRawIfNotUndefined ( "files" ) ;
2417
+ }
2418
+ }
2419
+ if ( extendedConfigCache ) {
2420
+ extendedConfigCache . set ( path , { extendedResult, extendedConfig } ) ;
2421
+ }
2422
+ }
2366
2423
if ( sourceFile ) {
2367
2424
sourceFile . extendedSourceFiles = [ extendedResult . fileName ] ;
2425
+ if ( extendedResult . extendedSourceFiles ) {
2426
+ sourceFile . extendedSourceFiles ! . push ( ...extendedResult . extendedSourceFiles ) ;
2427
+ }
2368
2428
}
2369
2429
if ( extendedResult . parseDiagnostics . length ) {
2370
2430
errors . push ( ...extendedResult . parseDiagnostics ) ;
2371
2431
return undefined ;
2372
2432
}
2373
-
2374
- const extendedDirname = getDirectoryPath ( extendedConfigPath ) ;
2375
- const extendedConfig = parseConfig ( /*json*/ undefined , extendedResult , host , extendedDirname ,
2376
- getBaseFileName ( extendedConfigPath ) , resolutionStack , errors ) ;
2377
- if ( sourceFile && extendedResult . extendedSourceFiles ) {
2378
- sourceFile . extendedSourceFiles ! . push ( ...extendedResult . extendedSourceFiles ) ;
2379
- }
2380
-
2381
- if ( isSuccessfulParsedTsconfig ( extendedConfig ) ) {
2382
- // Update the paths to reflect base path
2383
- const relativeDifference = convertToRelativePath ( extendedDirname , basePath , identity ) ;
2384
- const updatePath = ( path : string ) => isRootedDiskPath ( path ) ? path : combinePaths ( relativeDifference , path ) ;
2385
- const mapPropertiesInRawIfNotUndefined = ( propertyName : string ) => {
2386
- if ( raw [ propertyName ] ) {
2387
- raw [ propertyName ] = map ( raw [ propertyName ] , updatePath ) ;
2388
- }
2389
- } ;
2390
-
2391
- const { raw } = extendedConfig ;
2392
- mapPropertiesInRawIfNotUndefined ( "include" ) ;
2393
- mapPropertiesInRawIfNotUndefined ( "exclude" ) ;
2394
- mapPropertiesInRawIfNotUndefined ( "files" ) ;
2395
- }
2396
-
2397
- return extendedConfig ;
2433
+ return extendedConfig ! ;
2398
2434
}
2399
2435
2400
2436
function convertCompileOnSaveOptionFromJson ( jsonOption : any , basePath : string , errors : Push < Diagnostic > ) : boolean {
0 commit comments