Skip to content

Commit 80f1ba4

Browse files
committed
Cache files extended so we arent calculating the config again and again
1 parent fecafeb commit 80f1ba4

File tree

2 files changed

+79
-40
lines changed

2 files changed

+79
-40
lines changed

src/compiler/commandLineParser.ts

Lines changed: 75 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1341,7 +1341,12 @@ namespace ts {
13411341
/**
13421342
* Reads the config file, reports errors if any and exits if the config file cannot be found
13431343
*/
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 {
13451350
let configFileText: string | undefined;
13461351
try {
13471352
configFileText = host.readFile(configFileName);
@@ -1362,7 +1367,16 @@ namespace ts {
13621367
result.path = toPath(configFileName, cwd, createGetCanonicalFileName(host.useCaseSensitiveFileNames));
13631368
result.resolvedPath = result.path;
13641369
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+
);
13661380
}
13671381

13681382
/**
@@ -1976,8 +1990,8 @@ namespace ts {
19761990
* @param basePath A root directory to resolve relative path entries in the config
19771991
* file to. e.g. outDir
19781992
*/
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);
19811995
}
19821996

19831997
/*@internal*/
@@ -2016,11 +2030,12 @@ namespace ts {
20162030
configFileName?: string,
20172031
resolutionStack: Path[] = [],
20182032
extraFileExtensions: ReadonlyArray<FileExtensionInfo> = [],
2033+
extendedConfigCache?: Map<ExtendedConfigCacheEntry>
20192034
): ParsedCommandLine {
20202035
Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined));
20212036
const errors: Diagnostic[] = [];
20222037

2023-
const parsedConfig = parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors);
2038+
const parsedConfig = parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors, extendedConfigCache);
20242039
const { raw } = parsedConfig;
20252040
const options = extend(existingOptions, parsedConfig.options || {});
20262041
options.configFilePath = configFileName && normalizeSlashes(configFileName);
@@ -2187,13 +2202,14 @@ namespace ts {
21872202
* It does *not* resolve the included files.
21882203
*/
21892204
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>
21972213
): ParsedTsconfig {
21982214
basePath = normalizeSlashes(basePath);
21992215
const resolvedPath = getNormalizedAbsolutePath(configFileName || "", basePath);
@@ -2210,7 +2226,7 @@ namespace ts {
22102226
if (ownConfig.extendedConfigPath) {
22112227
// copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios.
22122228
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);
22142230
if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) {
22152231
const baseRaw = extendedConfig.raw;
22162232
const raw = ownConfig.raw;
@@ -2354,47 +2370,67 @@ namespace ts {
23542370
return undefined;
23552371
}
23562372

2373+
/*@internal*/
2374+
export interface ExtendedConfigCacheEntry {
2375+
extendedResult: TsConfigSourceFile;
2376+
extendedConfig: ParsedTsconfig | undefined;
2377+
}
2378+
23572379
function getExtendedConfig(
23582380
sourceFile: TsConfigSourceFile | undefined,
23592381
extendedConfigPath: string,
23602382
host: ParseConfigHost,
23612383
basePath: string,
23622384
resolutionStack: string[],
23632385
errors: Push<Diagnostic>,
2386+
extendedConfigCache?: Map<ExtendedConfigCacheEntry>
23642387
): 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+
}
23662423
if (sourceFile) {
23672424
sourceFile.extendedSourceFiles = [extendedResult.fileName];
2425+
if (extendedResult.extendedSourceFiles) {
2426+
sourceFile.extendedSourceFiles!.push(...extendedResult.extendedSourceFiles);
2427+
}
23682428
}
23692429
if (extendedResult.parseDiagnostics.length) {
23702430
errors.push(...extendedResult.parseDiagnostics);
23712431
return undefined;
23722432
}
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!;
23982434
}
23992435

24002436
function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Push<Diagnostic>): boolean {

src/compiler/tsbuild.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,7 @@ namespace ts {
402402
compilerHost.getParsedCommandLine = parseConfigFile;
403403

404404
const buildInfoChecked = createFileMap<true>(toPath);
405+
let extendedConfigCache: Map<ExtendedConfigCacheEntry> | undefined;
405406

406407
// Watch state
407408
const builderPrograms = createFileMap<T>(toPath);
@@ -478,7 +479,7 @@ namespace ts {
478479

479480
let diagnostic: Diagnostic | undefined;
480481
parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = d => diagnostic = d;
481-
const parsed = getParsedCommandLineOfConfigFile(configFilePath, baseCompilerOptions, parseConfigFileHost);
482+
const parsed = getParsedCommandLineOfConfigFile(configFilePath, baseCompilerOptions, parseConfigFileHost, extendedConfigCache);
482483
parseConfigFileHost.onUnRecoverableConfigFileDiagnostic = noop;
483484
configFileCache.setValue(configFilePath, parsed || diagnostic!);
484485
return parsed;
@@ -1368,6 +1369,7 @@ namespace ts {
13681369
} = changeCompilerHostLikeToUseCache(host, toPath, (...args) => savedGetSourceFile.call(compilerHost, ...args));
13691370
readFileWithCache = newReadFileWithCache;
13701371
compilerHost.getSourceFile = getSourceFileWithCache!;
1372+
extendedConfigCache = createMap();
13711373

13721374
const graph = getGlobalDependencyGraph();
13731375
reportBuildQueue(graph);
@@ -1429,6 +1431,7 @@ namespace ts {
14291431
host.writeFile = originalWriteFile;
14301432
compilerHost.getSourceFile = savedGetSourceFile;
14311433
readFileWithCache = savedReadFileWithCache;
1434+
extendedConfigCache = undefined;
14321435
return anyFailed ? ExitStatus.DiagnosticsPresent_OutputsSkipped : ExitStatus.Success;
14331436
}
14341437

0 commit comments

Comments
 (0)