Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 6, 2025

Completions panic with "index out of range [-1]" when requested inside new Map([...]) constructor at certain positions:

const m = new Map([
    [/*crash here*/'0', ['0', false]],
]);

Additionally, string literal completions were not being suggested in tuple contexts without typing a quote character first.

Changes

  • completions.go: Add special handling for OpenBracketToken and CommaToken in array literals

    • When previousToken is [, get contextual type for element at index 0
    • When previousToken is ,, count elements before cursor and get contextual type for next element
    • Prevents invalid tokens (which aren't array elements) from reaching checker's contextual type resolution
  • services.go: Add GetContextualTypeForArrayElement function

    • Exported wrapper around getContextualTypeForElementExpression for language service use
    • Enables proper contextual type resolution for array elements at specific indices
  • Tests: Added TestCompletionsInMapConstructorNoCrash and TestCompletionsInArrayLiteralWithContextualType

    • Verifies no crash at reported positions
    • Validates that string literal completions work in tuple contexts without typing quotes

Benefits

  1. Fixes the crash: Language service no longer passes non-element tokens to checker
  2. Enables better completions: String literal completions now work in tuple contexts without needing to type a quote first (e.g., let y: ["foo" | "bar"] = [/*here*/] now suggests "foo" and "bar")
  3. Better architecture: Language service handles token-level concerns, checker handles type-level concerns
Original prompt

This section details on the original issue you should resolve

<issue_title>Completions crash in call to new Map(...).</issue_title>
<issue_description>```ts
const m = new Map([
[/a/'0', ['0', false]]/b/,
]);


Request completions at `/*a*/` or `/*b*/`.

[error] panic handling requesttextDocument/completionruntime error: index out of range [-1]goroutine 3826 [running]:
runtime/debug.Stack()
runtime/debug/stack.go:26 +0x64
github.com/microsoft/typescript-go/internal/lsp.(*Server).recover(0x4000198008, 0x4019948ff0)
github.com/microsoft/typescript-go/internal/lsp/server.go:872 +0x40
panic({0x7ff7c70f3b80?, 0x40177be4b0?})
runtime/panic.go:783 +0x120
github.com/microsoft/typescript-go/internal/checker.(*Checker).getContextualTypeForElementExpression.func1(0x401a5d2ee0)
github.com/microsoft/typescript-go/internal/checker/checker.go:28915 +0x29c
github.com/microsoft/typescript-go/internal/checker.(*Checker).mapTypeEx(0x4005641e60?, 0x4018009db0?, 0x40178d3158?, 0x94?)
github.com/microsoft/typescript-go/internal/checker/checker.go:24914 +0xd4
github.com/microsoft/typescript-go/internal/checker.(*Checker).getContextualTypeForElementExpression(0x40106ea608?, 0x4018009d60?, 0x2?, 0x4?, 0x401978a6c0?, 0x7ff7c73b4af8?)
github.com/microsoft/typescript-go/internal/checker/checker.go:28910 +0x3c
github.com/microsoft/typescript-go/internal/checker.(*Checker).getContextualType(0x40106ea608, 0x401978a6c0, 0x4)
github.com/microsoft/typescript-go/internal/checker/checker.go:28328 +0x1e0
github.com/microsoft/typescript-go/internal/checker.(*Checker).GetContextualType.func1()
github.com/microsoft/typescript-go/internal/checker/services.go:310 +0x24
github.com/microsoft/typescript-go/internal/checker.runWithoutResolvedSignatureCaching[...](0x40106ea608?, 0x4018009db0, 0x400083f4a8?)
github.com/microsoft/typescript-go/internal/checker/services.go:365 +0x2f0
github.com/microsoft/typescript-go/internal/checker.runWithInferenceBlockedFromSourceNode[...](0x40106ea608?, 0x401978a6c0, 0x400083f4a8?)
github.com/microsoft/typescript-go/internal/checker/services.go:329 +0xe4
github.com/microsoft/typescript-go/internal/checker.(*Checker).GetContextualType(0x400083f620?, 0x400083f5c0?, 0x83f574?)
github.com/microsoft/typescript-go/internal/checker/services.go:310 +0x48
github.com/microsoft/typescript-go/internal/ls.getContextualType(0x401978a6c0, 0x400c205808?, 0x40106ea608?, 0x40106ea608)
github.com/microsoft/typescript-go/internal/ls/completions.go:2995 +0x2a0
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionData(0x40097bbe90, {0x7ff7c74e2b88, 0x40097bbda0}, 0x40106ea608, 0x400c205808, 0xb8, 0x400326e800)
github.com/microsoft/typescript-go/internal/ls/completions.go:1727 +0x1038
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).getCompletionsAtPosition(0x40097bbe90, {0x7ff7c74e2b88, 0x40097bbda0}, 0x400c205808, 0xb8, 0x0)
github.com/microsoft/typescript-go/internal/ls/completions.go:383 +0x22c
github.com/microsoft/typescript-go/internal/ls.(*LanguageService).ProvideCompletion(0x40097bbe90, {0x7ff7c74e2b88, 0x40097bbda0}, {0x400dc60000?, 0x40097bbda0?}, {0xdc60000?, 0x40?}, 0x4012c7a830)
github.com/microsoft/typescript-go/internal/ls/completions.go:44 +0xa0
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleCompletion(0x400443fe78?, {0x7ff7c74e2b88?, 0x40097bbda0?}, 0x400dc60000?, 0x400443fee8?)
github.com/microsoft/typescript-go/internal/lsp/server.go:1208 +0x3c
github.com/microsoft/typescript-go/internal/lsp.init.func1.registerLanguageServiceDocumentRequestHandler[...].16({0x7ff7c74e2b88, 0x40097bbda0}, 0x4019948ff0)
github.com/microsoft/typescript-go/internal/lsp/server.go:621 +0xec
github.com/microsoft/typescript-go/internal/lsp.(*Server).handleRequestOrNotification(0x4000198008, {0x7ff7c74e2bc0?, 0x401e249220?}, 0x4019948ff0)
github.com/microsoft/typescript-go/internal/lsp/server.go:502 +0x128
github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop.func1()
github.com/microsoft/typescript-go/internal/lsp/server.go:405 +0x34
created by github.com/microsoft/typescript-go/internal/lsp.(*Server).dispatchLoop in goroutine 20
github.com/microsoft/typescript-go/internal/lsp/server.go:425 +0x7a0


## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Fix completions crash in call to new Map Fix completions crash when IndexOfNode returns -1 Dec 6, 2025
Copilot finished work on behalf of DanielRosenwasser December 6, 2025 18:20
@DanielRosenwasser
Copy link
Member

This might be alright, but I don't know if this is the right layer to do this in. Maybe this is more of a language service thing to work off of? Is there some sort of missing element we can use instead of the [ token that is probably being passed in? I'm not sure.

Also, it does reveal an undesirable behavior in both the new and old codebases.

// @filename: a.ts
let x: "foo" | "bar" = /*a*/;

// @filename: b.ts
let y: ["foo" | "bar", string] = [/*b*/];

If you request completions at /*a*/, you will get completions for the string literals "foo" and "bar".

In the old codebase (and I assume with this fix?), you will not get these suggested at /*b*/ until you actually type in a quote character.

@DanielRosenwasser
Copy link
Member

@copilot try to address.

Copy link
Contributor Author

Copilot AI commented Dec 7, 2025

@copilot try to address.

I'll address this by adding special handling for OpenBracketToken in the language service layer. The fix will handle completions after [ in array literals by getting the contextual type for the appropriate tuple element, which will also enable string literal completions without needing to type a quote first.

Working on this now.

This might be alright, but I don't know if this is the right layer to do this in. Maybe this is more of a language service thing to work off of? Is there some sort of missing element we can use instea...

Fixed in 90ca278 by handling OpenBracketToken and CommaToken at the language service layer. The fix:

  1. Prevents invalid tokens from reaching the checker (fixing the crash)
  2. Enables string literal completions without typing quotes in tuple contexts (e.g., let y: ["foo" | "bar"] = [/*here*/] now suggests "foo" and "bar")

Both issues you mentioned are now resolved.

Copilot AI changed the title Fix completions crash when IndexOfNode returns -1 Fix completions crash and enable contextual type completions in array literals Dec 7, 2025
Copilot finished work on behalf of DanielRosenwasser December 7, 2025 02:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Completions crash in call to new Map(...).

2 participants