Skip to content

Commit 22ba111

Browse files
author
Andy Hanson
committed
Search for node_modules in parent directories when getting type roots.
1 parent 38de65a commit 22ba111

6 files changed

+126
-6
lines changed

src/compiler/program.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ namespace ts {
88

99
const emptyArray: any[] = [];
1010

11-
const defaultTypeRoots = ["node_modules/@types"];
12-
1311
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string {
1412
while (true) {
1513
const fileName = combinePaths(searchPath, "tsconfig.json");
@@ -168,7 +166,7 @@ namespace ts {
168166

169167
const typeReferenceExtensions = [".d.ts"];
170168

171-
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) {
169+
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost): string[] | undefined {
172170
if (options.typeRoots) {
173171
return options.typeRoots;
174172
}
@@ -181,10 +179,33 @@ namespace ts {
181179
currentDirectory = host.getCurrentDirectory();
182180
}
183181

184-
if (!currentDirectory) {
185-
return undefined;
182+
return currentDirectory && getDefaultTypeRoots(currentDirectory, host);
183+
}
184+
185+
function getDefaultTypeRoots(currentDirectory: string, host: ModuleResolutionHost): string[] | undefined {
186+
const nodeModules = getNearestNodeModules(currentDirectory, host);
187+
return nodeModules && [combinePaths(nodeModules, "@types")];
188+
}
189+
190+
function getNearestNodeModules(currentDirectory: string, host: ModuleResolutionHost): string | undefined {
191+
if (!host.directoryExists) {
192+
return combinePaths(currentDirectory, "node_modules");
193+
// And if it doesn't exist, tough.
194+
}
195+
196+
while (true) {
197+
const nodeModules = combinePaths(currentDirectory, "node_modules");
198+
if (host.directoryExists(nodeModules)) {
199+
return nodeModules;
200+
}
201+
else {
202+
const parent = getDirectoryPath(currentDirectory);
203+
if (parent === currentDirectory) {
204+
return undefined;
205+
}
206+
currentDirectory = parent;
207+
}
186208
}
187-
return map(defaultTypeRoots, d => combinePaths(currentDirectory, d));
188209
}
189210

190211
/**
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//// [tests/cases/compiler/typeRootsFromNodeModulesInParentDirectory.ts] ////
2+
3+
//// [index.d.ts]
4+
5+
declare module "xyz" {
6+
export const x: number;
7+
}
8+
9+
//// [a.ts]
10+
import { x } from "xyz";
11+
x;
12+
13+
14+
//// [a.js]
15+
"use strict";
16+
var xyz_1 = require("xyz");
17+
xyz_1.x;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== /src/a.ts ===
2+
import { x } from "xyz";
3+
>x : Symbol(x, Decl(a.ts, 0, 8))
4+
5+
x;
6+
>x : Symbol(x, Decl(a.ts, 0, 8))
7+
8+
=== /node_modules/@types/foo/index.d.ts ===
9+
10+
declare module "xyz" {
11+
export const x: number;
12+
>x : Symbol(x, Decl(index.d.ts, 2, 16))
13+
}
14+
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
[
2+
"======== Resolving module 'xyz' from '/src/a.ts'. ========",
3+
"Module resolution kind is not specified, using 'NodeJs'.",
4+
"Loading module 'xyz' from 'node_modules' folder.",
5+
"File '/src/node_modules/xyz.ts' does not exist.",
6+
"File '/src/node_modules/xyz.tsx' does not exist.",
7+
"File '/src/node_modules/xyz.d.ts' does not exist.",
8+
"File '/src/node_modules/xyz/package.json' does not exist.",
9+
"File '/src/node_modules/xyz/index.ts' does not exist.",
10+
"File '/src/node_modules/xyz/index.tsx' does not exist.",
11+
"File '/src/node_modules/xyz/index.d.ts' does not exist.",
12+
"File '/src/node_modules/@types/xyz.ts' does not exist.",
13+
"File '/src/node_modules/@types/xyz.tsx' does not exist.",
14+
"File '/src/node_modules/@types/xyz.d.ts' does not exist.",
15+
"File '/src/node_modules/@types/xyz/package.json' does not exist.",
16+
"File '/src/node_modules/@types/xyz/index.ts' does not exist.",
17+
"File '/src/node_modules/@types/xyz/index.tsx' does not exist.",
18+
"File '/src/node_modules/@types/xyz/index.d.ts' does not exist.",
19+
"File '/node_modules/xyz.ts' does not exist.",
20+
"File '/node_modules/xyz.tsx' does not exist.",
21+
"File '/node_modules/xyz.d.ts' does not exist.",
22+
"File '/node_modules/xyz/package.json' does not exist.",
23+
"File '/node_modules/xyz/index.ts' does not exist.",
24+
"File '/node_modules/xyz/index.tsx' does not exist.",
25+
"File '/node_modules/xyz/index.d.ts' does not exist.",
26+
"File '/node_modules/@types/xyz.ts' does not exist.",
27+
"File '/node_modules/@types/xyz.tsx' does not exist.",
28+
"File '/node_modules/@types/xyz.d.ts' does not exist.",
29+
"File '/node_modules/@types/xyz/package.json' does not exist.",
30+
"File '/node_modules/@types/xyz/index.ts' does not exist.",
31+
"File '/node_modules/@types/xyz/index.tsx' does not exist.",
32+
"File '/node_modules/@types/xyz/index.d.ts' does not exist.",
33+
"======== Module name 'xyz' was not resolved. ========",
34+
"======== Resolving type reference directive 'foo', containing file '/src/__inferred type names__.ts', root directory '/node_modules/@types'. ========",
35+
"Resolving with primary search path '/node_modules/@types'",
36+
"File '/node_modules/@types/foo/package.json' does not exist.",
37+
"File '/node_modules/@types/foo/index.d.ts' exist - use it as a name resolution result.",
38+
"======== Type reference directive 'foo' was successfully resolved to '/node_modules/@types/foo/index.d.ts', primary: true. ========"
39+
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== /src/a.ts ===
2+
import { x } from "xyz";
3+
>x : number
4+
5+
x;
6+
>x : number
7+
8+
=== /node_modules/@types/foo/index.d.ts ===
9+
10+
declare module "xyz" {
11+
export const x: number;
12+
>x : number
13+
}
14+
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// @noImplicitReferences: true
2+
// @traceResolution: true
3+
// @currentDirectory: /src
4+
5+
// @Filename: /node_modules/@types/foo/index.d.ts
6+
declare module "xyz" {
7+
export const x: number;
8+
}
9+
10+
// @Filename: /src/a.ts
11+
import { x } from "xyz";
12+
x;
13+
14+
// @Filename: /src/tsconfig.json
15+
{}

0 commit comments

Comments
 (0)