From 2399551afc7757293d4fa4c0e2c4ad46d762e8bd Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 22 Jun 2022 16:02:46 -0700 Subject: [PATCH 1/3] Heavy WIP --- src/compiler/checker.ts | 33 +-- src/compiler/transformer.ts | 1 + .../declarations/coalesceImports.ts | 211 ++++++++++++++++++ src/compiler/tsconfig.json | 1 + src/compiler/types.ts | 2 +- 5 files changed, 233 insertions(+), 15 deletions(-) create mode 100644 src/compiler/transformers/declarations/coalesceImports.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a53c1841b6ef4..16790ddf5978b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4644,24 +4644,29 @@ namespace ts { } } - function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult { + function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node, overrideMeaning?: SymbolFlags): SymbolVisibilityResult { // get symbol of the first identifier of the entityName let meaning: SymbolFlags; - if (entityName.parent.kind === SyntaxKind.TypeQuery || - entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) || - entityName.parent.kind === SyntaxKind.ComputedPropertyName) { - // Typeof value - meaning = SymbolFlags.Value | SymbolFlags.ExportValue; - } - else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression || - entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration) { - // Left identifier from type reference or TypeAlias - // Entity name of the import declaration - meaning = SymbolFlags.Namespace; + if (overrideMeaning) { + meaning = overrideMeaning; } else { - // Type Reference or TypeAlias entity = Identifier - meaning = SymbolFlags.Type; + if (entityName.parent.kind === SyntaxKind.TypeQuery || + entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) || + entityName.parent.kind === SyntaxKind.ComputedPropertyName) { + // Typeof value + meaning = SymbolFlags.Value | SymbolFlags.ExportValue; + } + else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression || + entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration) { + // Left identifier from type reference or TypeAlias + // Entity name of the import declaration + meaning = SymbolFlags.Namespace; + } + else { + // Type Reference or TypeAlias entity = Identifier + meaning = SymbolFlags.Type; + } } const firstIdentifier = getFirstIdentifier(entityName); diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index 12c6523839ddb..d2d4cbc0dc6f0 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -103,6 +103,7 @@ namespace ts { function getDeclarationTransformers(customTransformers?: CustomTransformers) { const transformers: TransformerFactory[] = []; transformers.push(transformDeclarations); + transformers.push(transformCoalesceImports); addRange(transformers, customTransformers && map(customTransformers.afterDeclarations, wrapDeclarationTransformerFactory)); return transformers; } diff --git a/src/compiler/transformers/declarations/coalesceImports.ts b/src/compiler/transformers/declarations/coalesceImports.ts new file mode 100644 index 0000000000000..356cebc6d257d --- /dev/null +++ b/src/compiler/transformers/declarations/coalesceImports.ts @@ -0,0 +1,211 @@ +/*@internal*/ +namespace ts { + export function transformCoalesceImports(context: TransformationContext) { + const { + factory, + getEmitResolver + } = context; + return chainBundle(context, transformSourceFile); + + type CoalesceKey = string & { __coalesceKey: void }; + + function getCoalesceKeyForAssertions(node: AssertClause | undefined): string | false { + if (node) { + if (some(node.elements, e => !isStringLiteralLike(e.value))) return false; // non-string assertion value, don't mess with it + return (map(node.elements, e => `${isIdentifier(e.name) ? idText(e.name) : e.name.text}:${(e.value as StringLiteralLike).text}`) || []).join(","); + } + return ""; + } + + function getCoalesceKeyForImport(node: ImportTypeNode | ImportDeclaration): CoalesceKey | false { + if (isImportTypeNode(node) && isLiteralTypeNode(node.argument) && isStringLiteralLike(node.argument.literal)) { + const assertionKey = getCoalesceKeyForAssertions(node.assertions?.assertClause); + if (assertionKey === false) { + return false; + } + return `${node.argument.literal.text}|${assertionKey}` as CoalesceKey; + } + if (isImportDeclaration(node) && isStringLiteralLike(node.moduleSpecifier)) { + const assertionKey = getCoalesceKeyForAssertions(node.assertClause); + if (assertionKey === false) { + return false; + } + return `${node.moduleSpecifier.text}|${assertionKey}` as CoalesceKey; + } + return false; + } + + function transformSourceFile(rootFile: SourceFile) { + if (!isExternalModule(rootFile)) { + return rootFile; + } + const memberwiseImportTypeNodesBySpecifier = createMultiMap(); + const memberwiseImportDeclarationsBySpecifier = createMultiMap(); + const namespaceImportTypeNodesBySpecifier = createMultiMap(); + const namespaceImportDeclarationsBySpecifier = createMultiMap(); + const resolver = getEmitResolver(); + visitEachChild(rootFile, collectRootImports, context); + return visitEachChild(rootFile, combineImportTypes, context); + + function collectRootImports(node: Node): VisitResult { + switch (node.kind) { + case SyntaxKind.ImportDeclaration: + Debug.assertNode(node, isImportDeclaration); + if (isStringLiteralLike(node.moduleSpecifier)) { + const set = node.importClause?.namedBindings && isNamespaceImport(node.importClause.namedBindings) ? namespaceImportDeclarationsBySpecifier : memberwiseImportDeclarationsBySpecifier; + const key = getCoalesceKeyForImport(node); + if (key !== false) { + set.add(key, node); + } + } + return visitEachChild(node, collectImports, context); + default: + return visitNode(node, collectImports); + } + } + + function collectImports(node: Node): VisitResult { + switch (node.kind) { + case SyntaxKind.ImportType: + Debug.assertNode(node, isImportTypeNode); + if (isLiteralTypeNode(node.argument) && isStringLiteralLike(node.argument.literal)) { + const set = node.qualifier ? memberwiseImportTypeNodesBySpecifier : namespaceImportTypeNodesBySpecifier; + const key = getCoalesceKeyForImport(node); + if (key !== false) { + set.add(key, node as LiteralImportTypeNode); + } + } + return visitEachChild(node, collectImports, context); + default: + return visitEachChild(node, collectImports, context); + } + } + + function updateEntityNameRoot(node: EntityName, root: EntityName): EntityName { + if (isIdentifier(node)) { + return root; + } + return factory.updateQualifiedName(node, updateEntityNameRoot(node.left, root), node.right); + } + + function getEntityNameForImportType(node: ImportTypeNode, decls: ImportDeclaration[]): EntityName { + const firstId = getFirstIdentifier(node.qualifier!); + return forEach(decls, d => { + if (idText(firstId) === "default" && d.importClause?.name) { + return updateEntityNameRoot(node.qualifier!, factory.createIdentifier(idText(d.importClause.name))); + } + const match = find((d.importClause?.namedBindings as NamedImports).elements, e => idText(e.propertyName || e.name) === idText(firstId)); + if (match) { + return updateEntityNameRoot(node.qualifier!, factory.createIdentifier(idText(match.name))); + } + }) || factory.cloneNode(node.qualifier!); + } + + function createOrUpdateImportClause(clause: ImportClause | undefined, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) { + if (!clause) { + return factory.createImportClause(/*isTypeOnly*/ true, name, namedBindings); + } + return factory.updateImportClause(clause, clause.isTypeOnly, name, namedBindings); + } + + function createOrUpdateNamedBindings(bindings: NamedImportBindings | undefined, specs: Identifier[], useLocations: Node[]) { + const specifiers = bindings && isNamedImports(bindings) ? [...bindings.elements] : []; + forEach(specs, s => { + if (find(specifiers, existing => idText(existing.propertyName || existing.name) === idText(s))) return; // skip duplicates (use a map to improve perf in degenerately large edge cases, maybe?) + const renamed = some(useLocations, n => resolver.isEntityNameVisible(s, n, SymbolFlags.All).accessibility === SymbolAccessibility.Accessible) ? factory.createUniqueName(idText(s)) : undefined; + specifiers.push(factory.createImportSpecifier(/*isTypeOnly*/ true, renamed ? s : undefined, renamed || s)); + }); + if (!bindings) { + return factory.createNamedImports(specifiers); + } + return factory.updateNamedImports(bindings as NamedImports, specifiers); + } + + function combineImportTypes(node: Node): VisitResult { + if (isSourceFile(node)) { + const newImports: ImportDeclaration[] = []; + + const newNamespaceImportsToMake = filter(arrayFrom(namespaceImportTypeNodesBySpecifier.entries()), entry => !namespaceImportDeclarationsBySpecifier.has(entry[0]) && length(entry[1]) > 1); + newNamespaceImportsToMake.forEach(([key, nodes]) => { + const newImport = factory.createImportDeclaration( + /*modifiers*/ undefined, + factory.createImportClause( + /*isTypeOnly*/ true, + /*name*/ undefined, + factory.createNamespaceImport(factory.createUniqueName("_ns")) + ), + nodes[0].argument.literal, + nodes[0].assertions?.assertClause + ); + newImports.push(newImport); + namespaceImportDeclarationsBySpecifier.set(key, [newImport]); + }); + + const newMemberwiseImportsToMake = filter(arrayFrom(memberwiseImportTypeNodesBySpecifier.entries()), entry => !memberwiseImportDeclarationsBySpecifier.has(entry[0]) && length(entry[1]) > 1); + newMemberwiseImportsToMake.forEach(([key, nodes]) => { + const importSpecifiers: ImportSpecifier[] = []; + forEach(nodes, n => { + const member = getFirstIdentifier(n.qualifier!); + // TODO: Use a map? _Usually_ this shouldn't be big enough to matter, but declaration files get big sometimes. + if (some(importSpecifiers, spec => idText(spec.propertyName || spec.name) === idText(member))) return; // already added + const renamed = some(nodes, n => resolver.isEntityNameVisible(member, n, SymbolFlags.All).accessibility === SymbolAccessibility.Accessible) ? factory.createUniqueName(idText(member)) : undefined; + const importSpec = factory.createImportSpecifier( + /*isTypeOnly*/ true, + renamed ? member : undefined, + renamed || member + ); + importSpecifiers.push(importSpec); + }); + const newImport = factory.createImportDeclaration( + /*modifiers*/ undefined, + factory.createImportClause( + /*isTypeOnly*/ false, + /*name*/ undefined, + factory.createNamedImports(importSpecifiers) + ), + nodes[0].argument.literal, + nodes[0].assertions?.assertClause + ); + newImports.push(newImport); + memberwiseImportDeclarationsBySpecifier.set(key, [newImport]); + }); + + return factory.updateSourceFile(node, setTextRange(factory.createNodeArray([...newImports, ...visitNodes(node.statements, combineImportTypes)], node.statements.hasTrailingComma), node.statements)); + } + if (isImportDeclaration(node)) { + const key = getCoalesceKeyForImport(node); + if (key !== false && memberwiseImportDeclarationsBySpecifier.has(key) && memberwiseImportDeclarationsBySpecifier.get(key)!.indexOf(node) >= 0 && memberwiseImportTypeNodesBySpecifier.has(key)) { + const requiredSpecifiers = map(memberwiseImportTypeNodesBySpecifier.get(key)!, n => getFirstIdentifier(n.qualifier!)); + const remainingSpecifiers = filter(requiredSpecifiers, s => !some(memberwiseImportDeclarationsBySpecifier.get(key)!, decl => !!(idText(s) === "default" && decl.importClause?.name) || !!(decl.importClause && decl.importClause.namedBindings && isNamedImports(decl.importClause.namedBindings) && some(decl.importClause.namedBindings.elements, elem => idText(elem.name) === idText(s))))); + if (length(remainingSpecifiers)) { + const nonDefaultSpecifiers = filter(remainingSpecifiers, spec => idText(spec) !== "default"); + return factory.updateImportDeclaration( + node, + node.modifiers, + createOrUpdateImportClause( + node.importClause, + node.importClause?.name || (length(nonDefaultSpecifiers) !== length(remainingSpecifiers) ? factory.createUniqueName("_default") : undefined), + length(nonDefaultSpecifiers) ? createOrUpdateNamedBindings(node.importClause?.namedBindings, nonDefaultSpecifiers, memberwiseImportTypeNodesBySpecifier.get(key)!) : node.importClause?.namedBindings), + node.moduleSpecifier, + node.assertClause + ); + } + } + } + if (isImportTypeNode(node)) { + const key = getCoalesceKeyForImport(node) + if (key !== false) { + const siblingTypeNodes = node.qualifier ? memberwiseImportTypeNodesBySpecifier : namespaceImportTypeNodesBySpecifier; + if (siblingTypeNodes.get(key)!.length > 1) { // only coalesce to an import statement when there are multiple statements to merge + const cache = node.qualifier ? memberwiseImportDeclarationsBySpecifier : namespaceImportDeclarationsBySpecifier; + const importDecls = cache.get(key)!; + const entityName: EntityName = !node.qualifier ? (importDecls[0].importClause!.namedBindings as NamespaceImport).name : getEntityNameForImportType(node, importDecls); + return setOriginalNode(node.isTypeOf ? factory.createTypeQueryNode(entityName) : factory.createTypeReferenceNode(entityName, visitNodes(node.typeArguments, combineImportTypes)), node); + } + } + } + return visitEachChild(node, combineImportTypes, context); + } + } + } +} diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index fccbe06558a23..b9cfae8b8d2c9 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -67,6 +67,7 @@ "transformers/module/esnextAnd2015.ts", "transformers/module/node.ts", "transformers/declarations/diagnostics.ts", + "transformers/declarations/coalesceImports.ts", "transformers/declarations.ts", "transformer.ts", "emitter.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index caaad5fb9ece0..382db85848700 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4988,7 +4988,7 @@ namespace ts { createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined; createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker): Expression; isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags | undefined, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; - isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult; + isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node, overrideMeaning?: SymbolFlags): SymbolVisibilityResult; // Returns the constant value this property access resolves to, or 'undefined' for a non-constant getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; getReferencedValueDeclaration(reference: Identifier): Declaration | undefined; From 68fdeb3c0245c3b621421b025a02465412956e86 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 29 Jun 2022 04:18:56 -0700 Subject: [PATCH 2/3] Coalesce repeated import types in declaration emit to import declarations --- src/compiler/checker.ts | 44 ++--- src/compiler/emitter.ts | 1 + src/compiler/factory/nodeFactory.ts | 14 +- .../declarations/coalesceImports.ts | 154 ++++++++++-------- src/compiler/transformers/utilities.ts | 2 +- src/compiler/types.ts | 5 +- .../declarationEmitAliasFromIndirectFile.js | 7 +- ...onEmitDefaultExportWithStaticAssignment.js | 4 +- ...rationEmitExportAliasVisibiilityMarking.js | 7 +- .../declarationEmitImportTypeCoalesceing.js | 57 +++++++ ...clarationEmitImportTypeCoalesceing.symbols | 72 ++++++++ ...declarationEmitImportTypeCoalesceing.types | 73 +++++++++ ...clarationEmitQualifiedAliasTypeArgument.js | 5 +- ...clarationEmitReexportedSymlinkReference.js | 4 +- .../exportClassExtendingIntersection.js | 4 +- ...importTypeGenericArrowTypeParenthesized.js | 9 +- .../jsDeclarationsUniqueSymbolUsage.js | 3 +- ...TypeModeDeclarationEmit1(module=node16).js | 37 ++++- ...peModeDeclarationEmit1(module=nodenext).js | 37 ++++- ...deDeclarationEmitErrors1(module=node16).js | 10 +- ...DeclarationEmitErrors1(module=nodenext).js | 10 +- .../privacyCannotNameAccessorDeclFile.js | 18 +- .../privacyCannotNameVarTypeDeclFile.js | 26 +-- ...FunctionCannotNameParameterTypeDeclFile.js | 42 ++--- ...acyFunctionCannotNameReturnTypeDeclFile.js | 26 +-- ...eactTransitiveImportHasValidDeclaration.js | 3 +- ...onEmit.multiFileBackReferenceToUnmapped.js | 5 +- .../declarationEmitImportTypeCoalesceing.ts | 28 ++++ 28 files changed, 526 insertions(+), 181 deletions(-) create mode 100644 tests/baselines/reference/declarationEmitImportTypeCoalesceing.js create mode 100644 tests/baselines/reference/declarationEmitImportTypeCoalesceing.symbols create mode 100644 tests/baselines/reference/declarationEmitImportTypeCoalesceing.types create mode 100644 tests/cases/compiler/declarationEmitImportTypeCoalesceing.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 16790ddf5978b..2b9a72b6eca4c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4644,29 +4644,24 @@ namespace ts { } } - function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node, overrideMeaning?: SymbolFlags): SymbolVisibilityResult { + function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult { // get symbol of the first identifier of the entityName let meaning: SymbolFlags; - if (overrideMeaning) { - meaning = overrideMeaning; + if (entityName.parent.kind === SyntaxKind.TypeQuery || + entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) || + entityName.parent.kind === SyntaxKind.ComputedPropertyName) { + // Typeof value + meaning = SymbolFlags.Value | SymbolFlags.ExportValue; + } + else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression || + entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration) { + // Left identifier from type reference or TypeAlias + // Entity name of the import declaration + meaning = SymbolFlags.Namespace; } else { - if (entityName.parent.kind === SyntaxKind.TypeQuery || - entityName.parent.kind === SyntaxKind.ExpressionWithTypeArguments && !isPartOfTypeNode(entityName.parent) || - entityName.parent.kind === SyntaxKind.ComputedPropertyName) { - // Typeof value - meaning = SymbolFlags.Value | SymbolFlags.ExportValue; - } - else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression || - entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration) { - // Left identifier from type reference or TypeAlias - // Entity name of the import declaration - meaning = SymbolFlags.Namespace; - } - else { - // Type Reference or TypeAlias entity = Identifier - meaning = SymbolFlags.Type; - } + // Type Reference or TypeAlias entity = Identifier + meaning = SymbolFlags.Type; } const firstIdentifier = getFirstIdentifier(entityName); @@ -6273,12 +6268,16 @@ namespace ts { const lastId = isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right; lastId.typeArguments = undefined; } - return factory.createImportTypeNode(lit, assertion, nonRootParts as EntityName, typeParameterNodes as readonly TypeNode[], isTypeOf); + const node = factory.createImportTypeNode(lit, assertion, nonRootParts as EntityName, typeParameterNodes as readonly TypeNode[], isTypeOf); + node.nextContainer = context.enclosingDeclaration; // `nextContainer` is used in the binder to track containers - reuse it on import types to smuggle out original context info + return node; } else { const splitNode = getTopmostIndexedAccessType(nonRootParts); const qualifier = (splitNode.objectType as TypeReferenceNode).typeName; - return factory.createIndexedAccessTypeNode(factory.createImportTypeNode(lit, assertion, qualifier, typeParameterNodes as readonly TypeNode[], isTypeOf), splitNode.indexType); + const node = factory.createImportTypeNode(lit, assertion, qualifier, typeParameterNodes as readonly TypeNode[], isTypeOf); + node.nextContainer = context.enclosingDeclaration; // `nextContainer` is used in the binder to track containers - reuse it on import types to smuggle out original context info + return factory.createIndexedAccessTypeNode(node, splitNode.indexType); } } @@ -43278,6 +43277,9 @@ namespace ts { createLiteralConstValue, isSymbolAccessible, isEntityNameVisible, + resolveName(name, location, meaning, excludeGlobals) { + return resolveName(getParseTreeNode(location), escapeLeadingUnderscores(name), meaning, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false, excludeGlobals); + }, getConstantValue: nodeIn => { const node = getParseTreeNode(nodeIn, canHaveConstantValue); return node ? getConstantValue(node) : undefined; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6759e51ef1f29..dfe871500b947 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -686,6 +686,7 @@ namespace ts { createLiteralConstValue: notImplemented, isSymbolAccessible: notImplemented, isEntityNameVisible: notImplemented, + resolveName: notImplemented, // Returns the constant value this property access resolves to: notImplemented, or 'undefined' for a non-constant getConstantValue: notImplemented, getReferencedValueDeclaration: notImplemented, diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 76a8c405d722b..29d5bc7849bb3 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -5354,10 +5354,16 @@ namespace ts { // @api function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) { - return node.sourceFiles !== sourceFiles - || node.prepends !== prepends - ? update(createBundle(sourceFiles, prepends), node) - : node; + if (node.sourceFiles !== sourceFiles + || node.prepends !== prepends) { + const newNode = update(createBundle(sourceFiles, prepends), node); + newNode.syntheticFileReferences = node.syntheticFileReferences; + newNode.syntheticLibReferences = node.syntheticLibReferences; + newNode.syntheticTypeReferences = node.syntheticTypeReferences; + newNode.hasNoDefaultLib = node.hasNoDefaultLib; + return newNode; + } + return node; } // @api diff --git a/src/compiler/transformers/declarations/coalesceImports.ts b/src/compiler/transformers/declarations/coalesceImports.ts index 356cebc6d257d..f15531eb01eaa 100644 --- a/src/compiler/transformers/declarations/coalesceImports.ts +++ b/src/compiler/transformers/declarations/coalesceImports.ts @@ -39,15 +39,67 @@ namespace ts { if (!isExternalModule(rootFile)) { return rootFile; } + const memberwiseImportTypeNodesBySpecifier = createMultiMap(); const memberwiseImportDeclarationsBySpecifier = createMultiMap(); const namespaceImportTypeNodesBySpecifier = createMultiMap(); const namespaceImportDeclarationsBySpecifier = createMultiMap(); const resolver = getEmitResolver(); + + let parent: Node = rootFile; visitEachChild(rootFile, collectRootImports, context); - return visitEachChild(rootFile, combineImportTypes, context); - + + const newImports: ImportDeclaration[] = []; + + const newNamespaceImportsToMake = filter(arrayFrom(namespaceImportTypeNodesBySpecifier.entries()), entry => !namespaceImportDeclarationsBySpecifier.has(entry[0]) && length(entry[1]) > 1); + newNamespaceImportsToMake.forEach(([key, nodes]) => { + const newImport = factory.createImportDeclaration( + /*modifiers*/ undefined, + factory.createImportClause( + /*isTypeOnly*/ true, + /*name*/ undefined, + factory.createNamespaceImport(factory.createUniqueName("_ns")) + ), + nodes[0].argument.literal, + nodes[0].assertions?.assertClause + ); + newImports.push(newImport); + namespaceImportDeclarationsBySpecifier.set(key, [newImport]); + }); + + const newMemberwiseImportsToMake = filter(arrayFrom(memberwiseImportTypeNodesBySpecifier.entries()), entry => !memberwiseImportDeclarationsBySpecifier.has(entry[0]) && length(entry[1]) > 1); + newMemberwiseImportsToMake.forEach(([key, nodes]) => { + const importSpecifiers: ImportSpecifier[] = []; + forEach(nodes, n => { + const member = getFirstIdentifier(n.qualifier!); + // TODO: Use a map? _Usually_ this shouldn't be big enough to matter, but declaration files get big sometimes. + if (some(importSpecifiers, spec => idText(spec.propertyName || spec.name) === idText(member))) return; // already added + const renamed = some(nodes, n => !!resolver.resolveName(idText(member), n.nextContainer || n, SymbolFlags.All, /*skipGlobals*/ false)) ? factory.createUniqueName(idText(member)) : undefined; + const importSpec = factory.createImportSpecifier( + /*isTypeOnly*/ true, + renamed ? member : undefined, + renamed || member + ); + importSpecifiers.push(importSpec); + }); + const newImport = factory.createImportDeclaration( + /*modifiers*/ undefined, + factory.createImportClause( + /*isTypeOnly*/ false, + /*name*/ undefined, + factory.createNamedImports(importSpecifiers) + ), + nodes[0].argument.literal, + nodes[0].assertions?.assertClause + ); + newImports.push(newImport); + memberwiseImportDeclarationsBySpecifier.set(key, [newImport]); + }); + + return factory.updateSourceFile(rootFile, setTextRange(factory.createNodeArray([...newImports, ...visitNodes(rootFile.statements, combineImportTypes)], rootFile.statements.hasTrailingComma), rootFile.statements)); + function collectRootImports(node: Node): VisitResult { + if (!node.parent) (node as Mutable).parent = parent; switch (node.kind) { case SyntaxKind.ImportDeclaration: Debug.assertNode(node, isImportDeclaration); @@ -58,6 +110,7 @@ namespace ts { set.add(key, node); } } + parent = node; return visitEachChild(node, collectImports, context); default: return visitNode(node, collectImports); @@ -65,6 +118,8 @@ namespace ts { } function collectImports(node: Node): VisitResult { + if (!node.parent) (node as Mutable).parent = parent; + parent = node; switch (node.kind) { case SyntaxKind.ImportType: Debug.assertNode(node, isImportTypeNode); @@ -94,9 +149,9 @@ namespace ts { if (idText(firstId) === "default" && d.importClause?.name) { return updateEntityNameRoot(node.qualifier!, factory.createIdentifier(idText(d.importClause.name))); } - const match = find((d.importClause?.namedBindings as NamedImports).elements, e => idText(e.propertyName || e.name) === idText(firstId)); + const match = find((d.importClause?.namedBindings as NamedImports).elements, e => idText(e.propertyName || e.name) === idText(firstId) && (!!e.name.autoGenerateFlags || !resolver.resolveName(idText(e.name), node.nextContainer || node, SymbolFlags.All, /*excludeGlobals*/ false))); if (match) { - return updateEntityNameRoot(node.qualifier!, factory.createIdentifier(idText(match.name))); + return updateEntityNameRoot(node.qualifier!, !!match.name.autoGenerateFlags ? match.name : factory.createIdentifier(idText(match.name))); } }) || factory.cloneNode(node.qualifier!); } @@ -110,10 +165,16 @@ namespace ts { function createOrUpdateNamedBindings(bindings: NamedImportBindings | undefined, specs: Identifier[], useLocations: Node[]) { const specifiers = bindings && isNamedImports(bindings) ? [...bindings.elements] : []; + const specMap = new Map(); + for (const spec of specifiers) { + specMap.set(idText(spec.propertyName || spec.name), spec); + } forEach(specs, s => { - if (find(specifiers, existing => idText(existing.propertyName || existing.name) === idText(s))) return; // skip duplicates (use a map to improve perf in degenerately large edge cases, maybe?) - const renamed = some(useLocations, n => resolver.isEntityNameVisible(s, n, SymbolFlags.All).accessibility === SymbolAccessibility.Accessible) ? factory.createUniqueName(idText(s)) : undefined; - specifiers.push(factory.createImportSpecifier(/*isTypeOnly*/ true, renamed ? s : undefined, renamed || s)); + const renamed = some(useLocations, n => !!resolver.resolveName(idText(s), n.nextContainer || n, SymbolFlags.All, /*skipGlobals*/ false)) ? factory.createUniqueName(idText(s)) : undefined; + if (!renamed ? specMap.has(idText(s)) : !!specMap.get(idText(s))?.name.autoGenerateFlags) return; // skip dupes (renamed ones can share a generated name) + const spec = factory.createImportSpecifier(/*isTypeOnly*/ true, renamed ? s : undefined, renamed || s); + specifiers.push(spec); + specMap.set(idText(s), spec); }); if (!bindings) { return factory.createNamedImports(specifiers); @@ -122,83 +183,42 @@ namespace ts { } function combineImportTypes(node: Node): VisitResult { - if (isSourceFile(node)) { - const newImports: ImportDeclaration[] = []; - - const newNamespaceImportsToMake = filter(arrayFrom(namespaceImportTypeNodesBySpecifier.entries()), entry => !namespaceImportDeclarationsBySpecifier.has(entry[0]) && length(entry[1]) > 1); - newNamespaceImportsToMake.forEach(([key, nodes]) => { - const newImport = factory.createImportDeclaration( - /*modifiers*/ undefined, - factory.createImportClause( - /*isTypeOnly*/ true, - /*name*/ undefined, - factory.createNamespaceImport(factory.createUniqueName("_ns")) - ), - nodes[0].argument.literal, - nodes[0].assertions?.assertClause - ); - newImports.push(newImport); - namespaceImportDeclarationsBySpecifier.set(key, [newImport]); - }); - - const newMemberwiseImportsToMake = filter(arrayFrom(memberwiseImportTypeNodesBySpecifier.entries()), entry => !memberwiseImportDeclarationsBySpecifier.has(entry[0]) && length(entry[1]) > 1); - newMemberwiseImportsToMake.forEach(([key, nodes]) => { - const importSpecifiers: ImportSpecifier[] = []; - forEach(nodes, n => { - const member = getFirstIdentifier(n.qualifier!); - // TODO: Use a map? _Usually_ this shouldn't be big enough to matter, but declaration files get big sometimes. - if (some(importSpecifiers, spec => idText(spec.propertyName || spec.name) === idText(member))) return; // already added - const renamed = some(nodes, n => resolver.isEntityNameVisible(member, n, SymbolFlags.All).accessibility === SymbolAccessibility.Accessible) ? factory.createUniqueName(idText(member)) : undefined; - const importSpec = factory.createImportSpecifier( - /*isTypeOnly*/ true, - renamed ? member : undefined, - renamed || member - ); - importSpecifiers.push(importSpec); - }); - const newImport = factory.createImportDeclaration( - /*modifiers*/ undefined, - factory.createImportClause( - /*isTypeOnly*/ false, - /*name*/ undefined, - factory.createNamedImports(importSpecifiers) - ), - nodes[0].argument.literal, - nodes[0].assertions?.assertClause - ); - newImports.push(newImport); - memberwiseImportDeclarationsBySpecifier.set(key, [newImport]); - }); - - return factory.updateSourceFile(node, setTextRange(factory.createNodeArray([...newImports, ...visitNodes(node.statements, combineImportTypes)], node.statements.hasTrailingComma), node.statements)); - } if (isImportDeclaration(node)) { + // TODO: Since imports are hoisted (albeit with TDZ), we technically need to modify every import declaration _before_ recuring + // on import type nodes to modify those, since technically the import an import type node relies on can occur _after_ it in + // a file. This is somewhat unfortunate since it makes this require 3 tree walks - one to gather the imports and import type nodes we care about, + // one (albeit likely shallow one) to modify the existing import declarations, and one to update all the import type nodes themselves. const key = getCoalesceKeyForImport(node); if (key !== false && memberwiseImportDeclarationsBySpecifier.has(key) && memberwiseImportDeclarationsBySpecifier.get(key)!.indexOf(node) >= 0 && memberwiseImportTypeNodesBySpecifier.has(key)) { - const requiredSpecifiers = map(memberwiseImportTypeNodesBySpecifier.get(key)!, n => getFirstIdentifier(n.qualifier!)); - const remainingSpecifiers = filter(requiredSpecifiers, s => !some(memberwiseImportDeclarationsBySpecifier.get(key)!, decl => !!(idText(s) === "default" && decl.importClause?.name) || !!(decl.importClause && decl.importClause.namedBindings && isNamedImports(decl.importClause.namedBindings) && some(decl.importClause.namedBindings.elements, elem => idText(elem.name) === idText(s))))); + const remainingSpecifiers = filter(memberwiseImportTypeNodesBySpecifier.get(key)!, + s => !some(memberwiseImportDeclarationsBySpecifier.get(key), + decl => !!(idText(getFirstIdentifier(s.qualifier!)) === "default" && decl.importClause?.name) || !!(decl.importClause && decl.importClause.namedBindings && isNamedImports(decl.importClause.namedBindings) && some(decl.importClause.namedBindings.elements, + elem => idText(elem.name) === idText(getFirstIdentifier(s.qualifier!)) && !resolver.resolveName(idText(elem.name), s.nextContainer || s, SymbolFlags.All, /*excludeGlobals*/ false) + )))); if (length(remainingSpecifiers)) { - const nonDefaultSpecifiers = filter(remainingSpecifiers, spec => idText(spec) !== "default"); - return factory.updateImportDeclaration( + const nonDefaultSpecifiers = filter(remainingSpecifiers, spec => idText(getFirstIdentifier(spec.qualifier!)) !== "default"); + const updated = factory.updateImportDeclaration( node, node.modifiers, createOrUpdateImportClause( node.importClause, node.importClause?.name || (length(nonDefaultSpecifiers) !== length(remainingSpecifiers) ? factory.createUniqueName("_default") : undefined), - length(nonDefaultSpecifiers) ? createOrUpdateNamedBindings(node.importClause?.namedBindings, nonDefaultSpecifiers, memberwiseImportTypeNodesBySpecifier.get(key)!) : node.importClause?.namedBindings), + length(nonDefaultSpecifiers) ? createOrUpdateNamedBindings(node.importClause?.namedBindings, map(nonDefaultSpecifiers, n => getFirstIdentifier(n.qualifier!)), memberwiseImportTypeNodesBySpecifier.get(key)!) : node.importClause?.namedBindings), node.moduleSpecifier, node.assertClause ); + memberwiseImportDeclarationsBySpecifier.remove(key, node); + memberwiseImportDeclarationsBySpecifier.add(key, updated); + return updated; } } } if (isImportTypeNode(node)) { - const key = getCoalesceKeyForImport(node) + const key = getCoalesceKeyForImport(node); if (key !== false) { - const siblingTypeNodes = node.qualifier ? memberwiseImportTypeNodesBySpecifier : namespaceImportTypeNodesBySpecifier; - if (siblingTypeNodes.get(key)!.length > 1) { // only coalesce to an import statement when there are multiple statements to merge - const cache = node.qualifier ? memberwiseImportDeclarationsBySpecifier : namespaceImportDeclarationsBySpecifier; - const importDecls = cache.get(key)!; + const cache = node.qualifier ? memberwiseImportDeclarationsBySpecifier : namespaceImportDeclarationsBySpecifier; + const importDecls = cache.get(key); + if (importDecls && importDecls[0]) { const entityName: EntityName = !node.qualifier ? (importDecls[0].importClause!.namedBindings as NamespaceImport).name : getEntityNameForImportType(node, importDecls); return setOriginalNode(node.isTypeOf ? factory.createTypeQueryNode(entityName) : factory.createTypeReferenceNode(entityName, visitNodes(node.typeArguments, combineImportTypes)), node); } diff --git a/src/compiler/transformers/utilities.ts b/src/compiler/transformers/utilities.ts index bbe8f165919bf..c557b9ec08903 100644 --- a/src/compiler/transformers/utilities.ts +++ b/src/compiler/transformers/utilities.ts @@ -33,7 +33,7 @@ namespace ts { } function transformBundle(node: Bundle) { - return context.factory.createBundle(map(node.sourceFiles, transformSourceFile), node.prepends); + return context.factory.updateBundle(node, map(node.sourceFiles, transformSourceFile), node.prepends); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 382db85848700..260e6b26ebcb0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -872,7 +872,7 @@ namespace ts { /* @internal */ original?: Node; // The original node if this is an updated node. /* @internal */ symbol: Symbol; // Symbol declared by node (initialized by binding) /* @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) - /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) + /* @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) - also used by the node builder to smuggle out original context information for declaration transforms /* @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) /* @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding) /* @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms) @@ -4988,7 +4988,8 @@ namespace ts { createTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: NodeBuilderFlags, tracker: SymbolTracker): TypeNode | undefined; createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker): Expression; isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags | undefined, shouldComputeAliasToMarkVisible: boolean): SymbolAccessibilityResult; - isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node, overrideMeaning?: SymbolFlags): SymbolVisibilityResult; + isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult; + resolveName(name: string, location: Node | undefined, meaning: SymbolFlags, excludeGlobals: boolean): Symbol | undefined; // Returns the constant value this property access resolves to, or 'undefined' for a non-constant getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): string | number | undefined; getReferencedValueDeclaration(reference: Identifier): Declaration | undefined; diff --git a/tests/baselines/reference/declarationEmitAliasFromIndirectFile.js b/tests/baselines/reference/declarationEmitAliasFromIndirectFile.js index 105b406cdadea..307e5991cc549 100644 --- a/tests/baselines/reference/declarationEmitAliasFromIndirectFile.js +++ b/tests/baselines/reference/declarationEmitAliasFromIndirectFile.js @@ -35,10 +35,11 @@ exports["default"] = fp.l10ns; //// [app.d.ts] +import { type CustomLocale, type Locale } from "./locale"; declare const _default: { - ar?: import("./locale").CustomLocale; - bg?: import("./locale").CustomLocale; + ar?: CustomLocale; + bg?: CustomLocale; } & { - default: import("./locale").Locale; + default: Locale; }; export default _default; diff --git a/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.js b/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.js index 2fc61a5577989..220452b390869 100644 --- a/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.js +++ b/tests/baselines/reference/declarationEmitDefaultExportWithStaticAssignment.js @@ -95,11 +95,11 @@ declare namespace Example { } export default Example; //// [index2.d.ts] -import { Foo } from './foo'; +import { Foo, type Foo as Foo_1 } from './foo'; export { Foo }; declare function Example(): void; declare namespace Example { - var Foo: typeof import("./foo").Foo; + var Foo: typeof Foo_1; } export default Example; //// [index3.d.ts] diff --git a/tests/baselines/reference/declarationEmitExportAliasVisibiilityMarking.js b/tests/baselines/reference/declarationEmitExportAliasVisibiilityMarking.js index 4f554c808cf66..3e1481703cf64 100644 --- a/tests/baselines/reference/declarationEmitExportAliasVisibiilityMarking.js +++ b/tests/baselines/reference/declarationEmitExportAliasVisibiilityMarking.js @@ -41,8 +41,9 @@ declare const _default: (suit: Suit, rank: Rank) => { }; export default _default; //// [index.d.ts] -export declare let lazyCard: () => Promise<(suit: import("./Types").Suit, rank: import("./Types").Rank) => { - suit: import("./Types").Suit; - rank: import("./Types").Rank; +import { type Suit, type Rank } from "./Types"; +export declare let lazyCard: () => Promise<(suit: Suit, rank: Rank) => { + suit: Suit; + rank: Rank; }>; export { Suit, Rank } from './Types'; diff --git a/tests/baselines/reference/declarationEmitImportTypeCoalesceing.js b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.js new file mode 100644 index 0000000000000..e835d210e2fb4 --- /dev/null +++ b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.js @@ -0,0 +1,57 @@ +//// [tests/cases/compiler/declarationEmitImportTypeCoalesceing.ts] //// + +//// [whole.d.ts] +declare namespace thing { + export const a = 1; + export interface A {} + export function getNs(): typeof thing; +} +export = thing; +//// [types.d.ts] +export interface A {} +export interface B {} +export interface C {} + +export declare function getA(): A; +export declare function getB(): B; +export declare function getC(): C; +//// [index.ts] +import { getA } from "./types"; +import { getNs } from "./whole"; + +export const a1 = getA(); +export const a2 = [getA()]; +export const a3 = { a: getA() }; + +export const ns1 = getNs(); +export const ns2 = [getNs()]; +export const ns3 = { a: getNs() }; + + +//// [index.js] +"use strict"; +exports.__esModule = true; +exports.ns3 = exports.ns2 = exports.ns1 = exports.a3 = exports.a2 = exports.a1 = void 0; +var types_1 = require("./types"); +var whole_1 = require("./whole"); +exports.a1 = (0, types_1.getA)(); +exports.a2 = [(0, types_1.getA)()]; +exports.a3 = { a: (0, types_1.getA)() }; +exports.ns1 = (0, whole_1.getNs)(); +exports.ns2 = [(0, whole_1.getNs)()]; +exports.ns3 = { a: (0, whole_1.getNs)() }; + + +//// [index.d.ts] +import type * as _ns_1 from "./whole"; +import { type A } from "./types"; +export declare const a1: A; +export declare const a2: A[]; +export declare const a3: { + a: A; +}; +export declare const ns1: typeof _ns_1; +export declare const ns2: (typeof _ns_1)[]; +export declare const ns3: { + a: typeof _ns_1; +}; diff --git a/tests/baselines/reference/declarationEmitImportTypeCoalesceing.symbols b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.symbols new file mode 100644 index 0000000000000..2290ca6739178 --- /dev/null +++ b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.symbols @@ -0,0 +1,72 @@ +=== tests/cases/compiler/whole.d.ts === +declare namespace thing { +>thing : Symbol(thing, Decl(whole.d.ts, 0, 0)) + + export const a = 1; +>a : Symbol(a, Decl(whole.d.ts, 1, 16)) + + export interface A {} +>A : Symbol(A, Decl(whole.d.ts, 1, 23)) + + export function getNs(): typeof thing; +>getNs : Symbol(getNs, Decl(whole.d.ts, 2, 25)) +>thing : Symbol(thing, Decl(whole.d.ts, 0, 0)) +} +export = thing; +>thing : Symbol(thing, Decl(whole.d.ts, 0, 0)) + +=== tests/cases/compiler/types.d.ts === +export interface A {} +>A : Symbol(A, Decl(types.d.ts, 0, 0)) + +export interface B {} +>B : Symbol(B, Decl(types.d.ts, 0, 21)) + +export interface C {} +>C : Symbol(C, Decl(types.d.ts, 1, 21)) + +export declare function getA(): A; +>getA : Symbol(getA, Decl(types.d.ts, 2, 21)) +>A : Symbol(A, Decl(types.d.ts, 0, 0)) + +export declare function getB(): B; +>getB : Symbol(getB, Decl(types.d.ts, 4, 34)) +>B : Symbol(B, Decl(types.d.ts, 0, 21)) + +export declare function getC(): C; +>getC : Symbol(getC, Decl(types.d.ts, 5, 34)) +>C : Symbol(C, Decl(types.d.ts, 1, 21)) + +=== tests/cases/compiler/index.ts === +import { getA } from "./types"; +>getA : Symbol(getA, Decl(index.ts, 0, 8)) + +import { getNs } from "./whole"; +>getNs : Symbol(getNs, Decl(index.ts, 1, 8)) + +export const a1 = getA(); +>a1 : Symbol(a1, Decl(index.ts, 3, 12)) +>getA : Symbol(getA, Decl(index.ts, 0, 8)) + +export const a2 = [getA()]; +>a2 : Symbol(a2, Decl(index.ts, 4, 12)) +>getA : Symbol(getA, Decl(index.ts, 0, 8)) + +export const a3 = { a: getA() }; +>a3 : Symbol(a3, Decl(index.ts, 5, 12)) +>a : Symbol(a, Decl(index.ts, 5, 19)) +>getA : Symbol(getA, Decl(index.ts, 0, 8)) + +export const ns1 = getNs(); +>ns1 : Symbol(ns1, Decl(index.ts, 7, 12)) +>getNs : Symbol(getNs, Decl(index.ts, 1, 8)) + +export const ns2 = [getNs()]; +>ns2 : Symbol(ns2, Decl(index.ts, 8, 12)) +>getNs : Symbol(getNs, Decl(index.ts, 1, 8)) + +export const ns3 = { a: getNs() }; +>ns3 : Symbol(ns3, Decl(index.ts, 9, 12)) +>a : Symbol(a, Decl(index.ts, 9, 20)) +>getNs : Symbol(getNs, Decl(index.ts, 1, 8)) + diff --git a/tests/baselines/reference/declarationEmitImportTypeCoalesceing.types b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.types new file mode 100644 index 0000000000000..eb6c266ee060b --- /dev/null +++ b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.types @@ -0,0 +1,73 @@ +=== tests/cases/compiler/whole.d.ts === +declare namespace thing { +>thing : typeof thing + + export const a = 1; +>a : 1 +>1 : 1 + + export interface A {} + export function getNs(): typeof thing; +>getNs : () => typeof thing +>thing : typeof thing +} +export = thing; +>thing : typeof thing + +=== tests/cases/compiler/types.d.ts === +export interface A {} +export interface B {} +export interface C {} + +export declare function getA(): A; +>getA : () => A + +export declare function getB(): B; +>getB : () => B + +export declare function getC(): C; +>getC : () => C + +=== tests/cases/compiler/index.ts === +import { getA } from "./types"; +>getA : () => import("tests/cases/compiler/types").A + +import { getNs } from "./whole"; +>getNs : () => typeof import("tests/cases/compiler/whole") + +export const a1 = getA(); +>a1 : import("tests/cases/compiler/types").A +>getA() : import("tests/cases/compiler/types").A +>getA : () => import("tests/cases/compiler/types").A + +export const a2 = [getA()]; +>a2 : import("tests/cases/compiler/types").A[] +>[getA()] : import("tests/cases/compiler/types").A[] +>getA() : import("tests/cases/compiler/types").A +>getA : () => import("tests/cases/compiler/types").A + +export const a3 = { a: getA() }; +>a3 : { a: import("tests/cases/compiler/types").A; } +>{ a: getA() } : { a: import("tests/cases/compiler/types").A; } +>a : import("tests/cases/compiler/types").A +>getA() : import("tests/cases/compiler/types").A +>getA : () => import("tests/cases/compiler/types").A + +export const ns1 = getNs(); +>ns1 : typeof import("tests/cases/compiler/whole") +>getNs() : typeof import("tests/cases/compiler/whole") +>getNs : () => typeof import("tests/cases/compiler/whole") + +export const ns2 = [getNs()]; +>ns2 : typeof import("tests/cases/compiler/whole")[] +>[getNs()] : typeof import("tests/cases/compiler/whole")[] +>getNs() : typeof import("tests/cases/compiler/whole") +>getNs : () => typeof import("tests/cases/compiler/whole") + +export const ns3 = { a: getNs() }; +>ns3 : { a: typeof import("tests/cases/compiler/whole"); } +>{ a: getNs() } : { a: typeof import("tests/cases/compiler/whole"); } +>a : typeof import("tests/cases/compiler/whole") +>getNs() : typeof import("tests/cases/compiler/whole") +>getNs : () => typeof import("tests/cases/compiler/whole") + diff --git a/tests/baselines/reference/declarationEmitQualifiedAliasTypeArgument.js b/tests/baselines/reference/declarationEmitQualifiedAliasTypeArgument.js index e69e65acf1df0..94829998f84c2 100644 --- a/tests/baselines/reference/declarationEmitQualifiedAliasTypeArgument.js +++ b/tests/baselines/reference/declarationEmitQualifiedAliasTypeArgument.js @@ -37,6 +37,7 @@ exports.fun2 = (0, bbb_1.create)(); //// [index.d.ts] +import { type INode } from "./bbb"; import { T, Q } from "./lib"; -export declare const fun: () => import("./bbb").INode; -export declare const fun2: () => import("./bbb").INode; +export declare const fun: () => INode; +export declare const fun2: () => INode; diff --git a/tests/baselines/reference/declarationEmitReexportedSymlinkReference.js b/tests/baselines/reference/declarationEmitReexportedSymlinkReference.js index 7fa2a4194d6c9..cdad7bbbfe330 100644 --- a/tests/baselines/reference/declarationEmitReexportedSymlinkReference.js +++ b/tests/baselines/reference/declarationEmitReexportedSymlinkReference.js @@ -70,7 +70,7 @@ __exportStar(require("./keys"), exports); //// [keys.d.ts] -import { MetadataAccessor } from "@raymondfeng/pkg2"; -export declare const ADMIN: MetadataAccessor; +import { MetadataAccessor, type IdType } from "@raymondfeng/pkg2"; +export declare const ADMIN: MetadataAccessor; //// [index.d.ts] export * from './keys'; diff --git a/tests/baselines/reference/exportClassExtendingIntersection.js b/tests/baselines/reference/exportClassExtendingIntersection.js index 9327a315f3a48..b9178b926a3bd 100644 --- a/tests/baselines/reference/exportClassExtendingIntersection.js +++ b/tests/baselines/reference/exportClassExtendingIntersection.js @@ -125,9 +125,9 @@ export interface MyMixin { } export declare function MyMixin>>(base: T): T & Constructor; //// [FinalClass.d.ts] -import { MyBaseClass } from './BaseClass'; +import { MyBaseClass, type Constructor } from './BaseClass'; import { MyMixin } from './MixinClass'; -declare const MyExtendedClass_base: typeof MyBaseClass & import("./BaseClass").Constructor; +declare const MyExtendedClass_base: typeof MyBaseClass & Constructor; export declare class MyExtendedClass extends MyExtendedClass_base { extendedClassProperty: number; } diff --git a/tests/baselines/reference/importTypeGenericArrowTypeParenthesized.js b/tests/baselines/reference/importTypeGenericArrowTypeParenthesized.js index 2de796f19baf1..c6e4ed9e5c993 100644 --- a/tests/baselines/reference/importTypeGenericArrowTypeParenthesized.js +++ b/tests/baselines/reference/importTypeGenericArrowTypeParenthesized.js @@ -34,9 +34,10 @@ exports.works2 = (0, module_1.fn)(function (x) { return x; }); //// [index.d.ts] /// -export declare const fail1: import("module").Modifier<((x: T) => T)>; -export declare const fail2: import("module").Modifier<((x: T) => T)>; -export declare const works1: import("module").Modifier<(x: number) => number>; +import { type Modifier } from "module"; +export declare const fail1: Modifier<((x: T) => T)>; +export declare const fail2: Modifier<((x: T) => T)>; +export declare const works1: Modifier<(x: number) => number>; declare type MakeItWork = (x: T) => T; -export declare const works2: import("module").Modifier; +export declare const works2: Modifier; export {}; diff --git a/tests/baselines/reference/jsDeclarationsUniqueSymbolUsage.js b/tests/baselines/reference/jsDeclarationsUniqueSymbolUsage.js index 5b931e6291155..2d218d810db12 100644 --- a/tests/baselines/reference/jsDeclarationsUniqueSymbolUsage.js +++ b/tests/baselines/reference/jsDeclarationsUniqueSymbolUsage.js @@ -24,8 +24,9 @@ export type WithSymbol = { [kSymbol]: true; }; //// [b.d.ts] +import { type WithSymbol } from './a'; /** * @returns {import('./a').WithSymbol} * @param {import('./a').WithSymbol} value */ -export function b(value: import('./a').WithSymbol): import('./a').WithSymbol; +export function b(value: WithSymbol): WithSymbol; diff --git a/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmit1(module=node16).js b/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmit1(module=node16).js index 4a65e05cdd90e..4c9f9e28770d2 100644 --- a/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmit1(module=node16).js +++ b/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmit1(module=node16).js @@ -31,6 +31,39 @@ exports.b = null; //// [index.d.ts] -export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "require" } }).RequireInterface & import("pkg", { assert: { "resolution-mode": "import" } }).ImportInterface; +import { type ImportInterface } from "pkg" assert { "resolution-mode": "import" }; +export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "require" } }).RequireInterface & ImportInterface; export declare const a: import("pkg").RequireInterface; -export declare const b: import("pkg", { assert: { "resolution-mode": "import" } }).ImportInterface; +export declare const b: ImportInterface; + + +//// [DtsFileErrors] + + +out/index.d.ts(1,15): error TS2305: Module '"pkg"' has no exported member 'ImportInterface'. +out/index.d.ts(1,44): error TS2821: Import assertions are only supported when the '--module' option is set to 'esnext' or 'nodenext'. + + +==== out/index.d.ts (2 errors) ==== + import { type ImportInterface } from "pkg" assert { "resolution-mode": "import" }; + ~~~~~~~~~~~~~~~ +!!! error TS2305: Module '"pkg"' has no exported member 'ImportInterface'. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2821: Import assertions are only supported when the '--module' option is set to 'esnext' or 'nodenext'. + export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "require" } }).RequireInterface & ImportInterface; + export declare const a: import("pkg").RequireInterface; + export declare const b: ImportInterface; + +==== /node_modules/pkg/package.json (0 errors) ==== + { + "name": "pkg", + "version": "0.0.1", + "exports": { + "import": "./import.js", + "require": "./require.js" + } + } +==== /node_modules/pkg/import.d.ts (0 errors) ==== + export interface ImportInterface {} +==== /node_modules/pkg/require.d.ts (0 errors) ==== + export interface RequireInterface {} \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmit1(module=nodenext).js b/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmit1(module=nodenext).js index 4a65e05cdd90e..70d97d5a4ae12 100644 --- a/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmit1(module=nodenext).js +++ b/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmit1(module=nodenext).js @@ -31,6 +31,39 @@ exports.b = null; //// [index.d.ts] -export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "require" } }).RequireInterface & import("pkg", { assert: { "resolution-mode": "import" } }).ImportInterface; +import { type ImportInterface } from "pkg" assert { "resolution-mode": "import" }; +export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "require" } }).RequireInterface & ImportInterface; export declare const a: import("pkg").RequireInterface; -export declare const b: import("pkg", { assert: { "resolution-mode": "import" } }).ImportInterface; +export declare const b: ImportInterface; + + +//// [DtsFileErrors] + + +out/index.d.ts(1,15): error TS2305: Module '"pkg"' has no exported member 'ImportInterface'. +out/index.d.ts(1,44): error TS2836: Import assertions are not allowed on statements that transpile to commonjs 'require' calls. + + +==== out/index.d.ts (2 errors) ==== + import { type ImportInterface } from "pkg" assert { "resolution-mode": "import" }; + ~~~~~~~~~~~~~~~ +!!! error TS2305: Module '"pkg"' has no exported member 'ImportInterface'. + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2836: Import assertions are not allowed on statements that transpile to commonjs 'require' calls. + export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "require" } }).RequireInterface & ImportInterface; + export declare const a: import("pkg").RequireInterface; + export declare const b: ImportInterface; + +==== /node_modules/pkg/package.json (0 errors) ==== + { + "name": "pkg", + "version": "0.0.1", + "exports": { + "import": "./import.js", + "require": "./require.js" + } + } +==== /node_modules/pkg/import.d.ts (0 errors) ==== + export interface ImportInterface {} +==== /node_modules/pkg/require.d.ts (0 errors) ==== + export interface RequireInterface {} \ No newline at end of file diff --git a/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmitErrors1(module=node16).js b/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmitErrors1(module=node16).js index 7fd0aff8e8f6e..94a135eb0af16 100644 --- a/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmitErrors1(module=node16).js +++ b/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmitErrors1(module=node16).js @@ -120,9 +120,10 @@ exports.b = null; //// [index.d.ts] -export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "foobar" } }).RequireInterface & import("pkg", { assert: { "resolution-mode": "import" } }).ImportInterface; +import { type ImportInterface } from "pkg" assert { "resolution-mode": "import" }; +export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "foobar" } }).RequireInterface & ImportInterface; export declare const a: import("pkg").RequireInterface; -export declare const b: import("pkg", { assert: { "resolution-mode": "import" } }).ImportInterface; +export declare const b: ImportInterface; //// [other.d.ts] export declare type LocalInterface = import("pkg", { assert: {} }); export declare const a: any; @@ -142,6 +143,7 @@ export declare type LocalInterface = import("pkg", { assert: {} }); export declare const a: any, Asserts1: any, RequireInterface: any; export declare const b: any, Asserts2: any, ImportInterface: any; //// [other5.d.ts] -export declare type LocalInterface = import("pkg", { assert: {} }).RequireInterface & import("pkg", { assert: {} }).ImportInterface; -export declare const a: import("pkg").RequireInterface; +import { type RequireInterface, type ImportInterface } from "pkg" assert {}; +export declare type LocalInterface = RequireInterface & ImportInterface; +export declare const a: RequireInterface; export declare const b: any; diff --git a/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmitErrors1(module=nodenext).js b/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmitErrors1(module=nodenext).js index 7fd0aff8e8f6e..94a135eb0af16 100644 --- a/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmitErrors1(module=nodenext).js +++ b/tests/baselines/reference/nodeModulesImportTypeModeDeclarationEmitErrors1(module=nodenext).js @@ -120,9 +120,10 @@ exports.b = null; //// [index.d.ts] -export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "foobar" } }).RequireInterface & import("pkg", { assert: { "resolution-mode": "import" } }).ImportInterface; +import { type ImportInterface } from "pkg" assert { "resolution-mode": "import" }; +export declare type LocalInterface = import("pkg", { assert: { "resolution-mode": "foobar" } }).RequireInterface & ImportInterface; export declare const a: import("pkg").RequireInterface; -export declare const b: import("pkg", { assert: { "resolution-mode": "import" } }).ImportInterface; +export declare const b: ImportInterface; //// [other.d.ts] export declare type LocalInterface = import("pkg", { assert: {} }); export declare const a: any; @@ -142,6 +143,7 @@ export declare type LocalInterface = import("pkg", { assert: {} }); export declare const a: any, Asserts1: any, RequireInterface: any; export declare const b: any, Asserts2: any, ImportInterface: any; //// [other5.d.ts] -export declare type LocalInterface = import("pkg", { assert: {} }).RequireInterface & import("pkg", { assert: {} }).ImportInterface; -export declare const a: import("pkg").RequireInterface; +import { type RequireInterface, type ImportInterface } from "pkg" assert {}; +export declare type LocalInterface = RequireInterface & ImportInterface; +export declare const a: RequireInterface; export declare const b: any; diff --git a/tests/baselines/reference/privacyCannotNameAccessorDeclFile.js b/tests/baselines/reference/privacyCannotNameAccessorDeclFile.js index d5a2ad2a7a098..8188c1ccae3bb 100644 --- a/tests/baselines/reference/privacyCannotNameAccessorDeclFile.js +++ b/tests/baselines/reference/privacyCannotNameAccessorDeclFile.js @@ -419,19 +419,21 @@ export declare function createExportedWidget3(): Widgets1.Widget3; export declare function createExportedWidget4(): Widgets1.SpecializedGlobalWidget.Widget4; //// [privacyCannotNameAccessorDeclFile_consumer.d.ts] /// +import { type Widget1, type SpecializedWidget } from "./privacyCannotNameAccessorDeclFile_Widgets"; +import { type Widget3, type SpecializedGlobalWidget } from "GlobalWidgets"; export declare class publicClassWithWithPrivateGetAccessorTypes { - static get myPublicStaticMethod(): import("./privacyCannotNameAccessorDeclFile_Widgets").Widget1; + static get myPublicStaticMethod(): Widget1; private static get myPrivateStaticMethod(); - get myPublicMethod(): import("./privacyCannotNameAccessorDeclFile_Widgets").Widget1; + get myPublicMethod(): Widget1; private get myPrivateMethod(); - static get myPublicStaticMethod1(): import("GlobalWidgets").Widget3; + static get myPublicStaticMethod1(): Widget3; private static get myPrivateStaticMethod1(); - get myPublicMethod1(): import("GlobalWidgets").Widget3; + get myPublicMethod1(): Widget3; private get myPrivateMethod1(); } export declare class publicClassWithPrivateModuleGetAccessorTypes { - static get myPublicStaticMethod(): import("./privacyCannotNameAccessorDeclFile_Widgets").SpecializedWidget.Widget2; - get myPublicMethod(): import("./privacyCannotNameAccessorDeclFile_Widgets").SpecializedWidget.Widget2; - static get myPublicStaticMethod1(): import("GlobalWidgets").SpecializedGlobalWidget.Widget4; - get myPublicMethod1(): import("GlobalWidgets").SpecializedGlobalWidget.Widget4; + static get myPublicStaticMethod(): SpecializedWidget.Widget2; + get myPublicMethod(): SpecializedWidget.Widget2; + static get myPublicStaticMethod1(): SpecializedGlobalWidget.Widget4; + get myPublicMethod1(): SpecializedGlobalWidget.Widget4; } diff --git a/tests/baselines/reference/privacyCannotNameVarTypeDeclFile.js b/tests/baselines/reference/privacyCannotNameVarTypeDeclFile.js index 91862eec66118..a7d65cb7134fe 100644 --- a/tests/baselines/reference/privacyCannotNameVarTypeDeclFile.js +++ b/tests/baselines/reference/privacyCannotNameVarTypeDeclFile.js @@ -246,23 +246,25 @@ export declare function createExportedWidget3(): Widgets1.Widget3; export declare function createExportedWidget4(): Widgets1.SpecializedGlobalWidget.Widget4; //// [privacyCannotNameVarTypeDeclFile_consumer.d.ts] /// +import { type Widget1, type SpecializedWidget } from "./privacyCannotNameVarTypeDeclFile_Widgets"; +import { type Widget3, type SpecializedGlobalWidget } from "GlobalWidgets"; export declare class publicClassWithWithPrivatePropertyTypes { - static myPublicStaticProperty: import("./privacyCannotNameVarTypeDeclFile_Widgets").Widget1; + static myPublicStaticProperty: Widget1; private static myPrivateStaticProperty; - myPublicProperty: import("./privacyCannotNameVarTypeDeclFile_Widgets").Widget1; + myPublicProperty: Widget1; private myPrivateProperty; - static myPublicStaticProperty1: import("GlobalWidgets").Widget3; + static myPublicStaticProperty1: Widget3; private static myPrivateStaticProperty1; - myPublicProperty1: import("GlobalWidgets").Widget3; + myPublicProperty1: Widget3; private myPrivateProperty1; } -export declare var publicVarWithPrivatePropertyTypes: import("./privacyCannotNameVarTypeDeclFile_Widgets").Widget1; -export declare var publicVarWithPrivatePropertyTypes1: import("GlobalWidgets").Widget3; +export declare var publicVarWithPrivatePropertyTypes: Widget1; +export declare var publicVarWithPrivatePropertyTypes1: Widget3; export declare class publicClassWithPrivateModulePropertyTypes { - static myPublicStaticProperty: import("./privacyCannotNameVarTypeDeclFile_Widgets").SpecializedWidget.Widget2; - myPublicProperty: import("./privacyCannotNameVarTypeDeclFile_Widgets").SpecializedWidget.Widget2; - static myPublicStaticProperty1: import("GlobalWidgets").SpecializedGlobalWidget.Widget4; - myPublicProperty1: import("GlobalWidgets").SpecializedGlobalWidget.Widget4; + static myPublicStaticProperty: SpecializedWidget.Widget2; + myPublicProperty: SpecializedWidget.Widget2; + static myPublicStaticProperty1: SpecializedGlobalWidget.Widget4; + myPublicProperty1: SpecializedGlobalWidget.Widget4; } -export declare var publicVarWithPrivateModulePropertyTypes: import("./privacyCannotNameVarTypeDeclFile_Widgets").SpecializedWidget.Widget2; -export declare var publicVarWithPrivateModulePropertyTypes1: import("GlobalWidgets").SpecializedGlobalWidget.Widget4; +export declare var publicVarWithPrivateModulePropertyTypes: SpecializedWidget.Widget2; +export declare var publicVarWithPrivateModulePropertyTypes1: SpecializedGlobalWidget.Widget4; diff --git a/tests/baselines/reference/privacyFunctionCannotNameParameterTypeDeclFile.js b/tests/baselines/reference/privacyFunctionCannotNameParameterTypeDeclFile.js index 2b662caefa44d..ce7c0488d4968 100644 --- a/tests/baselines/reference/privacyFunctionCannotNameParameterTypeDeclFile.js +++ b/tests/baselines/reference/privacyFunctionCannotNameParameterTypeDeclFile.js @@ -432,39 +432,41 @@ export declare function createExportedWidget3(): Widgets1.Widget3; export declare function createExportedWidget4(): Widgets1.SpecializedGlobalWidget.Widget4; //// [privacyFunctionCannotNameParameterTypeDeclFile_consumer.d.ts] /// +import { type Widget1, type SpecializedWidget } from "./privacyFunctionCannotNameParameterTypeDeclFile_Widgets"; +import { type Widget3, type SpecializedGlobalWidget } from "GlobalWidgets"; export declare class publicClassWithWithPrivateParmeterTypes { private param1; - param2: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").Widget1; - static myPublicStaticMethod(param?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").Widget1): void; + param2: Widget1; + static myPublicStaticMethod(param?: Widget1): void; private static myPrivateStaticMethod; - myPublicMethod(param?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").Widget1): void; + myPublicMethod(param?: Widget1): void; private myPrivateMethod; - constructor(param?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").Widget1, param1?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").Widget1, param2?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").Widget1); + constructor(param?: Widget1, param1?: Widget1, param2?: Widget1); } export declare class publicClassWithWithPrivateParmeterTypes1 { private param1; - param2: import("GlobalWidgets").Widget3; - static myPublicStaticMethod(param?: import("GlobalWidgets").Widget3): void; + param2: Widget3; + static myPublicStaticMethod(param?: Widget3): void; private static myPrivateStaticMethod; - myPublicMethod(param?: import("GlobalWidgets").Widget3): void; + myPublicMethod(param?: Widget3): void; private myPrivateMethod; - constructor(param?: import("GlobalWidgets").Widget3, param1?: import("GlobalWidgets").Widget3, param2?: import("GlobalWidgets").Widget3); + constructor(param?: Widget3, param1?: Widget3, param2?: Widget3); } -export declare function publicFunctionWithPrivateParmeterTypes(param?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").Widget1): void; -export declare function publicFunctionWithPrivateParmeterTypes1(param?: import("GlobalWidgets").Widget3): void; +export declare function publicFunctionWithPrivateParmeterTypes(param?: Widget1): void; +export declare function publicFunctionWithPrivateParmeterTypes1(param?: Widget3): void; export declare class publicClassWithPrivateModuleParameterTypes { private param1; - param2: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").SpecializedWidget.Widget2; - static myPublicStaticMethod(param?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").SpecializedWidget.Widget2): void; - myPublicMethod(param?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").SpecializedWidget.Widget2): void; - constructor(param?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").SpecializedWidget.Widget2, param1?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").SpecializedWidget.Widget2, param2?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").SpecializedWidget.Widget2); + param2: SpecializedWidget.Widget2; + static myPublicStaticMethod(param?: SpecializedWidget.Widget2): void; + myPublicMethod(param?: SpecializedWidget.Widget2): void; + constructor(param?: SpecializedWidget.Widget2, param1?: SpecializedWidget.Widget2, param2?: SpecializedWidget.Widget2); } export declare class publicClassWithPrivateModuleParameterTypes2 { private param1; - param2: import("GlobalWidgets").SpecializedGlobalWidget.Widget4; - static myPublicStaticMethod(param?: import("GlobalWidgets").SpecializedGlobalWidget.Widget4): void; - myPublicMethod(param?: import("GlobalWidgets").SpecializedGlobalWidget.Widget4): void; - constructor(param?: import("GlobalWidgets").SpecializedGlobalWidget.Widget4, param1?: import("GlobalWidgets").SpecializedGlobalWidget.Widget4, param2?: import("GlobalWidgets").SpecializedGlobalWidget.Widget4); + param2: SpecializedGlobalWidget.Widget4; + static myPublicStaticMethod(param?: SpecializedGlobalWidget.Widget4): void; + myPublicMethod(param?: SpecializedGlobalWidget.Widget4): void; + constructor(param?: SpecializedGlobalWidget.Widget4, param1?: SpecializedGlobalWidget.Widget4, param2?: SpecializedGlobalWidget.Widget4); } -export declare function publicFunctionWithPrivateModuleParameterTypes(param?: import("./privacyFunctionCannotNameParameterTypeDeclFile_Widgets").SpecializedWidget.Widget2): void; -export declare function publicFunctionWithPrivateModuleParameterTypes1(param?: import("GlobalWidgets").SpecializedGlobalWidget.Widget4): void; +export declare function publicFunctionWithPrivateModuleParameterTypes(param?: SpecializedWidget.Widget2): void; +export declare function publicFunctionWithPrivateModuleParameterTypes1(param?: SpecializedGlobalWidget.Widget4): void; diff --git a/tests/baselines/reference/privacyFunctionCannotNameReturnTypeDeclFile.js b/tests/baselines/reference/privacyFunctionCannotNameReturnTypeDeclFile.js index 2861e33a27e49..3114e60d414a3 100644 --- a/tests/baselines/reference/privacyFunctionCannotNameReturnTypeDeclFile.js +++ b/tests/baselines/reference/privacyFunctionCannotNameReturnTypeDeclFile.js @@ -389,23 +389,25 @@ export declare function createExportedWidget3(): Widgets1.Widget3; export declare function createExportedWidget4(): Widgets1.SpecializedGlobalWidget.Widget4; //// [privacyFunctionReturnTypeDeclFile_consumer.d.ts] /// +import { type Widget1, type SpecializedWidget } from "./privacyFunctionReturnTypeDeclFile_Widgets"; +import { type Widget3, type SpecializedGlobalWidget } from "GlobalWidgets"; export declare class publicClassWithWithPrivateParmeterTypes { - static myPublicStaticMethod(): import("./privacyFunctionReturnTypeDeclFile_Widgets").Widget1; + static myPublicStaticMethod(): Widget1; private static myPrivateStaticMethod; - myPublicMethod(): import("./privacyFunctionReturnTypeDeclFile_Widgets").Widget1; + myPublicMethod(): Widget1; private myPrivateMethod; - static myPublicStaticMethod1(): import("GlobalWidgets").Widget3; + static myPublicStaticMethod1(): Widget3; private static myPrivateStaticMethod1; - myPublicMethod1(): import("GlobalWidgets").Widget3; + myPublicMethod1(): Widget3; private myPrivateMethod1; } -export declare function publicFunctionWithPrivateParmeterTypes(): import("./privacyFunctionReturnTypeDeclFile_Widgets").Widget1; -export declare function publicFunctionWithPrivateParmeterTypes1(): import("GlobalWidgets").Widget3; +export declare function publicFunctionWithPrivateParmeterTypes(): Widget1; +export declare function publicFunctionWithPrivateParmeterTypes1(): Widget3; export declare class publicClassWithPrivateModuleReturnTypes { - static myPublicStaticMethod(): import("./privacyFunctionReturnTypeDeclFile_Widgets").SpecializedWidget.Widget2; - myPublicMethod(): import("./privacyFunctionReturnTypeDeclFile_Widgets").SpecializedWidget.Widget2; - static myPublicStaticMethod1(): import("GlobalWidgets").SpecializedGlobalWidget.Widget4; - myPublicMethod1(): import("GlobalWidgets").SpecializedGlobalWidget.Widget4; + static myPublicStaticMethod(): SpecializedWidget.Widget2; + myPublicMethod(): SpecializedWidget.Widget2; + static myPublicStaticMethod1(): SpecializedGlobalWidget.Widget4; + myPublicMethod1(): SpecializedGlobalWidget.Widget4; } -export declare function publicFunctionWithPrivateModuleReturnTypes(): import("./privacyFunctionReturnTypeDeclFile_Widgets").SpecializedWidget.Widget2; -export declare function publicFunctionWithPrivateModuleReturnTypes1(): import("GlobalWidgets").SpecializedGlobalWidget.Widget4; +export declare function publicFunctionWithPrivateModuleReturnTypes(): SpecializedWidget.Widget2; +export declare function publicFunctionWithPrivateModuleReturnTypes1(): SpecializedGlobalWidget.Widget4; diff --git a/tests/baselines/reference/reactTransitiveImportHasValidDeclaration.js b/tests/baselines/reference/reactTransitiveImportHasValidDeclaration.js index 1ac4b0dd6b45b..264dc51b0c686 100644 --- a/tests/baselines/reference/reactTransitiveImportHasValidDeclaration.js +++ b/tests/baselines/reference/reactTransitiveImportHasValidDeclaration.js @@ -44,5 +44,6 @@ exports["default"] = Form; //// [index.d.ts] /// -declare const Form: import("create-emotion-styled").StyledOtherComponent<{}, import("react").DetailedHTMLProps, HTMLDivElement>, any>; +import { type DetailedHTMLProps, type HTMLAttributes } from "react"; +declare const Form: import("create-emotion-styled").StyledOtherComponent<{}, DetailedHTMLProps, HTMLDivElement>, any>; export default Form; diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js index d3dda8098c8c9..560c54231d06d 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js @@ -42,5 +42,6 @@ exports.va2 = (0, other_1.fa)(); //// [main.d.ts] -export declare const va: import("ext").A2; -export declare const va2: import("ext").A2; +import { type A2 } from "ext"; +export declare const va: A2; +export declare const va2: A2; diff --git a/tests/cases/compiler/declarationEmitImportTypeCoalesceing.ts b/tests/cases/compiler/declarationEmitImportTypeCoalesceing.ts new file mode 100644 index 0000000000000..e72bea78ecaaa --- /dev/null +++ b/tests/cases/compiler/declarationEmitImportTypeCoalesceing.ts @@ -0,0 +1,28 @@ +// @declaration: true +// @filename: whole.d.ts +declare namespace thing { + export const a = 1; + export interface A {} + export function getNs(): typeof thing; +} +export = thing; +// @filename: types.d.ts +export interface A {} +export interface B {} +export interface C {} + +export declare function getA(): A; +export declare function getB(): B; +export declare function getC(): C; +// @filename: index.ts + +import { getA } from "./types"; +import { getNs } from "./whole"; + +export const a1 = getA(); +export const a2 = [getA()]; +export const a3 = { a: getA() }; + +export const ns1 = getNs(); +export const ns2 = [getNs()]; +export const ns3 = { a: getNs() }; From d989109d5670ae30c64490a3f0617e5399b1599b Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 29 Jun 2022 05:46:16 -0700 Subject: [PATCH 3/3] Add prettyDeclaration compiler option to toggle off new declaration emit layer --- src/compiler/commandLineParser.ts | 10 +++ src/compiler/diagnosticMessages.json | 8 ++ src/compiler/transformer.ts | 8 +- src/compiler/types.ts | 1 + src/compiler/utilities.ts | 4 + .../reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + .../declarationEmitImportTypeCoalesceing.js | 22 ++++-- ...clarationEmitImportTypeCoalesceing.symbols | 36 ++++++--- ...declarationEmitImportTypeCoalesceing.types | 27 ++++++- ...rtTypeCoalesceingPrettyDeclarationFalse.js | 55 ++++++++++++++ ...eCoalesceingPrettyDeclarationFalse.symbols | 72 ++++++++++++++++++ ...ypeCoalesceingPrettyDeclarationFalse.types | 73 +++++++++++++++++++ .../prettyDeclaration/tsconfig.json | 5 ++ .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../declarationDir-is-specified.js | 1 + ...-outDir-and-declarationDir-is-specified.js | 1 + .../when-outDir-is-specified.js | 1 + .../with-outFile.js | 1 + ...e-is-specified-with-declaration-enabled.js | 1 + .../without-outDir-or-outFile-is-specified.js | 1 + .../declarationEmitImportTypeCoalesceing.ts | 10 ++- ...rtTypeCoalesceingPrettyDeclarationFalse.ts | 29 ++++++++ 31 files changed, 352 insertions(+), 25 deletions(-) create mode 100644 tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.js create mode 100644 tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.symbols create mode 100644 tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.types create mode 100644 tests/baselines/reference/showConfig/Shows tsconfig for single option/prettyDeclaration/tsconfig.json create mode 100644 tests/cases/compiler/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.ts diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 370461abd8559..c6332b313f790 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -510,6 +510,16 @@ namespace ts { defaultValueDescription: false, description: Diagnostics.Create_sourcemaps_for_d_ts_files }, + { + name: "prettyDeclaration", + type: "boolean", + affectsEmit: true, + affectsMultiFileEmitBuildInfo: true, + category: Diagnostics.Emit, + transpileOptionValue: undefined, + description: Diagnostics.Enable_extra_transform_stages_that_make_declaration_emit_output_prettier, + defaultValueDescription: Diagnostics.true_if_declaration_is_true_false_otherwise, + }, { name: "emitDeclarationOnly", type: "boolean", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 3a7f155f12d82..393e3d9467c93 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -5835,6 +5835,14 @@ "category": "Message", "code": 6803 }, + "Enable extra transform stages that make declaration emit output prettier.": { + "category": "Message", + "code": 6804 + }, + "true if declaration is true, false otherwise.": { + "category": "Message", + "code": 6805 + }, "one of:": { "category": "Message", diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index d2d4cbc0dc6f0..5f190321d569d 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -34,7 +34,7 @@ namespace ts { export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers, emitOnlyDtsFiles?: boolean): EmitTransformers { return { scriptTransformers: getScriptTransformers(compilerOptions, customTransformers, emitOnlyDtsFiles), - declarationTransformers: getDeclarationTransformers(customTransformers), + declarationTransformers: getDeclarationTransformers(compilerOptions, customTransformers), }; } @@ -100,10 +100,12 @@ namespace ts { return transformers; } - function getDeclarationTransformers(customTransformers?: CustomTransformers) { + function getDeclarationTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers) { const transformers: TransformerFactory[] = []; transformers.push(transformDeclarations); - transformers.push(transformCoalesceImports); + if (getEmitPrettyDeclarations(compilerOptions)) { + transformers.push(transformCoalesceImports); + } addRange(transformers, customTransformers && map(customTransformers.afterDeclarations, wrapDeclarationTransformerFactory)); return transformers; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 260e6b26ebcb0..d128e131cadb0 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -6315,6 +6315,7 @@ namespace ts { declaration?: boolean; declarationMap?: boolean; emitDeclarationOnly?: boolean; + prettyDeclaration?: boolean; declarationDir?: string; /* @internal */ diagnostics?: boolean; /* @internal */ extendedDiagnostics?: boolean; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 0ac57b26fee15..9ede3591d2d7f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6444,6 +6444,10 @@ namespace ts { return !!(compilerOptions.declaration || compilerOptions.composite); } + export function getEmitPrettyDeclarations(compilerOptions: CompilerOptions): boolean { + return compilerOptions.prettyDeclaration !== undefined ? !!compilerOptions.prettyDeclaration : !!compilerOptions.declaration; + } + export function shouldPreserveConstEnums(compilerOptions: CompilerOptions): boolean { return !!(compilerOptions.preserveConstEnums || compilerOptions.isolatedModules); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index fb15ec4f0113b..b37e1d4afd809 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2981,6 +2981,7 @@ declare namespace ts { declaration?: boolean; declarationMap?: boolean; emitDeclarationOnly?: boolean; + prettyDeclaration?: boolean; declarationDir?: string; disableSizeLimit?: boolean; disableSourceOfProjectReferenceRedirect?: boolean; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index ed87f7ef8913b..7eb75ffb7d775 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2981,6 +2981,7 @@ declare namespace ts { declaration?: boolean; declarationMap?: boolean; emitDeclarationOnly?: boolean; + prettyDeclaration?: boolean; declarationDir?: string; disableSizeLimit?: boolean; disableSourceOfProjectReferenceRedirect?: boolean; diff --git a/tests/baselines/reference/declarationEmitImportTypeCoalesceing.js b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.js index e835d210e2fb4..fe471b6075cc4 100644 --- a/tests/baselines/reference/declarationEmitImportTypeCoalesceing.js +++ b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.js @@ -9,20 +9,24 @@ declare namespace thing { export = thing; //// [types.d.ts] export interface A {} -export interface B {} +export interface B {} export interface C {} export declare function getA(): A; -export declare function getB(): B; +export declare function getB(): B; export declare function getC(): C; //// [index.ts] -import { getA } from "./types"; +import { getA, getB } from "./types"; import { getNs } from "./whole"; export const a1 = getA(); export const a2 = [getA()]; export const a3 = { a: getA() }; +export const b1 = getB(); +export const b2 = [getB()]; +export const b3 = { a: getB() }; + export const ns1 = getNs(); export const ns2 = [getNs()]; export const ns3 = { a: getNs() }; @@ -31,12 +35,15 @@ export const ns3 = { a: getNs() }; //// [index.js] "use strict"; exports.__esModule = true; -exports.ns3 = exports.ns2 = exports.ns1 = exports.a3 = exports.a2 = exports.a1 = void 0; +exports.ns3 = exports.ns2 = exports.ns1 = exports.b3 = exports.b2 = exports.b1 = exports.a3 = exports.a2 = exports.a1 = void 0; var types_1 = require("./types"); var whole_1 = require("./whole"); exports.a1 = (0, types_1.getA)(); exports.a2 = [(0, types_1.getA)()]; exports.a3 = { a: (0, types_1.getA)() }; +exports.b1 = (0, types_1.getB)(); +exports.b2 = [(0, types_1.getB)()]; +exports.b3 = { a: (0, types_1.getB)() }; exports.ns1 = (0, whole_1.getNs)(); exports.ns2 = [(0, whole_1.getNs)()]; exports.ns3 = { a: (0, whole_1.getNs)() }; @@ -44,12 +51,17 @@ exports.ns3 = { a: (0, whole_1.getNs)() }; //// [index.d.ts] import type * as _ns_1 from "./whole"; -import { type A } from "./types"; +import { type A, type B, type C } from "./types"; export declare const a1: A; export declare const a2: A[]; export declare const a3: { a: A; }; +export declare const b1: B; +export declare const b2: B[]; +export declare const b3: { + a: B; +}; export declare const ns1: typeof _ns_1; export declare const ns2: (typeof _ns_1)[]; export declare const ns3: { diff --git a/tests/baselines/reference/declarationEmitImportTypeCoalesceing.symbols b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.symbols index 2290ca6739178..910993578ebb0 100644 --- a/tests/baselines/reference/declarationEmitImportTypeCoalesceing.symbols +++ b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.symbols @@ -19,27 +19,30 @@ export = thing; export interface A {} >A : Symbol(A, Decl(types.d.ts, 0, 0)) -export interface B {} +export interface B {} >B : Symbol(B, Decl(types.d.ts, 0, 21)) +>T : Symbol(T, Decl(types.d.ts, 1, 19)) export interface C {} ->C : Symbol(C, Decl(types.d.ts, 1, 21)) +>C : Symbol(C, Decl(types.d.ts, 1, 24)) export declare function getA(): A; >getA : Symbol(getA, Decl(types.d.ts, 2, 21)) >A : Symbol(A, Decl(types.d.ts, 0, 0)) -export declare function getB(): B; +export declare function getB(): B; >getB : Symbol(getB, Decl(types.d.ts, 4, 34)) >B : Symbol(B, Decl(types.d.ts, 0, 21)) +>C : Symbol(C, Decl(types.d.ts, 1, 24)) export declare function getC(): C; ->getC : Symbol(getC, Decl(types.d.ts, 5, 34)) ->C : Symbol(C, Decl(types.d.ts, 1, 21)) +>getC : Symbol(getC, Decl(types.d.ts, 5, 37)) +>C : Symbol(C, Decl(types.d.ts, 1, 24)) === tests/cases/compiler/index.ts === -import { getA } from "./types"; +import { getA, getB } from "./types"; >getA : Symbol(getA, Decl(index.ts, 0, 8)) +>getB : Symbol(getB, Decl(index.ts, 0, 14)) import { getNs } from "./whole"; >getNs : Symbol(getNs, Decl(index.ts, 1, 8)) @@ -57,16 +60,29 @@ export const a3 = { a: getA() }; >a : Symbol(a, Decl(index.ts, 5, 19)) >getA : Symbol(getA, Decl(index.ts, 0, 8)) +export const b1 = getB(); +>b1 : Symbol(b1, Decl(index.ts, 7, 12)) +>getB : Symbol(getB, Decl(index.ts, 0, 14)) + +export const b2 = [getB()]; +>b2 : Symbol(b2, Decl(index.ts, 8, 12)) +>getB : Symbol(getB, Decl(index.ts, 0, 14)) + +export const b3 = { a: getB() }; +>b3 : Symbol(b3, Decl(index.ts, 9, 12)) +>a : Symbol(a, Decl(index.ts, 9, 19)) +>getB : Symbol(getB, Decl(index.ts, 0, 14)) + export const ns1 = getNs(); ->ns1 : Symbol(ns1, Decl(index.ts, 7, 12)) +>ns1 : Symbol(ns1, Decl(index.ts, 11, 12)) >getNs : Symbol(getNs, Decl(index.ts, 1, 8)) export const ns2 = [getNs()]; ->ns2 : Symbol(ns2, Decl(index.ts, 8, 12)) +>ns2 : Symbol(ns2, Decl(index.ts, 12, 12)) >getNs : Symbol(getNs, Decl(index.ts, 1, 8)) export const ns3 = { a: getNs() }; ->ns3 : Symbol(ns3, Decl(index.ts, 9, 12)) ->a : Symbol(a, Decl(index.ts, 9, 20)) +>ns3 : Symbol(ns3, Decl(index.ts, 13, 12)) +>a : Symbol(a, Decl(index.ts, 13, 20)) >getNs : Symbol(getNs, Decl(index.ts, 1, 8)) diff --git a/tests/baselines/reference/declarationEmitImportTypeCoalesceing.types b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.types index eb6c266ee060b..1a9655403139a 100644 --- a/tests/baselines/reference/declarationEmitImportTypeCoalesceing.types +++ b/tests/baselines/reference/declarationEmitImportTypeCoalesceing.types @@ -16,21 +16,22 @@ export = thing; === tests/cases/compiler/types.d.ts === export interface A {} -export interface B {} +export interface B {} export interface C {} export declare function getA(): A; >getA : () => A -export declare function getB(): B; ->getB : () => B +export declare function getB(): B; +>getB : () => B export declare function getC(): C; >getC : () => C === tests/cases/compiler/index.ts === -import { getA } from "./types"; +import { getA, getB } from "./types"; >getA : () => import("tests/cases/compiler/types").A +>getB : () => import("tests/cases/compiler/types").B import { getNs } from "./whole"; >getNs : () => typeof import("tests/cases/compiler/whole") @@ -53,6 +54,24 @@ export const a3 = { a: getA() }; >getA() : import("tests/cases/compiler/types").A >getA : () => import("tests/cases/compiler/types").A +export const b1 = getB(); +>b1 : import("tests/cases/compiler/types").B +>getB() : import("tests/cases/compiler/types").B +>getB : () => import("tests/cases/compiler/types").B + +export const b2 = [getB()]; +>b2 : import("tests/cases/compiler/types").B[] +>[getB()] : import("tests/cases/compiler/types").B[] +>getB() : import("tests/cases/compiler/types").B +>getB : () => import("tests/cases/compiler/types").B + +export const b3 = { a: getB() }; +>b3 : { a: import("tests/cases/compiler/types").B; } +>{ a: getB() } : { a: import("tests/cases/compiler/types").B; } +>a : import("tests/cases/compiler/types").B +>getB() : import("tests/cases/compiler/types").B +>getB : () => import("tests/cases/compiler/types").B + export const ns1 = getNs(); >ns1 : typeof import("tests/cases/compiler/whole") >getNs() : typeof import("tests/cases/compiler/whole") diff --git a/tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.js b/tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.js new file mode 100644 index 0000000000000..235e6e247e2f4 --- /dev/null +++ b/tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.js @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.ts] //// + +//// [whole.d.ts] +declare namespace thing { + export const a = 1; + export interface A {} + export function getNs(): typeof thing; +} +export = thing; +//// [types.d.ts] +export interface A {} +export interface B {} +export interface C {} + +export declare function getA(): A; +export declare function getB(): B; +export declare function getC(): C; +//// [index.ts] +import { getA } from "./types"; +import { getNs } from "./whole"; + +export const a1 = getA(); +export const a2 = [getA()]; +export const a3 = { a: getA() }; + +export const ns1 = getNs(); +export const ns2 = [getNs()]; +export const ns3 = { a: getNs() }; + + +//// [index.js] +"use strict"; +exports.__esModule = true; +exports.ns3 = exports.ns2 = exports.ns1 = exports.a3 = exports.a2 = exports.a1 = void 0; +var types_1 = require("./types"); +var whole_1 = require("./whole"); +exports.a1 = (0, types_1.getA)(); +exports.a2 = [(0, types_1.getA)()]; +exports.a3 = { a: (0, types_1.getA)() }; +exports.ns1 = (0, whole_1.getNs)(); +exports.ns2 = [(0, whole_1.getNs)()]; +exports.ns3 = { a: (0, whole_1.getNs)() }; + + +//// [index.d.ts] +export declare const a1: import("./types").A; +export declare const a2: import("./types").A[]; +export declare const a3: { + a: import("./types").A; +}; +export declare const ns1: typeof import("./whole"); +export declare const ns2: typeof import("./whole")[]; +export declare const ns3: { + a: typeof import("./whole"); +}; diff --git a/tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.symbols b/tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.symbols new file mode 100644 index 0000000000000..2290ca6739178 --- /dev/null +++ b/tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.symbols @@ -0,0 +1,72 @@ +=== tests/cases/compiler/whole.d.ts === +declare namespace thing { +>thing : Symbol(thing, Decl(whole.d.ts, 0, 0)) + + export const a = 1; +>a : Symbol(a, Decl(whole.d.ts, 1, 16)) + + export interface A {} +>A : Symbol(A, Decl(whole.d.ts, 1, 23)) + + export function getNs(): typeof thing; +>getNs : Symbol(getNs, Decl(whole.d.ts, 2, 25)) +>thing : Symbol(thing, Decl(whole.d.ts, 0, 0)) +} +export = thing; +>thing : Symbol(thing, Decl(whole.d.ts, 0, 0)) + +=== tests/cases/compiler/types.d.ts === +export interface A {} +>A : Symbol(A, Decl(types.d.ts, 0, 0)) + +export interface B {} +>B : Symbol(B, Decl(types.d.ts, 0, 21)) + +export interface C {} +>C : Symbol(C, Decl(types.d.ts, 1, 21)) + +export declare function getA(): A; +>getA : Symbol(getA, Decl(types.d.ts, 2, 21)) +>A : Symbol(A, Decl(types.d.ts, 0, 0)) + +export declare function getB(): B; +>getB : Symbol(getB, Decl(types.d.ts, 4, 34)) +>B : Symbol(B, Decl(types.d.ts, 0, 21)) + +export declare function getC(): C; +>getC : Symbol(getC, Decl(types.d.ts, 5, 34)) +>C : Symbol(C, Decl(types.d.ts, 1, 21)) + +=== tests/cases/compiler/index.ts === +import { getA } from "./types"; +>getA : Symbol(getA, Decl(index.ts, 0, 8)) + +import { getNs } from "./whole"; +>getNs : Symbol(getNs, Decl(index.ts, 1, 8)) + +export const a1 = getA(); +>a1 : Symbol(a1, Decl(index.ts, 3, 12)) +>getA : Symbol(getA, Decl(index.ts, 0, 8)) + +export const a2 = [getA()]; +>a2 : Symbol(a2, Decl(index.ts, 4, 12)) +>getA : Symbol(getA, Decl(index.ts, 0, 8)) + +export const a3 = { a: getA() }; +>a3 : Symbol(a3, Decl(index.ts, 5, 12)) +>a : Symbol(a, Decl(index.ts, 5, 19)) +>getA : Symbol(getA, Decl(index.ts, 0, 8)) + +export const ns1 = getNs(); +>ns1 : Symbol(ns1, Decl(index.ts, 7, 12)) +>getNs : Symbol(getNs, Decl(index.ts, 1, 8)) + +export const ns2 = [getNs()]; +>ns2 : Symbol(ns2, Decl(index.ts, 8, 12)) +>getNs : Symbol(getNs, Decl(index.ts, 1, 8)) + +export const ns3 = { a: getNs() }; +>ns3 : Symbol(ns3, Decl(index.ts, 9, 12)) +>a : Symbol(a, Decl(index.ts, 9, 20)) +>getNs : Symbol(getNs, Decl(index.ts, 1, 8)) + diff --git a/tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.types b/tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.types new file mode 100644 index 0000000000000..eb6c266ee060b --- /dev/null +++ b/tests/baselines/reference/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.types @@ -0,0 +1,73 @@ +=== tests/cases/compiler/whole.d.ts === +declare namespace thing { +>thing : typeof thing + + export const a = 1; +>a : 1 +>1 : 1 + + export interface A {} + export function getNs(): typeof thing; +>getNs : () => typeof thing +>thing : typeof thing +} +export = thing; +>thing : typeof thing + +=== tests/cases/compiler/types.d.ts === +export interface A {} +export interface B {} +export interface C {} + +export declare function getA(): A; +>getA : () => A + +export declare function getB(): B; +>getB : () => B + +export declare function getC(): C; +>getC : () => C + +=== tests/cases/compiler/index.ts === +import { getA } from "./types"; +>getA : () => import("tests/cases/compiler/types").A + +import { getNs } from "./whole"; +>getNs : () => typeof import("tests/cases/compiler/whole") + +export const a1 = getA(); +>a1 : import("tests/cases/compiler/types").A +>getA() : import("tests/cases/compiler/types").A +>getA : () => import("tests/cases/compiler/types").A + +export const a2 = [getA()]; +>a2 : import("tests/cases/compiler/types").A[] +>[getA()] : import("tests/cases/compiler/types").A[] +>getA() : import("tests/cases/compiler/types").A +>getA : () => import("tests/cases/compiler/types").A + +export const a3 = { a: getA() }; +>a3 : { a: import("tests/cases/compiler/types").A; } +>{ a: getA() } : { a: import("tests/cases/compiler/types").A; } +>a : import("tests/cases/compiler/types").A +>getA() : import("tests/cases/compiler/types").A +>getA : () => import("tests/cases/compiler/types").A + +export const ns1 = getNs(); +>ns1 : typeof import("tests/cases/compiler/whole") +>getNs() : typeof import("tests/cases/compiler/whole") +>getNs : () => typeof import("tests/cases/compiler/whole") + +export const ns2 = [getNs()]; +>ns2 : typeof import("tests/cases/compiler/whole")[] +>[getNs()] : typeof import("tests/cases/compiler/whole")[] +>getNs() : typeof import("tests/cases/compiler/whole") +>getNs : () => typeof import("tests/cases/compiler/whole") + +export const ns3 = { a: getNs() }; +>ns3 : { a: typeof import("tests/cases/compiler/whole"); } +>{ a: getNs() } : { a: typeof import("tests/cases/compiler/whole"); } +>a : typeof import("tests/cases/compiler/whole") +>getNs() : typeof import("tests/cases/compiler/whole") +>getNs : () => typeof import("tests/cases/compiler/whole") + diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/prettyDeclaration/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/prettyDeclaration/tsconfig.json new file mode 100644 index 0000000000000..430b643bd7c00 --- /dev/null +++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/prettyDeclaration/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "prettyDeclaration": true + } +} diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index 75dcaeac2e2b9..95e6f74dcaf01 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -46,6 +46,7 @@ /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json index ce36f2a0fcfd7..7a13b7560de76 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json @@ -46,6 +46,7 @@ /* Emit */ "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index a4be57dd3410e..fb96731409f58 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -46,6 +46,7 @@ /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index faa350ae98575..ce6dbdc1e491d 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -46,6 +46,7 @@ /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index 09587994ffbcd..3da3f9b8b2c48 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -46,6 +46,7 @@ /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index abb2dfd47088b..a07ba6952fc64 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -46,6 +46,7 @@ /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index 75dcaeac2e2b9..95e6f74dcaf01 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -46,6 +46,7 @@ /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index 04aa9196bfc65..d963249bf3fe3 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -46,6 +46,7 @@ /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index 4eb9bb8aa4b84..8556145e37ce3 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -46,6 +46,7 @@ /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js index e3fc789404c06..3c0ba7c16c357 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js @@ -67,6 +67,7 @@ interface Array { length: number; [n: number]: T; } /* Emit */ "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js index 620c42fa2a32c..8332667297ff5 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js @@ -67,6 +67,7 @@ interface Array { length: number; [n: number]: T; } /* Emit */ "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js index 6800711e1a42f..af8d3b0ed178e 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js @@ -67,6 +67,7 @@ interface Array { length: number; [n: number]: T; } /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js index 7b96140fceb23..b73ed05a6f06a 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js @@ -67,6 +67,7 @@ interface Array { length: number; [n: number]: T; } /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ "outFile": "build/outFile.js", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js index 1b21f2ca83fcc..fbc4bb5d7ca65 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js @@ -67,6 +67,7 @@ interface Array { length: number; [n: number]: T; } /* Emit */ "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js index 1b80ab46e46ad..7cc158e04c5cd 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js @@ -67,6 +67,7 @@ interface Array { length: number; [n: number]: T; } /* Emit */ // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "prettyDeclaration": true, /* Enable extra transform stages that make declaration emit output prettier. */ // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ diff --git a/tests/cases/compiler/declarationEmitImportTypeCoalesceing.ts b/tests/cases/compiler/declarationEmitImportTypeCoalesceing.ts index e72bea78ecaaa..857a8028c6b2e 100644 --- a/tests/cases/compiler/declarationEmitImportTypeCoalesceing.ts +++ b/tests/cases/compiler/declarationEmitImportTypeCoalesceing.ts @@ -8,21 +8,25 @@ declare namespace thing { export = thing; // @filename: types.d.ts export interface A {} -export interface B {} +export interface B {} export interface C {} export declare function getA(): A; -export declare function getB(): B; +export declare function getB(): B; export declare function getC(): C; // @filename: index.ts -import { getA } from "./types"; +import { getA, getB } from "./types"; import { getNs } from "./whole"; export const a1 = getA(); export const a2 = [getA()]; export const a3 = { a: getA() }; +export const b1 = getB(); +export const b2 = [getB()]; +export const b3 = { a: getB() }; + export const ns1 = getNs(); export const ns2 = [getNs()]; export const ns3 = { a: getNs() }; diff --git a/tests/cases/compiler/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.ts b/tests/cases/compiler/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.ts new file mode 100644 index 0000000000000..68b03ef23eb7d --- /dev/null +++ b/tests/cases/compiler/declarationEmitImportTypeCoalesceingPrettyDeclarationFalse.ts @@ -0,0 +1,29 @@ +// @declaration: true +// @prettyDeclaration: false +// @filename: whole.d.ts +declare namespace thing { + export const a = 1; + export interface A {} + export function getNs(): typeof thing; +} +export = thing; +// @filename: types.d.ts +export interface A {} +export interface B {} +export interface C {} + +export declare function getA(): A; +export declare function getB(): B; +export declare function getC(): C; +// @filename: index.ts + +import { getA } from "./types"; +import { getNs } from "./whole"; + +export const a1 = getA(); +export const a2 = [getA()]; +export const a3 = { a: getA() }; + +export const ns1 = getNs(); +export const ns2 = [getNs()]; +export const ns3 = { a: getNs() };