From 8634b1ecd393732f1e82ea5e9e42ddfcecc57333 Mon Sep 17 00:00:00 2001 From: Rebecca Stambler Date: Thu, 6 Dec 2018 15:52:34 -0500 Subject: [PATCH] internal/lsp: improve handling of code completion snippets A few minor fixes: check that the insert text has the expected prefix before removing it, use a bytes.Buffer to build up snippets, and check that functions have parentheses in their insert text before trimming them. Change-Id: Iaeaf6fda25d6b0a375460b975188486685be1061 Reviewed-on: https://go-review.googlesource.com/c/152978 Reviewed-by: Ingo Oeser Reviewed-by: Ian Cottrell --- internal/lsp/completion.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go index d4012f3b8e..a95f59b85b 100644 --- a/internal/lsp/completion.go +++ b/internal/lsp/completion.go @@ -5,6 +5,7 @@ package lsp import ( + "bytes" "fmt" "sort" "strings" @@ -28,7 +29,7 @@ func toProtocolCompletionItems(items []source.CompletionItem, prefix string, pos continue } insertText, triggerSignatureHelp := labelToProtocolSnippets(item.Label, item.Kind, insertTextFormat, signatureHelpEnabled) - if prefix != "" { + if strings.HasPrefix(insertText, prefix) { insertText = insertText[len(prefix):] } i := protocol.CompletionItem{ @@ -90,14 +91,17 @@ func labelToProtocolSnippets(label string, kind source.CompletionItemKind, inser switch kind { case source.ConstantCompletionItem: // The label for constants is of the format " = ". - // We should now insert the " = " part of the label. + // We should not insert the " = " part of the label. if i := strings.Index(label, " ="); i >= 0 { return label[:i], false } case source.FunctionCompletionItem, source.MethodCompletionItem: - trimmed := label[:strings.Index(label, "(")] - params := strings.Trim(label[strings.Index(label, "("):], "()") - if params == "" { + var trimmed, params string + if i := strings.Index(label, "("); i >= 0 { + trimmed = label[:i] + params = strings.Trim(label[i:], "()") + } + if params == "" || trimmed == "" { return label, true } // Don't add parameters or parens for the plaintext insert format. @@ -118,14 +122,16 @@ func labelToProtocolSnippets(label string, kind source.CompletionItemKind, inser `}`, `\}`, `$`, `\$`, ) - trimmed += "(" + b := bytes.NewBufferString(trimmed) + b.WriteByte('(') for i, p := range strings.Split(params, ",") { if i != 0 { - trimmed += ", " + b.WriteString(", ") } - trimmed += fmt.Sprintf("${%v:%v}", i+1, r.Replace(strings.Trim(p, " "))) + fmt.Fprintf(b, "${%v:%v}", i+1, r.Replace(strings.Trim(p, " "))) } - return trimmed + ")", false + b.WriteByte(')') + return b.String(), false } return label, false