diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2df1a58387607..b82784de71d50 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4085,7 +4085,7 @@ namespace ts { // ambient module, just use declaration/symbol name (fallthrough) } else { - return `"${getResolvedExternalModuleName(context!.tracker.moduleResolverHost!, file, getSourceFileOfNode(getOriginalNode(context!.enclosingDeclaration)))}"`; + return `"${getResolvedExternalModuleNameForPossiblyExternalModule(context!.tracker.moduleResolverHost!, file, getSourceFileOfNode(getOriginalNode(context!.enclosingDeclaration)))}"`; } } const declaration = symbol.declarations[0]; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 3a19762f0a996..40ee1c5c9d8c0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5287,6 +5287,7 @@ namespace ts { getCanonicalFileName(f: string): string; getCommonSourceDirectory(): string; getCurrentDirectory(): string; + getCompilerOptions(): CompilerOptions; } /** @deprecated See comment on SymbolWriter */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 753ab32321de1..21248a1e26805 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2934,6 +2934,31 @@ namespace ts { }; } + /** @internal */ + export function getResolvedExternalModuleNameForPossiblyExternalModule(host: ModuleNameResolverHost, file: SourceFile, referenceFile?: SourceFile) { + const result = getResolvedExternalModuleName(host, file, referenceFile); + const opts = host.getCompilerOptions(); + if (getEmitModuleResolutionKind(opts) === ModuleResolutionKind.NodeJs) { + // Trim leading paths to `node_modules` to allow node module resolution to find the thing in the future without an exact path + // This simplification means if a package.json for `foo` directs us to `foo/lib/main` instead of `foo/index` we'll write `foo/lib/main` over `foo`, however + const parts = getPathComponents(result); + if (parts[0] !== "") { + return result; // rooted path, leave as is + } + else { + parts.shift(); + } + let index = 0; + while (parts[index] && (parts[index] === "." || parts[index] === "..")) { + index++; + } + if (parts[index] && parts[index] === "node_modules") { + return parts.slice(index + 1).join(directorySeparator); + } + } + return result; + } + export function getResolvedExternalModuleName(host: ModuleNameResolverHost, file: SourceFile, referenceFile?: SourceFile): string { return file.moduleName || getExternalModuleNameFromPath(host, file.fileName, referenceFile && referenceFile.fileName); } diff --git a/tests/baselines/reference/declarationEmitCommonJsModuleReferencedType.js b/tests/baselines/reference/declarationEmitCommonJsModuleReferencedType.js new file mode 100644 index 0000000000000..998eb27133877 --- /dev/null +++ b/tests/baselines/reference/declarationEmitCommonJsModuleReferencedType.js @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/declarationEmitCommonJsModuleReferencedType.ts] //// + +//// [index.d.ts] +export interface NestedProps {} +//// [index.d.ts] +export interface OtherIndexProps {} +//// [other.d.ts] +export interface OtherProps {} +//// [index.d.ts] +import { OtherProps } from "./other"; +import { OtherIndexProps } from "./other/index"; +import { NestedProps } from "nested"; +export interface SomeProps {} + +export function foo(): [SomeProps, OtherProps, OtherIndexProps, NestedProps]; +//// [index.d.ts] +export interface RootProps {} + +export function bar(): RootProps; +//// [entry.ts] +import { foo } from "foo"; +import { bar } from "root"; +export const x = foo(); +export const y = bar(); + + +//// [entry.js] +"use strict"; +exports.__esModule = true; +var foo_1 = require("foo"); +var root_1 = require("root"); +exports.x = foo_1.foo(); +exports.y = root_1.bar(); + + +//// [entry.d.ts] +export declare const x: [import("foo/index").SomeProps, import("foo/other").OtherProps, import("foo/other/index").OtherIndexProps, import("foo/node_modules/nested/index").NestedProps]; +export declare const y: import("root/index").RootProps; diff --git a/tests/baselines/reference/declarationEmitCommonJsModuleReferencedType.symbols b/tests/baselines/reference/declarationEmitCommonJsModuleReferencedType.symbols new file mode 100644 index 0000000000000..c9c0f98baeef2 --- /dev/null +++ b/tests/baselines/reference/declarationEmitCommonJsModuleReferencedType.symbols @@ -0,0 +1,55 @@ +=== tests/cases/compiler/r/node_modules/foo/node_modules/nested/index.d.ts === +export interface NestedProps {} +>NestedProps : Symbol(NestedProps, Decl(index.d.ts, 0, 0)) + +=== tests/cases/compiler/r/node_modules/foo/other/index.d.ts === +export interface OtherIndexProps {} +>OtherIndexProps : Symbol(OtherIndexProps, Decl(index.d.ts, 0, 0)) + +=== tests/cases/compiler/r/node_modules/foo/other.d.ts === +export interface OtherProps {} +>OtherProps : Symbol(OtherProps, Decl(other.d.ts, 0, 0)) + +=== tests/cases/compiler/r/node_modules/foo/index.d.ts === +import { OtherProps } from "./other"; +>OtherProps : Symbol(OtherProps, Decl(index.d.ts, 0, 8)) + +import { OtherIndexProps } from "./other/index"; +>OtherIndexProps : Symbol(OtherIndexProps, Decl(index.d.ts, 1, 8)) + +import { NestedProps } from "nested"; +>NestedProps : Symbol(NestedProps, Decl(index.d.ts, 2, 8)) + +export interface SomeProps {} +>SomeProps : Symbol(SomeProps, Decl(index.d.ts, 2, 37)) + +export function foo(): [SomeProps, OtherProps, OtherIndexProps, NestedProps]; +>foo : Symbol(foo, Decl(index.d.ts, 3, 29)) +>SomeProps : Symbol(SomeProps, Decl(index.d.ts, 2, 37)) +>OtherProps : Symbol(OtherProps, Decl(index.d.ts, 0, 8)) +>OtherIndexProps : Symbol(OtherIndexProps, Decl(index.d.ts, 1, 8)) +>NestedProps : Symbol(NestedProps, Decl(index.d.ts, 2, 8)) + +=== tests/cases/compiler/node_modules/root/index.d.ts === +export interface RootProps {} +>RootProps : Symbol(RootProps, Decl(index.d.ts, 0, 0)) + +export function bar(): RootProps; +>bar : Symbol(bar, Decl(index.d.ts, 0, 29)) +>RootProps : Symbol(RootProps, Decl(index.d.ts, 0, 0)) + +=== tests/cases/compiler/r/entry.ts === +import { foo } from "foo"; +>foo : Symbol(foo, Decl(entry.ts, 0, 8)) + +import { bar } from "root"; +>bar : Symbol(bar, Decl(entry.ts, 1, 8)) + +export const x = foo(); +>x : Symbol(x, Decl(entry.ts, 2, 12)) +>foo : Symbol(foo, Decl(entry.ts, 0, 8)) + +export const y = bar(); +>y : Symbol(y, Decl(entry.ts, 3, 12)) +>bar : Symbol(bar, Decl(entry.ts, 1, 8)) + diff --git a/tests/baselines/reference/declarationEmitCommonJsModuleReferencedType.types b/tests/baselines/reference/declarationEmitCommonJsModuleReferencedType.types new file mode 100644 index 0000000000000..77c252679da0d --- /dev/null +++ b/tests/baselines/reference/declarationEmitCommonJsModuleReferencedType.types @@ -0,0 +1,57 @@ +=== tests/cases/compiler/r/node_modules/foo/node_modules/nested/index.d.ts === +export interface NestedProps {} +>NestedProps : NestedProps + +=== tests/cases/compiler/r/node_modules/foo/other/index.d.ts === +export interface OtherIndexProps {} +>OtherIndexProps : OtherIndexProps + +=== tests/cases/compiler/r/node_modules/foo/other.d.ts === +export interface OtherProps {} +>OtherProps : OtherProps + +=== tests/cases/compiler/r/node_modules/foo/index.d.ts === +import { OtherProps } from "./other"; +>OtherProps : any + +import { OtherIndexProps } from "./other/index"; +>OtherIndexProps : any + +import { NestedProps } from "nested"; +>NestedProps : any + +export interface SomeProps {} +>SomeProps : SomeProps + +export function foo(): [SomeProps, OtherProps, OtherIndexProps, NestedProps]; +>foo : () => [SomeProps, OtherProps, OtherIndexProps, NestedProps] +>SomeProps : SomeProps +>OtherProps : OtherProps +>OtherIndexProps : OtherIndexProps +>NestedProps : NestedProps + +=== tests/cases/compiler/node_modules/root/index.d.ts === +export interface RootProps {} +>RootProps : RootProps + +export function bar(): RootProps; +>bar : () => RootProps +>RootProps : RootProps + +=== tests/cases/compiler/r/entry.ts === +import { foo } from "foo"; +>foo : () => [import("tests/cases/compiler/r/node_modules/foo/index").SomeProps, import("tests/cases/compiler/r/node_modules/foo/other").OtherProps, import("tests/cases/compiler/r/node_modules/foo/other/index").OtherIndexProps, import("tests/cases/compiler/r/node_modules/foo/node_modules/nested/index").NestedProps] + +import { bar } from "root"; +>bar : () => import("tests/cases/compiler/node_modules/root/index").RootProps + +export const x = foo(); +>x : [import("tests/cases/compiler/r/node_modules/foo/index").SomeProps, import("tests/cases/compiler/r/node_modules/foo/other").OtherProps, import("tests/cases/compiler/r/node_modules/foo/other/index").OtherIndexProps, import("tests/cases/compiler/r/node_modules/foo/node_modules/nested/index").NestedProps] +>foo() : [import("tests/cases/compiler/r/node_modules/foo/index").SomeProps, import("tests/cases/compiler/r/node_modules/foo/other").OtherProps, import("tests/cases/compiler/r/node_modules/foo/other/index").OtherIndexProps, import("tests/cases/compiler/r/node_modules/foo/node_modules/nested/index").NestedProps] +>foo : () => [import("tests/cases/compiler/r/node_modules/foo/index").SomeProps, import("tests/cases/compiler/r/node_modules/foo/other").OtherProps, import("tests/cases/compiler/r/node_modules/foo/other/index").OtherIndexProps, import("tests/cases/compiler/r/node_modules/foo/node_modules/nested/index").NestedProps] + +export const y = bar(); +>y : import("tests/cases/compiler/node_modules/root/index").RootProps +>bar() : import("tests/cases/compiler/node_modules/root/index").RootProps +>bar : () => import("tests/cases/compiler/node_modules/root/index").RootProps + diff --git a/tests/baselines/reference/importShouldNotBeElidedInDeclarationEmit.js b/tests/baselines/reference/importShouldNotBeElidedInDeclarationEmit.js index bb453e398b28b..65da71910619c 100644 --- a/tests/baselines/reference/importShouldNotBeElidedInDeclarationEmit.js +++ b/tests/baselines/reference/importShouldNotBeElidedInDeclarationEmit.js @@ -21,4 +21,4 @@ exports.thing = umd_1.makeThing(); //// [index.d.ts] -export declare const thing: import("./node_modules/umd").Thing; +export declare const thing: import("umd").Thing; diff --git a/tests/cases/compiler/declarationEmitCommonJsModuleReferencedType.ts b/tests/cases/compiler/declarationEmitCommonJsModuleReferencedType.ts new file mode 100644 index 0000000000000..5207d655037fd --- /dev/null +++ b/tests/cases/compiler/declarationEmitCommonJsModuleReferencedType.ts @@ -0,0 +1,23 @@ +// @declaration: true +// @filename: r/node_modules/foo/node_modules/nested/index.d.ts +export interface NestedProps {} +// @filename: r/node_modules/foo/other/index.d.ts +export interface OtherIndexProps {} +// @filename: r/node_modules/foo/other.d.ts +export interface OtherProps {} +// @filename: r/node_modules/foo/index.d.ts +import { OtherProps } from "./other"; +import { OtherIndexProps } from "./other/index"; +import { NestedProps } from "nested"; +export interface SomeProps {} + +export function foo(): [SomeProps, OtherProps, OtherIndexProps, NestedProps]; +// @filename: node_modules/root/index.d.ts +export interface RootProps {} + +export function bar(): RootProps; +// @filename: r/entry.ts +import { foo } from "foo"; +import { bar } from "root"; +export const x = foo(); +export const y = bar();