From eac0f8cdb8d5537628785763a33bf16d9a23b372 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 Aug 2025 22:14:06 +0000 Subject: [PATCH 1/2] Initial plan From 39fde9d71bbf9b3844487375c8b4f17309bccb84 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 11 Aug 2025 22:43:41 +0000 Subject: [PATCH 2/2] Fix getTokensFromNode template scanning issue Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com> --- internal/ls/signaturehelp.go | 31 +++++++++++++++++++++++++++++++ internal/ls/signaturehelp_test.go | 9 +++++++++ 2 files changed, 40 insertions(+) diff --git a/internal/ls/signaturehelp.go b/internal/ls/signaturehelp.go index 94984a9910..bacedb4bad 100644 --- a/internal/ls/signaturehelp.go +++ b/internal/ls/signaturehelp.go @@ -1083,6 +1083,12 @@ func getTokensFromNode(node *ast.Node, sourceFile *ast.SourceFile) []*ast.Node { if node == nil { return nil } + + // Special handling for template expressions + if node.Kind == ast.KindTemplateExpression { + return getTokensFromTemplateExpression(node, sourceFile) + } + var children []*ast.Node current := node left := node.Pos() @@ -1098,6 +1104,31 @@ func getTokensFromNode(node *ast.Node, sourceFile *ast.SourceFile) []*ast.Node { return children } +func getTokensFromTemplateExpression(node *ast.Node, sourceFile *ast.SourceFile) []*ast.Node { + templateExpr := node.AsTemplateExpression() + var children []*ast.Node + + // Add the template head + head := templateExpr.Head + children = append(children, head.AsNode()) + + // Add tokens for each template span + if templateExpr.TemplateSpans != nil { + for _, spanNode := range templateExpr.TemplateSpans.Nodes { + span := spanNode.AsTemplateSpan() + + // Add tokens from the expression part + exprTokens := getTokensFromNode(span.Expression.AsNode(), sourceFile) + children = append(children, exprTokens...) + + // Add the template literal part (middle or tail) + children = append(children, span.Literal.AsNode()) + } + } + + return children +} + func getTokenFromNodeList(nodeList *ast.NodeList, nodeListParent *ast.Node, sourceFile *ast.SourceFile) []*ast.Node { if nodeList == nil || nodeListParent == nil { return nil diff --git a/internal/ls/signaturehelp_test.go b/internal/ls/signaturehelp_test.go index ab639c4d41..8a68dad7d9 100644 --- a/internal/ls/signaturehelp_test.go +++ b/internal/ls/signaturehelp_test.go @@ -580,6 +580,15 @@ f("x", /**/);`, "": {text: `f(a: "x", b: "x", c: "x"): void`, parameterCount: 3, parameterSpan: `b: "x"`, activeParameter: &lsproto.UintegerOrNull{Uinteger: ptrTo(uint32(1))}}, }, }, + { + title: "signatureHelpTaggedTemplate", + input: `function tag(strings: TemplateStringsArray, ...values: any[]) { return ""; } +const value = 42; +const result = tag` + "`Hello ${value} /*1*/ world ${value}!`" + `;`, + expected: map[string]verifySignatureHelpOptions{ + "1": {text: "tag(strings: TemplateStringsArray, ...values: any[]): string", parameterCount: 2, parameterSpan: "...values: any[]", activeParameter: &lsproto.UintegerOrNull{Uinteger: ptrTo(uint32(1))}}, + }, + }, { title: "signatureHelpInParenthetical", input: `class base { constructor (public n: number, public y: string) { } }