From e0bf2294bb0c6d2f94e29cf1ccf154e5f11c3056 Mon Sep 17 00:00:00 2001 From: Danish Dua Date: Fri, 21 Aug 2020 17:16:29 -0400 Subject: [PATCH] internal/lsp/source: fix completion on final line of a document Span treats an end of file as the beginning of the next line, which for a final line ending without a newline is incorrect and leads to completions being ignored. We adjust the ending in case range end is on a different line here. Change-Id: Ic545dcb221493530b7e39d2be8eba57b69fb6597 Reviewed-on: https://go-review.googlesource.com/c/tools/+/249706 Run-TryBot: Danish Dua TryBot-Result: Gobot Gobot Reviewed-by: Heschi Kreinick --- internal/lsp/completion.go | 11 +++++++++++ internal/lsp/source/completion.go | 4 ++++ internal/span/token.go | 2 ++ 3 files changed, 17 insertions(+) diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go index 754b90d641..aa285251b1 100644 --- a/internal/lsp/completion.go +++ b/internal/lsp/completion.go @@ -42,6 +42,17 @@ func (s *Server) completion(ctx context.Context, params *protocol.CompletionPara if err != nil { return nil, err } + // Span treats an end of file as the beginning of the next line, which for + // a final line ending without a newline is incorrect and leads to + // completions being ignored. We adjust the ending in case ange end is on a + // different line here. + // This should be removed after the resolution of golang/go#41029 + if rng.Start.Line != rng.End.Line { + rng.End = protocol.Position{ + Character: rng.Start.Character + float64(len(surrounding.Content())), + Line: rng.Start.Line, + } + } // When using deep completions/fuzzy matching, report results as incomplete so // client fetches updated completions after every key stroke. diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go index 3c0ad9f179..bca2ac2e64 100644 --- a/internal/lsp/source/completion.go +++ b/internal/lsp/source/completion.go @@ -241,6 +241,10 @@ type Selection struct { mappedRange } +func (p Selection) Content() string { + return p.content +} + func (p Selection) Prefix() string { return p.content[:p.cursor-p.spanRange.Start] } diff --git a/internal/span/token.go b/internal/span/token.go index 1710b7779d..10b429efd1 100644 --- a/internal/span/token.go +++ b/internal/span/token.go @@ -114,6 +114,8 @@ func positionFromOffset(f *token.File, offset int) (string, int, int, error) { } pos := f.Pos(offset) p := f.Position(pos) + // TODO(golang/go#41029): Consider returning line, column instead of line+1, 1 if + // the file's last character is not a newline. if offset == f.Size() { return p.Filename, p.Line + 1, 1, nil }