Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] Type acquisition and module resolution updates #56074

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
da0c1bf
Write log about unresolved imports calculation
sheetalkamat Oct 17, 2023
79304e0
Add test when type acquisition changes
sheetalkamat Nov 7, 2023
19873e9
Verify getUnresolvedImports incrementally
sheetalkamat Oct 20, 2023
3c17c87
Handle unnecessary typings request force just because root files change
sheetalkamat Oct 11, 2023
ff93f09
When type acquisition is disabled, remove the typing files set as root
sheetalkamat Oct 11, 2023
aa99f9c
Close watchers for TI that are no longer needed
sheetalkamat Oct 11, 2023
a1462ad
Update the unresolved import list only if it will be used
sheetalkamat Oct 11, 2023
da1bf66
Do not update typings for project if type aquisition is disabled
sheetalkamat Oct 12, 2023
575fdfd
If typing installer is disabled invalidate all the resolutions from t…
sheetalkamat Oct 12, 2023
cdf74ed
Use globalCacheResolution to invalidate resolutions on typings update
sheetalkamat Oct 17, 2023
1f446f3
Instead of iterating over resolutions to invalidate per global cache …
sheetalkamat Oct 17, 2023
721b9f5
Update cached import list update as part of resolving modules instead…
sheetalkamat Oct 20, 2023
113a1f7
If the there is no change detected in module resolution we shouldnt n…
sheetalkamat Oct 20, 2023
c670bf0
Remove unnecessary timeout running added during wip to ensure catchin…
sheetalkamat Oct 25, 2023
1e66ff4
Now that work with unresolved imports cleanup is done, remove the tem…
sheetalkamat Nov 9, 2023
b268198
unresolved imports of empty array and undefined are same
sheetalkamat Nov 9, 2023
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 @@ -7998,6 +7998,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