From 4c046871b1a531c779b591ac1cc9ca5b90599425 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:18:31 +0000 Subject: [PATCH 1/4] Initial plan From 142baa74a3ca58added8156aa8ca0c91ef8217bb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:48:40 +0000 Subject: [PATCH 2/4] Implement TrackExistingEntityName to rename shadowed type parameters Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com> --- internal/checker/emitresolver.go | 13 +++++++++ internal/checker/nodebuilder.go | 6 +++++ internal/checker/nodebuilderimpl.go | 23 ++++++++++++++++ internal/printer/emitresolver.go | 1 + .../transformers/declarations/transform.go | 27 +++++++++++++++++-- 5 files changed, 68 insertions(+), 2 deletions(-) diff --git a/internal/checker/emitresolver.go b/internal/checker/emitresolver.go index 1a28c3c21e..37589c1e2a 100644 --- a/internal/checker/emitresolver.go +++ b/internal/checker/emitresolver.go @@ -1078,6 +1078,19 @@ func (r *emitResolver) CreateLateBoundIndexSignatures(emitContext *printer.EmitC return result } +func (r *emitResolver) TrackExistingEntityName(emitContext *printer.EmitContext, node *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node { + original := emitContext.ParseNode(node) + if original == nil { + return node + } + + r.checkerMu.Lock() + defer r.checkerMu.Unlock() + + requestNodeBuilder := NewNodeBuilder(r.checker, emitContext) // TODO: cache per-context + return requestNodeBuilder.TrackExistingEntityName(original, enclosingDeclaration, flags, internalFlags, tracker) +} + func (r *emitResolver) GetEffectiveDeclarationFlags(node *ast.Node, flags ast.ModifierFlags) ast.ModifierFlags { // node = emitContext.ParseNode(node) r.checkerMu.Lock() diff --git a/internal/checker/nodebuilder.go b/internal/checker/nodebuilder.go index bd629596c7..b83baacb16 100644 --- a/internal/checker/nodebuilder.go +++ b/internal/checker/nodebuilder.go @@ -162,6 +162,12 @@ func (b *NodeBuilder) TypeParameterToDeclaration(parameter *Type, enclosingDecla return b.exitContext(b.impl.typeParameterToDeclaration(parameter)) } +// TrackExistingEntityName tracks an existing entity name and returns a potentially renamed version. +func (b *NodeBuilder) TrackExistingEntityName(node *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node { + b.enterContext(enclosingDeclaration, flags, internalFlags, tracker) + return b.exitContext(b.impl.trackExistingEntityName(node)) +} + // TypePredicateToTypePredicateNode implements NodeBuilderInterface. func (b *NodeBuilder) TypePredicateToTypePredicateNode(predicate *TypePredicate, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node { b.enterContext(enclosingDeclaration, flags, internalFlags, tracker) diff --git a/internal/checker/nodebuilderimpl.go b/internal/checker/nodebuilderimpl.go index afdc9494d7..1469150c3d 100644 --- a/internal/checker/nodebuilderimpl.go +++ b/internal/checker/nodebuilderimpl.go @@ -1346,6 +1346,29 @@ func (b *nodeBuilderImpl) typeParameterToName(typeParameter *Type) *ast.Identifi return result.AsIdentifier() } +func (b *nodeBuilderImpl) trackExistingEntityName(node *ast.Node) *ast.Node { + if node == nil || !ast.IsIdentifier(node) { + return node + } + + // Get the symbol for this identifier + symbol := b.ch.getSymbolOfNode(node) + if symbol == nil { + return node + } + + // If it's a type parameter, use typeParameterToName to get a potentially renamed version + if symbol.Flags&ast.SymbolFlagsTypeParameter != 0 { + typeParam := b.ch.getDeclaredTypeOfSymbol(symbol) + if typeParam != nil { + return b.typeParameterToName(typeParam).AsNode() + } + } + + // For non-type-parameter identifiers, return a clone + return node.Clone(b.f) +} + func (b *nodeBuilderImpl) isMappedTypeHomomorphic(mapped *Type) bool { return b.ch.getHomomorphicTypeVariable(mapped) != nil } diff --git a/internal/printer/emitresolver.go b/internal/printer/emitresolver.go index 156709cf68..b4f85a13c3 100644 --- a/internal/printer/emitresolver.go +++ b/internal/printer/emitresolver.go @@ -65,4 +65,5 @@ type EmitResolver interface { CreateLiteralConstValue(emitContext *EmitContext, node *ast.Node, tracker nodebuilder.SymbolTracker) *ast.Node CreateTypeOfExpression(emitContext *EmitContext, expression *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node CreateLateBoundIndexSignatures(emitContext *EmitContext, container *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) []*ast.Node + TrackExistingEntityName(emitContext *EmitContext, node *ast.Node, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, tracker nodebuilder.SymbolTracker) *ast.Node } diff --git a/internal/transformers/declarations/transform.go b/internal/transformers/declarations/transform.go index 6217557d5f..c243c27a82 100644 --- a/internal/transformers/declarations/transform.go +++ b/internal/transformers/declarations/transform.go @@ -634,16 +634,39 @@ func (tx *DeclarationTransformer) transformExpressionWithTypeArguments(input *as } func (tx *DeclarationTransformer) transformTypeParameterDeclaration(input *ast.TypeParameterDeclaration) *ast.Node { + // Track the type parameter name to handle shadowing + tpName := tx.resolver.TrackExistingEntityName( + tx.EmitContext(), + input.Name(), + tx.enclosingDeclaration, + declarationEmitNodeBuilderFlags, + declarationEmitInternalNodeBuilderFlags, + tx.tracker, + ) + if isPrivateMethodTypeParameter(tx.host, input) && (input.DefaultType != nil || input.Constraint != nil) { return tx.Factory().UpdateTypeParameterDeclaration( input, input.Modifiers(), - input.Name(), + tpName, nil, nil, ) } - return tx.Visitor().VisitEachChild(input.AsNode()) + + // Visit children to transform constraint and default type + modifiers := tx.Visitor().VisitNodes(input.Modifiers()) + constraint := tx.Visitor().VisitNode(input.Constraint) + defaultType := tx.Visitor().VisitNode(input.DefaultType) + + // Update the type parameter declaration with the potentially renamed name + return tx.Factory().UpdateTypeParameterDeclaration( + input, + modifiers, + tpName, + constraint, + defaultType, + ) } func (tx *DeclarationTransformer) transformVariableDeclaration(input *ast.VariableDeclaration) *ast.Node { From 6f3c740bd872b6770bb5ff1113173e5c706da50b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 21:57:49 +0000 Subject: [PATCH 3/4] Fix type issue in transformTypeParameterDeclaration - use VisitModifiers Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com> --- internal/transformers/declarations/transform.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/transformers/declarations/transform.go b/internal/transformers/declarations/transform.go index c243c27a82..dad0fe47bf 100644 --- a/internal/transformers/declarations/transform.go +++ b/internal/transformers/declarations/transform.go @@ -655,7 +655,7 @@ func (tx *DeclarationTransformer) transformTypeParameterDeclaration(input *ast.T } // Visit children to transform constraint and default type - modifiers := tx.Visitor().VisitNodes(input.Modifiers()) + modifiers := tx.Visitor().VisitModifiers(input.Modifiers()) constraint := tx.Visitor().VisitNode(input.Constraint) defaultType := tx.Visitor().VisitNode(input.DefaultType) From 3cf133c6083c09dec41f6f3d26e8ad03fbc36624 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 22:00:17 +0000 Subject: [PATCH 4/4] Apply code formatting - remove trailing whitespace Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com> --- internal/checker/emitresolver.go | 2 +- internal/checker/nodebuilderimpl.go | 6 +++--- internal/transformers/declarations/transform.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/internal/checker/emitresolver.go b/internal/checker/emitresolver.go index 37589c1e2a..f5bc7ad854 100644 --- a/internal/checker/emitresolver.go +++ b/internal/checker/emitresolver.go @@ -1086,7 +1086,7 @@ func (r *emitResolver) TrackExistingEntityName(emitContext *printer.EmitContext, r.checkerMu.Lock() defer r.checkerMu.Unlock() - + requestNodeBuilder := NewNodeBuilder(r.checker, emitContext) // TODO: cache per-context return requestNodeBuilder.TrackExistingEntityName(original, enclosingDeclaration, flags, internalFlags, tracker) } diff --git a/internal/checker/nodebuilderimpl.go b/internal/checker/nodebuilderimpl.go index 1469150c3d..d2558c4d43 100644 --- a/internal/checker/nodebuilderimpl.go +++ b/internal/checker/nodebuilderimpl.go @@ -1350,13 +1350,13 @@ func (b *nodeBuilderImpl) trackExistingEntityName(node *ast.Node) *ast.Node { if node == nil || !ast.IsIdentifier(node) { return node } - + // Get the symbol for this identifier symbol := b.ch.getSymbolOfNode(node) if symbol == nil { return node } - + // If it's a type parameter, use typeParameterToName to get a potentially renamed version if symbol.Flags&ast.SymbolFlagsTypeParameter != 0 { typeParam := b.ch.getDeclaredTypeOfSymbol(symbol) @@ -1364,7 +1364,7 @@ func (b *nodeBuilderImpl) trackExistingEntityName(node *ast.Node) *ast.Node { return b.typeParameterToName(typeParam).AsNode() } } - + // For non-type-parameter identifiers, return a clone return node.Clone(b.f) } diff --git a/internal/transformers/declarations/transform.go b/internal/transformers/declarations/transform.go index dad0fe47bf..80e7afedfa 100644 --- a/internal/transformers/declarations/transform.go +++ b/internal/transformers/declarations/transform.go @@ -643,7 +643,7 @@ func (tx *DeclarationTransformer) transformTypeParameterDeclaration(input *ast.T declarationEmitInternalNodeBuilderFlags, tx.tracker, ) - + if isPrivateMethodTypeParameter(tx.host, input) && (input.DefaultType != nil || input.Constraint != nil) { return tx.Factory().UpdateTypeParameterDeclaration( input, @@ -653,12 +653,12 @@ func (tx *DeclarationTransformer) transformTypeParameterDeclaration(input *ast.T nil, ) } - + // Visit children to transform constraint and default type modifiers := tx.Visitor().VisitModifiers(input.Modifiers()) constraint := tx.Visitor().VisitNode(input.Constraint) defaultType := tx.Visitor().VisitNode(input.DefaultType) - + // Update the type parameter declaration with the potentially renamed name return tx.Factory().UpdateTypeParameterDeclaration( input,