diff --git a/internal/checker/emitresolver.go b/internal/checker/emitresolver.go index 7bf3719e58f..6054a2a7cd9 100644 --- a/internal/checker/emitresolver.go +++ b/internal/checker/emitresolver.go @@ -164,6 +164,13 @@ func (r *EmitResolver) determineIfDeclarationIsVisible(node *ast.Node) bool { // If the node is not exported or it is not ambient module element (except import declaration) if r.checker.getCombinedModifierFlagsCached(node)&ast.ModifierFlagsExport == 0 && !(node.Kind != ast.KindImportEqualsDeclaration && parent.Kind != ast.KindSourceFile && parent.Flags&ast.NodeFlagsAmbient != 0) { + // A declaration that is the target of an `export =` in its containing external + // module is externally visible, even though it isn't itself marked `export`. + // This mirrors the visibility marking done for export assignments, which would + // otherwise be skipped for modules that are referenced but never emitted. + if r.isExportEqualsTargetDeclaration(node) { + return true + } return ast.IsGlobalSourceFile(parent) } // Exported members/ambient module elements (exception import declaration) are visible if parent is visible @@ -233,6 +240,25 @@ func (r *EmitResolver) determineIfDeclarationIsVisible(node *ast.Node) bool { } } +// isExportEqualsTargetDeclaration reports whether the given declaration's symbol is the +// entity referenced by an `export =` in its containing external module. Such a declaration +// is externally visible because the `export =` re-exports it. +func (r *EmitResolver) isExportEqualsTargetDeclaration(node *ast.Node) bool { + symbol := r.checker.getSymbolOfDeclaration(node) + if symbol == nil { + return false + } + moduleSymbol := r.checker.getExternalModuleContainer(node) + if moduleSymbol == nil || moduleSymbol.Exports == nil { + return false + } + exportEquals := moduleSymbol.Exports[ast.InternalSymbolNameExportEquals] + if exportEquals == nil { + return false + } + return r.checker.getSymbolIfSameReference(exportEquals, symbol) != nil +} + func (r *EmitResolver) PrecalculateDeclarationEmitVisibility(file *ast.SourceFile) { r.checkerMu.Lock() defer r.checkerMu.Unlock() diff --git a/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.errors.txt b/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.errors.txt deleted file mode 100644 index 74964cf34b0..00000000000 --- a/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.errors.txt +++ /dev/null @@ -1,23 +0,0 @@ -/a.ts(3,26): error TS4060: Return type of exported function has or is using private name 'T'. - - -==== /node_modules/foo/index.d.ts (0 errors) ==== - export = foo; - declare namespace foo { - export type T = number; - } - -==== /a.ts (1 errors) ==== - import * as foo from "foo"; - declare module "foo" { - export function f(): T; // OK - ~ -!!! error TS4060: Return type of exported function has or is using private name 'T'. - } - -==== /b.ts (0 errors) ==== - import * as foo from "foo"; - declare module "foo" { - export function g(): foo.T; // OK - } - \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.js b/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.js index beb1cc76b9e..29fdf646b7e 100644 --- a/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.js +++ b/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.js @@ -27,6 +27,11 @@ Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "__esModule", { value: true }); +//// [a.d.ts] +declare module "foo" { + function f(): T; +} +export {}; //// [b.d.ts] import * as foo from "foo"; declare module "foo" { diff --git a/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.js.diff b/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.js.diff deleted file mode 100644 index 8329b7c720a..00000000000 --- a/testdata/baselines/reference/submodule/compiler/exportAssignmentMembersVisibleInAugmentation.js.diff +++ /dev/null @@ -1,14 +0,0 @@ ---- old.exportAssignmentMembersVisibleInAugmentation.js -+++ new.exportAssignmentMembersVisibleInAugmentation.js -@@= skipped -26, +26 lines =@@ - Object.defineProperty(exports, "__esModule", { value: true }); - - --//// [a.d.ts] --declare module "foo" { -- function f(): T; --} --export {}; - //// [b.d.ts] - import * as foo from "foo"; - declare module "foo" { \ No newline at end of file diff --git a/testdata/baselines/reference/submoduleTriaged/compiler/exportAssignmentMembersVisibleInAugmentation.errors.txt.diff b/testdata/baselines/reference/submoduleTriaged/compiler/exportAssignmentMembersVisibleInAugmentation.errors.txt.diff deleted file mode 100644 index 8deffb2f17a..00000000000 --- a/testdata/baselines/reference/submoduleTriaged/compiler/exportAssignmentMembersVisibleInAugmentation.errors.txt.diff +++ /dev/null @@ -1,27 +0,0 @@ ---- old.exportAssignmentMembersVisibleInAugmentation.errors.txt -+++ new.exportAssignmentMembersVisibleInAugmentation.errors.txt -@@= skipped -0, +0 lines =@@ -- -+/a.ts(3,26): error TS4060: Return type of exported function has or is using private name 'T'. -+ -+ -+==== /node_modules/foo/index.d.ts (0 errors) ==== -+ export = foo; -+ declare namespace foo { -+ export type T = number; -+ } -+ -+==== /a.ts (1 errors) ==== -+ import * as foo from "foo"; -+ declare module "foo" { -+ export function f(): T; // OK -+ ~ -+!!! error TS4060: Return type of exported function has or is using private name 'T'. -+ } -+ -+==== /b.ts (0 errors) ==== -+ import * as foo from "foo"; -+ declare module "foo" { -+ export function g(): foo.T; // OK -+ } -+ \ No newline at end of file diff --git a/testdata/submoduleTriaged.txt b/testdata/submoduleTriaged.txt index a5cc2830f8d..05f5afd4d52 100644 --- a/testdata/submoduleTriaged.txt +++ b/testdata/submoduleTriaged.txt @@ -30,7 +30,6 @@ compiler/declarationEmitTypeofRest.errors.txt.diff # Corsa changes how module augmentation interacts with export-equals and exported name visibility ## https://github.com/microsoft/typescript-go/issues/3481 compiler/augmentExportEquals2.errors.txt.diff -compiler/exportAssignmentMembersVisibleInAugmentation.errors.txt.diff # Corsa no longer emits the TS-1 internal diagnostic about pre-emit/post-emit diagnostic count mismatches ## https://github.com/microsoft/typescript-go/issues/3508