diff --git a/internal/fourslash/tests/manual/completionsInArrayLiteralWithContextualType_test.go b/internal/fourslash/tests/manual/completionsInArrayLiteralWithContextualType_test.go index 0325115183..7cf5b5fa7d 100644 --- a/internal/fourslash/tests/manual/completionsInArrayLiteralWithContextualType_test.go +++ b/internal/fourslash/tests/manual/completionsInArrayLiteralWithContextualType_test.go @@ -66,4 +66,19 @@ func TestCompletionsInArrayLiteralWithContextualType(t *testing.T) { }, }, }) + + // Test 4: Completions after `]` in a tuple should not crash (issue #2296) + // When completing after the closing bracket, we're outside the array literal + // so we shouldn't be getting contextual types for array elements + const content4 = `let x: [number] = [123]/*d*/;` + f4, done4 := fourslash.NewFourslash(t, nil /*capabilities*/, content4) + defer done4() + // Just verify that completions don't crash - accept any completion list + f4.VerifyCompletions(t, "d", &fourslash.CompletionsExpectedList{ + ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{ + CommitCharacters: &DefaultCommitCharacters, + EditRange: Ignored, + }, + Items: &fourslash.CompletionsExpectedItems{}, + }) } diff --git a/internal/ls/completions.go b/internal/ls/completions.go index a7f38f4afd..983117e587 100644 --- a/internal/ls/completions.go +++ b/internal/ls/completions.go @@ -2998,6 +2998,13 @@ func getContextualType(previousToken *ast.Node, position int, file *ast.SourceFi } } return nil + case ast.KindCloseBracketToken: + // When completing after `]` (e.g., `[x]/*here*/`), we should not provide a contextual type + // for the closing bracket token itself. Without this case, CloseBracketToken would fall through + // to the default case, and if the parent is an array literal, GetContextualType would try to + // find the token's index in the array elements (returning -1), leading to an out-of-bounds panic + // in getContextualTypeForElementExpression. + return nil case ast.KindQuestionToken: // When completing after `?` in a ternary conditional (e.g., `foo(a ? /*here*/)`), // we need to look at the parent conditional expression to find the contextual type.