From 0e8e5ec3e5c2b97180bae83ef62ffa4646fa2e06 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 2 Sep 2016 07:06:13 -0700 Subject: [PATCH] Search up for all node_modules directories available --- src/compiler/program.ts | 30 ++-- ...RootsFromMultipleNodeModulesDirectories.js | 31 ++++ ...FromMultipleNodeModulesDirectories.symbols | 34 ++++ ...mMultipleNodeModulesDirectories.trace.json | 157 ++++++++++++++++++ ...tsFromMultipleNodeModulesDirectories.types | 36 ++++ ...RootsFromMultipleNodeModulesDirectories.ts | 27 +++ 6 files changed, 301 insertions(+), 14 deletions(-) create mode 100644 tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.js create mode 100644 tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.symbols create mode 100644 tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.trace.json create mode 100644 tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.types create mode 100644 tests/cases/compiler/typeRootsFromMultipleNodeModulesDirectories.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 7a4adf9ff08..3cddeb03f38 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -183,31 +183,33 @@ namespace ts { } function getDefaultTypeRoots(currentDirectory: string, host: ModuleResolutionHost): string[] | undefined { - const nodeModules = getNearestNodeModules(currentDirectory, host); - return nodeModules && [combinePaths(nodeModules, "@types")]; + return map(getAllNodeModulesDirectories(currentDirectory, host), nodeModules => combinePaths(nodeModules, "@types")); } - function getNearestNodeModules(currentDirectory: string, host: ModuleResolutionHost): string | undefined { + /** Returns the path to every node_modules directory from some ancestor directory. */ + function getAllNodeModulesDirectories(currentDirectory: string, host: ModuleResolutionHost): string[] | undefined { if (!host.directoryExists) { - return combinePaths(currentDirectory, "node_modules"); + return [combinePaths(currentDirectory, "node_modules")]; // And if it doesn't exist, tough. } + const all: string[] = []; + while (true) { const nodeModules = combinePaths(currentDirectory, "node_modules"); if (host.directoryExists(nodeModules)) { - return nodeModules; + all.push(nodeModules); } - else { - const parent = getDirectoryPath(currentDirectory); - if (parent === currentDirectory) { - return undefined; - } - currentDirectory = parent; - } - } - } + const parent = getDirectoryPath(currentDirectory); + if (parent === currentDirectory) { + break; + } + currentDirectory = parent; + } + + return all; + } /** * @param {string | undefined} containingFile - file that contains type reference directive, can be undefined if containing file is unknown. * This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups diff --git a/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.js b/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.js new file mode 100644 index 00000000000..a2542ca9cc0 --- /dev/null +++ b/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.js @@ -0,0 +1,31 @@ +//// [tests/cases/compiler/typeRootsFromMultipleNodeModulesDirectories.ts] //// + +//// [index.d.ts] + +declare module "xyz" { + export const x: number; +} + +//// [index.d.ts] +declare module "pdq" { + export const y: number; +} + +//// [index.d.ts] +declare module "abc" { + export const z: number; +} + +//// [a.ts] +import { x } from "xyz"; +import { y } from "pdq"; +import { z } from "abc"; +x + y + z; + + +//// [a.js] +"use strict"; +var xyz_1 = require("xyz"); +var pdq_1 = require("pdq"); +var abc_1 = require("abc"); +xyz_1.x + pdq_1.y + abc_1.z; diff --git a/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.symbols b/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.symbols new file mode 100644 index 00000000000..67fd371f8ee --- /dev/null +++ b/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.symbols @@ -0,0 +1,34 @@ +=== /foo/bar/a.ts === +import { x } from "xyz"; +>x : Symbol(x, Decl(a.ts, 0, 8)) + +import { y } from "pdq"; +>y : Symbol(y, Decl(a.ts, 1, 8)) + +import { z } from "abc"; +>z : Symbol(z, Decl(a.ts, 2, 8)) + +x + y + z; +>x : Symbol(x, Decl(a.ts, 0, 8)) +>y : Symbol(y, Decl(a.ts, 1, 8)) +>z : Symbol(z, Decl(a.ts, 2, 8)) + +=== /node_modules/@types/dopey/index.d.ts === + +declare module "xyz" { + export const x: number; +>x : Symbol(x, Decl(index.d.ts, 2, 16)) +} + +=== /foo/node_modules/@types/grumpy/index.d.ts === +declare module "pdq" { + export const y: number; +>y : Symbol(y, Decl(index.d.ts, 1, 16)) +} + +=== /foo/node_modules/@types/sneezy/index.d.ts === +declare module "abc" { + export const z: number; +>z : Symbol(z, Decl(index.d.ts, 1, 16)) +} + diff --git a/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.trace.json b/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.trace.json new file mode 100644 index 00000000000..c734e57cda2 --- /dev/null +++ b/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.trace.json @@ -0,0 +1,157 @@ +[ + "======== Resolving module 'xyz' from '/foo/bar/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'xyz' from 'node_modules' folder.", + "File '/foo/bar/node_modules/xyz.ts' does not exist.", + "File '/foo/bar/node_modules/xyz.tsx' does not exist.", + "File '/foo/bar/node_modules/xyz.d.ts' does not exist.", + "File '/foo/bar/node_modules/xyz/package.json' does not exist.", + "File '/foo/bar/node_modules/xyz/index.ts' does not exist.", + "File '/foo/bar/node_modules/xyz/index.tsx' does not exist.", + "File '/foo/bar/node_modules/xyz/index.d.ts' does not exist.", + "File '/foo/bar/node_modules/@types/xyz.ts' does not exist.", + "File '/foo/bar/node_modules/@types/xyz.tsx' does not exist.", + "File '/foo/bar/node_modules/@types/xyz.d.ts' does not exist.", + "File '/foo/bar/node_modules/@types/xyz/package.json' does not exist.", + "File '/foo/bar/node_modules/@types/xyz/index.ts' does not exist.", + "File '/foo/bar/node_modules/@types/xyz/index.tsx' does not exist.", + "File '/foo/bar/node_modules/@types/xyz/index.d.ts' does not exist.", + "File '/foo/node_modules/xyz.ts' does not exist.", + "File '/foo/node_modules/xyz.tsx' does not exist.", + "File '/foo/node_modules/xyz.d.ts' does not exist.", + "File '/foo/node_modules/xyz/package.json' does not exist.", + "File '/foo/node_modules/xyz/index.ts' does not exist.", + "File '/foo/node_modules/xyz/index.tsx' does not exist.", + "File '/foo/node_modules/xyz/index.d.ts' does not exist.", + "File '/foo/node_modules/@types/xyz.ts' does not exist.", + "File '/foo/node_modules/@types/xyz.tsx' does not exist.", + "File '/foo/node_modules/@types/xyz.d.ts' does not exist.", + "File '/foo/node_modules/@types/xyz/package.json' does not exist.", + "File '/foo/node_modules/@types/xyz/index.ts' does not exist.", + "File '/foo/node_modules/@types/xyz/index.tsx' does not exist.", + "File '/foo/node_modules/@types/xyz/index.d.ts' does not exist.", + "File '/node_modules/xyz.ts' does not exist.", + "File '/node_modules/xyz.tsx' does not exist.", + "File '/node_modules/xyz.d.ts' does not exist.", + "File '/node_modules/xyz/package.json' does not exist.", + "File '/node_modules/xyz/index.ts' does not exist.", + "File '/node_modules/xyz/index.tsx' does not exist.", + "File '/node_modules/xyz/index.d.ts' does not exist.", + "File '/node_modules/@types/xyz.ts' does not exist.", + "File '/node_modules/@types/xyz.tsx' does not exist.", + "File '/node_modules/@types/xyz.d.ts' does not exist.", + "File '/node_modules/@types/xyz/package.json' does not exist.", + "File '/node_modules/@types/xyz/index.ts' does not exist.", + "File '/node_modules/@types/xyz/index.tsx' does not exist.", + "File '/node_modules/@types/xyz/index.d.ts' does not exist.", + "======== Module name 'xyz' was not resolved. ========", + "======== Resolving module 'pdq' from '/foo/bar/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'pdq' from 'node_modules' folder.", + "File '/foo/bar/node_modules/pdq.ts' does not exist.", + "File '/foo/bar/node_modules/pdq.tsx' does not exist.", + "File '/foo/bar/node_modules/pdq.d.ts' does not exist.", + "File '/foo/bar/node_modules/pdq/package.json' does not exist.", + "File '/foo/bar/node_modules/pdq/index.ts' does not exist.", + "File '/foo/bar/node_modules/pdq/index.tsx' does not exist.", + "File '/foo/bar/node_modules/pdq/index.d.ts' does not exist.", + "File '/foo/bar/node_modules/@types/pdq.ts' does not exist.", + "File '/foo/bar/node_modules/@types/pdq.tsx' does not exist.", + "File '/foo/bar/node_modules/@types/pdq.d.ts' does not exist.", + "File '/foo/bar/node_modules/@types/pdq/package.json' does not exist.", + "File '/foo/bar/node_modules/@types/pdq/index.ts' does not exist.", + "File '/foo/bar/node_modules/@types/pdq/index.tsx' does not exist.", + "File '/foo/bar/node_modules/@types/pdq/index.d.ts' does not exist.", + "File '/foo/node_modules/pdq.ts' does not exist.", + "File '/foo/node_modules/pdq.tsx' does not exist.", + "File '/foo/node_modules/pdq.d.ts' does not exist.", + "File '/foo/node_modules/pdq/package.json' does not exist.", + "File '/foo/node_modules/pdq/index.ts' does not exist.", + "File '/foo/node_modules/pdq/index.tsx' does not exist.", + "File '/foo/node_modules/pdq/index.d.ts' does not exist.", + "File '/foo/node_modules/@types/pdq.ts' does not exist.", + "File '/foo/node_modules/@types/pdq.tsx' does not exist.", + "File '/foo/node_modules/@types/pdq.d.ts' does not exist.", + "File '/foo/node_modules/@types/pdq/package.json' does not exist.", + "File '/foo/node_modules/@types/pdq/index.ts' does not exist.", + "File '/foo/node_modules/@types/pdq/index.tsx' does not exist.", + "File '/foo/node_modules/@types/pdq/index.d.ts' does not exist.", + "File '/node_modules/pdq.ts' does not exist.", + "File '/node_modules/pdq.tsx' does not exist.", + "File '/node_modules/pdq.d.ts' does not exist.", + "File '/node_modules/pdq/package.json' does not exist.", + "File '/node_modules/pdq/index.ts' does not exist.", + "File '/node_modules/pdq/index.tsx' does not exist.", + "File '/node_modules/pdq/index.d.ts' does not exist.", + "File '/node_modules/@types/pdq.ts' does not exist.", + "File '/node_modules/@types/pdq.tsx' does not exist.", + "File '/node_modules/@types/pdq.d.ts' does not exist.", + "File '/node_modules/@types/pdq/package.json' does not exist.", + "File '/node_modules/@types/pdq/index.ts' does not exist.", + "File '/node_modules/@types/pdq/index.tsx' does not exist.", + "File '/node_modules/@types/pdq/index.d.ts' does not exist.", + "======== Module name 'pdq' was not resolved. ========", + "======== Resolving module 'abc' from '/foo/bar/a.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'abc' from 'node_modules' folder.", + "File '/foo/bar/node_modules/abc.ts' does not exist.", + "File '/foo/bar/node_modules/abc.tsx' does not exist.", + "File '/foo/bar/node_modules/abc.d.ts' does not exist.", + "File '/foo/bar/node_modules/abc/package.json' does not exist.", + "File '/foo/bar/node_modules/abc/index.ts' does not exist.", + "File '/foo/bar/node_modules/abc/index.tsx' does not exist.", + "File '/foo/bar/node_modules/abc/index.d.ts' does not exist.", + "File '/foo/bar/node_modules/@types/abc.ts' does not exist.", + "File '/foo/bar/node_modules/@types/abc.tsx' does not exist.", + "File '/foo/bar/node_modules/@types/abc.d.ts' does not exist.", + "File '/foo/bar/node_modules/@types/abc/package.json' does not exist.", + "File '/foo/bar/node_modules/@types/abc/index.ts' does not exist.", + "File '/foo/bar/node_modules/@types/abc/index.tsx' does not exist.", + "File '/foo/bar/node_modules/@types/abc/index.d.ts' does not exist.", + "File '/foo/node_modules/abc.ts' does not exist.", + "File '/foo/node_modules/abc.tsx' does not exist.", + "File '/foo/node_modules/abc.d.ts' does not exist.", + "File '/foo/node_modules/abc/package.json' does not exist.", + "File '/foo/node_modules/abc/index.ts' does not exist.", + "File '/foo/node_modules/abc/index.tsx' does not exist.", + "File '/foo/node_modules/abc/index.d.ts' does not exist.", + "File '/foo/node_modules/@types/abc.ts' does not exist.", + "File '/foo/node_modules/@types/abc.tsx' does not exist.", + "File '/foo/node_modules/@types/abc.d.ts' does not exist.", + "File '/foo/node_modules/@types/abc/package.json' does not exist.", + "File '/foo/node_modules/@types/abc/index.ts' does not exist.", + "File '/foo/node_modules/@types/abc/index.tsx' does not exist.", + "File '/foo/node_modules/@types/abc/index.d.ts' does not exist.", + "File '/node_modules/abc.ts' does not exist.", + "File '/node_modules/abc.tsx' does not exist.", + "File '/node_modules/abc.d.ts' does not exist.", + "File '/node_modules/abc/package.json' does not exist.", + "File '/node_modules/abc/index.ts' does not exist.", + "File '/node_modules/abc/index.tsx' does not exist.", + "File '/node_modules/abc/index.d.ts' does not exist.", + "File '/node_modules/@types/abc.ts' does not exist.", + "File '/node_modules/@types/abc.tsx' does not exist.", + "File '/node_modules/@types/abc.d.ts' does not exist.", + "File '/node_modules/@types/abc/package.json' does not exist.", + "File '/node_modules/@types/abc/index.ts' does not exist.", + "File '/node_modules/@types/abc/index.tsx' does not exist.", + "File '/node_modules/@types/abc/index.d.ts' does not exist.", + "======== Module name 'abc' was not resolved. ========", + "======== Resolving type reference directive 'grumpy', containing file '/src/__inferred type names__.ts', root directory '/foo/node_modules/@types,/node_modules/@types'. ========", + "Resolving with primary search path '/foo/node_modules/@types, /node_modules/@types'", + "File '/foo/node_modules/@types/grumpy/package.json' does not exist.", + "File '/foo/node_modules/@types/grumpy/index.d.ts' exist - use it as a name resolution result.", + "======== Type reference directive 'grumpy' was successfully resolved to '/foo/node_modules/@types/grumpy/index.d.ts', primary: true. ========", + "======== Resolving type reference directive 'sneezy', containing file '/src/__inferred type names__.ts', root directory '/foo/node_modules/@types,/node_modules/@types'. ========", + "Resolving with primary search path '/foo/node_modules/@types, /node_modules/@types'", + "File '/foo/node_modules/@types/sneezy/package.json' does not exist.", + "File '/foo/node_modules/@types/sneezy/index.d.ts' exist - use it as a name resolution result.", + "======== Type reference directive 'sneezy' was successfully resolved to '/foo/node_modules/@types/sneezy/index.d.ts', primary: true. ========", + "======== Resolving type reference directive 'dopey', containing file '/src/__inferred type names__.ts', root directory '/foo/node_modules/@types,/node_modules/@types'. ========", + "Resolving with primary search path '/foo/node_modules/@types, /node_modules/@types'", + "File '/foo/node_modules/@types/dopey/package.json' does not exist.", + "File '/foo/node_modules/@types/dopey/index.d.ts' does not exist.", + "File '/node_modules/@types/dopey/package.json' does not exist.", + "File '/node_modules/@types/dopey/index.d.ts' exist - use it as a name resolution result.", + "======== Type reference directive 'dopey' was successfully resolved to '/node_modules/@types/dopey/index.d.ts', primary: true. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.types b/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.types new file mode 100644 index 00000000000..c47be9cdab3 --- /dev/null +++ b/tests/baselines/reference/typeRootsFromMultipleNodeModulesDirectories.types @@ -0,0 +1,36 @@ +=== /foo/bar/a.ts === +import { x } from "xyz"; +>x : number + +import { y } from "pdq"; +>y : number + +import { z } from "abc"; +>z : number + +x + y + z; +>x + y + z : number +>x + y : number +>x : number +>y : number +>z : number + +=== /node_modules/@types/dopey/index.d.ts === + +declare module "xyz" { + export const x: number; +>x : number +} + +=== /foo/node_modules/@types/grumpy/index.d.ts === +declare module "pdq" { + export const y: number; +>y : number +} + +=== /foo/node_modules/@types/sneezy/index.d.ts === +declare module "abc" { + export const z: number; +>z : number +} + diff --git a/tests/cases/compiler/typeRootsFromMultipleNodeModulesDirectories.ts b/tests/cases/compiler/typeRootsFromMultipleNodeModulesDirectories.ts new file mode 100644 index 00000000000..b7f194706a8 --- /dev/null +++ b/tests/cases/compiler/typeRootsFromMultipleNodeModulesDirectories.ts @@ -0,0 +1,27 @@ +// @noImplicitReferences: true +// @traceResolution: true +// @currentDirectory: /src + +// @Filename: /node_modules/@types/dopey/index.d.ts +declare module "xyz" { + export const x: number; +} + +// @Filename: /foo/node_modules/@types/grumpy/index.d.ts +declare module "pdq" { + export const y: number; +} + +// @Filename: /foo/node_modules/@types/sneezy/index.d.ts +declare module "abc" { + export const z: number; +} + +// @Filename: /foo/bar/a.ts +import { x } from "xyz"; +import { y } from "pdq"; +import { z } from "abc"; +x + y + z; + +// @Filename: /foo/bar/tsconfig.json +{}