Skip to content

fix(lsp): complete string union literals containing dots#34664

Merged
littledivy merged 1 commit into
mainfrom
orch/divybot-395
Jun 1, 2026
Merged

fix(lsp): complete string union literals containing dots#34664
littledivy merged 1 commit into
mainfrom
orch/divybot-395

Conversation

@divybot

@divybot divybot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Problem

Autocompleting a string union literal type whose members contain . is broken in the Deno LSP. Given:

type T = "foo.bar" | "foo.baz";
const x: T = "foo.b"; // completing here

Accepting the foo.bar suggestion produces a mangled result — everything typed before the last . is forgotten. Plain tsc/VSCode handle this correctly. Reported in #28075.

Cause

For a string union (Types) completion, TSC sets a per-entry replacementSpan (covering the string contents) but does not set insertText. Deno's CompletionEntry::as_completion_item only constructed a text_edit when both the replacement span and insertText were Some:

if let (Some(text_span), Some(new_text)) = (range, &insert_text) { ... }

So the edit was silently dropped, leaving the editor to apply its own word-based replacement. Because . is a word boundary, only the text after the last dot was replaced.

Fix

When a replacementSpan is present but insertText is not, fall back to the entry name as the inserted text — matching VSCode's TypeScript integration (insertText ?? name). This makes the full string content get replaced.

Test

Added lsp_completions_string_union_with_dot, which asserts the completion item carries a text_edit spanning the whole string content. Verified it fails before the change (text_edit is None) and passes after. The full existing lsp_completions/auto-import/registry completion suite (28 tests) still passes.

Closes denoland/divybot#395
Fixes #28075
Fixes #28083

When TSC returns completions for a string union literal type, each entry
carries a `replacementSpan` covering the string contents but no
`insertText`. The previous code only built a `text_edit` when both the
replacement span and an `insertText` were present, so the edit was
dropped and the editor fell back to its own word-based replacement. With
a `.` in the string, that replaced only the text after the last dot,
"forgetting" everything before it.

Fall back to the entry name as the inserted text when `insertText` is
absent (matching VSCode's TypeScript integration), so the whole string
content is replaced.

Co-Authored-By: Divy Srivastava <[email protected]>
@littledivy
littledivy enabled auto-merge (squash) June 1, 2026 13:42
@littledivy
littledivy merged commit 4218623 into main Jun 1, 2026
138 checks passed
@littledivy
littledivy deleted the orch/divybot-395 branch June 1, 2026 13:45
littledivy added a commit to crowlKats/deno that referenced this pull request Jun 10, 2026
)

## Problem

Autocompleting a string union literal type whose members contain `.` is
broken in the Deno LSP. Given:

```ts
type T = "foo.bar" | "foo.baz";
const x: T = "foo.b"; // completing here
```

Accepting the `foo.bar` suggestion produces a mangled result —
everything typed before the last `.` is forgotten. Plain `tsc`/VSCode
handle this correctly. Reported in denoland#28075.

## Cause

For a string union (`Types`) completion, TSC sets a per-entry
`replacementSpan` (covering the string contents) but does **not** set
`insertText`. Deno's `CompletionEntry::as_completion_item` only
constructed a `text_edit` when **both** the replacement span and
`insertText` were `Some`:

```rust
if let (Some(text_span), Some(new_text)) = (range, &insert_text) { ... }
```

So the edit was silently dropped, leaving the editor to apply its own
word-based replacement. Because `.` is a word boundary, only the text
after the last dot was replaced.

## Fix

When a `replacementSpan` is present but `insertText` is not, fall back
to the entry name as the inserted text — matching VSCode's TypeScript
integration (`insertText ?? name`). This makes the full string content
get replaced.

## Test

Added `lsp_completions_string_union_with_dot`, which asserts the
completion item carries a `text_edit` spanning the whole string content.
Verified it fails before the change (`text_edit` is `None`) and passes
after. The full existing `lsp_completions`/auto-import/registry
completion suite (28 tests) still passes.

Closes denoland/divybot#395
Fixes denoland#28075

Co-authored-by: divybot <[email protected]>
Co-authored-by: Divy Srivastava <[email protected]>
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.

Control/Cmd + hovering over import strings doesn't highlight the full string lsp: Autocompleting string unions with dots in them is broken

2 participants