Skip to content

Commit f01fcb7

Browse files
author
Andy Hanson
committed
Search for node_modules in parent directories when getting type roots.
1 parent d6dac6a commit f01fcb7

15 files changed

+421
-20
lines changed

src/compiler/program.ts

+29-4
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ namespace ts {
169169

170170
const typeReferenceExtensions = [".d.ts"];
171171

172-
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) {
172+
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost): string[] | undefined {
173173
if (options.typeRoots) {
174174
return options.typeRoots;
175175
}
@@ -182,11 +182,36 @@ namespace ts {
182182
currentDirectory = host.getCurrentDirectory();
183183
}
184184

185-
if (!currentDirectory) {
186-
return undefined;
185+
return currentDirectory && getDefaultTypeRoots(currentDirectory, host);
186+
}
187+
188+
/**
189+
* Returns the path to every node_modules/@types directory from some ancestor directory.
190+
* Returns undefined if there are none.
191+
*/
192+
function getDefaultTypeRoots(currentDirectory: string, host: ModuleResolutionHost): string[] | undefined {
193+
if (!host.directoryExists) {
194+
return [combinePaths(currentDirectory, nodeModulesAtTypes)];
195+
}
196+
197+
let typeRoots: string[];
198+
199+
while (true) {
200+
const atTypes = combinePaths(currentDirectory, nodeModulesAtTypes);
201+
if (host.directoryExists(atTypes)) {
202+
(typeRoots || (typeRoots = [])).push(atTypes);
203+
}
204+
205+
const parent = getDirectoryPath(currentDirectory);
206+
if (parent === currentDirectory) {
207+
break;
208+
}
209+
currentDirectory = parent;
187210
}
188-
return map(defaultTypeRoots, d => combinePaths(currentDirectory, d));
211+
212+
return typeRoots;
189213
}
214+
const nodeModulesAtTypes = combinePaths("node_modules", "@types");
190215

191216
/**
192217
* @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown.

tests/baselines/reference/library-reference-11.trace.json

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
[
2-
"======== Resolving type reference directive 'jquery', containing file '/a/b/consumer.ts', root directory '/node_modules/@types'. ========",
3-
"Resolving with primary search path '/node_modules/@types'",
4-
"File '/node_modules/@types/jquery/package.json' does not exist.",
5-
"File '/node_modules/@types/jquery/index.d.ts' does not exist.",
2+
"======== Resolving type reference directive 'jquery', containing file '/a/b/consumer.ts', root directory not set. ========",
3+
"Root directory cannot be determined, skipping primary search paths.",
64
"Looking up in 'node_modules' folder, initial location '/a/b'",
75
"File '/a/b/node_modules/jquery.ts' does not exist.",
86
"File '/a/b/node_modules/jquery.d.ts' does not exist.",

tests/baselines/reference/library-reference-12.trace.json

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
[
2-
"======== Resolving type reference directive 'jquery', containing file '/a/b/consumer.ts', root directory '/node_modules/@types'. ========",
3-
"Resolving with primary search path '/node_modules/@types'",
4-
"File '/node_modules/@types/jquery/package.json' does not exist.",
5-
"File '/node_modules/@types/jquery/index.d.ts' does not exist.",
2+
"======== Resolving type reference directive 'jquery', containing file '/a/b/consumer.ts', root directory not set. ========",
3+
"Root directory cannot be determined, skipping primary search paths.",
64
"Looking up in 'node_modules' folder, initial location '/a/b'",
75
"File '/a/b/node_modules/jquery.ts' does not exist.",
86
"File '/a/b/node_modules/jquery.d.ts' does not exist.",

tests/baselines/reference/library-reference-3.trace.json

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
[
2-
"======== Resolving type reference directive 'jquery', containing file '/src/consumer.ts', root directory '/src/node_modules/@types'. ========",
3-
"Resolving with primary search path '/src/node_modules/@types'",
4-
"File '/src/node_modules/@types/jquery/package.json' does not exist.",
5-
"File '/src/node_modules/@types/jquery/index.d.ts' does not exist.",
2+
"======== Resolving type reference directive 'jquery', containing file '/src/consumer.ts', root directory not set. ========",
3+
"Root directory cannot be determined, skipping primary search paths.",
64
"Looking up in 'node_modules' folder, initial location '/src'",
75
"File '/src/node_modules/jquery.ts' does not exist.",
86
"File '/src/node_modules/jquery.d.ts' does not exist.",

tests/baselines/reference/library-reference-7.trace.json

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
[
2-
"======== Resolving type reference directive 'jquery', containing file '/src/consumer.ts', root directory '/node_modules/@types'. ========",
3-
"Resolving with primary search path '/node_modules/@types'",
4-
"File '/node_modules/@types/jquery/package.json' does not exist.",
5-
"File '/node_modules/@types/jquery/index.d.ts' does not exist.",
2+
"======== Resolving type reference directive 'jquery', containing file '/src/consumer.ts', root directory not set. ========",
3+
"Root directory cannot be determined, skipping primary search paths.",
64
"Looking up in 'node_modules' folder, initial location '/src'",
75
"File '/src/node_modules/jquery.ts' does not exist.",
86
"File '/src/node_modules/jquery.d.ts' does not exist.",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//// [tests/cases/compiler/typeRootsFromMultipleNodeModulesDirectories.ts] ////
2+
3+
//// [index.d.ts]
4+
5+
declare module "xyz" {
6+
export const x: number;
7+
}
8+
9+
//// [index.d.ts]
10+
declare module "pdq" {
11+
export const y: number;
12+
}
13+
14+
//// [index.d.ts]
15+
declare module "abc" {
16+
export const z: number;
17+
}
18+
19+
//// [a.ts]
20+
import { x } from "xyz";
21+
import { y } from "pdq";
22+
import { z } from "abc";
23+
x + y + z;
24+
25+
26+
//// [a.js]
27+
"use strict";
28+
var xyz_1 = require("xyz");
29+
var pdq_1 = require("pdq");
30+
var abc_1 = require("abc");
31+
xyz_1.x + pdq_1.y + abc_1.z;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== /foo/bar/a.ts ===
2+
import { x } from "xyz";
3+
>x : Symbol(x, Decl(a.ts, 0, 8))
4+
5+
import { y } from "pdq";
6+
>y : Symbol(y, Decl(a.ts, 1, 8))
7+
8+
import { z } from "abc";
9+
>z : Symbol(z, Decl(a.ts, 2, 8))
10+
11+
x + y + z;
12+
>x : Symbol(x, Decl(a.ts, 0, 8))
13+
>y : Symbol(y, Decl(a.ts, 1, 8))
14+
>z : Symbol(z, Decl(a.ts, 2, 8))
15+
16+
=== /node_modules/@types/dopey/index.d.ts ===
17+
18+
declare module "xyz" {
19+
export const x: number;
20+
>x : Symbol(x, Decl(index.d.ts, 2, 16))
21+
}
22+
23+
=== /foo/node_modules/@types/grumpy/index.d.ts ===
24+
declare module "pdq" {
25+
export const y: number;
26+
>y : Symbol(y, Decl(index.d.ts, 1, 16))
27+
}
28+
29+
=== /foo/node_modules/@types/sneezy/index.d.ts ===
30+
declare module "abc" {
31+
export const z: number;
32+
>z : Symbol(z, Decl(index.d.ts, 1, 16))
33+
}
34+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
[
2+
"======== Resolving module 'xyz' from '/foo/bar/a.ts'. ========",
3+
"Module resolution kind is not specified, using 'NodeJs'.",
4+
"Loading module 'xyz' from 'node_modules' folder.",
5+
"File '/foo/bar/node_modules/xyz.ts' does not exist.",
6+
"File '/foo/bar/node_modules/xyz.tsx' does not exist.",
7+
"File '/foo/bar/node_modules/xyz.d.ts' does not exist.",
8+
"File '/foo/bar/node_modules/xyz/package.json' does not exist.",
9+
"File '/foo/bar/node_modules/xyz/index.ts' does not exist.",
10+
"File '/foo/bar/node_modules/xyz/index.tsx' does not exist.",
11+
"File '/foo/bar/node_modules/xyz/index.d.ts' does not exist.",
12+
"File '/foo/bar/node_modules/@types/xyz.ts' does not exist.",
13+
"File '/foo/bar/node_modules/@types/xyz.tsx' does not exist.",
14+
"File '/foo/bar/node_modules/@types/xyz.d.ts' does not exist.",
15+
"File '/foo/bar/node_modules/@types/xyz/package.json' does not exist.",
16+
"File '/foo/bar/node_modules/@types/xyz/index.ts' does not exist.",
17+
"File '/foo/bar/node_modules/@types/xyz/index.tsx' does not exist.",
18+
"File '/foo/bar/node_modules/@types/xyz/index.d.ts' does not exist.",
19+
"File '/foo/node_modules/xyz.ts' does not exist.",
20+
"File '/foo/node_modules/xyz.tsx' does not exist.",
21+
"File '/foo/node_modules/xyz.d.ts' does not exist.",
22+
"File '/foo/node_modules/xyz/package.json' does not exist.",
23+
"File '/foo/node_modules/xyz/index.ts' does not exist.",
24+
"File '/foo/node_modules/xyz/index.tsx' does not exist.",
25+
"File '/foo/node_modules/xyz/index.d.ts' does not exist.",
26+
"File '/foo/node_modules/@types/xyz.ts' does not exist.",
27+
"File '/foo/node_modules/@types/xyz.tsx' does not exist.",
28+
"File '/foo/node_modules/@types/xyz.d.ts' does not exist.",
29+
"File '/foo/node_modules/@types/xyz/package.json' does not exist.",
30+
"File '/foo/node_modules/@types/xyz/index.ts' does not exist.",
31+
"File '/foo/node_modules/@types/xyz/index.tsx' does not exist.",
32+
"File '/foo/node_modules/@types/xyz/index.d.ts' does not exist.",
33+
"File '/node_modules/xyz.ts' does not exist.",
34+
"File '/node_modules/xyz.tsx' does not exist.",
35+
"File '/node_modules/xyz.d.ts' does not exist.",
36+
"File '/node_modules/xyz/package.json' does not exist.",
37+
"File '/node_modules/xyz/index.ts' does not exist.",
38+
"File '/node_modules/xyz/index.tsx' does not exist.",
39+
"File '/node_modules/xyz/index.d.ts' does not exist.",
40+
"File '/node_modules/@types/xyz.ts' does not exist.",
41+
"File '/node_modules/@types/xyz.tsx' does not exist.",
42+
"File '/node_modules/@types/xyz.d.ts' does not exist.",
43+
"File '/node_modules/@types/xyz/package.json' does not exist.",
44+
"File '/node_modules/@types/xyz/index.ts' does not exist.",
45+
"File '/node_modules/@types/xyz/index.tsx' does not exist.",
46+
"File '/node_modules/@types/xyz/index.d.ts' does not exist.",
47+
"======== Module name 'xyz' was not resolved. ========",
48+
"======== Resolving module 'pdq' from '/foo/bar/a.ts'. ========",
49+
"Module resolution kind is not specified, using 'NodeJs'.",
50+
"Loading module 'pdq' from 'node_modules' folder.",
51+
"File '/foo/bar/node_modules/pdq.ts' does not exist.",
52+
"File '/foo/bar/node_modules/pdq.tsx' does not exist.",
53+
"File '/foo/bar/node_modules/pdq.d.ts' does not exist.",
54+
"File '/foo/bar/node_modules/pdq/package.json' does not exist.",
55+
"File '/foo/bar/node_modules/pdq/index.ts' does not exist.",
56+
"File '/foo/bar/node_modules/pdq/index.tsx' does not exist.",
57+
"File '/foo/bar/node_modules/pdq/index.d.ts' does not exist.",
58+
"File '/foo/bar/node_modules/@types/pdq.ts' does not exist.",
59+
"File '/foo/bar/node_modules/@types/pdq.tsx' does not exist.",
60+
"File '/foo/bar/node_modules/@types/pdq.d.ts' does not exist.",
61+
"File '/foo/bar/node_modules/@types/pdq/package.json' does not exist.",
62+
"File '/foo/bar/node_modules/@types/pdq/index.ts' does not exist.",
63+
"File '/foo/bar/node_modules/@types/pdq/index.tsx' does not exist.",
64+
"File '/foo/bar/node_modules/@types/pdq/index.d.ts' does not exist.",
65+
"File '/foo/node_modules/pdq.ts' does not exist.",
66+
"File '/foo/node_modules/pdq.tsx' does not exist.",
67+
"File '/foo/node_modules/pdq.d.ts' does not exist.",
68+
"File '/foo/node_modules/pdq/package.json' does not exist.",
69+
"File '/foo/node_modules/pdq/index.ts' does not exist.",
70+
"File '/foo/node_modules/pdq/index.tsx' does not exist.",
71+
"File '/foo/node_modules/pdq/index.d.ts' does not exist.",
72+
"File '/foo/node_modules/@types/pdq.ts' does not exist.",
73+
"File '/foo/node_modules/@types/pdq.tsx' does not exist.",
74+
"File '/foo/node_modules/@types/pdq.d.ts' does not exist.",
75+
"File '/foo/node_modules/@types/pdq/package.json' does not exist.",
76+
"File '/foo/node_modules/@types/pdq/index.ts' does not exist.",
77+
"File '/foo/node_modules/@types/pdq/index.tsx' does not exist.",
78+
"File '/foo/node_modules/@types/pdq/index.d.ts' does not exist.",
79+
"File '/node_modules/pdq.ts' does not exist.",
80+
"File '/node_modules/pdq.tsx' does not exist.",
81+
"File '/node_modules/pdq.d.ts' does not exist.",
82+
"File '/node_modules/pdq/package.json' does not exist.",
83+
"File '/node_modules/pdq/index.ts' does not exist.",
84+
"File '/node_modules/pdq/index.tsx' does not exist.",
85+
"File '/node_modules/pdq/index.d.ts' does not exist.",
86+
"File '/node_modules/@types/pdq.ts' does not exist.",
87+
"File '/node_modules/@types/pdq.tsx' does not exist.",
88+
"File '/node_modules/@types/pdq.d.ts' does not exist.",
89+
"File '/node_modules/@types/pdq/package.json' does not exist.",
90+
"File '/node_modules/@types/pdq/index.ts' does not exist.",
91+
"File '/node_modules/@types/pdq/index.tsx' does not exist.",
92+
"File '/node_modules/@types/pdq/index.d.ts' does not exist.",
93+
"======== Module name 'pdq' was not resolved. ========",
94+
"======== Resolving module 'abc' from '/foo/bar/a.ts'. ========",
95+
"Module resolution kind is not specified, using 'NodeJs'.",
96+
"Loading module 'abc' from 'node_modules' folder.",
97+
"File '/foo/bar/node_modules/abc.ts' does not exist.",
98+
"File '/foo/bar/node_modules/abc.tsx' does not exist.",
99+
"File '/foo/bar/node_modules/abc.d.ts' does not exist.",
100+
"File '/foo/bar/node_modules/abc/package.json' does not exist.",
101+
"File '/foo/bar/node_modules/abc/index.ts' does not exist.",
102+
"File '/foo/bar/node_modules/abc/index.tsx' does not exist.",
103+
"File '/foo/bar/node_modules/abc/index.d.ts' does not exist.",
104+
"File '/foo/bar/node_modules/@types/abc.ts' does not exist.",
105+
"File '/foo/bar/node_modules/@types/abc.tsx' does not exist.",
106+
"File '/foo/bar/node_modules/@types/abc.d.ts' does not exist.",
107+
"File '/foo/bar/node_modules/@types/abc/package.json' does not exist.",
108+
"File '/foo/bar/node_modules/@types/abc/index.ts' does not exist.",
109+
"File '/foo/bar/node_modules/@types/abc/index.tsx' does not exist.",
110+
"File '/foo/bar/node_modules/@types/abc/index.d.ts' does not exist.",
111+
"File '/foo/node_modules/abc.ts' does not exist.",
112+
"File '/foo/node_modules/abc.tsx' does not exist.",
113+
"File '/foo/node_modules/abc.d.ts' does not exist.",
114+
"File '/foo/node_modules/abc/package.json' does not exist.",
115+
"File '/foo/node_modules/abc/index.ts' does not exist.",
116+
"File '/foo/node_modules/abc/index.tsx' does not exist.",
117+
"File '/foo/node_modules/abc/index.d.ts' does not exist.",
118+
"File '/foo/node_modules/@types/abc.ts' does not exist.",
119+
"File '/foo/node_modules/@types/abc.tsx' does not exist.",
120+
"File '/foo/node_modules/@types/abc.d.ts' does not exist.",
121+
"File '/foo/node_modules/@types/abc/package.json' does not exist.",
122+
"File '/foo/node_modules/@types/abc/index.ts' does not exist.",
123+
"File '/foo/node_modules/@types/abc/index.tsx' does not exist.",
124+
"File '/foo/node_modules/@types/abc/index.d.ts' does not exist.",
125+
"File '/node_modules/abc.ts' does not exist.",
126+
"File '/node_modules/abc.tsx' does not exist.",
127+
"File '/node_modules/abc.d.ts' does not exist.",
128+
"File '/node_modules/abc/package.json' does not exist.",
129+
"File '/node_modules/abc/index.ts' does not exist.",
130+
"File '/node_modules/abc/index.tsx' does not exist.",
131+
"File '/node_modules/abc/index.d.ts' does not exist.",
132+
"File '/node_modules/@types/abc.ts' does not exist.",
133+
"File '/node_modules/@types/abc.tsx' does not exist.",
134+
"File '/node_modules/@types/abc.d.ts' does not exist.",
135+
"File '/node_modules/@types/abc/package.json' does not exist.",
136+
"File '/node_modules/@types/abc/index.ts' does not exist.",
137+
"File '/node_modules/@types/abc/index.tsx' does not exist.",
138+
"File '/node_modules/@types/abc/index.d.ts' does not exist.",
139+
"======== Module name 'abc' was not resolved. ========",
140+
"======== Resolving type reference directive 'grumpy', containing file '/src/__inferred type names__.ts', root directory '/foo/node_modules/@types,/node_modules/@types'. ========",
141+
"Resolving with primary search path '/foo/node_modules/@types, /node_modules/@types'",
142+
"File '/foo/node_modules/@types/grumpy/package.json' does not exist.",
143+
"File '/foo/node_modules/@types/grumpy/index.d.ts' exist - use it as a name resolution result.",
144+
"======== Type reference directive 'grumpy' was successfully resolved to '/foo/node_modules/@types/grumpy/index.d.ts', primary: true. ========",
145+
"======== Resolving type reference directive 'sneezy', containing file '/src/__inferred type names__.ts', root directory '/foo/node_modules/@types,/node_modules/@types'. ========",
146+
"Resolving with primary search path '/foo/node_modules/@types, /node_modules/@types'",
147+
"File '/foo/node_modules/@types/sneezy/package.json' does not exist.",
148+
"File '/foo/node_modules/@types/sneezy/index.d.ts' exist - use it as a name resolution result.",
149+
"======== Type reference directive 'sneezy' was successfully resolved to '/foo/node_modules/@types/sneezy/index.d.ts', primary: true. ========",
150+
"======== Resolving type reference directive 'dopey', containing file '/src/__inferred type names__.ts', root directory '/foo/node_modules/@types,/node_modules/@types'. ========",
151+
"Resolving with primary search path '/foo/node_modules/@types, /node_modules/@types'",
152+
"File '/foo/node_modules/@types/dopey/package.json' does not exist.",
153+
"File '/foo/node_modules/@types/dopey/index.d.ts' does not exist.",
154+
"File '/node_modules/@types/dopey/package.json' does not exist.",
155+
"File '/node_modules/@types/dopey/index.d.ts' exist - use it as a name resolution result.",
156+
"======== Type reference directive 'dopey' was successfully resolved to '/node_modules/@types/dopey/index.d.ts', primary: true. ========"
157+
]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
=== /foo/bar/a.ts ===
2+
import { x } from "xyz";
3+
>x : number
4+
5+
import { y } from "pdq";
6+
>y : number
7+
8+
import { z } from "abc";
9+
>z : number
10+
11+
x + y + z;
12+
>x + y + z : number
13+
>x + y : number
14+
>x : number
15+
>y : number
16+
>z : number
17+
18+
=== /node_modules/@types/dopey/index.d.ts ===
19+
20+
declare module "xyz" {
21+
export const x: number;
22+
>x : number
23+
}
24+
25+
=== /foo/node_modules/@types/grumpy/index.d.ts ===
26+
declare module "pdq" {
27+
export const y: number;
28+
>y : number
29+
}
30+
31+
=== /foo/node_modules/@types/sneezy/index.d.ts ===
32+
declare module "abc" {
33+
export const z: number;
34+
>z : number
35+
}
36+
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;
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+

0 commit comments

Comments
 (0)