mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-11 01:34:55 -06:00
add optional 'directoryExists' method to hosts to reduce amount of disk probings that are known to fail
This commit is contained in:
parent
b168da9248
commit
36af815bba
@ -53,13 +53,13 @@ namespace ts {
|
||||
if (getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) {
|
||||
const failedLookupLocations: string[] = [];
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
let resolvedFileName = loadNodeModuleFromFile(supportedExtensions, candidate, failedLookupLocations, host);
|
||||
let resolvedFileName = loadNodeModuleFromFile(supportedExtensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, host);
|
||||
|
||||
if (resolvedFileName) {
|
||||
return { resolvedModule: { resolvedFileName }, failedLookupLocations };
|
||||
}
|
||||
|
||||
resolvedFileName = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, host);
|
||||
resolvedFileName = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, host);
|
||||
return resolvedFileName
|
||||
? { resolvedModule: { resolvedFileName }, failedLookupLocations }
|
||||
: { resolvedModule: undefined, failedLookupLocations };
|
||||
@ -69,12 +69,22 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function loadNodeModuleFromFile(extensions: string[], candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string {
|
||||
/* @internal */
|
||||
export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean } ): boolean {
|
||||
// if host does not support 'directoryExists' assume that directory will exist
|
||||
return !host.directoryExists || host.directoryExists(directoryName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary
|
||||
* in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations.
|
||||
*/
|
||||
function loadNodeModuleFromFile(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, host: ModuleResolutionHost): string {
|
||||
return forEach(extensions, tryLoad);
|
||||
|
||||
function tryLoad(ext: string): string {
|
||||
const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext;
|
||||
if (host.fileExists(fileName)) {
|
||||
if (!onlyRecordFailures && host.fileExists(fileName)) {
|
||||
return fileName;
|
||||
}
|
||||
else {
|
||||
@ -84,9 +94,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], host: ModuleResolutionHost): string {
|
||||
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, host: ModuleResolutionHost): string {
|
||||
const packageJsonPath = combinePaths(candidate, "package.json");
|
||||
if (host.fileExists(packageJsonPath)) {
|
||||
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, host);
|
||||
if (directoryExists && host.fileExists(packageJsonPath)) {
|
||||
|
||||
let jsonContent: { typings?: string };
|
||||
|
||||
@ -100,7 +111,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (typeof jsonContent.typings === "string") {
|
||||
const result = loadNodeModuleFromFile(extensions, normalizePath(combinePaths(candidate, jsonContent.typings)), failedLookupLocation, host);
|
||||
const path = normalizePath(combinePaths(candidate, jsonContent.typings));
|
||||
const result = loadNodeModuleFromFile(extensions, path, failedLookupLocation, !directoryProbablyExists(getDirectoryPath(path), host), host);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@ -111,7 +123,7 @@ namespace ts {
|
||||
failedLookupLocation.push(packageJsonPath);
|
||||
}
|
||||
|
||||
return loadNodeModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocation, host);
|
||||
return loadNodeModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocation, !directoryExists, host);
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModules(moduleName: string, directory: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations {
|
||||
@ -121,14 +133,15 @@ namespace ts {
|
||||
const baseName = getBaseFileName(directory);
|
||||
if (baseName !== "node_modules") {
|
||||
const nodeModulesFolder = combinePaths(directory, "node_modules");
|
||||
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, host);
|
||||
const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName));
|
||||
// Load only typescript files irrespective of allowJs option if loading from node modules
|
||||
let result = loadNodeModuleFromFile(supportedTypeScriptExtensions, candidate, failedLookupLocations, host);
|
||||
let result = loadNodeModuleFromFile(supportedTypeScriptExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, host);
|
||||
if (result) {
|
||||
return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations };
|
||||
}
|
||||
|
||||
result = loadNodeModuleFromDirectory(supportedTypeScriptExtensions, candidate, failedLookupLocations, host);
|
||||
result = loadNodeModuleFromDirectory(supportedTypeScriptExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, host);
|
||||
if (result) {
|
||||
return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations };
|
||||
}
|
||||
@ -281,7 +294,8 @@ namespace ts {
|
||||
getCanonicalFileName,
|
||||
getNewLine: () => newLine,
|
||||
fileExists: fileName => sys.fileExists(fileName),
|
||||
readFile: fileName => sys.readFile(fileName)
|
||||
readFile: fileName => sys.readFile(fileName),
|
||||
directoryExists: directoryName => sys.directoryExists(directoryName)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -2649,6 +2649,8 @@ namespace ts {
|
||||
// readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json'
|
||||
// to determine location of bundled typings for node module
|
||||
readFile(fileName: string): string;
|
||||
|
||||
directoryExists?(directoryName: string): boolean;
|
||||
}
|
||||
|
||||
export interface ResolvedModule {
|
||||
|
||||
@ -267,6 +267,10 @@ namespace Harness.LanguageService {
|
||||
log(s: string): void { this.nativeHost.log(s); }
|
||||
trace(s: string): void { this.nativeHost.trace(s); }
|
||||
error(s: string): void { this.nativeHost.error(s); }
|
||||
directoryExists(directoryName: string): boolean {
|
||||
// for tests pessimistically assume that directory always exists
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class ClassifierShimProxy implements ts.Classifier {
|
||||
|
||||
@ -100,7 +100,8 @@ namespace ts.server {
|
||||
this.filenameToScript = createFileMap<ScriptInfo>();
|
||||
this.moduleResolutionHost = {
|
||||
fileExists: fileName => this.fileExists(fileName),
|
||||
readFile: fileName => this.host.readFile(fileName)
|
||||
readFile: fileName => this.host.readFile(fileName),
|
||||
directoryExists: directoryName => this.host.directoryExists(directoryName)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1034,6 +1034,7 @@ namespace ts {
|
||||
* host specific questions using 'getScriptSnapshot'.
|
||||
*/
|
||||
resolveModuleNames?(moduleNames: string[], containingFile: string): ResolvedModule[];
|
||||
directoryExists?(directoryName: string): boolean;
|
||||
}
|
||||
|
||||
//
|
||||
@ -1911,7 +1912,8 @@ namespace ts {
|
||||
getCurrentDirectory: () => "",
|
||||
getNewLine: () => newLine,
|
||||
fileExists: (fileName): boolean => fileName === inputFileName,
|
||||
readFile: (fileName): string => ""
|
||||
readFile: (fileName): string => "",
|
||||
directoryExists: directoryExists => true
|
||||
};
|
||||
|
||||
const program = createProgram([inputFileName], options, compilerHost);
|
||||
@ -2768,6 +2770,10 @@ namespace ts {
|
||||
// stub missing host functionality
|
||||
const entry = hostCache.getOrCreateEntry(fileName);
|
||||
return entry && entry.scriptSnapshot.getText(0, entry.scriptSnapshot.getLength());
|
||||
},
|
||||
directoryExists: directoryName => {
|
||||
Debug.assert(!host.resolveModuleNames);
|
||||
return directoryProbablyExists(directoryName, host);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -62,6 +62,7 @@ namespace ts {
|
||||
useCaseSensitiveFileNames?(): boolean;
|
||||
|
||||
getModuleResolutionsForFile?(fileName: string): string;
|
||||
directoryExists(directoryName: string): boolean;
|
||||
}
|
||||
|
||||
/** Public interface of the the of a config service shim instance.*/
|
||||
@ -274,6 +275,7 @@ namespace ts {
|
||||
private tracingEnabled = false;
|
||||
|
||||
public resolveModuleNames: (moduleName: string[], containingFile: string) => ResolvedModule[];
|
||||
public directoryExists: (directoryName: string) => boolean;
|
||||
|
||||
constructor(private shimHost: LanguageServiceShimHost) {
|
||||
// if shimHost is a COM object then property check will become method call with no arguments.
|
||||
@ -287,6 +289,9 @@ namespace ts {
|
||||
});
|
||||
};
|
||||
}
|
||||
if ("directoryExists" in this.shimHost) {
|
||||
this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName);
|
||||
}
|
||||
}
|
||||
|
||||
public log(s: string): void {
|
||||
@ -405,9 +410,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export class CoreServicesShimHostAdapter implements ParseConfigHost {
|
||||
export class CoreServicesShimHostAdapter implements ParseConfigHost, ModuleResolutionHost {
|
||||
|
||||
public directoryExists: (directoryName: string) => boolean;
|
||||
|
||||
constructor(private shimHost: CoreServicesShimHost) {
|
||||
if ("directoryExists" in this.shimHost) {
|
||||
this.directoryExists = directoryName => this.shimHost.directoryExists(directoryName);
|
||||
}
|
||||
}
|
||||
|
||||
public readDirectory(rootDir: string, extension: string, exclude: string[]): string[] {
|
||||
@ -424,11 +434,11 @@ namespace ts {
|
||||
}
|
||||
return JSON.parse(encoded);
|
||||
}
|
||||
|
||||
|
||||
public fileExists(fileName: string): boolean {
|
||||
return this.shimHost.fileExists(fileName);
|
||||
}
|
||||
|
||||
|
||||
public readFile(fileName: string): string {
|
||||
return this.shimHost.readFile(fileName);
|
||||
}
|
||||
|
||||
@ -26,15 +26,36 @@ module ts {
|
||||
content?: string
|
||||
}
|
||||
|
||||
function createModuleResolutionHost(...files: File[]): ModuleResolutionHost {
|
||||
function createModuleResolutionHost(hasDirectoryExists: boolean, ...files: File[]): ModuleResolutionHost {
|
||||
let map = arrayToMap(files, f => f.name);
|
||||
|
||||
return { fileExists, readFile };
|
||||
|
||||
function fileExists(path: string): boolean {
|
||||
return hasProperty(map, path);
|
||||
if (hasDirectoryExists) {
|
||||
const directories: Map<string> = {};
|
||||
for (const f of files) {
|
||||
let name = getDirectoryPath(f.name);
|
||||
while (true) {
|
||||
directories[name] = name;
|
||||
let baseName = getDirectoryPath(name);
|
||||
if (baseName === name) {
|
||||
break;
|
||||
}
|
||||
name = baseName;
|
||||
}
|
||||
}
|
||||
return {
|
||||
readFile,
|
||||
directoryExists: path => {
|
||||
return hasProperty(directories, path);
|
||||
},
|
||||
fileExists: path => {
|
||||
assert.isTrue(hasProperty(directories, getDirectoryPath(path)), "'fileExists' request in non-existing directory");
|
||||
return hasProperty(map, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return { readFile, fileExists: path => hasProperty(map, path), };
|
||||
}
|
||||
|
||||
function readFile(path: string): string {
|
||||
return hasProperty(map, path) ? map[path].content : undefined;
|
||||
}
|
||||
@ -51,9 +72,14 @@ module ts {
|
||||
|
||||
function testLoadAsFile(containingFileName: string, moduleFileNameNoExt: string, moduleName: string): void {
|
||||
for (let ext of supportedTypeScriptExtensions) {
|
||||
test(ext, /*hasDirectoryExists*/ false);
|
||||
test(ext, /*hasDirectoryExists*/ true);
|
||||
}
|
||||
|
||||
function test(ext: string, hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: containingFileName }
|
||||
let moduleFile = { name: moduleFileNameNoExt + ext }
|
||||
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(containingFile, moduleFile));
|
||||
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
|
||||
@ -69,6 +95,7 @@ module ts {
|
||||
}
|
||||
|
||||
assert.deepEqual(resolution.failedLookupLocations, failedLookupLocations);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -89,14 +116,19 @@ module ts {
|
||||
});
|
||||
|
||||
function testLoadingFromPackageJson(containingFileName: string, packageJsonFileName: string, fieldRef: string, moduleFileName: string, moduleName: string): void {
|
||||
let containingFile = { name: containingFileName };
|
||||
let packageJson = { name: packageJsonFileName, content: JSON.stringify({ "typings": fieldRef }) };
|
||||
let moduleFile = { name: moduleFileName };
|
||||
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(containingFile, packageJson, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
// expect three failed lookup location - attempt to load module as file with all supported extensions
|
||||
assert.equal(resolution.failedLookupLocations.length, supportedTypeScriptExtensions.length);
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: containingFileName };
|
||||
let packageJson = { name: packageJsonFileName, content: JSON.stringify({ "typings": fieldRef }) };
|
||||
let moduleFile = { name: moduleFileName };
|
||||
let resolution = nodeModuleNameResolver(moduleName, containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
// expect three failed lookup location - attempt to load module as file with all supported extensions
|
||||
assert.equal(resolution.failedLookupLocations.length, supportedTypeScriptExtensions.length);
|
||||
}
|
||||
}
|
||||
|
||||
it("module name as directory - load from 'typings'", () => {
|
||||
@ -107,16 +139,21 @@ module ts {
|
||||
});
|
||||
|
||||
function testTypingsIgnored(typings: any): void {
|
||||
let containingFile = { name: "/a/b.ts" };
|
||||
let packageJson = { name: "/node_modules/b/package.json", content: JSON.stringify({ "typings": typings }) };
|
||||
let moduleFile = { name: "/a/b.d.ts" };
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
let indexPath = "/node_modules/b/index.d.ts";
|
||||
let indexFile = { name: indexPath }
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: "/a/b.ts" };
|
||||
let packageJson = { name: "/node_modules/b/package.json", content: JSON.stringify({ "typings": typings }) };
|
||||
let moduleFile = { name: "/a/b.d.ts" };
|
||||
|
||||
let resolution = nodeModuleNameResolver("b", containingFile.name, {}, createModuleResolutionHost(containingFile, packageJson, moduleFile, indexFile));
|
||||
let indexPath = "/node_modules/b/index.d.ts";
|
||||
let indexFile = { name: indexPath }
|
||||
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, indexPath);
|
||||
let resolution = nodeModuleNameResolver("b", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, moduleFile, indexFile));
|
||||
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, indexPath);
|
||||
}
|
||||
}
|
||||
|
||||
it("module name as directory - handle invalid 'typings'", () => {
|
||||
@ -128,89 +165,110 @@ module ts {
|
||||
});
|
||||
|
||||
it("module name as directory - load index.d.ts", () => {
|
||||
let containingFile = { name: "/a/b/c.ts" };
|
||||
let packageJson = { name: "/a/b/foo/package.json", content: JSON.stringify({ main: "/c/d" }) };
|
||||
let indexFile = { name: "/a/b/foo/index.d.ts" };
|
||||
let resolution = nodeModuleNameResolver("./foo", containingFile.name, {}, createModuleResolutionHost(containingFile, packageJson, indexFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, indexFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
"/a/b/foo.ts",
|
||||
"/a/b/foo.tsx",
|
||||
"/a/b/foo.d.ts",
|
||||
"/a/b/foo/index.ts",
|
||||
"/a/b/foo/index.tsx",
|
||||
]);
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: "/a/b/c.ts" };
|
||||
let packageJson = { name: "/a/b/foo/package.json", content: JSON.stringify({ main: "/c/d" }) };
|
||||
let indexFile = { name: "/a/b/foo/index.d.ts" };
|
||||
let resolution = nodeModuleNameResolver("./foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, packageJson, indexFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, indexFile.name);
|
||||
assert.equal(!!resolution.resolvedModule.isExternalLibraryImport, false);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
"/a/b/foo.ts",
|
||||
"/a/b/foo.tsx",
|
||||
"/a/b/foo.d.ts",
|
||||
"/a/b/foo/index.ts",
|
||||
"/a/b/foo/index.tsx",
|
||||
]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("Node module resolution - non-relative paths", () => {
|
||||
it("load module as file - ts files not loaded", () => {
|
||||
let containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
let moduleFile = { name: "/a/b/node_modules/foo.ts" };
|
||||
let resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
"/a/b/c/d/node_modules/foo.ts",
|
||||
"/a/b/c/d/node_modules/foo.tsx",
|
||||
"/a/b/c/d/node_modules/foo.d.ts",
|
||||
"/a/b/c/d/node_modules/foo/package.json",
|
||||
"/a/b/c/d/node_modules/foo/index.ts",
|
||||
"/a/b/c/d/node_modules/foo/index.tsx",
|
||||
"/a/b/c/d/node_modules/foo/index.d.ts",
|
||||
"/a/b/c/node_modules/foo.ts",
|
||||
"/a/b/c/node_modules/foo.tsx",
|
||||
"/a/b/c/node_modules/foo.d.ts",
|
||||
"/a/b/c/node_modules/foo/package.json",
|
||||
"/a/b/c/node_modules/foo/index.ts",
|
||||
"/a/b/c/node_modules/foo/index.tsx",
|
||||
"/a/b/c/node_modules/foo/index.d.ts",
|
||||
])
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
let moduleFile = { name: "/a/b/node_modules/foo.ts" };
|
||||
let resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
"/a/b/c/d/node_modules/foo.ts",
|
||||
"/a/b/c/d/node_modules/foo.tsx",
|
||||
"/a/b/c/d/node_modules/foo.d.ts",
|
||||
"/a/b/c/d/node_modules/foo/package.json",
|
||||
"/a/b/c/d/node_modules/foo/index.ts",
|
||||
"/a/b/c/d/node_modules/foo/index.tsx",
|
||||
"/a/b/c/d/node_modules/foo/index.d.ts",
|
||||
"/a/b/c/node_modules/foo.ts",
|
||||
"/a/b/c/node_modules/foo.tsx",
|
||||
"/a/b/c/node_modules/foo.d.ts",
|
||||
"/a/b/c/node_modules/foo/package.json",
|
||||
"/a/b/c/node_modules/foo/index.ts",
|
||||
"/a/b/c/node_modules/foo/index.tsx",
|
||||
"/a/b/c/node_modules/foo/index.d.ts",
|
||||
])
|
||||
}
|
||||
});
|
||||
|
||||
it("load module as file", () => {
|
||||
let containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
let moduleFile = { name: "/a/b/node_modules/foo.d.ts" };
|
||||
let resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(resolution.resolvedModule.isExternalLibraryImport, true);
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: "/a/b/c/d/e.ts" };
|
||||
let moduleFile = { name: "/a/b/node_modules/foo.d.ts" };
|
||||
let resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(resolution.resolvedModule.isExternalLibraryImport, true);
|
||||
}
|
||||
});
|
||||
|
||||
it("load module as directory", () => {
|
||||
let containingFile = { name: "/a/node_modules/b/c/node_modules/d/e.ts" };
|
||||
let moduleFile = { name: "/a/node_modules/foo/index.d.ts" };
|
||||
let resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(resolution.resolvedModule.isExternalLibraryImport, true);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.tsx",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/package.json",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/index.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/index.tsx",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/index.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo.tsx",
|
||||
"/a/node_modules/b/c/node_modules/foo.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo/package.json",
|
||||
"/a/node_modules/b/c/node_modules/foo/index.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo/index.tsx",
|
||||
"/a/node_modules/b/c/node_modules/foo/index.d.ts",
|
||||
"/a/node_modules/b/node_modules/foo.ts",
|
||||
"/a/node_modules/b/node_modules/foo.tsx",
|
||||
"/a/node_modules/b/node_modules/foo.d.ts",
|
||||
"/a/node_modules/b/node_modules/foo/package.json",
|
||||
"/a/node_modules/b/node_modules/foo/index.ts",
|
||||
"/a/node_modules/b/node_modules/foo/index.tsx",
|
||||
"/a/node_modules/b/node_modules/foo/index.d.ts",
|
||||
"/a/node_modules/foo.ts",
|
||||
"/a/node_modules/foo.tsx",
|
||||
"/a/node_modules/foo.d.ts",
|
||||
"/a/node_modules/foo/package.json",
|
||||
"/a/node_modules/foo/index.ts",
|
||||
"/a/node_modules/foo/index.tsx"
|
||||
]);
|
||||
test(/*hasDirectoryExists*/ false);
|
||||
test(/*hasDirectoryExists*/ true);
|
||||
|
||||
function test(hasDirectoryExists: boolean) {
|
||||
let containingFile = { name: "/a/node_modules/b/c/node_modules/d/e.ts" };
|
||||
let moduleFile = { name: "/a/node_modules/foo/index.d.ts" };
|
||||
let resolution = nodeModuleNameResolver("foo", containingFile.name, {}, createModuleResolutionHost(hasDirectoryExists, containingFile, moduleFile));
|
||||
assert.equal(resolution.resolvedModule.resolvedFileName, moduleFile.name);
|
||||
assert.equal(resolution.resolvedModule.isExternalLibraryImport, true);
|
||||
assert.deepEqual(resolution.failedLookupLocations, [
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.tsx",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/package.json",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/index.ts",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/index.tsx",
|
||||
"/a/node_modules/b/c/node_modules/d/node_modules/foo/index.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo.tsx",
|
||||
"/a/node_modules/b/c/node_modules/foo.d.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo/package.json",
|
||||
"/a/node_modules/b/c/node_modules/foo/index.ts",
|
||||
"/a/node_modules/b/c/node_modules/foo/index.tsx",
|
||||
"/a/node_modules/b/c/node_modules/foo/index.d.ts",
|
||||
"/a/node_modules/b/node_modules/foo.ts",
|
||||
"/a/node_modules/b/node_modules/foo.tsx",
|
||||
"/a/node_modules/b/node_modules/foo.d.ts",
|
||||
"/a/node_modules/b/node_modules/foo/package.json",
|
||||
"/a/node_modules/b/node_modules/foo/index.ts",
|
||||
"/a/node_modules/b/node_modules/foo/index.tsx",
|
||||
"/a/node_modules/b/node_modules/foo/index.d.ts",
|
||||
"/a/node_modules/foo.ts",
|
||||
"/a/node_modules/foo.tsx",
|
||||
"/a/node_modules/foo.d.ts",
|
||||
"/a/node_modules/foo/package.json",
|
||||
"/a/node_modules/foo/index.ts",
|
||||
"/a/node_modules/foo/index.tsx"
|
||||
]);
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -400,4 +458,21 @@ import b = require("./moduleB.ts");
|
||||
test(files, { module: ts.ModuleKind.CommonJS, forceConsistentCasingInFileNames: true }, "/a/B/c", /* useCaseSensitiveFileNames */ false, ["moduleD.ts"], []);
|
||||
})
|
||||
});
|
||||
|
||||
function notImplemented(name: string): () => any {
|
||||
return () => assert(`${name} is not implemented and should not be called`);
|
||||
}
|
||||
|
||||
describe("ModuleResolutionHost.directoryExists", () => {
|
||||
it("No 'fileExists' calls if containing directory is missing", () => {
|
||||
const host: ModuleResolutionHost = {
|
||||
readFile: notImplemented("readFile"),
|
||||
fileExists: notImplemented("fileExists"),
|
||||
directoryExists: _ => false
|
||||
};
|
||||
|
||||
const result = resolveModuleName("someName", "/a/b/c/d", { moduleResolution: ModuleResolutionKind.NodeJs }, host);
|
||||
assert(!result.resolvedModule);
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user