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:
parent
142b776bb0
commit
7bd96bd597
@ -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 {
|
||||
|
@ -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 {
|
||||
|
15
internal/lsp/testdata/assign/assign.go.in
vendored
Normal file
15
internal/lsp/testdata/assign/assign.go.in
vendored
Normal 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(" //")
|
||||
}
|
4
internal/lsp/testdata/summary.txt.golden
vendored
4
internal/lsp/testdata/summary.txt.golden
vendored
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user