Read reusable module cache information from the buildinfo

This commit is contained in:
Sheetal Nandi
2022-12-09 14:49:20 -08:00
parent 1eeea260d6
commit 76100d729f
4 changed files with 64 additions and 29 deletions
+60 -25
View File
@@ -170,6 +170,11 @@ export interface ReusableBuilderProgramState extends BuilderState {
modules: Map<Path, ModeAwareCache<ResolvedModuleWithFailedLookupLocations>> | undefined;
typeRefs: Map<Path, ModeAwareCache<ResolvedTypeReferenceDirectiveWithFailedLookupLocations>> | undefined;
};
resuableCacheResolutions?: {
resolutions: ProgramBuildInfoCacheResolutions;
fileNames: readonly string[];
buildInfoPath: string;
}
}
/** @internal */
@@ -496,6 +501,8 @@ function convertToDiagnosticRelatedInformation(diagnostic: ReusableDiagnosticRel
*/
function releaseCache(state: BuilderProgramState) {
BuilderState.releaseCache(state);
// Store the resolutions if possible
if (!state.resuableCacheResolutions) getCacheResolutions(state);
state.program = undefined;
}
@@ -1013,9 +1020,10 @@ export function isProgramBundleEmitBuildInfo(info: ProgramBuildInfo): info is Pr
/**
* Gets the program information to be emitted in buildInfo so that we can use it to create new program
*/
function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | undefined): BuildInfo {
function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | undefined, buildInfoPath: string,): BuildInfo {
const currentDirectory = Debug.checkDefined(state.program).getCurrentDirectory();
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory));
buildInfoPath = getNormalizedAbsolutePath(buildInfoPath, currentDirectory);
const buildInfoDirectory = getDirectoryPath(buildInfoPath);
// Convert the file name to Path here if we set the fileName instead to optimize multiple d.ts file emits and having to compute Canonical path
const latestChangedDtsFile = state.latestChangedDtsFile ? relativeToBuildInfoEnsuringAbsolutePath(state.latestChangedDtsFile) : undefined;
const fileNames: string[] = [];
@@ -1271,13 +1279,18 @@ function getBuildInfo(state: BuilderProgramState, bundle: BundleBuildInfo | unde
if (!resolutions) return;
Debug.assertIsDefined(names);
Debug.assertIsDefined(resolutionEntries);
return {
resolutions,
names,
resolutionEntries,
modules,
typeRefs,
state.resuableCacheResolutions = {
resolutions: {
resolutions,
names,
resolutionEntries,
modules,
typeRefs,
},
fileNames,
buildInfoPath,
};
return state.resuableCacheResolutions.resolutions;
}
function toProgramBuildInfoResolutionCache<T extends ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations>(
@@ -1495,7 +1508,7 @@ export function createBuilderProgram(kind: BuilderProgramKind, { newProgram, hos
}
const state = createBuilderProgramState(newProgram, oldState);
newProgram.getBuildInfo = bundle => getBuildInfo(state, bundle);
newProgram.getBuildInfo = (bundle, buildInfoPath) => getBuildInfo(state, bundle, buildInfoPath);
// To ensure that we arent storing any references to old program or new program without state
newProgram = undefined!; // TODO: GH#18217
@@ -1839,14 +1852,38 @@ export function toProgramEmitPending(value: ProgramBuildInfoBundlePendingEmit, o
return !value ? getBuilderFileEmit(options || {}) : value;
}
/** @internal */
export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo, buildInfoPath: string, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram {
const program = buildInfo.program!;
function getProgramBuildInfoFilePathDecoder(fileNames: readonly string[], buildInfoPath: string, host: ReadBuildProgramHost) {
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(buildInfoPath, host.getCurrentDirectory()));
const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames());
let filePaths: Path[] | undefined;
let fileAbsolutePaths: string[] | undefined;
return { toAbsolutePath, toFilePath, toFileAbsolutePath };
function toPath(path: string) {
return ts.toPath(path, buildInfoDirectory, getCanonicalFileName);
}
function toAbsolutePath(path: string) {
return getNormalizedAbsolutePath(path, buildInfoDirectory);
}
function toFilePath(fileId: ProgramBuildInfoFileId): Path {
return filePaths?.[fileId - 1] ??
((filePaths ??= new Array(fileNames.length))[fileId - 1] = toPath(fileNames[fileId - 1]));
}
function toFileAbsolutePath(fileId: ProgramBuildInfoAbsoluteFileId): string {
return fileAbsolutePaths?.[fileId - 1] ??
((fileAbsolutePaths ??= new Array(fileNames.length))[fileId - 1] = toAbsolutePath(fileNames[fileId - 1]));
}
}
/** @internal */
export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo, buildInfoPath: string, host: ReadBuildProgramHost): EmitAndSemanticDiagnosticsBuilderProgram {
const program = buildInfo.program!;
const { toFilePath, toAbsolutePath } = getProgramBuildInfoFilePathDecoder(program.fileNames, buildInfoPath, host);
let state: ReusableBuilderProgramState;
const filePaths = program.fileNames?.map(toPath);
let filePathsSetList: Set<Path>[] | undefined;
const latestChangedDtsFile = program.latestChangedDtsFile ? toAbsolutePath(program.latestChangedDtsFile) : undefined;
if (isProgramBundleEmitBuildInfo(program)) {
@@ -1862,6 +1899,7 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo,
outSignature: program.outSignature,
programEmitPending: program.pendingEmit === undefined ? undefined : toProgramEmitPending(program.pendingEmit, program.options),
bundle: buildInfo.bundle,
resuableCacheResolutions: toResuableCacheResolutions(),
};
}
else {
@@ -1897,6 +1935,7 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo,
changedFilesSet: new Set(map(program.changeFileSet, toFilePath)),
latestChangedDtsFile,
emitSignatures: emitSignatures?.size ? emitSignatures : undefined,
resuableCacheResolutions: toResuableCacheResolutions(),
};
}
@@ -1926,18 +1965,6 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo,
hasChangedEmitSignature: returnFalse,
};
function toPath(path: string) {
return ts.toPath(path, buildInfoDirectory, getCanonicalFileName);
}
function toAbsolutePath(path: string) {
return getNormalizedAbsolutePath(path, buildInfoDirectory);
}
function toFilePath(fileId: ProgramBuildInfoFileId) {
return filePaths[fileId - 1];
}
function toFilePathsSet(fileIdsListId: ProgramBuildInfoFileIdListId) {
return filePathsSetList![fileIdsListId - 1];
}
@@ -1953,6 +1980,14 @@ export function createBuilderProgramUsingProgramBuildInfo(buildInfo: BuildInfo,
);
return map;
}
function toResuableCacheResolutions(): BuilderProgramState["resuableCacheResolutions"] {
return program.cacheResolutions && {
resolutions: program.cacheResolutions,
fileNames: program.fileNames,
buildInfoPath,
};
}
}
/** @internal */
+1 -1
View File
@@ -811,7 +811,7 @@ export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFi
emitSkipped = true;
return;
}
const buildInfo = host.getBuildInfo(bundle) || createBuildInfo(/*program*/ undefined, bundle);
const buildInfo = host.getBuildInfo(bundle, buildInfoPath) || createBuildInfo(/*program*/ undefined, bundle);
// Pass buildinfo as additional data to avoid having to reparse
writeFile(host, emitterDiagnostics, buildInfoPath, getBuildInfoText(buildInfo), /*writeByteOrderMark*/ false, /*sourceFiles*/ undefined, { buildInfo });
}
+1 -1
View File
@@ -2491,7 +2491,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg
return host.fileExists(f);
},
useCaseSensitiveFileNames: () => host.useCaseSensitiveFileNames(),
getBuildInfo: bundle => program.getBuildInfo?.(bundle),
getBuildInfo: (bundle, buildInfoPath) => program.getBuildInfo?.(bundle, buildInfoPath),
getSourceFileFromReference: (file, ref) => program.getSourceFileFromReference(file, ref),
redirectTargetsMap,
getFileIncludeReasons: program.getFileIncludeReasons,
+2 -2
View File
@@ -4539,7 +4539,7 @@ export interface Program extends ScriptReferenceHost {
/** @internal */ forEachResolvedProjectReference<T>(cb: (resolvedProjectReference: ResolvedProjectReference) => T | undefined): T | undefined;
/** @internal */ getResolvedProjectReferenceByPath(projectReferencePath: Path): ResolvedProjectReference | undefined;
/** @internal */ isSourceOfProjectReferenceRedirect(fileName: string): boolean;
/** @internal */ getBuildInfo?(bundle: BundleBuildInfo | undefined): BuildInfo;
/** @internal */ getBuildInfo?(bundle: BundleBuildInfo | undefined, buildInfoPath: string): BuildInfo;
/** @internal */ emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult;
/**
* This implementation handles file exists to be true if file is source of project reference redirect when program is created using useSourceOfProjectReferenceRedirect
@@ -7687,7 +7687,7 @@ export interface EmitHost extends ScriptReferenceHost, ModuleSpecifierResolution
getPrependNodes(): readonly (InputFiles | UnparsedSource)[];
writeFile: WriteFileCallback;
getBuildInfo(bundle: BundleBuildInfo | undefined): BuildInfo | undefined;
getBuildInfo(bundle: BundleBuildInfo | undefined, buildInfoPath: string): BuildInfo | undefined;
getSourceFileFromReference: Program["getSourceFileFromReference"];
readonly redirectTargetsMap: RedirectTargetsMap;
createHash?(data: string): string;