1
0
mirror of https://github.com/golang/go synced 2024-11-18 19:54:44 -07:00
go/internal/lsp/completion.go
Rebecca Stambler d5eafb537d internal/lsp: add InsertText to completions
If signature help is enabled, we should not offer parameter suggestions.
If signature help is not enabled, the user should be able to tab
through parameter completions.

Change-Id: I10990ef4aefb306ddbf51ed14cc1110065eba655
Reviewed-on: https://go-review.googlesource.com/c/150637
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
2018-11-20 22:45:09 +00:00

104 lines
3.3 KiB
Go

// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package lsp
import (
"fmt"
"sort"
"strings"
"golang.org/x/tools/internal/lsp/protocol"
"golang.org/x/tools/internal/lsp/source"
)
func toProtocolCompletionItems(items []source.CompletionItem, snippetsSupported, signatureHelpEnabled bool) []protocol.CompletionItem {
var results []protocol.CompletionItem
sort.Slice(items, func(i, j int) bool {
return items[i].Score > items[j].Score
})
insertTextFormat := protocol.PlainTextFormat
if snippetsSupported {
insertTextFormat = protocol.SnippetTextFormat
}
for _, item := range items {
results = append(results, protocol.CompletionItem{
Label: item.Label,
InsertText: labelToProtocolSnippets(item.Label, item.Kind, insertTextFormat, signatureHelpEnabled),
Detail: item.Detail,
Kind: float64(toProtocolCompletionItemKind(item.Kind)),
InsertTextFormat: insertTextFormat,
})
}
return results
}
func toProtocolCompletionItemKind(kind source.CompletionItemKind) protocol.CompletionItemKind {
switch kind {
case source.InterfaceCompletionItem:
return protocol.InterfaceCompletion
case source.StructCompletionItem:
return protocol.StructCompletion
case source.TypeCompletionItem:
return protocol.TypeParameterCompletion // ??
case source.ConstantCompletionItem:
return protocol.ConstantCompletion
case source.FieldCompletionItem:
return protocol.FieldCompletion
case source.ParameterCompletionItem, source.VariableCompletionItem:
return protocol.VariableCompletion
case source.FunctionCompletionItem:
return protocol.FunctionCompletion
case source.MethodCompletionItem:
return protocol.MethodCompletion
case source.PackageCompletionItem:
return protocol.ModuleCompletion // ??
default:
return protocol.TextCompletion
}
}
func labelToProtocolSnippets(label string, kind source.CompletionItemKind, insertTextFormat protocol.InsertTextFormat, signatureHelpEnabled bool) string {
switch kind {
case source.ConstantCompletionItem:
// The label for constants is of the format "<identifier> = <value>".
// We should now insert the " = <value>" part of the label.
return label[:strings.Index(label, " =")]
case source.FunctionCompletionItem, source.MethodCompletionItem:
trimmed := label[:strings.Index(label, "(")]
params := strings.Trim(label[strings.Index(label, "("):], "()")
if params == "" {
return label
}
// Don't add parameters or parens for the plaintext insert format.
if insertTextFormat == protocol.PlainTextFormat {
return trimmed
}
// If we do have signature help enabled, the user can see parameters as
// they type in the function, so we just return empty parentheses.
if signatureHelpEnabled {
return trimmed + "($1)"
}
// If signature help is not enabled, we should give the user parameters
// that they can tab through. The insert text format follows the
// specification defined by Microsoft for LSP. The "$", "}, and "\"
// characters should be escaped.
r := strings.NewReplacer(
`\`, `\\`,
`}`, `\}`,
`$`, `\$`,
)
trimmed += "("
for i, p := range strings.Split(params, ",") {
if i != 0 {
trimmed += ", "
}
trimmed += fmt.Sprintf("${%v:%v}", i+1, r.Replace(strings.Trim(p, " ")))
}
return trimmed + ")"
}
return label
}