Merge pull request #25521 from Microsoft/dontWatchAmbientModules

Do not watch modules that get resolved by ambient modules
This commit is contained in:
Sheetal Nandi 2018-07-09 17:02:33 -07:00 committed by GitHub
commit 357f0d6fbd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 27 deletions

View file

@ -81,6 +81,7 @@ namespace ts {
let filesWithInvalidatedResolutions: Map<true> | undefined; let filesWithInvalidatedResolutions: Map<true> | undefined;
let filesWithInvalidatedNonRelativeUnresolvedImports: Map<ReadonlyArray<string>> | undefined; let filesWithInvalidatedNonRelativeUnresolvedImports: Map<ReadonlyArray<string>> | undefined;
let allFilesHaveInvalidatedResolution = false; let allFilesHaveInvalidatedResolution = false;
const nonRelativeExternalModuleResolutions = createMultiMap<ResolutionWithFailedLookupLocations>();
const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory!()); // TODO: GH#18217 const getCurrentDirectory = memoize(() => resolutionHost.getCurrentDirectory!()); // TODO: GH#18217
const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost(); const cachedDirectoryStructureHost = resolutionHost.getCachedDirectoryStructureHost();
@ -154,6 +155,7 @@ namespace ts {
function clear() { function clear() {
clearMap(directoryWatchesOfFailedLookups, closeFileWatcherOf); clearMap(directoryWatchesOfFailedLookups, closeFileWatcherOf);
customFailedLookupPaths.clear(); customFailedLookupPaths.clear();
nonRelativeExternalModuleResolutions.clear();
closeTypeRootsWatch(); closeTypeRootsWatch();
resolvedModuleNames.clear(); resolvedModuleNames.clear();
resolvedTypeReferenceDirectives.clear(); resolvedTypeReferenceDirectives.clear();
@ -199,19 +201,20 @@ namespace ts {
perDirectoryResolvedModuleNames.clear(); perDirectoryResolvedModuleNames.clear();
nonRelaticeModuleNameCache.clear(); nonRelaticeModuleNameCache.clear();
perDirectoryResolvedTypeReferenceDirectives.clear(); perDirectoryResolvedTypeReferenceDirectives.clear();
nonRelativeExternalModuleResolutions.forEach(watchFailedLookupLocationOfNonRelativeModuleResolutions);
nonRelativeExternalModuleResolutions.clear();
} }
function finishCachingPerDirectoryResolution() { function finishCachingPerDirectoryResolution() {
allFilesHaveInvalidatedResolution = false; allFilesHaveInvalidatedResolution = false;
filesWithInvalidatedNonRelativeUnresolvedImports = undefined; filesWithInvalidatedNonRelativeUnresolvedImports = undefined;
clearPerDirectoryResolutions();
directoryWatchesOfFailedLookups.forEach((watcher, path) => { directoryWatchesOfFailedLookups.forEach((watcher, path) => {
if (watcher.refCount === 0) { if (watcher.refCount === 0) {
directoryWatchesOfFailedLookups.delete(path); directoryWatchesOfFailedLookups.delete(path);
watcher.watcher.close(); watcher.watcher.close();
} }
}); });
clearPerDirectoryResolutions();
} }
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): CachedResolvedModuleWithFailedLookupLocations { function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): CachedResolvedModuleWithFailedLookupLocations {
@ -275,7 +278,7 @@ namespace ts {
perDirectoryResolution.set(name, resolution); perDirectoryResolution.set(name, resolution);
} }
resolutionsInFile.set(name, resolution); resolutionsInFile.set(name, resolution);
watchFailedLookupLocationOfResolution(resolution); watchFailedLookupLocationsOfExternalModuleResolutions(name, resolution);
if (existingResolution) { if (existingResolution) {
stopWatchFailedLookupLocationOfResolution(existingResolution); stopWatchFailedLookupLocationOfResolution(existingResolution);
} }
@ -441,18 +444,27 @@ namespace ts {
return fileExtensionIsOneOf(path, failedLookupDefaultExtensions); return fileExtensionIsOneOf(path, failedLookupDefaultExtensions);
} }
function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) { function watchFailedLookupLocationsOfExternalModuleResolutions(name: string, resolution: ResolutionWithFailedLookupLocations) {
// No need to set the resolution refCount // No need to set the resolution refCount
if (!resolution.failedLookupLocations || !resolution.failedLookupLocations.length) { if (resolution.failedLookupLocations && resolution.failedLookupLocations.length) {
return; if (resolution.refCount) {
resolution.refCount++;
}
else {
resolution.refCount = 1;
if (isExternalModuleNameRelative(name)) {
watchFailedLookupLocationOfResolution(resolution);
}
else {
nonRelativeExternalModuleResolutions.add(name, resolution);
}
}
} }
}
if (resolution.refCount !== undefined) { function watchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
resolution.refCount++; Debug.assert(!!resolution.refCount);
return;
}
resolution.refCount = 1;
const { failedLookupLocations } = resolution; const { failedLookupLocations } = resolution;
let setAtRoot = false; let setAtRoot = false;
for (const failedLookupLocation of failedLookupLocations) { for (const failedLookupLocation of failedLookupLocations) {
@ -480,6 +492,16 @@ namespace ts {
} }
} }
function setRefCountToUndefined(resolution: ResolutionWithFailedLookupLocations) {
resolution.refCount = undefined;
}
function watchFailedLookupLocationOfNonRelativeModuleResolutions(resolutions: ResolutionWithFailedLookupLocations[], name: string) {
const updateResolution = resolutionHost.getCurrentProgram().getTypeChecker().tryFindAmbientModuleWithoutAugmentations(name) ?
setRefCountToUndefined : watchFailedLookupLocationOfResolution;
resolutions.forEach(updateResolution);
}
function setDirectoryWatcher(dir: string, dirPath: Path, nonRecursive?: boolean) { function setDirectoryWatcher(dir: string, dirPath: Path, nonRecursive?: boolean) {
const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath); const dirWatcher = directoryWatchesOfFailedLookups.get(dirPath);
if (dirWatcher) { if (dirWatcher) {
@ -492,11 +514,11 @@ namespace ts {
} }
function stopWatchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) { function stopWatchFailedLookupLocationOfResolution(resolution: ResolutionWithFailedLookupLocations) {
if (!resolution.failedLookupLocations || !resolution.failedLookupLocations.length) { if (!resolution.refCount) {
return; return;
} }
resolution.refCount!--; resolution.refCount--;
if (resolution.refCount) { if (resolution.refCount) {
return; return;
} }

View file

@ -8486,7 +8486,7 @@ new C();`
}); });
}); });
it("when watching directories for failed lookup locations in amd resolution", () => { describe("when watching directories for failed lookup locations in amd resolution", () => {
const projectRoot = "/user/username/projects/project"; const projectRoot = "/user/username/projects/project";
const nodeFile: File = { const nodeFile: File = {
path: `${projectRoot}/src/typings/node.d.ts`, path: `${projectRoot}/src/typings/node.d.ts`,
@ -8530,19 +8530,35 @@ export const x = 10;`
} }
}) })
}; };
const files = [nodeFile, electronFile, srcFile, moduleFile, configFile, libFile];
const host = createServerHost(files); function verifyModuleResolution(useNodeFile: boolean) {
const service = createProjectService(host); const files = [...(useNodeFile ? [nodeFile] : []), electronFile, srcFile, moduleFile, configFile, libFile];
service.openClientFile(srcFile.path, srcFile.content, ScriptKind.TS, projectRoot); const host = createServerHost(files);
checkProjectActualFiles(service.configuredProjects.get(configFile.path)!, files.map(f => f.path)); const service = createProjectService(host);
checkWatchedFilesDetailed(host, mapDefined(files, f => f === srcFile ? undefined : f.path), 1); service.openClientFile(srcFile.path, srcFile.content, ScriptKind.TS, projectRoot);
checkWatchedDirectoriesDetailed(host, [`${projectRoot}`], 1, /*recursive*/ false); // failed lookup for fs checkProjectActualFiles(service.configuredProjects.get(configFile.path)!, files.map(f => f.path));
const expectedWatchedDirectories = createMap<number>(); checkWatchedFilesDetailed(host, mapDefined(files, f => f === srcFile ? undefined : f.path), 1);
expectedWatchedDirectories.set(`${projectRoot}/src`, 2); // Wild card and failed lookup if (useNodeFile) {
expectedWatchedDirectories.set(`${projectRoot}/somefolder`, 1); // failed lookup for somefolder/module2 checkWatchedDirectories(host, emptyArray, /*recursive*/ false); // since fs resolves to ambient module, shouldnt watch failed lookup
expectedWatchedDirectories.set(`${projectRoot}/node_modules`, 1); // failed lookup for with node_modules/@types/fs }
expectedWatchedDirectories.set(`${projectRoot}/src/typings`, 1); // typeroot directory else {
checkWatchedDirectoriesDetailed(host, expectedWatchedDirectories, /*recursive*/ true); checkWatchedDirectoriesDetailed(host, [`${projectRoot}`], 1, /*recursive*/ false); // failed lookup for fs
}
const expectedWatchedDirectories = createMap<number>();
expectedWatchedDirectories.set(`${projectRoot}/src`, 2); // Wild card and failed lookup
expectedWatchedDirectories.set(`${projectRoot}/somefolder`, 1); // failed lookup for somefolder/module2
expectedWatchedDirectories.set(`${projectRoot}/node_modules`, 1); // failed lookup for with node_modules/@types/fs
expectedWatchedDirectories.set(`${projectRoot}/src/typings`, 1); // typeroot directory
checkWatchedDirectoriesDetailed(host, expectedWatchedDirectories, /*recursive*/ true);
}
it("when resolves to ambient module", () => {
verifyModuleResolution(/*useNodeFile*/ true);
});
it("when resolution fails", () => {
verifyModuleResolution(/*useNodeFile*/ false);
});
}); });
}); });