From cf0278bbac4202de0f5b5b603c5544c365bc0955 Mon Sep 17 00:00:00 2001 From: Gavin Kline Date: Fri, 9 Oct 2026 17:42:49 -1000 Subject: [PATCH 1/2] Create declaration emit diagnostic selectors on demand Every declaration visited by the declaration transformer installed a closure that selects the diagnostic to report if one of its symbols turns out to be inaccessible, and returned a second closure to restore the previous context. Almost no visited declaration reports such an error, so the closures were pure allocation overhead: about one in nine allocations of a type check with declaration emit enabled. The context now records the declaration node and builds the selector only when an accessibility error is reported. The handful of sites that need a custom selector keep passing a function. The saved context is a plain struct restored by a method, so the deferred restore no longer allocates. Co-Authored-By: Claude Fable 5.1 --- .../transformers/declarations/diagnostics.go | 18 +++ .../transformers/declarations/tracker.go | 20 +-- .../transformers/declarations/transform.go | 115 ++++++++++-------- 3 files changed, 91 insertions(+), 62 deletions(-) diff --git a/tsc/internal/transformers/declarations/diagnostics.go b/tsc/internal/transformers/declarations/diagnostics.go index 1050afa933eff..1999ad88f0fe4 100644 --- a/tsc/internal/transformers/declarations/diagnostics.go +++ b/tsc/internal/transformers/declarations/diagnostics.go @@ -9,6 +9,24 @@ import ( type GetSymbolAccessibilityDiagnostic = func(symbolAccessibilityResult printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic +// symbolAccessibilityDiagnosticContext selects the diagnostic reported when a declaration uses a +// symbol that cannot be named. Nearly every visited declaration establishes a context and almost +// none of them report an error, so the selector for a declaration node is created only on demand. +type symbolAccessibilityDiagnosticContext struct { + node *ast.Node // declaration whose selector is created when needed + fn GetSymbolAccessibilityDiagnostic // explicit selector, used instead of node when set +} + +func (ctx symbolAccessibilityDiagnosticContext) get(symbolAccessibilityResult printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { + if ctx.fn != nil { + return ctx.fn(symbolAccessibilityResult) + } + if ctx.node != nil { + return createGetSymbolAccessibilityDiagnosticForNode(ctx.node)(symbolAccessibilityResult) + } + return nil +} + type SymbolAccessibilityDiagnostic struct { errorNode *ast.Node diagnosticMessage *diagnostics.Message diff --git a/tsc/internal/transformers/declarations/tracker.go b/tsc/internal/transformers/declarations/tracker.go index 14d0fcd5e5032..d4f3dbcf7d898 100644 --- a/tsc/internal/transformers/declarations/tracker.go +++ b/tsc/internal/transformers/declarations/tracker.go @@ -214,7 +214,7 @@ func (s *SymbolTrackerImpl) handleSymbolAccessibilityError(symbolAccessibilityRe // The checker should issue errors on unresolvable names, skip the declaration emit error for using a private/unreachable name for those } else if symbolAccessibilityResult.Accessibility != printer.SymbolAccessibilityNotResolved { // Report error - errorInfo := s.state.getSymbolAccessibilityDiagnostic(symbolAccessibilityResult) + errorInfo := s.state.diagnosticContext.get(symbolAccessibilityResult) if errorInfo != nil { info := *errorInfo diagNode := symbolAccessibilityResult.ErrorNode @@ -237,15 +237,15 @@ func createDiagnosticForNode(node *ast.Node, message *diagnostics.Message, args } type SymbolTrackerSharedState struct { - lateMarkedStatements []*ast.Node - diagnostics []*ast.Diagnostic - getSymbolAccessibilityDiagnostic GetSymbolAccessibilityDiagnostic - errorNameNode *ast.Node - isolatedDeclarations bool - stripInternal bool - currentSourceFile *ast.SourceFile - resolver printer.EmitResolver - reportExpandoFunctionErrors func(node *ast.Node) + lateMarkedStatements []*ast.Node + diagnostics []*ast.Diagnostic + diagnosticContext symbolAccessibilityDiagnosticContext + errorNameNode *ast.Node + isolatedDeclarations bool + stripInternal bool + currentSourceFile *ast.SourceFile + resolver printer.EmitResolver + reportExpandoFunctionErrors func(node *ast.Node) } func (s *SymbolTrackerSharedState) addDiagnostic(diag *ast.Diagnostic) { diff --git a/tsc/internal/transformers/declarations/transform.go b/tsc/internal/transformers/declarations/transform.go index f0187f2f2590c..69b026fbdade0 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -285,7 +285,7 @@ func (tx *DeclarationTransformer) visitSourceFile(node *ast.SourceFile) *ast.Nod tx.needsScopeFixMarker = false tx.resultHasScopeMarker = false tx.enclosingDeclaration = node.AsNode() - tx.state.getSymbolAccessibilityDiagnostic = throwDiagnostic + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{fn: throwDiagnostic} tx.resultHasExternalModuleIndicator = false tx.suppressNewDiagnosticContexts = false tx.state.lateMarkedStatements = make([]*ast.Node, 0) @@ -542,26 +542,37 @@ func (tx *DeclarationTransformer) getTypeReferences() (result []*ast.FileReferen return result } -func (tx *DeclarationTransformer) setupDiagnosticContext(input *ast.Node) (bool, func()) { +// savedDiagnosticContext is the state that restoreDiagnosticContext reinstates once a declaration has been visited. +type savedDiagnosticContext struct { + diagnosticContext symbolAccessibilityDiagnosticContext + errorNameNode *ast.Node + suppressNewDiagnosticContexts bool +} + +func (tx *DeclarationTransformer) setupDiagnosticContext(input *ast.Node) (bool, savedDiagnosticContext) { canProduceDiagnostic := canProduceDiagnostics(input) - oldWithinObjectLiteralType := tx.suppressNewDiagnosticContexts + saved := savedDiagnosticContext{ + diagnosticContext: tx.state.diagnosticContext, + errorNameNode: tx.state.errorNameNode, + suppressNewDiagnosticContexts: tx.suppressNewDiagnosticContexts, + } shouldEnterSuppressNewDiagnosticsContextContext := (input.Kind == ast.KindTypeLiteral || input.Kind == ast.KindMappedType) && !(input.Parent.Kind == ast.KindTypeAliasDeclaration || input.Parent.Kind == ast.KindJSTypeAliasDeclaration) - oldDiag := tx.state.getSymbolAccessibilityDiagnostic if canProduceDiagnostic && !tx.suppressNewDiagnosticContexts { - tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input) + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{node: input} } - oldName := tx.state.errorNameNode if shouldEnterSuppressNewDiagnosticsContextContext { tx.suppressNewDiagnosticContexts = true } - return canProduceDiagnostic, func() { - tx.state.getSymbolAccessibilityDiagnostic = oldDiag - tx.state.errorNameNode = oldName - tx.suppressNewDiagnosticContexts = oldWithinObjectLiteralType - } + return canProduceDiagnostic, saved +} + +func (tx *DeclarationTransformer) restoreDiagnosticContext(saved savedDiagnosticContext) { + tx.state.diagnosticContext = saved.diagnosticContext + tx.state.errorNameNode = saved.errorNameNode + tx.suppressNewDiagnosticContexts = saved.suppressNewDiagnosticContexts } func (tx *DeclarationTransformer) visitDeclarationSubtree(input *ast.Node) *ast.Node { @@ -610,8 +621,8 @@ func (tx *DeclarationTransformer) visitDeclarationSubtree(input *ast.Node) *ast. tx.enclosingDeclaration = input } - canProduceDiagnostic, cleanupDiagnosticContext := tx.setupDiagnosticContext(input) - defer cleanupDiagnosticContext() + canProduceDiagnostic, savedDiagnosticContext := tx.setupDiagnosticContext(input) + defer tx.restoreDiagnosticContext(savedDiagnosticContext) var result *ast.Node @@ -700,16 +711,16 @@ func (tx *DeclarationTransformer) visitDeclarationSubtree(input *ast.Node) *ast. } func (tx *DeclarationTransformer) checkName(node *ast.Node) { - oldDiag := tx.state.getSymbolAccessibilityDiagnostic + oldDiag := tx.state.diagnosticContext if !tx.suppressNewDiagnosticContexts { - tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNodeName(node) + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{fn: createGetSymbolAccessibilityDiagnosticForNodeName(node)} } tx.state.errorNameNode = node.Name() debug.Assert(ast.HasDynamicName(node)) // Should only be called with dynamic names entityName := node.Name().Expression() tx.checkEntityNameVisibility(entityName, tx.enclosingDeclaration) if !tx.suppressNewDiagnosticContexts { - tx.state.getSymbolAccessibilityDiagnostic = oldDiag + tx.state.diagnosticContext = oldDiag } tx.state.errorNameNode = nil } @@ -1230,12 +1241,12 @@ func (tx *DeclarationTransformer) transformExportAssignment(input *ast.Node, ass return exportAssignment } - tx.state.getSymbolAccessibilityDiagnostic = func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{fn: func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { return &SymbolAccessibilityDiagnostic{ diagnosticMessage: diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, errorNode: input, } - } + }} tx.tracker.PushErrorFallbackNode(assignment) // Check if the expression is a class expression - emit as a class declaration + export assignment @@ -1468,12 +1479,12 @@ func (tx *DeclarationTransformer) transformCommonJSExportWorker(input *ast.Node, if name.Text() == "default" { // const _default: Type; export default _default; newId := tx.Factory().NewUniqueNameEx("_default", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) - tx.state.getSymbolAccessibilityDiagnostic = func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{fn: func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { return &SymbolAccessibilityDiagnostic{ diagnosticMessage: diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, errorNode: input, } - } + }} tx.tracker.PushErrorFallbackNode(input) type_ := tx.ensureType(input, false) varDecl := tx.Factory().NewVariableDeclaration(newId, nil, type_, nil) @@ -1509,12 +1520,12 @@ func (tx *DeclarationTransformer) transformCommonJSExportWorker(input *ast.Node, } // const _exported: Type; export {_exported as "name"}; newId := tx.Factory().NewUniqueNameEx("_exported", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) - tx.state.getSymbolAccessibilityDiagnostic = func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{fn: func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { return &SymbolAccessibilityDiagnostic{ diagnosticMessage: diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0, errorNode: input, } - } + }} tx.tracker.PushErrorFallbackNode(input) type_ := tx.ensureType(input, false) varDecl := tx.Factory().NewVariableDeclaration(newId, nil, type_, nil) @@ -1668,11 +1679,11 @@ func (tx *DeclarationTransformer) ensureType(node *ast.Node, ignorePrivate bool) oldErrorNameNode := tx.state.errorNameNode tx.state.errorNameNode = node.Name() - var oldDiag GetSymbolAccessibilityDiagnostic + var oldDiag symbolAccessibilityDiagnosticContext if !tx.suppressNewDiagnosticContexts { - oldDiag = tx.state.getSymbolAccessibilityDiagnostic + oldDiag = tx.state.diagnosticContext if canProduceDiagnostics(node) { - tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(node) + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{node: node} } } var typeNode *ast.Node @@ -1691,7 +1702,7 @@ func (tx *DeclarationTransformer) ensureType(node *ast.Node, ignorePrivate bool) tx.state.errorNameNode = oldErrorNameNode if !tx.suppressNewDiagnosticContexts { - tx.state.getSymbolAccessibilityDiagnostic = oldDiag + tx.state.diagnosticContext = oldDiag } if typeNode == nil { return tx.Factory().NewKeywordTypeNode(ast.KindAnyKeyword) @@ -1754,10 +1765,10 @@ func (tx *DeclarationTransformer) transformTopLevelDeclaration(input *ast.Node) } canProduceDiagnostic := canProduceDiagnostics(input) - oldDiag := tx.state.getSymbolAccessibilityDiagnostic + oldDiag := tx.state.diagnosticContext oldName := tx.state.errorNameNode if canProduceDiagnostic { - tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(input) + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{node: input} } saveNeedsDeclare := tx.needsDeclare @@ -1783,7 +1794,7 @@ func (tx *DeclarationTransformer) transformTopLevelDeclaration(input *ast.Node) } tx.enclosingDeclaration = previousEnclosingDeclaration - tx.state.getSymbolAccessibilityDiagnostic = oldDiag + tx.state.diagnosticContext = oldDiag tx.needsDeclare = saveNeedsDeclare tx.state.errorNameNode = oldName return result @@ -1932,12 +1943,12 @@ func (tx *DeclarationTransformer) buildClassMembers(classNode *ast.Node, extraMe ctor := ast.GetFirstConstructorWithBody(classNode) var parameterProperties []*ast.Node if ctor != nil { - oldDiag := tx.state.getSymbolAccessibilityDiagnostic + oldDiag := tx.state.diagnosticContext for _, param := range ctor.AsConstructorDeclaration().Parameters.Nodes { if !ast.HasSyntacticModifier(param, ast.ModifierFlagsParameterPropertyModifier) || tx.shouldStripInternal(param) { continue } - tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param) + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{node: param} if param.Name().Kind == ast.KindIdentifier { updated := tx.Factory().NewPropertyDeclaration( tx.ensureModifiers(param), @@ -1953,7 +1964,7 @@ func (tx *DeclarationTransformer) buildClassMembers(classNode *ast.Node, extraMe parameterProperties = append(parameterProperties, tx.walkBindingPattern(param.Name().AsBindingPattern(), param)...) } } - tx.state.getSymbolAccessibilityDiagnostic = oldDiag + tx.state.diagnosticContext = oldDiag } // When the class has at least one private identifier, create a unique constant identifier to retain the nominal typing behavior @@ -2016,13 +2027,13 @@ func (tx *DeclarationTransformer) transformClassDeclaration(input *ast.ClassDecl oldId = input.Name().Text() } newId := tx.Factory().NewUniqueNameEx(oldId+"_base", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) - tx.state.getSymbolAccessibilityDiagnostic = func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{fn: func(_ printer.SymbolAccessibilityResult) *SymbolAccessibilityDiagnostic { return &SymbolAccessibilityDiagnostic{ diagnosticMessage: diagnostics.X_extends_clause_of_exported_class_0_has_or_is_using_private_name_1, errorNode: extendsClause, typeName: input.Name(), } - } + }} varDecl := tx.Factory().NewVariableDeclaration( newId, @@ -2365,11 +2376,11 @@ func (tx *DeclarationTransformer) ensureTypeParams(node *ast.Node, params *ast.T } oldErrorNameNode := tx.state.errorNameNode tx.state.errorNameNode = node.Name() - var oldDiag GetSymbolAccessibilityDiagnostic + var oldDiag symbolAccessibilityDiagnosticContext if !tx.suppressNewDiagnosticContexts { - oldDiag = tx.state.getSymbolAccessibilityDiagnostic + oldDiag = tx.state.diagnosticContext if canProduceDiagnostics(node) { - tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(node) + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{node: node} } } @@ -2384,7 +2395,7 @@ func (tx *DeclarationTransformer) ensureTypeParams(node *ast.Node, params *ast.T tx.state.errorNameNode = oldErrorNameNode if !tx.suppressNewDiagnosticContexts { - tx.state.getSymbolAccessibilityDiagnostic = oldDiag + tx.state.diagnosticContext = oldDiag } return typeParameters } @@ -2401,9 +2412,9 @@ func (tx *DeclarationTransformer) updateParamList(node *ast.Node, params *ast.Pa } func (tx *DeclarationTransformer) ensureParameter(p *ast.ParameterDeclaration) *ast.Node { - oldDiag := tx.state.getSymbolAccessibilityDiagnostic + oldDiag := tx.state.diagnosticContext if !tx.suppressNewDiagnosticContexts { - tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p.AsNode()) + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{node: p.AsNode()} } var questionToken *ast.TokenNode if tx.resolver.IsOptionalParameter(p.AsNode()) { @@ -2422,7 +2433,7 @@ func (tx *DeclarationTransformer) ensureParameter(p *ast.ParameterDeclaration) * tx.ensureType(p.AsNode(), true), tx.ensureNoInitializer(p.AsNode()), ) - tx.state.getSymbolAccessibilityDiagnostic = oldDiag + tx.state.diagnosticContext = oldDiag return result } @@ -2468,10 +2479,10 @@ func (tx *DeclarationTransformer) transformImportEqualsDeclaration(decl *ast.Imp tx.Factory().UpdateExternalModuleReference(decl.ModuleReference.AsExternalModuleReference(), tx.rewriteModuleSpecifier(decl.AsNode(), specifier)), ) } else { - oldDiag := tx.state.getSymbolAccessibilityDiagnostic - tx.state.getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(decl.AsNode()) + oldDiag := tx.state.diagnosticContext + tx.state.diagnosticContext = symbolAccessibilityDiagnosticContext{node: decl.AsNode()} tx.checkEntityNameVisibility(decl.ModuleReference, tx.enclosingDeclaration) - tx.state.getSymbolAccessibilityDiagnostic = oldDiag + tx.state.diagnosticContext = oldDiag return decl.AsNode() } } @@ -2679,8 +2690,8 @@ func (tx *DeclarationTransformer) stripDeclareModifiers(node *ast.Node) *ast.Nod func (tx *DeclarationTransformer) visitCJSExportAssignments(expression *ast.Node) *ast.Node { if expression != nil { - _, cleanupDiagnosticContext := tx.setupDiagnosticContext(expression) - defer cleanupDiagnosticContext() + _, savedDiagnosticContext := tx.setupDiagnosticContext(expression) + defer tx.restoreDiagnosticContext(savedDiagnosticContext) switch ast.GetAssignmentDeclarationKind(expression) { case ast.JSDeclarationKindModuleExports: if tx.state.currentSourceFile.CommonJSModuleIndicator != nil { @@ -2699,8 +2710,8 @@ func (tx *DeclarationTransformer) visitCJSExportAssignments(expression *ast.Node func (tx *DeclarationTransformer) visitNestedExpression(expression *ast.Node) *ast.Node { if expression != nil { - _, cleanupDiagnosticContext := tx.setupDiagnosticContext(expression) - defer cleanupDiagnosticContext() + _, savedDiagnosticContext := tx.setupDiagnosticContext(expression) + defer tx.restoreDiagnosticContext(savedDiagnosticContext) switch ast.GetAssignmentDeclarationKind(expression) { case ast.JSDeclarationKindProperty: tx.transformExpandoAssignment(expression.AsBinaryExpression()) @@ -2796,8 +2807,8 @@ func (tx *DeclarationTransformer) transformExpandoAssignment(node *ast.BinaryExp localName = tx.Factory().NewGeneratedNameForNode(node.AsNode()) } - _, cleanupDiagnosticContext := tx.setupDiagnosticContext(node.AsNode()) - defer cleanupDiagnosticContext() + _, savedDiagnosticContext := tx.setupDiagnosticContext(node.AsNode()) + defer tx.restoreDiagnosticContext(savedDiagnosticContext) preexistingExpandoHasExport := core.Some(tx.expandoMembers[hostId], ast.IsExportDeclaration) @@ -2896,8 +2907,8 @@ func (tx *DeclarationTransformer) transformExpandoHost(name *ast.Node, declarati modifierFlags ^= ast.ModifierFlagsExport } - _, cleanupDiagnosticContext := tx.setupDiagnosticContext(declaration) - defer cleanupDiagnosticContext() + _, savedDiagnosticContext := tx.setupDiagnosticContext(declaration) + defer tx.restoreDiagnosticContext(savedDiagnosticContext) modifiers := tx.Factory().NewModifierList(ast.CreateModifiersFromModifierFlags(modifierFlags, tx.Factory().NewModifier)) replacement := make([]*ast.Node, 0) From 4ca431b6b06c1280135a59bf063e0ee39f504ae6 Mon Sep 17 00:00:00 2001 From: Gavin Kline Date: Fri, 9 Oct 2026 22:46:43 -1000 Subject: [PATCH 2/2] Add test for declaration emit errors in each declaration context Each exported declaration infers a type that declaration emit cannot name, so every kind of declaration reports its own accessibility error. The baselines were generated before diagnostic selectors were made lazy and are unchanged by it. Co-Authored-By: Claude Opus 5.5 --- ...ionEmitInaccessibleNameContexts.errors.txt | 125 +++++++++++ ...declarationEmitInaccessibleNameContexts.js | 110 ++++++++++ ...rationEmitInaccessibleNameContexts.symbols | 164 +++++++++++++++ ...larationEmitInaccessibleNameContexts.types | 194 ++++++++++++++++++ ...declarationEmitInaccessibleNameContexts.ts | 61 ++++++ 5 files changed, 654 insertions(+) create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.errors.txt create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.js create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.symbols create mode 100644 tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.types create mode 100644 tsc/testdata/tests/cases/compiler/declarationEmitInaccessibleNameContexts.ts diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.errors.txt b/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.errors.txt new file mode 100644 index 0000000000000..ccb63ea37c7eb --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.errors.txt @@ -0,0 +1,125 @@ +hidden.ts(1,17): error TS4060: Return type of exported function has or is using private name 'Hidden'. +hidden.ts(5,17): error TS4060: Return type of exported function has or is using private name 'HiddenProp'. +index.ts(3,14): error TS4023: Exported variable 'variable' has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(4,12): error TS4023: Exported variable '[destructured]' has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(5,17): error TS4058: Return type of exported function has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(6,42): error TS4076: Parameter 'p' of exported function has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(7,14): error TS4023: Exported variable 'arrow' has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(10,5): error TS4029: Public property 'property' of exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(11,12): error TS4026: Public static property 'staticProperty' of exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(13,17): error TS4061: Parameter 'parameterProperty' of constructor from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(14,5): error TS4053: Return type of public method from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(15,12): error TS4050: Return type of public static method from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(16,25): error TS4071: Parameter 'p' of public method from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(17,9): error TS4041: Return type of public getter 'getter' from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(18,9): error TS4041: Return type of public getter 'accessor' from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(19,18): error TS4108: Parameter 'v' of accessor has or is using name 'Hidden' from external module '"hidden"' but cannot be named. +index.ts(22,30): error TS4020: 'extends' clause of exported class 'Derived' has or is using private name 'HiddenProp'. +index.ts(25,1): error TS4032: Property 'prop' of exported interface has or is using name 'Hidden' from private module '"hidden"'. +index.ts(27,1): error TS4032: Property 'prop' of exported interface has or is using name 'Hidden' from private module '"hidden"'. +index.ts(30,18): error TS4023: Exported variable 'inNamespace' has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(31,21): error TS4058: Return type of exported function has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(34,14): error TS4023: Exported variable 'objectLiteral' has or is using name 'Hidden' from external module "hidden" but cannot be named. +index.ts(41,1): error TS4082: Default export of the module has or is using private name 'Hidden'. + + +==== hidden.ts (2 errors) ==== + export function make() { + ~~~~ +!!! error TS4060: Return type of exported function has or is using private name 'Hidden'. + interface Hidden { x: number } + return { x: 1 } as Hidden; + } + export function makeClass() { + ~~~~~~~~~ +!!! error TS4060: Return type of exported function has or is using private name 'HiddenProp'. + interface HiddenProp { x: number } + class HiddenBase { y = { x: 1 } as HiddenProp } + return HiddenBase; + } + +==== index.ts (21 errors) ==== + import { make, makeClass } from "./hidden"; + + export const variable = make(); + ~~~~~~~~ +!!! error TS4023: Exported variable 'variable' has or is using name 'Hidden' from external module "hidden" but cannot be named. + export let [destructured] = [make()]; + ~~~~~~~~~~~~~~ +!!! error TS4023: Exported variable '[destructured]' has or is using name 'Hidden' from external module "hidden" but cannot be named. + export function returnType() { return make(); } + ~~~~~~~~~~ +!!! error TS4058: Return type of exported function has or is using name 'Hidden' from external module "hidden" but cannot be named. + export function parameterWithInitializer(p = make()) { return 0; } + ~~~~~~~~~~ +!!! error TS4076: Parameter 'p' of exported function has or is using name 'Hidden' from external module "hidden" but cannot be named. + export const arrow = (p = make()) => p; + ~~~~~ +!!! error TS4023: Exported variable 'arrow' has or is using name 'Hidden' from external module "hidden" but cannot be named. + + export class C { + property = make(); + ~~~~~~~~ +!!! error TS4029: Public property 'property' of exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. + static staticProperty = make(); + ~~~~~~~~~~~~~~ +!!! error TS4026: Public static property 'staticProperty' of exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. + #privateField = make(); + constructor(public parameterProperty = make()) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS4061: Parameter 'parameterProperty' of constructor from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. + method() { return make(); } + ~~~~~~ +!!! error TS4053: Return type of public method from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. + static staticMethod() { return make(); } + ~~~~~~~~~~~~ +!!! error TS4050: Return type of public static method from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. + methodWithParameter(p = make()) { return 0; } + ~~~~~~~~~~ +!!! error TS4071: Parameter 'p' of public method from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. + get getter() { return make(); } + ~~~~~~ +!!! error TS4041: Return type of public getter 'getter' from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. + get accessor() { return make(); } + ~~~~~~~~ +!!! error TS4041: Return type of public getter 'accessor' from exported class has or is using name 'Hidden' from external module "hidden" but cannot be named. + set accessor(v) { v; } + ~ +!!! error TS4108: Parameter 'v' of accessor has or is using name 'Hidden' from external module '"hidden"' but cannot be named. + } + + export class Derived extends makeClass() {} + ~~~~~~~~~~~ +!!! error TS4020: 'extends' clause of exported class 'Derived' has or is using private name 'HiddenProp'. + + export function host() {} + host.prop = make(); + ~~~~~~~~~~~~~~~~~~ +!!! error TS4032: Property 'prop' of exported interface has or is using name 'Hidden' from private module '"hidden"'. + export const arrowHost = () => 0; + arrowHost.prop = make(); + ~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS4032: Property 'prop' of exported interface has or is using name 'Hidden' from private module '"hidden"'. + + export namespace N { + export const inNamespace = make(); + ~~~~~~~~~~~ +!!! error TS4023: Exported variable 'inNamespace' has or is using name 'Hidden' from external module "hidden" but cannot be named. + export function returnInNamespace() { return make(); } + ~~~~~~~~~~~~~~~~~ +!!! error TS4058: Return type of exported function has or is using name 'Hidden' from external module "hidden" but cannot be named. + } + + export const objectLiteral = { + ~~~~~~~~~~~~~ +!!! error TS4023: Exported variable 'objectLiteral' has or is using name 'Hidden' from external module "hidden" but cannot be named. + nested: make(), + method() { return make(); }, + }; + + export function generic>(t?: T) { return t; } + + export default make(); + ~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS4082: Default export of the module has or is using private name 'Hidden'. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.js b/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.js new file mode 100644 index 0000000000000..c583f15f2874b --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.js @@ -0,0 +1,110 @@ +//// [tests/cases/compiler/declarationEmitInaccessibleNameContexts.ts] //// + +//// [hidden.ts] +export function make() { + interface Hidden { x: number } + return { x: 1 } as Hidden; +} +export function makeClass() { + interface HiddenProp { x: number } + class HiddenBase { y = { x: 1 } as HiddenProp } + return HiddenBase; +} + +//// [index.ts] +import { make, makeClass } from "./hidden"; + +export const variable = make(); +export let [destructured] = [make()]; +export function returnType() { return make(); } +export function parameterWithInitializer(p = make()) { return 0; } +export const arrow = (p = make()) => p; + +export class C { + property = make(); + static staticProperty = make(); + #privateField = make(); + constructor(public parameterProperty = make()) {} + method() { return make(); } + static staticMethod() { return make(); } + methodWithParameter(p = make()) { return 0; } + get getter() { return make(); } + get accessor() { return make(); } + set accessor(v) { v; } +} + +export class Derived extends makeClass() {} + +export function host() {} +host.prop = make(); +export const arrowHost = () => 0; +arrowHost.prop = make(); + +export namespace N { + export const inNamespace = make(); + export function returnInNamespace() { return make(); } +} + +export const objectLiteral = { + nested: make(), + method() { return make(); }, +}; + +export function generic>(t?: T) { return t; } + +export default make(); + + +//// [hidden.js] +export function make() { + return { x: 1 }; +} +export function makeClass() { + class HiddenBase { + constructor() { + this.y = { x: 1 }; + } + } + return HiddenBase; +} +//// [index.js] +var _C_privateField; +import { make, makeClass } from "./hidden"; +export const variable = make(); +export let [destructured] = [make()]; +export function returnType() { return make(); } +export function parameterWithInitializer(p = make()) { return 0; } +export const arrow = (p = make()) => p; +export class C { + constructor(parameterProperty = make()) { + this.parameterProperty = parameterProperty; + this.property = make(); + _C_privateField.set(this, make()); + } + method() { return make(); } + static staticMethod() { return make(); } + methodWithParameter(p = make()) { return 0; } + get getter() { return make(); } + get accessor() { return make(); } + set accessor(v) { v; } +} +_C_privateField = new WeakMap(); +C.staticProperty = make(); +export class Derived extends makeClass() { +} +export function host() { } +host.prop = make(); +export const arrowHost = () => 0; +arrowHost.prop = make(); +export var N; +(function (N) { + N.inNamespace = make(); + function returnInNamespace() { return make(); } + N.returnInNamespace = returnInNamespace; +})(N || (N = {})); +export const objectLiteral = { + nested: make(), + method() { return make(); }, +}; +export function generic(t) { return t; } +export default make(); diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.symbols b/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.symbols new file mode 100644 index 0000000000000..20ba38c7b6283 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.symbols @@ -0,0 +1,164 @@ +//// [tests/cases/compiler/declarationEmitInaccessibleNameContexts.ts] //// + +=== hidden.ts === +export function make() { +>make : Symbol(make, Decl(hidden.ts, 0, 0)) + + interface Hidden { x: number } +>Hidden : Symbol(Hidden, Decl(hidden.ts, 0, 24)) +>x : Symbol(Hidden.x, Decl(hidden.ts, 1, 22)) + + return { x: 1 } as Hidden; +>x : Symbol(x, Decl(hidden.ts, 2, 12)) +>Hidden : Symbol(Hidden, Decl(hidden.ts, 0, 24)) +} +export function makeClass() { +>makeClass : Symbol(makeClass, Decl(hidden.ts, 3, 1)) + + interface HiddenProp { x: number } +>HiddenProp : Symbol(HiddenProp, Decl(hidden.ts, 4, 29)) +>x : Symbol(HiddenProp.x, Decl(hidden.ts, 5, 26)) + + class HiddenBase { y = { x: 1 } as HiddenProp } +>HiddenBase : Symbol(HiddenBase, Decl(hidden.ts, 5, 38)) +>y : Symbol(HiddenBase.y, Decl(hidden.ts, 6, 22)) +>x : Symbol(x, Decl(hidden.ts, 6, 28)) +>HiddenProp : Symbol(HiddenProp, Decl(hidden.ts, 4, 29)) + + return HiddenBase; +>HiddenBase : Symbol(HiddenBase, Decl(hidden.ts, 5, 38)) +} + +=== index.ts === +import { make, makeClass } from "./hidden"; +>make : Symbol(make, Decl(index.ts, 0, 8)) +>makeClass : Symbol(makeClass, Decl(index.ts, 0, 14)) + +export const variable = make(); +>variable : Symbol(variable, Decl(index.ts, 2, 12)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + +export let [destructured] = [make()]; +>destructured : Symbol(destructured, Decl(index.ts, 3, 12)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + +export function returnType() { return make(); } +>returnType : Symbol(returnType, Decl(index.ts, 3, 37)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + +export function parameterWithInitializer(p = make()) { return 0; } +>parameterWithInitializer : Symbol(parameterWithInitializer, Decl(index.ts, 4, 47)) +>p : Symbol(p, Decl(index.ts, 5, 41)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + +export const arrow = (p = make()) => p; +>arrow : Symbol(arrow, Decl(index.ts, 6, 12)) +>p : Symbol(p, Decl(index.ts, 6, 22)) +>make : Symbol(make, Decl(index.ts, 0, 8)) +>p : Symbol(p, Decl(index.ts, 6, 22)) + +export class C { +>C : Symbol(C, Decl(index.ts, 6, 39)) + + property = make(); +>property : Symbol(C.property, Decl(index.ts, 8, 16)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + static staticProperty = make(); +>staticProperty : Symbol(C.staticProperty, Decl(index.ts, 9, 22)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + #privateField = make(); +>#privateField : Symbol(C.#privateField, Decl(index.ts, 10, 35)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + constructor(public parameterProperty = make()) {} +>parameterProperty : Symbol(C.parameterProperty, Decl(index.ts, 12, 16)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + method() { return make(); } +>method : Symbol(C.method, Decl(index.ts, 12, 53)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + static staticMethod() { return make(); } +>staticMethod : Symbol(C.staticMethod, Decl(index.ts, 13, 31)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + methodWithParameter(p = make()) { return 0; } +>methodWithParameter : Symbol(C.methodWithParameter, Decl(index.ts, 14, 44)) +>p : Symbol(p, Decl(index.ts, 15, 24)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + get getter() { return make(); } +>getter : Symbol(C.getter, Decl(index.ts, 15, 49)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + get accessor() { return make(); } +>accessor : Symbol(C.accessor, Decl(index.ts, 16, 35), Decl(index.ts, 17, 37)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + set accessor(v) { v; } +>accessor : Symbol(C.accessor, Decl(index.ts, 16, 35), Decl(index.ts, 17, 37)) +>v : Symbol(v, Decl(index.ts, 18, 17)) +>v : Symbol(v, Decl(index.ts, 18, 17)) +} + +export class Derived extends makeClass() {} +>Derived : Symbol(Derived, Decl(index.ts, 19, 1)) +>makeClass : Symbol(makeClass, Decl(index.ts, 0, 14)) + +export function host() {} +>host : Symbol(host, Decl(index.ts, 21, 43)) + +host.prop = make(); +>host.prop : Symbol(host.prop, Decl(index.ts, 23, 25)) +>host : Symbol(host, Decl(index.ts, 21, 43)) +>prop : Symbol(host.prop, Decl(index.ts, 23, 25)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + +export const arrowHost = () => 0; +>arrowHost : Symbol(arrowHost, Decl(index.ts, 25, 12)) + +arrowHost.prop = make(); +>arrowHost.prop : Symbol(arrowHost.prop, Decl(index.ts, 25, 33)) +>arrowHost : Symbol(arrowHost, Decl(index.ts, 25, 12)) +>prop : Symbol(arrowHost.prop, Decl(index.ts, 25, 33)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + +export namespace N { +>N : Symbol(N, Decl(index.ts, 26, 24)) + + export const inNamespace = make(); +>inNamespace : Symbol(inNamespace, Decl(index.ts, 29, 16)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + export function returnInNamespace() { return make(); } +>returnInNamespace : Symbol(returnInNamespace, Decl(index.ts, 29, 38)) +>make : Symbol(make, Decl(index.ts, 0, 8)) +} + +export const objectLiteral = { +>objectLiteral : Symbol(objectLiteral, Decl(index.ts, 33, 12)) + + nested: make(), +>nested : Symbol(nested, Decl(index.ts, 33, 30)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + + method() { return make(); }, +>method : Symbol(method, Decl(index.ts, 34, 19)) +>make : Symbol(make, Decl(index.ts, 0, 8)) + +}; + +export function generic>(t?: T) { return t; } +>generic : Symbol(generic, Decl(index.ts, 36, 2)) +>T : Symbol(T, Decl(index.ts, 38, 24)) +>ReturnType : Symbol(ReturnType, Decl(lib.es5.d.ts, --, --)) +>make : Symbol(make, Decl(index.ts, 0, 8)) +>t : Symbol(t, Decl(index.ts, 38, 53)) +>T : Symbol(T, Decl(index.ts, 38, 24)) +>t : Symbol(t, Decl(index.ts, 38, 53)) + +export default make(); +>make : Symbol(make, Decl(index.ts, 0, 8)) + diff --git a/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.types b/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.types new file mode 100644 index 0000000000000..b7cdc57653a41 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/declarationEmitInaccessibleNameContexts.types @@ -0,0 +1,194 @@ +//// [tests/cases/compiler/declarationEmitInaccessibleNameContexts.ts] //// + +=== hidden.ts === +export function make() { +>make : () => Hidden + + interface Hidden { x: number } +>x : number + + return { x: 1 } as Hidden; +>{ x: 1 } as Hidden : Hidden +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 +} +export function makeClass() { +>makeClass : () => typeof HiddenBase + + interface HiddenProp { x: number } +>x : number + + class HiddenBase { y = { x: 1 } as HiddenProp } +>HiddenBase : HiddenBase +>y : HiddenProp +>{ x: 1 } as HiddenProp : HiddenProp +>{ x: 1 } : { x: number; } +>x : number +>1 : 1 + + return HiddenBase; +>HiddenBase : typeof HiddenBase +} + +=== index.ts === +import { make, makeClass } from "./hidden"; +>make : () => Hidden +>makeClass : () => typeof HiddenBase + +export const variable = make(); +>variable : Hidden +>make() : Hidden +>make : () => Hidden + +export let [destructured] = [make()]; +>destructured : Hidden +>[make()] : [Hidden] +>make() : Hidden +>make : () => Hidden + +export function returnType() { return make(); } +>returnType : () => Hidden +>make() : Hidden +>make : () => Hidden + +export function parameterWithInitializer(p = make()) { return 0; } +>parameterWithInitializer : (p?: Hidden) => number +>p : Hidden +>make() : Hidden +>make : () => Hidden +>0 : 0 + +export const arrow = (p = make()) => p; +>arrow : (p?: Hidden) => Hidden +>(p = make()) => p : (p?: Hidden) => Hidden +>p : Hidden +>make() : Hidden +>make : () => Hidden +>p : Hidden + +export class C { +>C : C + + property = make(); +>property : Hidden +>make() : Hidden +>make : () => Hidden + + static staticProperty = make(); +>staticProperty : Hidden +>make() : Hidden +>make : () => Hidden + + #privateField = make(); +>#privateField : Hidden +>make() : Hidden +>make : () => Hidden + + constructor(public parameterProperty = make()) {} +>parameterProperty : Hidden +>make() : Hidden +>make : () => Hidden + + method() { return make(); } +>method : () => Hidden +>make() : Hidden +>make : () => Hidden + + static staticMethod() { return make(); } +>staticMethod : () => Hidden +>make() : Hidden +>make : () => Hidden + + methodWithParameter(p = make()) { return 0; } +>methodWithParameter : (p?: Hidden) => number +>p : Hidden +>make() : Hidden +>make : () => Hidden +>0 : 0 + + get getter() { return make(); } +>getter : Hidden +>make() : Hidden +>make : () => Hidden + + get accessor() { return make(); } +>accessor : Hidden +>make() : Hidden +>make : () => Hidden + + set accessor(v) { v; } +>accessor : Hidden +>v : Hidden +>v : Hidden +} + +export class Derived extends makeClass() {} +>Derived : Derived +>makeClass() : HiddenBase +>makeClass : () => typeof HiddenBase + +export function host() {} +>host : { (): void; prop: Hidden; } + +host.prop = make(); +>host.prop = make() : Hidden +>host.prop : Hidden +>host : { (): void; prop: Hidden; } +>prop : Hidden +>make() : Hidden +>make : () => Hidden + +export const arrowHost = () => 0; +>arrowHost : { (): number; prop: Hidden; } +>() => 0 : { (): number; prop: Hidden; } +>0 : 0 + +arrowHost.prop = make(); +>arrowHost.prop = make() : Hidden +>arrowHost.prop : Hidden +>arrowHost : { (): number; prop: Hidden; } +>prop : Hidden +>make() : Hidden +>make : () => Hidden + +export namespace N { +>N : typeof N + + export const inNamespace = make(); +>inNamespace : Hidden +>make() : Hidden +>make : () => Hidden + + export function returnInNamespace() { return make(); } +>returnInNamespace : () => Hidden +>make() : Hidden +>make : () => Hidden +} + +export const objectLiteral = { +>objectLiteral : { nested: Hidden; method(): Hidden; } +>{ nested: make(), method() { return make(); },} : { nested: Hidden; method(): Hidden; } + + nested: make(), +>nested : Hidden +>make() : Hidden +>make : () => Hidden + + method() { return make(); }, +>method : () => Hidden +>make() : Hidden +>make : () => Hidden + +}; + +export function generic>(t?: T) { return t; } +>generic :