mirror of
https://github.com/golang/go
synced 2024-11-18 15:34:53 -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 {
|
if scope == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Names:
|
||||||
for _, name := range scope.Names() {
|
for _, name := range scope.Names() {
|
||||||
declScope, obj := scope.LookupParent(name, c.pos)
|
declScope, obj := scope.LookupParent(name, c.pos)
|
||||||
if declScope != scope {
|
if declScope != scope {
|
||||||
continue // Name was declared in some enclosing scope, or not at all.
|
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
|
// 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.
|
// containing the declaration of obj. Don't resolve types for packages.
|
||||||
if _, ok := obj.(*types.PkgName); !ok && !typeIsValid(obj.Type()) {
|
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.
|
// Don't suggest "iota" outside of const decls.
|
||||||
if obj == builtinIota && !c.inConstDecl() {
|
if obj == builtinIota && !c.inConstDecl() {
|
||||||
continue
|
continue
|
||||||
@ -1160,6 +1172,11 @@ Nodes:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return inf
|
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:
|
case *ast.CallExpr:
|
||||||
// Only consider CallExpr args if position falls between parens.
|
// Only consider CallExpr args if position falls between parens.
|
||||||
if node.Lparen <= c.pos && c.pos <= node.Rparen {
|
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
|
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
|
// typeConversion returns the type being converted to if call is a type
|
||||||
// conversion expression.
|
// conversion expression.
|
||||||
func typeConversion(call *ast.CallExpr, info *types.Info) types.Type {
|
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 --
|
-- summary --
|
||||||
CompletionsCount = 223
|
CompletionsCount = 224
|
||||||
CompletionSnippetCount = 53
|
CompletionSnippetCount = 53
|
||||||
UnimportedCompletionsCount = 4
|
UnimportedCompletionsCount = 4
|
||||||
DeepCompletionsCount = 5
|
DeepCompletionsCount = 5
|
||||||
FuzzyCompletionsCount = 7
|
FuzzyCompletionsCount = 7
|
||||||
RankedCompletionsCount = 26
|
RankedCompletionsCount = 28
|
||||||
CaseSensitiveCompletionsCount = 4
|
CaseSensitiveCompletionsCount = 4
|
||||||
DiagnosticsCount = 35
|
DiagnosticsCount = 35
|
||||||
FoldingRangesCount = 2
|
FoldingRangesCount = 2
|
||||||
|
Loading…
Reference in New Issue
Block a user