From 19f38b8a54a3903f27d0e6a481895810e3da3702 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Jun 2025 13:44:54 +0000 Subject: [PATCH 1/2] Initial plan for issue From bcbf4ac119bc068349b6d268f50505e6165abd20 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 9 Jun 2025 14:01:52 +0000 Subject: [PATCH 2/2] Add JSDocImplementsTag support to reparser to create synthetic heritage clauses Co-authored-by: sandersn <293473+sandersn@users.noreply.github.com> --- internal/parser/reparser.go | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/internal/parser/reparser.go b/internal/parser/reparser.go index b0d7b79dad..584ce1e5a8 100644 --- a/internal/parser/reparser.go +++ b/internal/parser/reparser.go @@ -208,6 +208,71 @@ func (p *Parser) reparseTags(parent *ast.Node, jsDoc []*ast.Node) { fun.FunctionLikeData().Type = p.makeNewType(tag.AsJSDocReturnTag().TypeExpression, fun) } } + case ast.KindJSDocImplementsTag: + implementsTag := tag.AsJSDocImplementsTag() + if parent.Kind == ast.KindClassDeclaration { + class := parent.AsClassDeclaration() + + // Create ExpressionWithTypeArguments from the class name + expression := implementsTag.ClassName + // For JSDoc @implements, we use the className as-is without extracting type arguments + // since it's already parsed appropriately in parseExpressionWithTypeArgumentsForAugments + var typeArguments *ast.NodeList + if expression.Kind == ast.KindExpressionWithTypeArguments { + exprWithArgs := expression.AsExpressionWithTypeArguments() + expression = exprWithArgs.Expression + typeArguments = exprWithArgs.TypeArguments + } + + // Create a new ExpressionWithTypeArguments + implementsExpression := p.factory.NewExpressionWithTypeArguments(expression, typeArguments) + implementsExpression.Loc = tag.Loc + implementsExpression.Flags = p.contextFlags | ast.NodeFlagsReparsed + + // Create implements heritage clause + implementsClause := p.factory.NewHeritageClause(ast.KindImplementsKeyword, p.factory.NewNodeList([]*ast.Node{implementsExpression})) + implementsClause.Loc = tag.Loc + implementsClause.Flags = p.contextFlags | ast.NodeFlagsReparsed + + // Add to existing heritage clauses or create new list + var heritageList []*ast.Node + if class.HeritageClauses != nil { + heritageList = append(heritageList, class.HeritageClauses.Nodes...) + } + heritageList = append(heritageList, implementsClause) + + class.HeritageClauses = p.factory.NewNodeList(heritageList) + } else if parent.Kind == ast.KindClassExpression { + class := parent.AsClassExpression() + + // Create ExpressionWithTypeArguments from the class name + expression := implementsTag.ClassName + var typeArguments *ast.NodeList + if expression.Kind == ast.KindExpressionWithTypeArguments { + exprWithArgs := expression.AsExpressionWithTypeArguments() + expression = exprWithArgs.Expression + typeArguments = exprWithArgs.TypeArguments + } + + // Create a new ExpressionWithTypeArguments + implementsExpression := p.factory.NewExpressionWithTypeArguments(expression, typeArguments) + implementsExpression.Loc = tag.Loc + implementsExpression.Flags = p.contextFlags | ast.NodeFlagsReparsed + + // Create implements heritage clause + implementsClause := p.factory.NewHeritageClause(ast.KindImplementsKeyword, p.factory.NewNodeList([]*ast.Node{implementsExpression})) + implementsClause.Loc = tag.Loc + implementsClause.Flags = p.contextFlags | ast.NodeFlagsReparsed + + // Add to existing heritage clauses or create new list + var heritageList []*ast.Node + if class.HeritageClauses != nil { + heritageList = append(heritageList, class.HeritageClauses.Nodes...) + } + heritageList = append(heritageList, implementsClause) + + class.HeritageClauses = p.factory.NewNodeList(heritageList) + } } } }