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

internal/lsp/source: improve completion in value spec

If the enclosing value spec specifies a type on the LHS, we now prefer
completions of that type on the RHS. For example:

i := 123
var foo int = // prefer "i" since we know we want an int

I also added a special case to lexical() to know that we can't offer
objects defined on the LHS as completions on the RHS. For example:

var foo int = // don't offer "foo" as completion

Change-Id: I8e24245a2bc86a29887360e7f642a4cbb87fa6ca
Reviewed-on: https://go-review.googlesource.com/c/tools/+/212401
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Muir Manders 2019-12-22 15:04:15 -08:00 committed by Rebecca Stambler
parent 142b776bb0
commit 7bd96bd597
4 changed files with 44 additions and 2 deletions

View File

@ -714,11 +714,14 @@ func (c *completer) lexical() error {
if scope == nil {
continue
}
Names:
for _, name := range scope.Names() {
declScope, obj := scope.LookupParent(name, c.pos)
if declScope != scope {
continue // Name was declared in some enclosing scope, or not at all.
}
// 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()) {
@ -738,6 +741,15 @@ func (c *completer) lexical() error {
}
}
// Don't use LHS of value spec in RHS.
if vs := enclosingValueSpec(c.path, c.pos); vs != nil {
for _, ident := range vs.Names {
if obj.Pos() == ident.Pos() {
continue Names
}
}
}
// Don't suggest "iota" outside of const decls.
if obj == builtinIota && !c.inConstDecl() {
continue
@ -1160,6 +1172,11 @@ Nodes:
}
}
return inf
case *ast.ValueSpec:
if node.Type != nil && c.pos > node.Type.End() {
inf.objType = c.pkg.GetTypesInfo().TypeOf(node.Type)
}
break Nodes
case *ast.CallExpr:
// Only consider CallExpr args if position falls between parens.
if node.Lparen <= c.pos && c.pos <= node.Rparen {

View File

@ -441,6 +441,16 @@ func enclosingSelector(path []ast.Node, pos token.Pos) *ast.SelectorExpr {
return nil
}
func enclosingValueSpec(path []ast.Node, pos token.Pos) *ast.ValueSpec {
for _, n := range path {
if vs, ok := n.(*ast.ValueSpec); ok {
return vs
}
}
return nil
}
// typeConversion returns the type being converted to if call is a type
// conversion expression.
func typeConversion(call *ast.CallExpr, info *types.Info) types.Type {

View File

@ -0,0 +1,15 @@
package assign
func _() {
var (
myInt int //@item(assignInt, "myInt", "int", "var")
myStr string //@item(assignStr, "myStr", "string", "var")
)
var _ string = my //@rank(" //", assignStr, assignInt)
var _ string = //@rank(" //", assignStr, assignInt)
}
func _() {
var a string = a //@complete(" //")
}

View File

@ -1,10 +1,10 @@
-- summary --
CompletionsCount = 223
CompletionsCount = 224
CompletionSnippetCount = 53
UnimportedCompletionsCount = 4
DeepCompletionsCount = 5
FuzzyCompletionsCount = 7
RankedCompletionsCount = 26
RankedCompletionsCount = 28
CaseSensitiveCompletionsCount = 4
DiagnosticsCount = 35
FoldingRangesCount = 2