From 501e442ffc487526a3bd9b850dcaeb4fe4ff4e68 Mon Sep 17 00:00:00 2001 From: Will Nayes Date: Tue, 5 Jul 2022 11:08:43 -0500 Subject: [PATCH] Elide import equals in transpileModule if referenced only by export type (#49664) * Elide import equals in transpileModule if referenced only by export type. * Revise approach to avoid marking alias in export type as referenced. * Handle type only export specifier. --- src/compiler/checker.ts | 27 ++++++++++++++++--- .../unittests/services/transpile.ts | 14 ++++++++++ ...t equals referenced only by export type.js | 3 +++ ...renced only by export type.oldTranspile.js | 3 +++ ...nced only by type only export specifier.js | 3 +++ ...type only export specifier.oldTranspile.js | 3 +++ 6 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/transpile/Elides import equals referenced only by export type.js create mode 100644 tests/baselines/reference/transpile/Elides import equals referenced only by export type.oldTranspile.js create mode 100644 tests/baselines/reference/transpile/Elides import equals referenced only by type only export specifier.js create mode 100644 tests/baselines/reference/transpile/Elides import equals referenced only by type only export specifier.oldTranspile.js diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 11ac767e5ae..e2c436e9776 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25783,9 +25783,7 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n") return getTypeOfSymbol(symbol); } - // We should only mark aliases as referenced if there isn't a local value declaration - // for the symbol. Also, don't mark any property access expression LHS - checkPropertyAccessExpression will handle that - if (!(node.parent && isPropertyAccessExpression(node.parent) && node.parent.expression === node)) { + if (shouldMarkIdentifierAliasReferenced(node)) { markAliasReferenced(symbol, node); } @@ -25933,6 +25931,25 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n") return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType; } + function shouldMarkIdentifierAliasReferenced(node: Identifier): boolean { + const parent = node.parent; + if (parent) { + // A property access expression LHS? checkPropertyAccessExpression will handle that. + if (isPropertyAccessExpression(parent) && parent.expression === node) { + return false; + } + // Next two check for an identifier inside a type only export. + if (isExportSpecifier(parent) && parent.isTypeOnly) { + return false; + } + const greatGrandparent = parent.parent?.parent; + if (greatGrandparent && isExportDeclaration(greatGrandparent) && greatGrandparent.isTypeOnly) { + return false; + } + } + return true; + } + function isInsideFunctionOrInstancePropertyInitializer(node: Node, threshold: Node): boolean { return !!findAncestor(node, n => n === threshold ? "quit" : isFunctionLike(n) || ( n.parent && isPropertyDeclaration(n.parent) && !hasStaticModifier(n.parent) && n.parent.initializer === n @@ -41307,7 +41324,9 @@ m2: ${(this.mapper2 as unknown as DebugTypeMapper).__debugToString().split("\n") error(exportedName, Diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, idText(exportedName)); } else { - markExportAsReferenced(node); + if (!node.isTypeOnly && !node.parent.parent.isTypeOnly) { + markExportAsReferenced(node); + } const target = symbol && (symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol); if (!target || target === unknownSymbol || target.flags & SymbolFlags.Value) { checkExpressionCached(node.propertyName || node.name); diff --git a/src/testRunner/unittests/services/transpile.ts b/src/testRunner/unittests/services/transpile.ts index 2e0c8ea2454..e0cfa72f53e 100644 --- a/src/testRunner/unittests/services/transpile.ts +++ b/src/testRunner/unittests/services/transpile.ts @@ -485,5 +485,19 @@ export { a as alias }; export * as alias from './file';`, { noSetFileName: true }); + + transpilesCorrectly("Elides import equals referenced only by export type", + `import IFoo = Namespace.IFoo;` + + `export type { IFoo };`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + } + ); + + transpilesCorrectly("Elides import equals referenced only by type only export specifier", + `import IFoo = Namespace.IFoo;` + + `export { type IFoo };`, { + options: { compilerOptions: { module: ModuleKind.CommonJS } } + } + ); }); } diff --git a/tests/baselines/reference/transpile/Elides import equals referenced only by export type.js b/tests/baselines/reference/transpile/Elides import equals referenced only by export type.js new file mode 100644 index 00000000000..e9493d9d591 --- /dev/null +++ b/tests/baselines/reference/transpile/Elides import equals referenced only by export type.js @@ -0,0 +1,3 @@ +"use strict"; +exports.__esModule = true; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Elides import equals referenced only by export type.oldTranspile.js b/tests/baselines/reference/transpile/Elides import equals referenced only by export type.oldTranspile.js new file mode 100644 index 00000000000..e9493d9d591 --- /dev/null +++ b/tests/baselines/reference/transpile/Elides import equals referenced only by export type.oldTranspile.js @@ -0,0 +1,3 @@ +"use strict"; +exports.__esModule = true; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Elides import equals referenced only by type only export specifier.js b/tests/baselines/reference/transpile/Elides import equals referenced only by type only export specifier.js new file mode 100644 index 00000000000..e9493d9d591 --- /dev/null +++ b/tests/baselines/reference/transpile/Elides import equals referenced only by type only export specifier.js @@ -0,0 +1,3 @@ +"use strict"; +exports.__esModule = true; +//# sourceMappingURL=file.js.map \ No newline at end of file diff --git a/tests/baselines/reference/transpile/Elides import equals referenced only by type only export specifier.oldTranspile.js b/tests/baselines/reference/transpile/Elides import equals referenced only by type only export specifier.oldTranspile.js new file mode 100644 index 00000000000..e9493d9d591 --- /dev/null +++ b/tests/baselines/reference/transpile/Elides import equals referenced only by type only export specifier.oldTranspile.js @@ -0,0 +1,3 @@ +"use strict"; +exports.__esModule = true; +//# sourceMappingURL=file.js.map \ No newline at end of file