diff --git a/internal/checker/checker.go b/internal/checker/checker.go index ff0060a7a6..23961a6eb4 100644 --- a/internal/checker/checker.go +++ b/internal/checker/checker.go @@ -9648,6 +9648,17 @@ func (c *Checker) getArgumentArityError(node *ast.Node, signatures []*Signature, } return diagnostic default: + // 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 { + 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..9db3818205 --- /dev/null +++ b/internal/fourslash/tests/signatureHelpNestedCallTrailingComma_test.go @@ -0,0 +1,28 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "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): any; + +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, + TriggerKind: lsproto.SignatureHelpTriggerKindInvoked, + }) +}