Skip to content

Commit 6198fa3

Browse files
committed
Keep buildinfos for lifetime of the solution builder and project
1 parent 7734528 commit 6198fa3

File tree

2 files changed

+26
-13
lines changed

2 files changed

+26
-13
lines changed

src/compiler/tsbuildPublic.ts

+24-11
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,6 @@ namespace ts {
210210
originalWriteFile: CompilerHost["writeFile"] | undefined;
211211
originalReadFileWithCache: CompilerHost["readFile"];
212212
originalGetSourceFile: CompilerHost["getSourceFile"];
213-
buildInfoCache: ESMap<Path, BuildInfo | false>;
214213
}
215214

216215
interface FileWatcherWithModifiedTime {
@@ -219,6 +218,11 @@ namespace ts {
219218
modifiedTime: Date | undefined;
220219
}
221220

221+
interface BuildInfoCacheEntry {
222+
path: Path;
223+
buildInfo: BuildInfo | false | string;
224+
}
225+
222226
interface SolutionBuilderState<T extends BuilderProgram = BuilderProgram> extends WatchFactory<WatchType, ResolvedConfigFileName> {
223227
readonly host: SolutionBuilderHost<T>;
224228
readonly hostWithWatch: SolutionBuilderWithWatchHost<T>;
@@ -239,6 +243,7 @@ namespace ts {
239243
readonly projectStatus: ESMap<ResolvedConfigFilePath, UpToDateStatus>;
240244
readonly buildInfoChecked: ESMap<ResolvedConfigFilePath, true>;
241245
readonly extendedConfigCache: ESMap<string, ExtendedConfigCacheEntry>;
246+
readonly buildInfoCache: ESMap<ResolvedConfigFilePath, BuildInfoCacheEntry>;
242247

243248
readonly builderPrograms: ESMap<ResolvedConfigFilePath, T>;
244249
readonly diagnostics: ESMap<ResolvedConfigFilePath, readonly Diagnostic[]>;
@@ -301,7 +306,7 @@ namespace ts {
301306
compilerHost.resolveTypeReferenceDirectives = (typeReferenceDirectiveNames, containingFile, redirectedReference, _options, containingFileMode) =>
302307
loadWithTypeDirectiveCache<ResolvedTypeReferenceDirective>(Debug.checkEachDefined(typeReferenceDirectiveNames), containingFile, redirectedReference, containingFileMode, loader);
303308
}
304-
compilerHost.getBuildInfo = fileName => getBuildInfo(state, fileName);
309+
compilerHost.getBuildInfo = (fileName, configFilePath) => getBuildInfo(state, fileName, toResolvedConfigFilePath(state, configFilePath as ResolvedConfigFileName));
305310

306311
const { watchFile, watchDirectory, writeLog } = createWatchFactory<ResolvedConfigFileName>(hostWithWatch, options);
307312

@@ -324,6 +329,7 @@ namespace ts {
324329
projectStatus: new Map(),
325330
buildInfoChecked: new Map(),
326331
extendedConfigCache: new Map(),
332+
buildInfoCache: new Map(),
327333

328334
builderPrograms: new Map(),
329335
diagnostics: new Map(),
@@ -487,6 +493,7 @@ namespace ts {
487493
mutateMapSkippingNewValues(state.diagnostics, currentProjects, noopOnDelete);
488494
mutateMapSkippingNewValues(state.projectPendingBuild, currentProjects, noopOnDelete);
489495
mutateMapSkippingNewValues(state.projectErrorsReported, currentProjects, noopOnDelete);
496+
mutateMapSkippingNewValues(state.buildInfoCache, currentProjects, noopOnDelete);
490497

491498
// Remove watches for the program no longer in the solution
492499
if (state.watch) {
@@ -575,7 +582,6 @@ namespace ts {
575582
originalWriteFile,
576583
originalReadFileWithCache,
577584
originalGetSourceFile,
578-
buildInfoCache: new Map(),
579585
};
580586
}
581587

@@ -978,6 +984,7 @@ namespace ts {
978984
let newestDeclarationFileContentChangedTime: Date | undefined;
979985
const emitterDiagnostics = createDiagnosticCollection();
980986
const emittedOutputs = new Map<Path, string>();
987+
const buildInfo = state.buildInfoCache.get(projectPath);
981988
outputFiles.forEach(({ name, text, writeByteOrderMark }) => {
982989
if (resultFlags === BuildResultFlags.DeclarationOutputUnchanged && isDeclarationFileName(name)) {
983990
// Check for unchanged .d.ts files
@@ -991,7 +998,7 @@ namespace ts {
991998

992999
const path = toPath(state, name);
9931000
emittedOutputs.set(path, name);
994-
state.cache?.buildInfoCache.delete(path);
1001+
if (buildInfo?.path === path) buildInfo.buildInfo = text;
9951002
writeFile(writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
9961003
});
9971004

@@ -1010,7 +1017,8 @@ namespace ts {
10101017
Debug.assert(step === BuildStep.EmitBuildInfo);
10111018
const emitResult = program.emitBuildInfo((name, data, writeByteOrderMark, onError, sourceFiles) => {
10121019
const path = toPath(state, name);
1013-
state.cache?.buildInfoCache.delete(path);
1020+
const buildInfo = state.buildInfoCache.get(projectPath);
1021+
if (buildInfo?.path === path) buildInfo.buildInfo = data;
10141022
if (writeFileCallback) writeFileCallback(name, data, writeByteOrderMark, onError, sourceFiles);
10151023
else state.compilerHost.writeFile(name, data, writeByteOrderMark, onError, sourceFiles);
10161024
}, cancellationToken);
@@ -1110,10 +1118,11 @@ namespace ts {
11101118
Debug.assert(!!outputFiles.length);
11111119
const emitterDiagnostics = createDiagnosticCollection();
11121120
const emittedOutputs = new Map<Path, string>();
1121+
const buildInfo = state.buildInfoCache.get(projectPath);
11131122
outputFiles.forEach(({ name, text, writeByteOrderMark }) => {
11141123
const path = toPath(state, name);
11151124
emittedOutputs.set(path, name);
1116-
state.cache?.buildInfoCache.delete(path);
1125+
if (buildInfo?.path === path) buildInfo.buildInfo = text;
11171126
writeFile(writeFileCallback ? { writeFile: writeFileCallback } : compilerHost, emitterDiagnostics, name, text, writeByteOrderMark);
11181127
});
11191128

@@ -1402,13 +1411,17 @@ namespace ts {
14021411
};
14031412
}
14041413

1405-
function getBuildInfo(state: SolutionBuilderState, buildInfoPath: string): BuildInfo | undefined {
1414+
function getBuildInfo(state: SolutionBuilderState, buildInfoPath: string, resolvedConfigPath: ResolvedConfigFilePath): BuildInfo | undefined {
14061415
const path = toPath(state, buildInfoPath);
1407-
const existing = state.cache?.buildInfoCache.get(path);
1408-
if (existing !== undefined) return existing || undefined;
1416+
const existing = state.buildInfoCache.get(resolvedConfigPath);
1417+
if (existing !== undefined && existing.path === path) {
1418+
return isString(existing.buildInfo) ?
1419+
existing.buildInfo = ts.getBuildInfo(existing.buildInfo) :
1420+
existing.buildInfo || undefined;
1421+
}
14091422
const value = state.readFileWithCache(buildInfoPath);
14101423
const buildInfo = value ? ts.getBuildInfo(value) : undefined;
1411-
state.cache?.buildInfoCache.set(path, buildInfo || false);
1424+
state.buildInfoCache.set(resolvedConfigPath, { path, buildInfo: buildInfo || false });
14121425
return buildInfo;
14131426
}
14141427

@@ -1487,7 +1500,7 @@ namespace ts {
14871500
};
14881501
}
14891502

1490-
const buildInfo = Debug.checkDefined(getBuildInfo(state, buildInfoPath));
1503+
const buildInfo = Debug.checkDefined(getBuildInfo(state, buildInfoPath, resolvedPath));
14911504
if (!state.buildInfoChecked.has(resolvedPath)) {
14921505
state.buildInfoChecked.set(resolvedPath, true);
14931506
if (buildInfo && (buildInfo.bundle || buildInfo.program) && buildInfo.version !== version) {

src/compiler/watchPublic.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ namespace ts {
44
getCurrentDirectory(): string;
55
readFile(fileName: string): string | undefined;
66
/*@internal*/
7-
getBuildInfo?(fileName: string): BuildInfo | undefined;
7+
getBuildInfo?(fileName: string, configFilePath: string | undefined): BuildInfo | undefined;
88
}
99
export function readBuilderProgram(compilerOptions: CompilerOptions, host: ReadBuildProgramHost) {
1010
if (outFile(compilerOptions)) return undefined;
1111
const buildInfoPath = getTsBuildInfoEmitOutputFilePath(compilerOptions);
1212
if (!buildInfoPath) return undefined;
1313
let buildInfo;
1414
if (host.getBuildInfo) {
15-
buildInfo = host.getBuildInfo(buildInfoPath);
15+
buildInfo = host.getBuildInfo(buildInfoPath, compilerOptions.configFilePath);
1616
if (!buildInfo) return undefined;
1717
}
1818
else {

0 commit comments

Comments
 (0)