@@ -24,6 +24,7 @@ import (
2424 "runtime/debug"
2525 "slices"
2626 "strings"
27+ "unicode/utf16"
2728
2829 "github.com/bufbuild/buf/private/buf/bufformat"
2930 "github.com/bufbuild/protocompile/experimental/ir"
@@ -304,20 +305,13 @@ func (s *server) Formatting(
304305 if newText == file .text {
305306 return nil , nil
306307 }
307- // XXX: The current compiler does not expose a span for the full file. Instead of
308- // potentially undershooting the correct span (which can cause comments at the
309- // start and end of the file to be duplicated), we instead manually count up the
310- // number of lines in the file. This is comparatively cheap, compared to sending the
311- // entire file over a domain socket.
312- var lastLine , lastLineStart int
313- for i := range len (file .text ) {
314- // NOTE: we are iterating over bytes, not runes.
315- if file .text [i ] == '\n' {
316- lastLine ++
317- lastLineStart = i + 1 // Skip the \n.
318- }
308+
309+ // Calculate the end location for the file range.
310+ endLine := strings .Count (file .text , "\n " )
311+ endCharacter := 0
312+ for _ , char := range file .text [strings .LastIndexByte (file .text , '\n' )+ 1 :] {
313+ endCharacter += utf16 .RuneLen (char )
319314 }
320- lastChar := len (file .text [lastLineStart :]) - 1 // Bytes, not runes!
321315 return []protocol.TextEdit {
322316 {
323317 Range : protocol.Range {
@@ -326,8 +320,8 @@ func (s *server) Formatting(
326320 Character : 0 ,
327321 },
328322 End : protocol.Position {
329- Line : uint32 (lastLine ),
330- Character : uint32 (lastChar ),
323+ Line : uint32 (endLine ),
324+ Character : uint32 (endCharacter ),
331325 },
332326 },
333327 NewText : newText ,
0 commit comments