Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 97 additions & 83 deletions src/compiler/resolutionCache.ts

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8063,6 +8063,8 @@ export interface ResolvedModuleWithFailedLookupLocations {
* have been resolvable under different module resolution settings.
*/
alternateResult?: string;
/** @internal */
globalCacheResolution?: ResolvedModuleWithFailedLookupLocations | false;
}

export interface ResolvedTypeReferenceDirective {
Expand Down
1 change: 0 additions & 1 deletion src/compiler/watchPublic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,6 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
configFileName ?
getDirectoryPath(getNormalizedAbsolutePath(configFileName, currentDirectory)) :
currentDirectory,
/*logChangesWhenResolvingModule*/ false,
);
// Resolve module using host module resolution strategy if provided otherwise use resolution cache to resolve module names
compilerHost.resolveModuleNameLiterals = maybeBind(host, host.resolveModuleNameLiterals);
Expand Down
44 changes: 41 additions & 3 deletions src/harness/incrementalUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export function verifyResolutionCache(
projectName: string,
): void {
const currentDirectory = resolutionHostCacheHost.getCurrentDirectory!();
const expected = ts.createResolutionCache(resolutionHostCacheHost, actual.rootDirForResolution, /*logChangesWhenResolvingModule*/ false);
const expected = ts.createResolutionCache(resolutionHostCacheHost, actual.rootDirForResolution);
expected.startCachingPerDirectoryResolution();

type ExpectedResolution = ts.CachedResolvedModuleWithFailedLookupLocations & ts.CachedResolvedTypeReferenceDirectiveWithFailedLookupLocations;
Expand Down Expand Up @@ -269,6 +269,14 @@ export function verifyResolutionCache(
verifyFileWatchesOfAffectingLocations(expected.fileWatchesOfAffectingLocations, actual.fileWatchesOfAffectingLocations);
verifyPackageDirWatchers(expected.packageDirWatchers, actual.packageDirWatchers);
verifyDirPathToSymlinkPackageRefCount(expected.dirPathToSymlinkPackageRefCount, actual.dirPathToSymlinkPackageRefCount);
ts.Debug.assert(
expected.countResolutionsResolvedWithGlobalCache() === actual.countResolutionsResolvedWithGlobalCache(),
`${projectName}:: Expected ResolutionsResolvedWithGlobalCache count ${expected.countResolutionsResolvedWithGlobalCache()} but got ${actual.countResolutionsResolvedWithGlobalCache()}`,
);
ts.Debug.assert(
expected.countResolutionsResolvedWithoutGlobalCache() === actual.countResolutionsResolvedWithoutGlobalCache(),
`${projectName}:: Expected ResolutionsResolvedWithoutGlobalCache count ${expected.countResolutionsResolvedWithoutGlobalCache()} but got ${actual.countResolutionsResolvedWithoutGlobalCache()}`,
);

// Stop watching resolutions to verify everything gets closed.
expected.startCachingPerDirectoryResolution();
Expand All @@ -284,6 +292,8 @@ export function verifyResolutionCache(
ts.Debug.assert(expected.resolutionsWithOnlyAffectingLocations.size === 0, `${projectName}:: resolutionsWithOnlyAffectingLocations should be released`);
ts.Debug.assert(expected.directoryWatchesOfFailedLookups.size === 0, `${projectName}:: directoryWatchesOfFailedLookups should be released`);
ts.Debug.assert(expected.fileWatchesOfAffectingLocations.size === 0, `${projectName}:: fileWatchesOfAffectingLocations should be released`);
ts.Debug.assert(expected.countResolutionsResolvedWithGlobalCache() === 0, `${projectName}:: ResolutionsResolvedWithGlobalCache should be cleared`);
ts.Debug.assert(expected.countResolutionsResolvedWithoutGlobalCache() === 0, `${projectName}:: ResolutionsResolvedWithoutGlobalCache should be cleared`);

function collectResolutionToRefFromCache<T extends ts.ResolutionWithFailedLookupLocations>(
cacheType: string,
Expand Down Expand Up @@ -329,6 +339,7 @@ export function verifyResolutionCache(
failedLookupLocations: resolved.failedLookupLocations,
affectingLocations: resolved.affectingLocations,
alternateResult: resolved.alternateResult,
globalCacheResolution: resolved.globalCacheResolution,
};
expectedToResolution.set(expectedResolution, resolved);
resolutionToExpected.set(resolved, expectedResolution);
Expand Down Expand Up @@ -448,17 +459,25 @@ function verifySet(
expected?.forEach(expected =>
ts.Debug.assert(
actual?.has(expected),
`${caption}:: Expected should be present in actual`,
`${caption}:: ${expected} should be present in actual`,
)
);
actual?.forEach(actual =>
ts.Debug.assert(
expected?.has(actual),
`${caption}:: Actual should be present in expected`,
`${caption}:: ${actual} should be present in expected`,
)
);
}

function verifyArray(
expected: readonly string[] | undefined,
actual: readonly string[] | undefined,
caption: string,
) {
return verifySet(expected && new Set(expected), actual && new Set(actual), caption);
}

function verifyProgram(service: ts.server.ProjectService, project: ts.server.Project) {
if (service.serverMode === ts.LanguageServiceMode.Syntactic) return;
const options = project.getCompilerOptions();
Expand Down Expand Up @@ -572,6 +591,24 @@ function verifyProgram(service: ts.server.ProjectService, project: ts.server.Pro
verifyResolutionCache(project.resolutionCache, project.getCurrentProgram()!, resolutionHostCacheHost, project.projectName);
}

function verifyUnresolvedImports(_service: ts.server.ProjectService, project: ts.server.Project) {
const cachedUnresolvedImportsPerFile = new Map<ts.Path, readonly string[]>();
const lastCachedUnresolvedImportsList = project.useTypingsFromGlobalCache() ?
ts.server.getUnresolvedImports(project.getCurrentProgram()!, cachedUnresolvedImportsPerFile) :
undefined;
verifyArray(
lastCachedUnresolvedImportsList,
project.lastCachedUnresolvedImportsList,
`${project.getProjectName()}:: lastCachedUnresolvedImportsList`,
);
verifyMap(
cachedUnresolvedImportsPerFile,
project.cachedUnresolvedImportsPerFile,
(expected, actual, caption) => verifyArray(expected, actual, caption),
`${project.getProjectName()}:: cachedUnresolvedImportsPerFile`,
);
}

interface ResolveSingleModuleNameWithoutWatchingData {
resolutionToData: Map<ts.ResolutionWithFailedLookupLocations, Pick<ts.ResolvedModuleWithFailedLookupLocations, "failedLookupLocations" | "affectingLocations" | "resolutionDiagnostics">>;
packageJsonMap: Map<ts.Path, ts.PackageJsonInfoCacheEntry> | undefined;
Expand Down Expand Up @@ -648,6 +685,7 @@ export interface IncrementalVerifierCallbacks {
export function incrementalVerifier(service: ts.server.ProjectService): void {
service.verifyDocumentRegistry = withIncrementalVerifierCallbacks(service, verifyDocumentRegistry);
service.verifyProgram = withIncrementalVerifierCallbacks(service, verifyProgram);
service.verifyUnresovedImports = withIncrementalVerifierCallbacks(service, verifyUnresolvedImports);
service.onProjectCreation = onProjectCreation;
}

Expand Down
8 changes: 2 additions & 6 deletions src/server/editorServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1424,6 +1424,7 @@ export class ProjectService {
/** @internal */ baseline: (title?: string) => void = noop;
/** @internal */ verifyDocumentRegistry: typeof noop = noop;
/** @internal */ verifyProgram: (project: Project) => void = noop;
/** @internal */ verifyUnresovedImports: (project: Project) => void = noop;
/** @internal */ onProjectCreation: (project: Project) => void = noop;
/** @internal */ canUseWatchEvents: boolean;

Expand Down Expand Up @@ -1594,12 +1595,7 @@ export class ProjectService {
switch (response.kind) {
case ActionSet:
// Update the typing files and update the project
project.updateTypingFiles(
response.compilerOptions,
response.typeAcquisition,
response.unresolvedImports,
response.typings,
);
project.updateTypingFiles(response);
return;
case ActionInvalidate:
// Do not clear resolution cache, there was changes detected in typings, so enque typing request and let it get us correct results
Expand Down
Loading