Skip to content

fix(editor): replace the whole typed word when accepting a completion#1601

Merged
datlechin merged 2 commits into
mainfrom
fix/autocomplete-apply-range
Jun 6, 2026
Merged

fix(editor): replace the whole typed word when accepting a completion#1601
datlechin merged 2 commits into
mainfrom
fix/autocomplete-apply-range

Conversation

@datlechin

Copy link
Copy Markdown
Member

Problem

User report: with a column named message, typing mess and pressing Tab inserts memessage instead of message. The completion left the first typed characters in place and replaced only a tail subrange.

Root cause

SQLCompletionAdapter.completionWindowApplyCompletion built the replace range from a stored token start paired with the live cursor:

  • the start was computed asynchronously when the suggestion window opened (50ms debounce, actor hops, on-demand schema fetches, 5,000-char window offset, statement-offset arithmetic)
  • completionOnCursorMove kept the window open across keystrokes but never updated the stored range
  • the fuzzy filter let candidates survive a corrupted effective prefix (ss fuzzy-matches message), so nothing self-corrected before Tab

Any drift in that pipeline became a wrong location, and Tab replaced the wrong subrange. The happy path was correct, which is why the bug appeared only intermittently (fast typing during a schema fetch, multi-statement or multibyte documents).

Fix

Compute the replacement range from the live text at accept time, the way AppKit's own completion (rangeForUserCompletion) behaves:

  • new SQLTokenBoundary holds the single identifier-boundary rule (UTF-16 scanning, stops at . so qualified-name segment completion keeps its semantics) and replacementRange(in:cursor:fallback:)
  • completionWindowApplyCompletion and completionOnCursorMove both use it, so the visible filtering and the applied range always agree; the stored range remains only as a fallback when no cursor is supplied
  • SQLContextAnalyzer delegates its boundary checks to the shared rule so analyzer and adapter cannot diverge again

Tests

11 unit tests in SQLTokenBoundaryTests: plain word, dot segments, quoted identifiers, multibyte text before the token, cursor clamping, empty prefix, and the regression case (stale stored range + live cursor must produce SELECT message, never SELECT memessage). All pass locally; swiftlint lint --strict clean on changed files.

@datlechin datlechin merged commit 73544f5 into main Jun 6, 2026
4 checks passed
@datlechin datlechin deleted the fix/autocomplete-apply-range branch June 6, 2026 10:25
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.

1 participant