From c62d5e28f8f61edac868d0538c32a0694db872ba Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 06:31:45 +0000 Subject: [PATCH 1/3] Initial plan From a453037c1953481679d35907b67b8afbc819957b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 06:59:45 +0000 Subject: [PATCH 2/3] Fix signature help crash on call target when nested call has trailing comma Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> --- internal/checker/checker.go | 10 +++++ ...gnatureHelpNestedCallTrailingComma_test.go | 38 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 internal/fourslash/tests/signatureHelpNestedCallTrailingComma_test.go diff --git a/internal/checker/checker.go b/internal/checker/checker.go index ff0060a7a6..26c041c8b7 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -9648,6 +9648,16 @@ func (c *Checker) getArgumentArityError(node *ast.Node, signatures []*Signature, } return diagnostic default: + // Handle edge case where maxCount >= len(args) + // This can happen when signature resolution fails for reasons other than argument count, + // such as when trailing commas create OmittedExpressions that affect type inference. + if maxCount >= len(args) { + diagnostic := NewDiagnosticForNode(errorNode, message, parameterRange, len(args)) + if headMessage != nil { + diagnostic = ast.NewDiagnosticChain(diagnostic, headMessage) + } + return diagnostic + } sourceFile := ast.GetSourceFileOfNode(node) pos := scanner.SkipTrivia(sourceFile.Text(), args[maxCount].Pos()) end := args[len(args)-1].End() diff --git a/internal/fourslash/tests/signatureHelpNestedCallTrailingComma_test.go b/internal/fourslash/tests/signatureHelpNestedCallTrailingComma_test.go new file mode 100644 index 0000000000..c45e38ba73 --- /dev/null +++ b/internal/fourslash/tests/signatureHelpNestedCallTrailingComma_test.go @@ -0,0 +1,38 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + . "github.com/microsoft/typescript-go/internal/fourslash/tests/util" + "github.com/microsoft/typescript-go/internal/lsp/lsproto" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSignatureHelpNestedCallTrailingComma(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + // Regression test for crash when requesting signature help on a call target + // where the nested call has a trailing comma. + // Both outer and inner calls must have trailing commas, and outer must be generic. + const content = `declare function outer(range: T): T; +declare function inner(a: any, b: any, c: any, d: any, e: any): any; + +outer( + inner(/*1*/ + undefined, + undefined, + undefined, + undefined, + undefined, + ), +);` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.GoToMarker(t, "1") + f.VerifySignatureHelpPresent(t, &lsproto.SignatureHelpContext{ + IsRetrigger: false, + TriggerCharacter: PtrTo("("), + TriggerKind: lsproto.SignatureHelpTriggerKindTriggerCharacter, + }) +} From 0d98c09fc24ff8db4606bb0fe383d0419356a94c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 07:32:37 +0000 Subject: [PATCH 3/3] Fix signature help crash with trailing comma and update test with minimal repro Co-authored-by: DanielRosenwasser <972891+DanielRosenwasser@users.noreply.github.com> --- internal/checker/checker.go | 7 ++++--- ...ignatureHelpNestedCallTrailingComma_test.go | 18 ++++-------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/internal/checker/checker.go b/internal/checker/checker.go index 26c041c8b7..23961a6eb4 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -9648,9 +9648,10 @@ func (c *Checker) getArgumentArityError(node *ast.Node, signatures []*Signature, } return diagnostic default: - // Handle edge case where maxCount >= len(args) - // This can happen when signature resolution fails for reasons other than argument count, - // such as when trailing commas create OmittedExpressions that affect type inference. + // Guard against out-of-bounds access when maxCount >= len(args). + // This can happen when we reach this fallback error path but the argument + // count actually matches the parameter count (e.g., due to trailing commas + // causing signature resolution to fail for other reasons). if maxCount >= len(args) { diagnostic := NewDiagnosticForNode(errorNode, message, parameterRange, len(args)) if headMessage != nil { diff --git a/internal/fourslash/tests/signatureHelpNestedCallTrailingComma_test.go b/internal/fourslash/tests/signatureHelpNestedCallTrailingComma_test.go index c45e38ba73..9db3818205 100644 --- a/internal/fourslash/tests/signatureHelpNestedCallTrailingComma_test.go +++ b/internal/fourslash/tests/signatureHelpNestedCallTrailingComma_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/microsoft/typescript-go/internal/fourslash" - . "github.com/microsoft/typescript-go/internal/fourslash/tests/util" "github.com/microsoft/typescript-go/internal/lsp/lsproto" "github.com/microsoft/typescript-go/internal/testutil" ) @@ -16,23 +15,14 @@ func TestSignatureHelpNestedCallTrailingComma(t *testing.T) { // where the nested call has a trailing comma. // Both outer and inner calls must have trailing commas, and outer must be generic. const content = `declare function outer(range: T): T; -declare function inner(a: any, b: any, c: any, d: any, e: any): any; +declare function inner(a: any): any; -outer( - inner(/*1*/ - undefined, - undefined, - undefined, - undefined, - undefined, - ), -);` +outer(inner/*1*/(undefined,),);` f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) defer done() f.GoToMarker(t, "1") f.VerifySignatureHelpPresent(t, &lsproto.SignatureHelpContext{ - IsRetrigger: false, - TriggerCharacter: PtrTo("("), - TriggerKind: lsproto.SignatureHelpTriggerKindTriggerCharacter, + IsRetrigger: false, + TriggerKind: lsproto.SignatureHelpTriggerKindInvoked, }) }