diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go index 2f54c68a9bf..bcc4e0e9276 100644 --- a/internal/lsp/completion.go +++ b/internal/lsp/completion.go @@ -65,11 +65,7 @@ func toProtocolCompletionItems(candidates []source.CompletionItem, prefix string } insertText := candidate.InsertText if insertTextFormat == protocol.SnippetTextFormat { - if usePlaceholders && candidate.PlaceholderSnippet != nil { - insertText = candidate.PlaceholderSnippet.String() - } else if candidate.Snippet != nil { - insertText = candidate.Snippet.String() - } + insertText = candidate.Snippet(usePlaceholders) } item := protocol.CompletionItem{ Label: candidate.Label, diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go index 1c309c500fa..2a132d58215 100644 --- a/internal/lsp/source/completion.go +++ b/internal/lsp/source/completion.go @@ -44,7 +44,7 @@ type CompletionItem struct { // // foo(${1:}) // - Snippet *snippet.Builder + plainSnippet *snippet.Builder // PlaceholderSnippet is the LSP snippet for the completion ite, containing // placeholders. The LSP specification contains details about LSP snippets. @@ -56,7 +56,21 @@ type CompletionItem struct { // // foo(${1:a int}, ${2: b int}, ${3: c int}) // - PlaceholderSnippet *snippet.Builder + placeholderSnippet *snippet.Builder +} + +// Snippet is a convenience function that determines the snippet that should be +// used for an item, depending on if the callee wants placeholders or not. +func (i *CompletionItem) Snippet(usePlaceholders bool) string { + if usePlaceholders { + if i.placeholderSnippet != nil { + return i.placeholderSnippet.String() + } + } + if i.plainSnippet != nil { + return i.plainSnippet.String() + } + return i.InsertText } type CompletionItemKind int diff --git a/internal/lsp/source/completion_format.go b/internal/lsp/source/completion_format.go index ce6f2f9ea0b..68942548fa9 100644 --- a/internal/lsp/source/completion_format.go +++ b/internal/lsp/source/completion_format.go @@ -81,8 +81,8 @@ func (c *completer) item(obj types.Object, score float64) CompletionItem { Detail: detail, Kind: kind, Score: score, - Snippet: plainSnippet, - PlaceholderSnippet: placeholderSnippet, + plainSnippet: plainSnippet, + placeholderSnippet: placeholderSnippet, } } @@ -126,7 +126,7 @@ func (c *completer) formatBuiltin(obj types.Object, score float64) CompletionIte params, _ := c.formatFieldList(decl.Type.Params) results, writeResultParens := c.formatFieldList(decl.Type.Results) item.Label, item.Detail = formatFunction(obj.Name(), params, results, writeResultParens) - item.Snippet, item.PlaceholderSnippet = c.functionCallSnippets(obj.Name(), params) + item.plainSnippet, item.placeholderSnippet = c.functionCallSnippets(obj.Name(), params) case *types.TypeName: if types.IsInterface(obj.Type()) { item.Kind = InterfaceCompletionItem diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go index 7c3db45f6e7..7913b9cdbaa 100644 --- a/internal/lsp/source/source_test.go +++ b/internal/lsp/source/source_test.go @@ -173,32 +173,22 @@ func (r *runner) checkCompletionSnippets(ctx context.Context, t *testing.T, data } wantCompletion := items[want.CompletionItem] - var gotItem *source.CompletionItem + var got *source.CompletionItem for _, item := range list { if item.Label == wantCompletion.Label { - gotItem = &item + got = &item break } } - - if gotItem == nil { + if got == nil { t.Fatalf("%s: couldn't find completion matching %q", src.URI(), wantCompletion.Label) } - var expected string + expected := want.PlainSnippet if usePlaceholders { expected = want.PlaceholderSnippet - } else { - expected = want.PlainSnippet } - insertText := gotItem.InsertText - if usePlaceholders && gotItem.PlaceholderSnippet != nil { - insertText = gotItem.PlaceholderSnippet.String() - } else if gotItem.Snippet != nil { - insertText = gotItem.Snippet.String() - } - - if expected != insertText { + if insertText := got.Snippet(usePlaceholders); expected != insertText { t.Errorf("%s: expected snippet %q, got %q", src, expected, insertText) } }