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:
parent
11eff242d1
commit
ea181f53ac
@ -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{}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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(" //")
|
||||
}
|
||||
|
2
internal/lsp/testdata/lsp/summary.txt.golden
vendored
2
internal/lsp/testdata/lsp/summary.txt.golden
vendored
@ -4,7 +4,7 @@ CompletionSnippetCount = 67
|
||||
UnimportedCompletionsCount = 11
|
||||
DeepCompletionsCount = 5
|
||||
FuzzyCompletionsCount = 8
|
||||
RankedCompletionsCount = 86
|
||||
RankedCompletionsCount = 85
|
||||
CaseSensitiveCompletionsCount = 4
|
||||
DiagnosticsCount = 38
|
||||
FoldingRangesCount = 2
|
||||
|
Loading…
Reference in New Issue
Block a user