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
28 changes: 14 additions & 14 deletions src/compiler/resolutionCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,24 +220,17 @@ namespace ts {

function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, redirectedReference?: ResolvedProjectReference): CachedResolvedModuleWithFailedLookupLocations {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to fix the merge conflict

const primaryResult = ts.resolveModuleName(moduleName, containingFile, compilerOptions, host, moduleResolutionCache, redirectedReference);
// return result immediately only if global cache support is not enabled or if it is .ts, .tsx or .d.ts
if (!resolutionHost.getGlobalCache) {
return primaryResult;
}

// otherwise try to load typings from @types
const globalCache = resolutionHost.getGlobalCache();
const globalCache = resolutionHost.getGlobalCache ? resolutionHost.getGlobalCache() : undefined;
if (globalCache !== undefined && !isExternalModuleNameRelative(moduleName) && !(primaryResult.resolvedModule && extensionIsTS(primaryResult.resolvedModule.extension))) {
// create different collection of failed lookup locations for second pass
// if it will fail and we've already found something during the first pass - we don't want to pollute its results
const { resolvedModule, failedLookupLocations } = loadModuleFromGlobalCache(moduleName, resolutionHost.projectName, compilerOptions, host, globalCache);
if (resolvedModule) {
return { resolvedModule, failedLookupLocations: addRange(primaryResult.failedLookupLocations as string[], failedLookupLocations) };
}
return { resolvedModule: resolvedModule || primaryResult.resolvedModule, failedLookupLocations: [...primaryResult.failedLookupLocations, ...failedLookupLocations] };
}
else {
// Default return the result from the first pass
return primaryResult;
}

// Default return the result from the first pass
return primaryResult;
}

function resolveNamesWithLocalCache<T extends ResolutionWithFailedLookupLocations, R extends ResolutionWithResolvedFileName>(
Expand Down Expand Up @@ -390,10 +383,17 @@ namespace ts {
return true;
}

const globalCache = resolutionHost.getGlobalCache ? resolutionHost.getGlobalCache() : undefined;
// Using identity for getCanonicalFileName because assuming that if a path came from globalCache its case hasn't been changed.
if (globalCache !== undefined && dirPath === globalCache) {
return true;
}

// Path must have at least 3 components
for (let searchIndex = nextDirectorySeparator + 1, searchLevels = 2; searchLevels > 0; searchLevels--) {
searchIndex = dirPath.indexOf(directorySeparator, searchIndex) + 1;
if (searchIndex === 0) {
// Folder isnt at expected minimun levels
// Folder isnt at expected minimum levels
return false;
}
}
Expand Down
36 changes: 21 additions & 15 deletions src/testRunner/unittests/typingsInstaller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,7 @@ namespace ts.projectSystem {
});

it("should install typings for unresolved imports", () => {
const file = {
const file: TestFSWithWatch.File = {
path: "/a/b/app.js",
content: `
import * as fs from "fs";
Expand All @@ -954,36 +954,42 @@ namespace ts.projectSystem {
const cachePath = "/a/cache";
const node = {
path: cachePath + "/node_modules/@types/node/index.d.ts",
content: "export let x: number"
content: "export let x: number",
};
const commander = {
path: cachePath + "/node_modules/@types/commander/index.d.ts",
content: "export let y: string"
const commanderJS: TestFSWithWatch.File = {
path: "/node_modules/commander/index.js",
content: "module.exports = 0",
};
const host = createServerHost([file]);

const typeNames: ReadonlyArray<string> = ["node", "commander"];
const typePath = (name: string): string => `${cachePath}/node_modules/@types/${name}/index.d.ts`;
const host = createServerHost([file, node, commanderJS]);
const installer = new (class extends Installer {
constructor() {
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry("node", "commander") });
super(host, { globalTypingsCacheLocation: cachePath, typesRegistry: createTypesRegistry(...typeNames) });
}
installWorker(_requestId: number, _args: string[], _cwd: string, cb: TI.RequestCompletedAction) {
const installedTypings = ["@types/node", "@types/commander"];
const typingFiles = [node, commander];
const installedTypings = typeNames.map(name => `@types/${name}`);
const typingFiles = typeNames.map((name): TestFSWithWatch.File => ({ path: typePath(name), content: "" }));
executeCommand(this, host, installedTypings, typingFiles, cb);
}
})();
const service = createProjectService(host, { typingsInstaller: installer });
service.openClientFile(file.path);

checkWatchedFiles(host, [...flatMap(["/a/b", "/a", ""], x => [x + "/tsconfig.json", x + "/jsconfig.json"]), "/a/lib/lib.d.ts"]);
checkWatchedDirectories(host, [], /*recursive*/ false);
checkWatchedDirectories(host, ["/node_modules", "/a/b/node_modules", "/a/cache/node_modules", "/a/b/node_modules/@types", "/a/b/bower_components"], /*recursive*/ true);

service.checkNumberOfProjects({ inferredProjects: 1 });
checkProjectActualFiles(service.inferredProjects[0], [file.path]);
checkProjectActualFiles(service.inferredProjects[0], [file.path, commanderJS.path]);

installer.installAll(/*expectedCount*/1);

assert.isTrue(host.fileExists(node.path), "typings for 'node' should be created");
assert.isTrue(host.fileExists(commander.path), "typings for 'commander' should be created");

for (const name of typeNames) {
assert.isTrue(host.fileExists(typePath(name)), `typings for '${name}' should be created`);
}
host.checkTimeoutQueueLengthAndRun(2);
checkProjectActualFiles(service.inferredProjects[0], [file.path, node.path, commander.path]);
checkProjectActualFiles(service.inferredProjects[0], [file.path, ...typeNames.map(typePath)]);
});

it("should pick typing names from non-relative unresolved imports", () => {
Expand Down