diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go index 73e8ec30c9..32f951b610 100644 --- a/internal/lsp/source/completion.go +++ b/internal/lsp/source/completion.go @@ -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 { diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go index 5588165827..7a648394b7 100644 --- a/internal/lsp/source/util.go +++ b/internal/lsp/source/util.go @@ -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 { diff --git a/internal/lsp/testdata/assign/assign.go.in b/internal/lsp/testdata/assign/assign.go.in new file mode 100644 index 0000000000..f07c461c79 --- /dev/null +++ b/internal/lsp/testdata/assign/assign.go.in @@ -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(" //") +} diff --git a/internal/lsp/testdata/summary.txt.golden b/internal/lsp/testdata/summary.txt.golden index fd8456e7cb..ff727e2566 100644 --- a/internal/lsp/testdata/summary.txt.golden +++ b/internal/lsp/testdata/summary.txt.golden @@ -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