Skip to content

Commit bef492e

Browse files
committed
Create old buildInfo program from program so host can be passed around correctly
1 parent b71c45a commit bef492e

File tree

5 files changed

+55
-71
lines changed

5 files changed

+55
-71
lines changed

src/compiler/builder.ts

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,17 +1895,22 @@ namespace ts {
18951895
}
18961896
}
18971897

1898-
function createGetProgramOrOldBuildInfoProgramUndefined(state: ReusableBuilderProgramState): () => Program | OldBuildInfoProgram | undefined {
1899-
let oldProgram: OldBuildInfoProgram | undefined;
1900-
return () => state.program ?? oldProgram ?? (oldProgram = memoize(() => createOldBuildInfoProgram(
1901-
state.compilerOptions,
1902-
state.cacheResolutions,
1903-
// Prefer cached resolutions over serialized format
1904-
!state.cacheResolutions ? state.resuableCacheResolutions : undefined,
1905-
))());
1898+
function createGetProgramOrOldBuildInfoProgramUndefined(state: ReusableBuilderProgramState): () => Program | OldBuildInfoProgramConstructor | undefined {
1899+
return () => state.program ??
1900+
(state.cacheResolutions || state.resuableCacheResolutions ?
1901+
(host => createOldBuildInfoProgram(
1902+
host,
1903+
state.compilerOptions,
1904+
state.cacheResolutions,
1905+
// Prefer cached resolutions over serialized format
1906+
!state.cacheResolutions ? state.resuableCacheResolutions : undefined,
1907+
)) :
1908+
undefined
1909+
);
19061910
}
19071911

19081912
export function createOldBuildInfoProgram(
1913+
host: OldBuildInfoProgramHost,
19091914
compilerOptions: CompilerOptions,
19101915
cacheResolutions: ReusableBuilderProgramState["cacheResolutions"],
19111916
resuableCacheResolutions: ReusableBuilderProgramState["resuableCacheResolutions"],
@@ -1929,8 +1934,7 @@ namespace ts {
19291934

19301935
return {
19311936
getCompilerOptions: () => compilerOptions,
1932-
getResolvedModule: (host, dirPath, name, mode, redirectedReference) => getResolvedFromCache(
1933-
host,
1937+
getResolvedModule: (dirPath, name, mode, redirectedReference) => getResolvedFromCache(
19341938
cacheResolutions?.modules,
19351939
resuableCacheResolutions?.cache.modules,
19361940
decodedResolvedModules,
@@ -1941,8 +1945,7 @@ namespace ts {
19411945
cacheResolutions?.moduleNameToDirectoryMap,
19421946
decodedModuleNameToDirectoryMap,
19431947
),
1944-
getResolvedTypeReferenceDirective: (host, dirPath, name, mode, redirectedReference) => getResolvedFromCache(
1945-
host,
1948+
getResolvedTypeReferenceDirective: (dirPath, name, mode, redirectedReference) => getResolvedFromCache(
19461949
cacheResolutions?.typeRefs,
19471950
resuableCacheResolutions?.cache.typeRefs,
19481951
decodedResolvedTypeRefs,
@@ -1953,24 +1956,15 @@ namespace ts {
19531956
/*moduleNameToDirectoryMap*/ undefined,
19541957
/*decodedModuleNameToDirectoryMap*/ undefined,
19551958
),
1956-
clearRedirectsMap: () => {
1957-
cacheResolutions?.modules?.clearRedirectsMap();
1958-
cacheResolutions?.typeRefs?.clearRedirectsMap();
1959-
cacheResolutions?.moduleNameToDirectoryMap.clearRedirectsMap();
1960-
decodedResolvedModules.clearRedirectsMap();
1961-
decodedResolvedTypeRefs.clearRedirectsMap();
1962-
decodedModuleNameToDirectoryMap.clearRedirectsMap();
1963-
}
19641959
};
19651960

1966-
function fileExists(host: OldBuildInfoProgramResolutionHost, fileName: string) {
1961+
function fileExists(fileName: string) {
19671962
let result = fileExistsMap.get(fileName);
19681963
if (result === undefined) fileExistsMap.set(fileName, result = host.fileExists(fileName));
19691964
return result;
19701965
}
19711966

19721967
function affectingLocationsSame(
1973-
host: OldBuildInfoProgramResolutionHost,
19741968
fileName: string,
19751969
expected: PackageJsonInfoCacheEntry | string | undefined
19761970
): boolean {
@@ -1990,7 +1984,6 @@ namespace ts {
19901984
}
19911985

19921986
function getResolvedFromCache<T extends ResolvedModuleWithFailedLookupLocations | ResolvedTypeReferenceDirectiveWithFailedLookupLocations>(
1993-
host: OldBuildInfoProgramResolutionHost,
19941987
cache: CacheWithRedirects<Path, ModeAwareCache<T>> | undefined,
19951988
reusableCache: ProgramBuildInfoResolutionCacheWithRedirects | undefined,
19961989
decodedReusableCache: DecodedResolvedMap,
@@ -2006,14 +1999,11 @@ namespace ts {
20061999
moduleNameToDirectoryMap?.getMapOfCacheRedirects(redirectedReference)?.get(getModeAwareCacheKey(name, mode))?.get(dirPath);
20072000
if (fromCache) {
20082001
return fileExists(
2009-
host,
20102002
(fromCache as ResolvedModuleWithFailedLookupLocations).resolvedModule?.resolvedFileName ||
20112003
(fromCache as ResolvedTypeReferenceDirectiveWithFailedLookupLocations).resolvedTypeReferenceDirective!.resolvedFileName!
20122004
) && every(
20132005
fromCache.affectingLocations,
2014-
fileName => affectingLocationsSame(
2015-
host, fileName, cacheResolutions!.packageJsonCache?.getPackageJsonInfo(fileName)
2016-
)
2006+
fileName => affectingLocationsSame(fileName, cacheResolutions!.packageJsonCache?.getPackageJsonInfo(fileName))
20172007
) ? fromCache as Resolution : undefined;
20182008
}
20192009
if (!reusableCache) return undefined;
@@ -2043,7 +2033,7 @@ namespace ts {
20432033

20442034
const resolutionId = decodedReusableCache.getMapOfCacheRedirects(redirectedReference)?.get(dirPath)?.get(name, mode) ||
20452035
decodedModuleNameToDirectoryMap?.getMapOfCacheRedirects(redirectedReference)?.get(getModeAwareCacheKey(name, mode))?.get(dirPath);
2046-
return resolutionId ? toResolution(host, resolutionId) : undefined;
2036+
return resolutionId ? toResolution(resolutionId) : undefined;
20472037
}
20482038

20492039
function setBuildInfoResolutionEntries(
@@ -2116,16 +2106,16 @@ namespace ts {
21162106
));
21172107
}
21182108

2119-
function toAffectingFileLocation(host: OldBuildInfoProgramResolutionHost, fileId: ProgramBuildInfoAbsoluteFileId) {
2109+
function toAffectingFileLocation(fileId: ProgramBuildInfoAbsoluteFileId) {
21202110
if (!decodedHashes && resuableCacheResolutions!.cache.hash) {
21212111
decodedHashes = arrayToMap(resuableCacheResolutions!.cache.hash, hash => isArray(hash) ? hash[0] : hash, hash => isArray(hash) ? hash[1] : undefined);
21222112
}
21232113
const hash = decodedHashes?.get(fileId);
21242114
const file = resuableCacheResolutions!.getProgramBuildInfoFilePathDecoder().toFileAbsolutePath(fileId);
2125-
return affectingLocationsSame(host, file, hash) ? file : undefined;
2115+
return affectingLocationsSame(file, hash) ? file : undefined;
21262116
}
21272117

2128-
function toResolution(host: OldBuildInfoProgramResolutionHost, resolutionId: ProgramBuildInfoResolutionId): Resolution | undefined {
2118+
function toResolution(resolutionId: ProgramBuildInfoResolutionId): Resolution | undefined {
21292119
const existing = resolutions?.[resolutionId - 1];
21302120
if (existing !== undefined) return existing || undefined;
21312121
resolutions ??= new Array(resuableCacheResolutions!.cache.resolutions.length);
@@ -2134,8 +2124,8 @@ namespace ts {
21342124
resolution.resolvedModule?.resolvedFileName || resolution.resolvedTypeReferenceDirective!.resolvedFileName
21352125
);
21362126
let affectingLocations: string[] | undefined;
2137-
if (fileExists(host, resolvedFileName) && every(resolution.affectingLocations, fileId => {
2138-
const file = toAffectingFileLocation(host, fileId);
2127+
if (fileExists(resolvedFileName) && every(resolution.affectingLocations, fileId => {
2128+
const file = toAffectingFileLocation(fileId);
21392129
if (file) (affectingLocations ??= []).push(file);
21402130
return !!file;
21412131
})) {

src/compiler/builderPublic.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ namespace ts {
5151
* Returns current program that could be undefined if the program was released, or cached build info program (currently module and type ref cache)
5252
*/
5353
/*@internal*/
54-
getProgramOrOldBuildInfoProgramUndefined(): Program | OldBuildInfoProgram | undefined;
54+
getProgramOrOldBuildInfoProgramUndefined(): Program | OldBuildInfoProgramConstructor | undefined;
5555
/**
5656
* Releases reference to the program, making all the other operations that need program to fail.
5757
*/

src/compiler/program.ts

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,6 @@ namespace ts {
872872
function lookupFromPackageJson(): NonNullable<ResolutionMode> {
873873
const scope = getPackageScopeForPath(fileName, packageJsonInfoCache, host, options);
874874
return scope?.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
875-
876875
}
877876
}
878877

@@ -983,7 +982,7 @@ namespace ts {
983982
return optionsHaveChanges(program.getCompilerOptions(), newOptions, sourceFileAffectingCompilerOptions);
984983
}
985984

986-
function createCreateProgramOptions(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program | OldBuildInfoProgram, configFileParsingDiagnostics?: readonly Diagnostic[]): CreateProgramOptionsWithOldBuildInfoProgram {
985+
function createCreateProgramOptions(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program | OldBuildInfoProgramConstructor, configFileParsingDiagnostics?: readonly Diagnostic[]): CreateProgramOptionsWithOldBuildInfoProgramConstructor {
987986
return {
988987
rootNames,
989988
options,
@@ -993,10 +992,6 @@ namespace ts {
993992
};
994993
}
995994

996-
function isOldBuildInfoProgram(program: Program | OldBuildInfoProgram | undefined): program is OldBuildInfoProgram {
997-
return !!(program as OldBuildInfoProgram | undefined)?.getResolvedModule;
998-
}
999-
1000995
/**
1001996
* Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
1002997
* that represent a compilation unit.
@@ -1009,7 +1004,7 @@ namespace ts {
10091004
*/
10101005
export function createProgram(createProgramOptions: CreateProgramOptions): Program;
10111006
/*@internal*/
1012-
export function createProgram(createProgramOptions: CreateProgramOptionsWithOldBuildInfoProgram): Program; // eslint-disable-line @typescript-eslint/unified-signatures
1007+
export function createProgram(createProgramOptions: CreateProgramOptionsWithOldBuildInfoProgramConstructor): Program; // eslint-disable-line @typescript-eslint/unified-signatures
10131008
/**
10141009
* Create a new 'Program' instance. A Program is an immutable collection of 'SourceFile's and a 'CompilerOptions'
10151010
* that represent a compilation unit.
@@ -1025,12 +1020,10 @@ namespace ts {
10251020
* @returns A 'Program' object.
10261021
*/
10271022
export function createProgram(rootNames: readonly string[], options: CompilerOptions, host?: CompilerHost, oldProgram?: Program, configFileParsingDiagnostics?: readonly Diagnostic[]): Program;
1028-
export function createProgram(rootNamesOrOptions: readonly string[] | CreateProgramOptionsWithOldBuildInfoProgram, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: readonly Diagnostic[]): Program {
1023+
export function createProgram(rootNamesOrOptions: readonly string[] | CreateProgramOptionsWithOldBuildInfoProgramConstructor, _options?: CompilerOptions, _host?: CompilerHost, _oldProgram?: Program, _configFileParsingDiagnostics?: readonly Diagnostic[]): Program {
10291024
const createProgramOptions = isArray(rootNamesOrOptions) ? createCreateProgramOptions(rootNamesOrOptions, _options!, _host, _oldProgram, _configFileParsingDiagnostics) : rootNamesOrOptions; // TODO: GH#18217
10301025
const { rootNames, options, configFileParsingDiagnostics, projectReferences } = createProgramOptions;
1031-
let { oldProgram: oldProgramOrOldBuildInfoProgram } = createProgramOptions;
1032-
let oldProgram = isOldBuildInfoProgram(oldProgramOrOldBuildInfoProgram) ? undefined : oldProgramOrOldBuildInfoProgram;
1033-
let oldBuildInfoProgram = isOldBuildInfoProgram(oldProgramOrOldBuildInfoProgram) ? oldProgramOrOldBuildInfoProgram : undefined;
1026+
let { oldProgram: oldProgramOrOldBuildInfoProgramConstructor } = createProgramOptions;
10341027

10351028
let processingDefaultLibFiles: SourceFile[] | undefined;
10361029
let processingOtherFiles: SourceFile[] | undefined;
@@ -1178,8 +1171,9 @@ namespace ts {
11781171
loadWithTypeDirectiveCache(typeReferenceDirectiveNames, containingFile, redirectedReference, containingFileMode, loader);
11791172
}
11801173

1181-
let oldBuildInfoProgramResolutionHost: OldBuildInfoProgramResolutionHost | undefined;
1182-
if (oldBuildInfoProgram) {
1174+
let oldProgram = typeof oldProgramOrOldBuildInfoProgramConstructor === "object" ? oldProgramOrOldBuildInfoProgramConstructor : undefined;
1175+
let oldBuildInfoProgram: OldBuildInfoProgram | undefined;
1176+
if (!oldProgram && typeof oldProgramOrOldBuildInfoProgramConstructor === "function") {
11831177
const state: ModuleResolutionState = {
11841178
host,
11851179
compilerOptions: options,
@@ -1192,21 +1186,22 @@ namespace ts {
11921186
requestContainingDirectory: undefined,
11931187
reportResolutionDiagnostic: noop
11941188
};
1195-
oldBuildInfoProgramResolutionHost = {
1189+
oldBuildInfoProgram = oldProgramOrOldBuildInfoProgramConstructor({
11961190
fileExists: fileName => host.fileExists(fileName),
11971191
createHash: maybeBind(host, host.createHash),
11981192
getPackageJsonInfo: fileName => getPackageJsonInfo(getDirectoryPath(fileName), /*onlyRecordFailures*/ false, state),
1199-
};
1200-
// Ensure redirected references are verified before using existing cache
1201-
oldBuildInfoProgram.clearRedirectsMap();
1202-
moduleResolutionCache?.setOldResolutionCache({
1203-
getResolved: (dirPath, name, mode, redirectedReference) =>
1204-
oldBuildInfoProgram?.getResolvedModule(oldBuildInfoProgramResolutionHost!, dirPath, name, mode, redirectedReference)
1205-
});
1206-
typeReferenceDirectiveResolutionCache?.setOldResolutionCache({
1207-
getResolved: (dirPath, name, mode, redirectedReference) =>
1208-
oldBuildInfoProgram?.getResolvedTypeReferenceDirective(oldBuildInfoProgramResolutionHost!, dirPath, name, mode, redirectedReference)
12091193
});
1194+
if (oldBuildInfoProgram) {
1195+
// Ensure redirected references are verified before using existing cache
1196+
moduleResolutionCache?.setOldResolutionCache({
1197+
getResolved: (dirPath, name, mode, redirectedReference) =>
1198+
oldBuildInfoProgram?.getResolvedModule(dirPath, name, mode, redirectedReference)
1199+
});
1200+
typeReferenceDirectiveResolutionCache?.setOldResolutionCache({
1201+
getResolved: (dirPath, name, mode, redirectedReference) =>
1202+
oldBuildInfoProgram?.getResolvedTypeReferenceDirective(dirPath, name, mode, redirectedReference)
1203+
});
1204+
}
12101205
}
12111206

12121207
// Map from a stringified PackageId to the source file with that id.
@@ -1380,7 +1375,7 @@ namespace ts {
13801375
// unconditionally set oldProgram to undefined to prevent it from being captured in closure
13811376
oldProgram = undefined;
13821377
oldBuildInfoProgram = undefined;
1383-
oldProgramOrOldBuildInfoProgram = undefined;
1378+
oldProgramOrOldBuildInfoProgramConstructor = undefined;
13841379

13851380
const program: Program = {
13861381
getRootFileNames: () => rootNames,
@@ -1650,7 +1645,6 @@ namespace ts {
16501645
const oldResolution = !oldBuildInfoProgram ?
16511646
oldSourceFile?.resolvedModules?.get(moduleName, mode) :
16521647
oldBuildInfoProgram.getResolvedModule(
1653-
oldBuildInfoProgramResolutionHost!,
16541648
getDirectoryPath(file.path),
16551649
moduleName,
16561650
mode,
@@ -1824,7 +1818,6 @@ namespace ts {
18241818
const oldResolution = !oldBuildInfoProgram ?
18251819
(containingSourceFile ? oldSourceFile?.resolvedTypeReferenceDirectiveNames : oldProgram?.getAutomaticTypeDirectiveResolutions())?.get(typeDirectiveName, mode) :
18261820
oldBuildInfoProgram.getResolvedTypeReferenceDirective(
1827-
oldBuildInfoProgramResolutionHost!,
18281821
getDirectoryPath(containingSourceFile? containingSourceFile.path : toPath(inferredTypeFile!)),
18291822
typeDirectiveName,
18301823
mode,
@@ -1913,13 +1906,13 @@ namespace ts {
19131906
function tryReuseStructureFromOldProgram(): StructureIsReused {
19141907
// check properties that can affect structure of the program or module resolution strategy
19151908
// if any of these properties has changed - structure cannot be reused
1916-
const oldOptions = oldProgramOrOldBuildInfoProgram?.getCompilerOptions();
1909+
const oldOptions = oldProgram?.getCompilerOptions() || oldBuildInfoProgram?.getCompilerOptions();
19171910
if (!oldOptions || changesAffectModuleResolution(oldOptions, options)) {
19181911
return StructureIsReused.Not;
19191912
}
19201913

19211914
const result = tryReuseStructureFromOldProgramWorker();
1922-
return options.cacheResolutions && oldProgramOrOldBuildInfoProgram && result === StructureIsReused.Not ?
1915+
return options.cacheResolutions && (oldProgram || oldBuildInfoProgram) && result === StructureIsReused.Not ?
19231916
StructureIsReused.SafeModuleCache :
19241917
result;
19251918
}

src/compiler/types.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6607,24 +6607,21 @@ namespace ts {
66076607
}
66086608

66096609
/*@internal*/
6610-
export interface OldBuildInfoProgramResolutionHost {
6610+
export interface OldBuildInfoProgramHost {
66116611
fileExists(fileName: string): boolean;
66126612
createHash?(data: string): string;
66136613
getPackageJsonInfo(fileName: string): PackageJsonInfoCacheEntry | undefined;
66146614
}
66156615
/*@internal*/
66166616
export interface OldBuildInfoProgram {
66176617
getCompilerOptions(): CompilerOptions;
6618-
clearRedirectsMap(): void;
66196618
getResolvedModule(
6620-
host: OldBuildInfoProgramResolutionHost,
66216619
dirPath: Path,
66226620
name: string,
66236621
mode: ResolutionMode,
66246622
redirectedReference: ResolvedProjectReference | undefined,
66256623
): ResolvedModuleWithFailedLookupLocations | undefined;
66266624
getResolvedTypeReferenceDirective(
6627-
host: OldBuildInfoProgramResolutionHost,
66286625
dirPath: Path,
66296626
name: string,
66306627
mode: ResolutionMode,
@@ -6633,7 +6630,10 @@ namespace ts {
66336630
}
66346631

66356632
/*@internal*/
6636-
export type CreateProgramOptionsWithOldBuildInfoProgram = Omit<CreateProgramOptions, "oldProgram"> & { oldProgram?: OldBuildInfoProgram | Program; };
6633+
export type OldBuildInfoProgramConstructor = (host: OldBuildInfoProgramHost) => OldBuildInfoProgram | undefined;
6634+
6635+
/*@internal*/
6636+
export type CreateProgramOptionsWithOldBuildInfoProgramConstructor = Omit<CreateProgramOptions, "oldProgram"> & { oldProgram?: Program | OldBuildInfoProgramConstructor; };
66376637

66386638
/* @internal */
66396639
export interface CommandLineOptionBase {

0 commit comments

Comments
 (0)