diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 85a19df7f0694..51853695d5dad 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2430,7 +2430,7 @@ namespace ts { } } - export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode | ImportCall): Expression | undefined { + export function getExternalModuleName(node: AnyImportOrReExport | ImportTypeNode | ImportCall | ModuleDeclaration): Expression | undefined { switch (node.kind) { case SyntaxKind.ImportDeclaration: case SyntaxKind.ExportDeclaration: @@ -2441,6 +2441,8 @@ namespace ts { return isLiteralImportTypeNode(node) ? node.argument.literal : undefined; case SyntaxKind.CallExpression: return node.arguments[0]; + case SyntaxKind.ModuleDeclaration: + return node.name.kind === SyntaxKind.StringLiteral ? node.name : undefined; default: return Debug.assertNever(node); } @@ -4118,11 +4120,21 @@ namespace ts { return file.moduleName || getExternalModuleNameFromPath(host, file.fileName, referenceFile && referenceFile.fileName); } + function getCanonicalAbsolutePath(host: ResolveModuleNameResolutionHost, path: string) { + return host.getCanonicalFileName(getNormalizedAbsolutePath(path, host.getCurrentDirectory())); + } + export function getExternalModuleNameFromDeclaration(host: ResolveModuleNameResolutionHost, resolver: EmitResolver, declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode): string | undefined { const file = resolver.getExternalModuleFileFromDeclaration(declaration); if (!file || file.isDeclarationFile) { return undefined; } + // If the declaration already uses a non-relative name, and is outside the common source directory, continue to use it + const specifier = getExternalModuleName(declaration); + if (specifier && isStringLiteralLike(specifier) && !pathIsRelative(specifier.text) && + getCanonicalAbsolutePath(host, file.path).indexOf(getCanonicalAbsolutePath(host, ensureTrailingDirectorySeparator(host.getCommonSourceDirectory()))) === -1) { + return undefined; + } return getResolvedExternalModuleName(host, file); } diff --git a/tests/baselines/reference/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.js b/tests/baselines/reference/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.js new file mode 100644 index 0000000000000..cf0c04350a84d --- /dev/null +++ b/tests/baselines/reference/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.js @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.ts] //// + +//// [index.ts] +export * from "./src/" +//// [index.ts] +export class B {} +//// [index.ts] +import { B } from "b"; + +export default function () { + return new B(); +} +//// [index.ts] +export * from "./src/" + + + +//// [index.d.ts] +declare module "src/index" { + import { B } from "b"; + export default function (): B; +} +declare module "index" { + export * from "src/index"; +} + + +//// [DtsFileErrors] + + +dist/index.d.ts(2,23): error TS2307: Cannot find module 'b' or its corresponding type declarations. + + +==== dist/index.d.ts (1 errors) ==== + declare module "src/index" { + import { B } from "b"; + ~~~ +!!! error TS2307: Cannot find module 'b' or its corresponding type declarations. + export default function (): B; + } + declare module "index" { + export * from "src/index"; + } + \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.symbols b/tests/baselines/reference/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.symbols new file mode 100644 index 0000000000000..baa1d95cce7a9 --- /dev/null +++ b/tests/baselines/reference/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.symbols @@ -0,0 +1,16 @@ +=== /a/index.ts === +export * from "./src/" +No type information for this code.=== /b/index.ts === +export * from "./src/" +No type information for this code.=== /b/src/index.ts === +export class B {} +>B : Symbol(B, Decl(index.ts, 0, 0)) + +=== /a/src/index.ts === +import { B } from "b"; +>B : Symbol(B, Decl(index.ts, 0, 8)) + +export default function () { + return new B(); +>B : Symbol(B, Decl(index.ts, 0, 8)) +} diff --git a/tests/baselines/reference/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.types b/tests/baselines/reference/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.types new file mode 100644 index 0000000000000..a0218c7fe7f81 --- /dev/null +++ b/tests/baselines/reference/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.types @@ -0,0 +1,17 @@ +=== /a/index.ts === +export * from "./src/" +No type information for this code.=== /b/index.ts === +export * from "./src/" +No type information for this code.=== /b/src/index.ts === +export class B {} +>B : B + +=== /a/src/index.ts === +import { B } from "b"; +>B : typeof B + +export default function () { + return new B(); +>new B() : B +>B : typeof B +} diff --git a/tests/cases/compiler/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.ts b/tests/cases/compiler/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.ts new file mode 100644 index 0000000000000..17ccd6bdd7440 --- /dev/null +++ b/tests/cases/compiler/declarationEmitCommonSourceDirectoryDoesNotContainAllFiles.ts @@ -0,0 +1,18 @@ +// @declaration: true +// @emitDeclarationOnly: true +// @outFile: dist/index.d.ts +// @currentDirectory: /a +// @noImplicitReferences: true +// @filename: /b/index.ts +export * from "./src/" +// @filename: /b/src/index.ts +export class B {} +// @filename: /a/src/index.ts +import { B } from "b"; + +export default function () { + return new B(); +} +// @filename: /a/index.ts +export * from "./src/" +// @link: /b -> /a/node_modules/b \ No newline at end of file