1
0
mirror of https://github.com/golang/go synced 2024-11-18 16:44:43 -07:00

internal/lsp/source: filter candidates when type name required

Now when we expect a type name at the cursor, we omit non-type name
completion candidates. For example:

inch := 1
var foo in<> // don't offer "inch"

I also added expected type name detection for value specs:

// Expect a type name at <>
var foo <>

Fixes golang/go#32806.

Change-Id: I32477cb286d2050bac5ccc767f8a608124fa5acd
Reviewed-on: https://go-review.googlesource.com/c/tools/+/216400
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Muir Manders 2020-01-27 10:04:02 -08:00 committed by Robert Findley
parent 11eff242d1
commit ea181f53ac
12 changed files with 52 additions and 34 deletions

View File

@ -324,6 +324,15 @@ func (c *completer) found(cand candidate) {
return
}
// If we know we want a type name, don't offer non-type name
// candidates. However, do offer package names since they can
// contain type names, and do offer any candidate without a type
// since we aren't sure if it is a type name or not (i.e. unimported
// candidate).
if c.wantTypeName() && obj.Type() != nil && !isTypeName(obj) && !isPkgName(obj) {
return
}
if c.matchingCandidate(&cand, nil) {
cand.score *= highScore
} else if isTypeName(obj) {
@ -856,7 +865,7 @@ func (c *completer) lexical() error {
// If obj's type is invalid, find the AST node that defines the lexical block
// containing the declaration of obj. Don't resolve types for packages.
if _, ok := obj.(*types.PkgName); !ok && !typeIsValid(obj.Type()) {
if !isPkgName(obj) && !typeIsValid(obj.Type()) {
// Match the scope to its ast.Node. If the scope is the package scope,
// use the *ast.File as the starting node.
var node ast.Node
@ -1720,6 +1729,11 @@ Nodes:
wantComparable = c.pos == n.Pos()+token.Pos(len("map["))
}
break Nodes
case *ast.ValueSpec:
if n.Type != nil && n.Type.Pos() <= c.pos && c.pos <= n.Type.End() {
wantTypeName = true
}
break Nodes
default:
if breaksExpectedTypeInference(p) {
return typeNameInference{}

View File

@ -415,6 +415,11 @@ func isUntyped(T types.Type) bool {
return false
}
func isPkgName(obj types.Object) bool {
_, ok := obj.(*types.PkgName)
return ok
}
// isSelector returns the enclosing *ast.SelectorExpr when pos is in the
// selector.
func enclosingSelector(path []ast.Node, pos token.Pos) *ast.SelectorExpr {

View File

@ -9,14 +9,14 @@ func _() {
val string //@item(atVal, "val", "string", "var")
)
[] //@complete(" //", atVal, PackageFoo)
[] //@complete(" //", PackageFoo)
[]val //@complete(" //", atVal)
[]val //@complete(" //")
[]foo.StructFoo //@complete(" //", StructFoo)
[]foo.StructFoo(nil) //@complete("(", StructFoo)
[]*foo.StructFoo //@complete(" //", StructFoo)
[...]foo.StructFoo //@complete(" //", StructFoo)
@ -32,12 +32,12 @@ func _() {
var mark []myInt //@item(atMark, "mark", "[]myInt", "var")
var s []myInt //@item(atS, "s", "[]myInt", "var")
s = []m //@complete(" //", atMyInt, atMark)
s = [] //@complete(" //", atMyInt, atMark, atS, PackageFoo)
s = []m //@complete(" //", atMyInt)
s = [] //@complete(" //", atMyInt, PackageFoo)
var a [1]myInt
a = [1]m //@complete(" //", atMyInt, atMark)
a = [1]m //@complete(" //", atMyInt)
var ds [][]myInt
ds = [][]m //@complete(" //", atMyInt, atMark)
ds = [][]m //@complete(" //", atMyInt)
}

View File

@ -10,13 +10,13 @@ func helper(i foo.IntFoo) {} //@item(helper, "helper", "func(i foo.IntFoo)", "fu
func _() {
help //@complete("l", helper)
_ = foo.StructFoo{} //@complete("S", IntFoo, StructFoo, Foo)
_ = foo.StructFoo{} //@complete("S", IntFoo, StructFoo)
}
// Bar is a function.
func Bar() { //@item(Bar, "Bar", "func()", "func", "Bar is a function.")
foo.Foo() //@complete("F", Foo, IntFoo, StructFoo)
var _ foo.IntFoo //@complete("I", Foo, IntFoo, StructFoo)
var _ foo.IntFoo //@complete("I", IntFoo, StructFoo)
foo.() //@complete("(", Foo, IntFoo, StructFoo)
}

View File

@ -33,13 +33,12 @@ func _() {
cap() //@rank(")", builtinSlice, builtinMap),rank(")", builtinArray, builtinString),rank(")", builtinArrayPtr, builtinPtr),rank(")", builtinChan, builtinInt)
make() //@rank(")", builtinMapType, int),rank(")", builtinChanType, int),rank(")", builtinSliceType, int),rank(")", builtinMapType, builtinMap)
make() //@rank(")", builtinMapType, int),rank(")", builtinChanType, int),rank(")", builtinSliceType, int),rank(")", builtinMapType, int)
make(aSliceType, a) //@rank(")", builtinInt, builtinSlice)
var _ []int = make() //@rank(")", builtinSliceType, builtinSlice)
var _ []int = make() //@rank(")", builtinSliceType, builtinMapType)
type myStruct struct{} //@item(builtinStructType, "myStruct", "struct{...}", "struct")
new() //@rank(")", builtinStructType, builtinInt)
var _ *myStruct = new() //@rank(")", builtinStructType, int)
for k := range a { //@rank(" {", builtinSlice, builtinInt),rank(" {", builtinString, builtinInt),rank(" {", builtinChan, builtinInt),rank(" {", builtinArray, builtinInt),rank(" {", builtinArrayPtr, builtinInt),rank(" {", builtinMap, builtinInt),

View File

@ -3,25 +3,25 @@ package fieldlist
var myInt int //@item(flVar, "myInt", "int", "var")
type myType int //@item(flType, "myType", "int", "type")
func (my) _() {} //@complete(") _", flType, flVar)
func (my my) _() {} //@complete(" my)"),complete(") _", flType, flVar)
func (my) _() {} //@complete(") _", flType)
func (my my) _() {} //@complete(" my)"),complete(") _", flType)
func (myType) _() {} //@complete(") {", flType, flVar)
func (myType) _() {} //@complete(") {", flType)
func (myType) _(my my) {} //@complete(" my)"),complete(") {", flType, flVar)
func (myType) _(my my) {} //@complete(" my)"),complete(") {", flType)
func (myType) _() my {} //@complete(" {", flType, flVar)
func (myType) _() my {} //@complete(" {", flType)
func (myType) _() (my my) {} //@complete(" my"),complete(") {", flType, flVar)
func (myType) _() (my my) {} //@complete(" my"),complete(") {", flType)
func _() {
var _ struct {
//@complete("", flType, flVar)
m my //@complete(" my"),complete(" //", flType, flVar)
//@complete("", flType)
m my //@complete(" my"),complete(" //", flType)
}
var _ interface {
//@complete("", flType, flVar)
m() my //@complete("("),complete(" //", flType, flVar)
//@complete("", flType)
m() my //@complete("("),complete(" //", flType)
}
}

View File

@ -4,11 +4,11 @@ var stringAVar = "var" //@item(stringAVar, "stringAVar", "string", "var")
func stringBFunc() string { return "str" } //@item(stringBFunc, "stringBFunc", "func() string", "func")
type stringer struct{} //@item(stringer, "stringer", "struct{...}", "struct")
func _() stringer //@complete("tr", stringer, stringAVar, stringBFunc)
func _() stringer //@complete("tr", stringer)
func _(val stringer) {} //@complete("tr", stringer, stringAVar, stringBFunc)
func _(val stringer) {} //@complete("tr", stringer)
func (stringer) _() {} //@complete("tr", stringer, stringAVar, stringBFunc)
func (stringer) _() {} //@complete("tr", stringer)
func _() {
var s struct {

View File

@ -11,8 +11,8 @@ func _() {
// comparable
type aStruct struct{} //@item(mapStructType, "aStruct", "struct{...}", "struct")
map[]a{} //@complete("]", mapSliceTypePtr, mapStructType, mapVar)
map[]a{} //@complete("]", mapSliceTypePtr, mapStructType)
map[a]a{} //@complete("]", mapSliceTypePtr, mapStructType, mapVar)
map[a]a{} //@complete("{", mapSliceType, mapStructType, mapVar)
map[a]a{} //@complete("]", mapSliceTypePtr, mapStructType)
map[a]a{} //@complete("{", mapSliceType, mapStructType)
}

View File

@ -4,5 +4,5 @@ func _() {
type flower int //@item(flower, "flower", "int", "type")
var fig string //@item(fig, "fig", "string", "var")
_ = interface{}(nil).(f) //@complete(") //", flower, fig)
_ = interface{}(nil).(f) //@complete(") //", flower)
}

View File

@ -5,7 +5,7 @@ func _() {
var banana string //@item(banana, "banana", "string", "var")
switch interface{}(pear).(type) {
case b: //@complete(":", basket, banana)
case b: //@complete(":", basket)
b //@complete(" //", banana, basket)
}
}

View File

@ -1,6 +1,6 @@
package unresolved
func foo(interface{}) { //@item(unresolvedFoo, "foo", "func(interface{})", "func")
func foo(interface{}) {
// don't crash on fake "resolved" type
foo(func(i, j f //@complete(" //", unresolvedFoo)
foo(func(i, j f //@complete(" //")
}

View File

@ -4,7 +4,7 @@ CompletionSnippetCount = 67
UnimportedCompletionsCount = 11
DeepCompletionsCount = 5
FuzzyCompletionsCount = 8
RankedCompletionsCount = 86
RankedCompletionsCount = 85
CaseSensitiveCompletionsCount = 4
DiagnosticsCount = 38
FoldingRangesCount = 2