diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-16 04:38:32 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-16 04:38:32 +0200 |
| commit | 5e0cf1ede41b2887db98ca61c8100cbe1da61170 (patch) | |
| tree | d3d172643fb18d8e9b03af591125909babb9c0d8 /internal/lsp/handlers.go | |
| parent | 409cec495ae619fa874e0e827ac620b881f84941 (diff) | |
Fix byte vs UTF-16 indexing in LSP position handling
Adds utf16OffsetToByteOffset helper to correctly convert LSP character
positions (UTF-16 code units) to Go string byte offsets. Fixes trigger
detection, prefix heuristic, and completion text slicing for files
containing multi-byte characters.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/lsp/handlers.go')
| -rw-r--r-- | internal/lsp/handlers.go | 11 |
1 files changed, 7 insertions, 4 deletions
diff --git a/internal/lsp/handlers.go b/internal/lsp/handlers.go index ebdefc1..ad2f98d 100644 --- a/internal/lsp/handlers.go +++ b/internal/lsp/handlers.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "strings" + "unicode/utf8" ) func (s *Server) handle(req Request) { @@ -274,16 +275,18 @@ func (s *Server) isTriggerEvent(p CompletionParams, current string) bool { } // For TriggerForIncomplete (3), require manual char check below } - // 2) Fallback: check the character immediately prior to cursor - idx := p.Position.Character - if idx <= 0 || idx > len(current) { + // 2) Fallback: check the character immediately prior to cursor. + // Convert UTF-16 offset to byte offset for correct multi-byte handling. + byteIdx := utf16OffsetToByteOffset(current, p.Position.Character) + if byteIdx <= 0 || byteIdx > len(current) { return false } // Bare double-open should not trigger via fallback char either (only when configured) if containsAny(current, doubleSeqs) && !hasDoubleOpenTrigger(current, open, openChar, closeChar) { return false } - ch := string(current[idx-1]) + r, _ := utf8.DecodeLastRuneInString(current[:byteIdx]) + ch := string(r) for _, c := range triggerChars { if c == ch { return true |
