diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2e48c4ca1bc..f788e8a78d6 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3908,6 +3908,7 @@ namespace ts { const typeParameterNodes = overrideTypeArguments || lookupTypeParameterNodes(chain, 0, context); const specifier = getSpecifierForModuleSymbol(chain[0], context); const lit = createLiteralTypeNode(createLiteral(specifier)); + if (context.tracker.trackExternalModuleSymbolOfImportTypeNode) context.tracker.trackExternalModuleSymbolOfImportTypeNode(chain[0]); context.approximateLength += specifier.length + 10; // specifier + import("") if (!nonRootParts || isEntityName(nonRootParts)) { if (nonRootParts) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e0bc826f66c..b2b52d11ffd 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -113,6 +113,7 @@ namespace ts { let bundleInfo: BundleInfo = createDefaultBundleInfo(); let emitSkipped = false; + let exportedModulesFromDeclarationEmit: ExportedModulesFromDeclarationEmit | undefined; // Emit each output file performance.mark("beforePrint"); @@ -125,6 +126,7 @@ namespace ts { diagnostics: emitterDiagnostics.getDiagnostics(), emittedFiles: emittedFilesList, sourceMaps: sourceMapDataList, + exportedModulesFromDeclarationEmit }; function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath, declarationMapPath, bundleInfoPath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { @@ -222,6 +224,11 @@ namespace ts { if (!declBlocked || emitOnlyDtsFiles) { Debug.assert(declarationTransform.transformed.length === 1, "Should only see one output from the decl transform"); printSourceFileOrBundle(declarationFilePath, declarationMapPath, declarationTransform.transformed[0], /* bundleInfopath*/ undefined, declarationPrinter, declarationSourceMap); + if (emitOnlyDtsFiles && declarationTransform.transformed[0].kind === SyntaxKind.SourceFile) { + const sourceFile = declarationTransform.transformed[0] as SourceFile; + exportedModulesFromDeclarationEmit = sourceFile.getExportedModulesFromDeclarationEmit && + sourceFile.getExportedModulesFromDeclarationEmit(); + } } declarationTransform.dispose(); } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index dcfc50dd007..700dac68d2b 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -37,6 +37,8 @@ namespace ts { let lateMarkedStatements: LateVisibilityPaintedStatement[] | undefined; let lateStatementReplacementMap: Map>; let suppressNewDiagnosticContexts: boolean; + let exportedModuleSpecifiers: StringLiteralLike[] | undefined; + let exportedModuleSymbolsUsingImportTypeNodes: Symbol[] | undefined; const host = context.getEmitHost(); const symbolTracker: SymbolTracker = { @@ -46,6 +48,7 @@ namespace ts { reportPrivateInBaseOfClassExpression, moduleResolverHost: host, trackReferencedAmbientModule, + trackExternalModuleSymbolOfImportTypeNode }; let errorNameNode: DeclarationName | undefined; @@ -115,6 +118,12 @@ namespace ts { } } + function trackExternalModuleSymbolOfImportTypeNode(symbol: Symbol) { + if (!isBundledEmit) { + (exportedModuleSymbolsUsingImportTypeNodes || (exportedModuleSymbolsUsingImportTypeNodes = [])).push(symbol); + } + } + function trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) { if (symbol.flags & SymbolFlags.TypeParameter) return; handleSymbolAccessibilityError(resolver.isSymbolAccessible(symbol, enclosingDeclaration, meaning, /*shouldComputeAliasesToMakeVisible*/ true)); @@ -224,6 +233,12 @@ namespace ts { combinedStatements = setTextRange(createNodeArray([...combinedStatements, createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([]), /*moduleSpecifier*/ undefined)]), combinedStatements); } const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib); + if (exportedModuleSpecifiers || exportedModuleSymbolsUsingImportTypeNodes) { + updated.getExportedModulesFromDeclarationEmit = () => ({ + exportedModuleSpecifiers: exportedModuleSpecifiers || emptyArray, + exportedModuleSymbolsUsingImportTypeNodes: exportedModuleSymbolsUsingImportTypeNodes || emptyArray + }); + } return updated; function getFileReferencesForUsedTypeReferences() { @@ -483,10 +498,15 @@ namespace ts { function rewriteModuleSpecifier(parent: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration | ImportTypeNode, input: T | undefined): T | StringLiteral { if (!input) return undefined!; // TODO: GH#18217 resultHasExternalModuleIndicator = resultHasExternalModuleIndicator || (parent.kind !== SyntaxKind.ModuleDeclaration && parent.kind !== SyntaxKind.ImportType); - if (input.kind === SyntaxKind.StringLiteral && isBundledEmit) { - const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent); - if (newName) { - return createLiteral(newName); + if (isStringLiteralLike(input)) { + if (isBundledEmit) { + const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent); + if (newName) { + return createLiteral(newName); + } + } + else { + (exportedModuleSpecifiers || (exportedModuleSpecifiers = [])).push(input); } } return input; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e1f347282b9..79d0f91b0fb 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2624,6 +2624,14 @@ namespace ts { /* @internal */ pragmas: PragmaMap; /* @internal */ localJsxNamespace?: __String; /* @internal */ localJsxFactory?: EntityName; + + /*@internal*/ getExportedModulesFromDeclarationEmit?(): ExportedModulesFromDeclarationEmit; + } + + /*@internal*/ + export interface ExportedModulesFromDeclarationEmit { + exportedModuleSpecifiers: ReadonlyArray; + exportedModuleSymbolsUsingImportTypeNodes: ReadonlyArray; } export interface Bundle extends Node { @@ -2866,6 +2874,7 @@ namespace ts { diagnostics: ReadonlyArray; emittedFiles?: string[]; // Array of files the compiler wrote to disk /* @internal */ sourceMaps?: SourceMapData[]; // Array of sourceMapData if compiler emitted sourcemaps + /* @internal */ exportedModulesFromDeclarationEmit?: ExportedModulesFromDeclarationEmit; } /* @internal */ @@ -5324,6 +5333,7 @@ namespace ts { reportInaccessibleUniqueSymbolError?(): void; moduleResolverHost?: ModuleSpecifierResolutionHost; trackReferencedAmbientModule?(decl: ModuleDeclaration, symbol: Symbol): void; + trackExternalModuleSymbolOfImportTypeNode?(symbol: Symbol): void; } export interface TextSpan {