internal/lsp: rank types higher when completing in return of a function
Completion now ranks type names higher for func receiver, type params and type results (e.g. func (<>) foo(<>) (<>) {}). Fixes golang/go#29152 Change-Id: Icdd18b1b344c1cd617a4f45a7b071e53c1345478 GitHub-Last-Rev: e6acb1f2d2a7e571ffcecc500e407fdefd118fed GitHub-Pull-Request: golang/tools#73 Reviewed-on: https://go-review.googlesource.com/c/159797 TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
718ddee956
commit
7414d4c1f7
|
@ -35,7 +35,7 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
|
|||
|
||||
// We hardcode the expected number of test cases to ensure that all tests
|
||||
// are being executed. If a test is added, this number must be changed.
|
||||
const expectedCompletionsCount = 60
|
||||
const expectedCompletionsCount = 63
|
||||
const expectedDiagnosticsCount = 13
|
||||
const expectedFormatCount = 3
|
||||
const expectedDefinitionsCount = 16
|
||||
|
|
|
@ -86,20 +86,24 @@ func Completion(ctx context.Context, f File, pos token.Pos) (items []CompletionI
|
|||
typ := expectedType(path, pos, pkg.TypesInfo)
|
||||
sig := enclosingFunction(path, pos, pkg.TypesInfo)
|
||||
pkgStringer := qualifier(file, pkg.Types, pkg.TypesInfo)
|
||||
preferTypeNames := wantTypeNames(pos, path)
|
||||
|
||||
seen := make(map[types.Object]bool)
|
||||
|
||||
// found adds a candidate completion.
|
||||
// Only the first candidate of a given name is considered.
|
||||
found := func(obj types.Object, weight float64, items []CompletionItem) []CompletionItem {
|
||||
if obj.Pkg() != nil && obj.Pkg() != pkg.Types && !obj.Exported() {
|
||||
return items // inaccessible
|
||||
}
|
||||
|
||||
if !seen[obj] {
|
||||
seen[obj] = true
|
||||
if typ != nil && matchingTypes(typ, obj.Type()) {
|
||||
weight *= 10.0
|
||||
}
|
||||
if _, ok := obj.(*types.TypeName); !ok && preferTypeNames {
|
||||
weight *= 0.01
|
||||
}
|
||||
item := formatCompletion(obj, pkgStringer, weight, func(v *types.Var) bool {
|
||||
return isParameter(sig, v)
|
||||
})
|
||||
|
@ -202,6 +206,34 @@ func selector(sel *ast.SelectorExpr, pos token.Pos, info *types.Info, found find
|
|||
return items, nil
|
||||
}
|
||||
|
||||
// wantTypeNames checks if given token position is inside func receiver, type params
|
||||
// or type results (e.g func (<>) foo(<>) (<>) {} ).
|
||||
func wantTypeNames(pos token.Pos, path []ast.Node) bool {
|
||||
for _, p := range path {
|
||||
switch n := p.(type) {
|
||||
case *ast.FuncDecl:
|
||||
recv := n.Recv
|
||||
if recv != nil && recv.Pos() <= pos && pos <= recv.End() {
|
||||
return true
|
||||
}
|
||||
|
||||
if n.Type != nil {
|
||||
params := n.Type.Params
|
||||
if params != nil && params.Pos() <= pos && pos <= params.End() {
|
||||
return true
|
||||
}
|
||||
|
||||
results := n.Type.Results
|
||||
if results != nil && results.Pos() <= pos && pos <= results.End() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// lexical finds completions in the lexical environment.
|
||||
func lexical(path []ast.Node, pos token.Pos, pkg *types.Package, info *types.Info, found finder) (items []CompletionItem) {
|
||||
var scopes []*types.Scope // scopes[i], where i<len(path), is the possibly nil Scope of path[i].
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package func_rank
|
||||
|
||||
var stringAVar = "var" //@item(stringAVar, "stringAVar", "string", "var")
|
||||
func stringBFunc() string { return "str" } //@item(stringBFunc, "stringBFunc()", "string", "func")
|
||||
type stringer struct{} //@item(stringer, "stringer", "struct{...}", "struct")
|
||||
|
||||
func _() stringer //@complete("tr", stringer, stringAVar, stringBFunc)
|
||||
|
||||
func _(val stringer) {} //@complete("tr", stringer, stringAVar, stringBFunc)
|
||||
|
||||
func (stringer) _() {} //@complete("tr", stringer, stringAVar, stringBFunc)
|
||||
|
Loading…
Reference in New Issue