internal/lsp: add literal completions for basic types

Normally you don't want literal candidates for basic types (e.g.
"int(0)") since you can type the literal value without the type name.
One exception is if you are creating a named basic type that
implements an interface. For example:

http.Handle("/", http.FileServer(<>))

will now give "http.Dir()" as a candidate since http.Dir is a named
string type that implements the required interface http.FileSystem.

Change-Id: Id2470c45e469ea25cd0f9849cfdad19ac0e784bb
Reviewed-on: https://go-review.googlesource.com/c/tools/+/195838
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Muir Manders 2019-09-16 19:07:16 -07:00 committed by Rebecca Stambler
parent 92496828d1
commit a044388aa5
3 changed files with 36 additions and 1 deletions

View File

@ -85,6 +85,13 @@ func (c *completer) literal(literalType types.Type) {
switch t := literalType.Underlying().(type) {
case *types.Struct, *types.Array, *types.Slice, *types.Map:
c.compositeLiteral(t, typeName, float64(score))
case *types.Basic:
// Add a literal completion for basic types that implement our
// expected interface (e.g. named string type http.Dir
// implements http.FileSystem).
if isInterface(c.expectedType.objType) {
c.basicLiteral(t, typeName, float64(score))
}
}
}
@ -261,6 +268,26 @@ func (c *completer) compositeLiteral(T types.Type, typeName string, matchScore f
})
}
// basicLiteral adds a literal completion item for the given basic
// type name typeName.
func (c *completer) basicLiteral(T types.Type, typeName string, matchScore float64) {
snip := &snippet.Builder{}
snip.WriteText(typeName + "(")
snip.WriteFinalTabstop()
snip.WriteText(")")
nonSnippet := typeName + "()"
c.items = append(c.items, CompletionItem{
Label: nonSnippet,
InsertText: nonSnippet,
Detail: T.String(),
Score: matchScore * literalCandidateScore,
Kind: VariableCompletionItem,
snippet: snip,
})
}
// makeCall adds a completion item for a "make()" call given a specific type.
func (c *completer) makeCall(typeName string, secondArg string, matchScore float64) {
// Keep it simple and don't add any placeholders for optional "make()" arguments.

View File

@ -66,6 +66,10 @@ func (myImpl) foo() {}
func (*myImpl) bar() {}
type myBasicImpl string
func (myBasicImpl) foo() {}
func _() {
type myIntf interface {
foo()
@ -76,6 +80,10 @@ func _() {
var mi myIntf
mi = m //@snippet(" //", litImpl, "myImpl{\\}", "myImpl{\\}")
myBasicImpl() //@item(litBasicImpl, "myBasicImpl()", "string", "var")
mi = m //@snippet(" //", litBasicImpl, "myBasicImpl($0)", "myBasicImpl($0)")
// only satisfied by pointer to myImpl
type myPtrIntf interface {
bar()

View File

@ -30,7 +30,7 @@ import (
// are being executed. If a test is added, this number must be changed.
const (
ExpectedCompletionsCount = 152
ExpectedCompletionSnippetCount = 35
ExpectedCompletionSnippetCount = 36
ExpectedUnimportedCompletionsCount = 1
ExpectedDeepCompletionsCount = 5
ExpectedFuzzyCompletionsCount = 6