Have classic module resolution use @types as a fallback
This commit is contained in:
parent
d72a0430ca
commit
4907fd1d44
|
@ -95,7 +95,7 @@ namespace ts {
|
|||
currentDirectory = host.getCurrentDirectory();
|
||||
}
|
||||
|
||||
return currentDirectory && getDefaultTypeRoots(currentDirectory, host);
|
||||
return currentDirectory !== undefined && getDefaultTypeRoots(currentDirectory, host);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -675,23 +675,33 @@ namespace ts {
|
|||
|
||||
/* @internal */
|
||||
export function loadModuleFromNodeModules(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, checkOneLevel: boolean): string {
|
||||
return loadModuleFromNodeModulesWorker(moduleName, directory, failedLookupLocations, state, checkOneLevel, /*typesOnly*/ false);
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): string {
|
||||
return loadModuleFromNodeModulesWorker(moduleName, directory, failedLookupLocations, state, /*checkOneLevel*/ false, /*typesOnly*/ true);
|
||||
}
|
||||
|
||||
function loadModuleFromNodeModulesWorker(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState, checkOneLevel: boolean, typesOnly: boolean): string {
|
||||
directory = normalizeSlashes(directory);
|
||||
while (true) {
|
||||
const baseName = getBaseFileName(directory);
|
||||
if (baseName !== "node_modules") {
|
||||
// Try to load source from the package
|
||||
const packageResult = loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state);
|
||||
if (packageResult && hasTypeScriptFileExtension(packageResult)) {
|
||||
// Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package
|
||||
return packageResult;
|
||||
}
|
||||
else {
|
||||
// Else prefer a types package over non-TypeScript results (e.g. JavaScript files)
|
||||
const typesResult = loadModuleFromNodeModulesFolder(combinePaths("@types", moduleName), directory, failedLookupLocations, state);
|
||||
if (typesResult || packageResult) {
|
||||
return typesResult || packageResult;
|
||||
let packageResult: string | undefined;
|
||||
if (!typesOnly) {
|
||||
// Try to load source from the package
|
||||
packageResult = loadModuleFromNodeModulesFolder(moduleName, directory, failedLookupLocations, state);
|
||||
if (packageResult && hasTypeScriptFileExtension(packageResult)) {
|
||||
// Always prefer a TypeScript (.ts, .tsx, .d.ts) file shipped with the package
|
||||
return packageResult;
|
||||
}
|
||||
}
|
||||
|
||||
// Else prefer a types package over non-TypeScript results (e.g. JavaScript files)
|
||||
const typesResult = loadModuleFromNodeModulesFolder(combinePaths("@types", moduleName), directory, failedLookupLocations, state);
|
||||
if (typesResult || packageResult) {
|
||||
return typesResult || packageResult;
|
||||
}
|
||||
}
|
||||
|
||||
const parentPath = getDirectoryPath(directory);
|
||||
|
@ -709,7 +719,7 @@ namespace ts {
|
|||
const state = { compilerOptions, host, traceEnabled, skipTsx: !compilerOptions.jsx };
|
||||
const failedLookupLocations: string[] = [];
|
||||
const supportedExtensions = getSupportedExtensions(compilerOptions);
|
||||
let containingDirectory = getDirectoryPath(containingFile);
|
||||
const containingDirectory = getDirectoryPath(containingFile);
|
||||
|
||||
const resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loadModuleFromFile, failedLookupLocations, supportedExtensions, state);
|
||||
if (resolvedFileName) {
|
||||
|
@ -718,18 +728,9 @@ namespace ts {
|
|||
|
||||
let referencedSourceFile: string;
|
||||
if (moduleHasNonRelativeName(moduleName)) {
|
||||
while (true) {
|
||||
const searchName = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
if (referencedSourceFile) {
|
||||
break;
|
||||
}
|
||||
const parentPath = getDirectoryPath(containingDirectory);
|
||||
if (parentPath === containingDirectory) {
|
||||
break;
|
||||
}
|
||||
containingDirectory = parentPath;
|
||||
}
|
||||
referencedSourceFile = referencedSourceFile = loadModuleFromAncestorDirectories(moduleName, containingDirectory, supportedExtensions, failedLookupLocations, state) ||
|
||||
// If we didn't find the file normally, look it up in @types.
|
||||
loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state);
|
||||
}
|
||||
else {
|
||||
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
|
@ -741,4 +742,20 @@ namespace ts {
|
|||
? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations }
|
||||
: { resolvedModule: undefined, failedLookupLocations };
|
||||
}
|
||||
|
||||
/** Climb up parent directories looking for a module. */
|
||||
function loadModuleFromAncestorDirectories(moduleName: string, containingDirectory: string, supportedExtensions: string[], failedLookupLocations: string[], state: ModuleResolutionState): string | undefined {
|
||||
while (true) {
|
||||
const searchName = normalizePath(combinePaths(containingDirectory, moduleName));
|
||||
const referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
|
||||
if (referencedSourceFile) {
|
||||
return referencedSourceFile;
|
||||
}
|
||||
const parentPath = getDirectoryPath(containingDirectory);
|
||||
if (parentPath === containingDirectory) {
|
||||
return undefined;
|
||||
}
|
||||
containingDirectory = parentPath;
|
||||
}
|
||||
}
|
||||
}
|
18
tests/baselines/reference/typingsLookupAmd.js
Normal file
18
tests/baselines/reference/typingsLookupAmd.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
//// [tests/cases/conformance/typings/typingsLookupAmd.ts] ////
|
||||
|
||||
//// [index.d.ts]
|
||||
|
||||
export declare class A {}
|
||||
|
||||
//// [index.d.ts]
|
||||
import {A} from "a";
|
||||
export declare class B extends A {}
|
||||
|
||||
//// [foo.ts]
|
||||
import {B} from "b";
|
||||
|
||||
|
||||
//// [foo.js]
|
||||
define(["require", "exports"], function (require, exports) {
|
||||
"use strict";
|
||||
});
|
17
tests/baselines/reference/typingsLookupAmd.symbols
Normal file
17
tests/baselines/reference/typingsLookupAmd.symbols
Normal file
|
@ -0,0 +1,17 @@
|
|||
=== /x/y/foo.ts ===
|
||||
import {B} from "b";
|
||||
>B : Symbol(B, Decl(foo.ts, 0, 8))
|
||||
|
||||
=== /node_modules/@types/a/index.d.ts ===
|
||||
|
||||
export declare class A {}
|
||||
>A : Symbol(A, Decl(index.d.ts, 0, 0))
|
||||
|
||||
=== /x/node_modules/@types/b/index.d.ts ===
|
||||
import {A} from "a";
|
||||
>A : Symbol(A, Decl(index.d.ts, 0, 8))
|
||||
|
||||
export declare class B extends A {}
|
||||
>B : Symbol(B, Decl(index.d.ts, 0, 20))
|
||||
>A : Symbol(A, Decl(index.d.ts, 0, 8))
|
||||
|
59
tests/baselines/reference/typingsLookupAmd.trace.json
Normal file
59
tests/baselines/reference/typingsLookupAmd.trace.json
Normal file
|
@ -0,0 +1,59 @@
|
|||
[
|
||||
"======== Resolving module 'b' from '/x/y/foo.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'Classic'.",
|
||||
"File '/x/y/b.ts' does not exist.",
|
||||
"File '/x/y/b.d.ts' does not exist.",
|
||||
"File '/x/b.ts' does not exist.",
|
||||
"File '/x/b.d.ts' does not exist.",
|
||||
"File '/b.ts' does not exist.",
|
||||
"File '/b.d.ts' does not exist.",
|
||||
"File '/x/y/node_modules/@types/b.ts' does not exist.",
|
||||
"File '/x/y/node_modules/@types/b.d.ts' does not exist.",
|
||||
"File '/x/y/node_modules/@types/b/package.json' does not exist.",
|
||||
"File '/x/y/node_modules/@types/b/index.ts' does not exist.",
|
||||
"File '/x/y/node_modules/@types/b/index.d.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/b.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/b.d.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/b/package.json' does not exist.",
|
||||
"File '/x/node_modules/@types/b/index.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/b/index.d.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name 'b' was successfully resolved to '/x/node_modules/@types/b/index.d.ts'. ========",
|
||||
"======== Resolving module 'a' from '/x/node_modules/@types/b/index.d.ts'. ========",
|
||||
"Module resolution kind is not specified, using 'Classic'.",
|
||||
"File '/x/node_modules/@types/b/a.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/b/a.d.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/a.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/a.d.ts' does not exist.",
|
||||
"File '/x/node_modules/a.ts' does not exist.",
|
||||
"File '/x/node_modules/a.d.ts' does not exist.",
|
||||
"File '/x/a.ts' does not exist.",
|
||||
"File '/x/a.d.ts' does not exist.",
|
||||
"File '/a.ts' does not exist.",
|
||||
"File '/a.d.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/b/node_modules/@types/a.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/b/node_modules/@types/a.d.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/b/node_modules/@types/a/package.json' does not exist.",
|
||||
"File '/x/node_modules/@types/b/node_modules/@types/a/index.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/b/node_modules/@types/a/index.d.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/node_modules/@types/a.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/node_modules/@types/a.d.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/node_modules/@types/a/package.json' does not exist.",
|
||||
"File '/x/node_modules/@types/node_modules/@types/a/index.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/node_modules/@types/a/index.d.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/a.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/a.d.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/a/package.json' does not exist.",
|
||||
"File '/x/node_modules/@types/a/index.ts' does not exist.",
|
||||
"File '/x/node_modules/@types/a/index.d.ts' does not exist.",
|
||||
"File '/node_modules/@types/a.ts' does not exist.",
|
||||
"File '/node_modules/@types/a.d.ts' does not exist.",
|
||||
"File '/node_modules/@types/a/package.json' does not exist.",
|
||||
"File '/node_modules/@types/a/index.ts' does not exist.",
|
||||
"File '/node_modules/@types/a/index.d.ts' exist - use it as a name resolution result.",
|
||||
"======== Module name 'a' was successfully resolved to '/node_modules/@types/a/index.d.ts'. ========",
|
||||
"======== Resolving type reference directive 'a', containing file '/__inferred type names__.ts', root directory '/node_modules/@types'. ========",
|
||||
"Resolving with primary search path '/node_modules/@types'",
|
||||
"File '/node_modules/@types/a/package.json' does not exist.",
|
||||
"File '/node_modules/@types/a/index.d.ts' exist - use it as a name resolution result.",
|
||||
"======== Type reference directive 'a' was successfully resolved to '/node_modules/@types/a/index.d.ts', primary: true. ========"
|
||||
]
|
17
tests/baselines/reference/typingsLookupAmd.types
Normal file
17
tests/baselines/reference/typingsLookupAmd.types
Normal file
|
@ -0,0 +1,17 @@
|
|||
=== /x/y/foo.ts ===
|
||||
import {B} from "b";
|
||||
>B : typeof B
|
||||
|
||||
=== /node_modules/@types/a/index.d.ts ===
|
||||
|
||||
export declare class A {}
|
||||
>A : A
|
||||
|
||||
=== /x/node_modules/@types/b/index.d.ts ===
|
||||
import {A} from "a";
|
||||
>A : typeof A
|
||||
|
||||
export declare class B extends A {}
|
||||
>B : B
|
||||
>A : A
|
||||
|
14
tests/cases/conformance/typings/typingsLookupAmd.ts
Normal file
14
tests/cases/conformance/typings/typingsLookupAmd.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
// @traceResolution: true
|
||||
// @noImplicitReferences: true
|
||||
// @currentDirectory: /
|
||||
// @module: amd
|
||||
|
||||
// @filename: /node_modules/@types/a/index.d.ts
|
||||
export declare class A {}
|
||||
|
||||
// @filename: /x/node_modules/@types/b/index.d.ts
|
||||
import {A} from "a";
|
||||
export declare class B extends A {}
|
||||
|
||||
// @filename: /x/y/foo.ts
|
||||
import {B} from "b";
|
Loading…
Reference in a new issue