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

internal/lsp/source: support dereferencing for completion

In cases like:

    var j *int
    var i int = <>

We will now provide "*j" as a completion candidate.

Change-Id: I1d35c2dca4864f13f7534e15b17450d784985557
Reviewed-on: https://go-review.googlesource.com/c/tools/+/215358
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 2020-01-18 13:33:26 -08:00 committed by Rebecca Stambler
parent 7b0c362a2f
commit 9bae6688e3
5 changed files with 29 additions and 5 deletions

View File

@ -383,6 +383,9 @@ type candidate struct {
// makePointer is true if the candidate type name T should be made into *T.
makePointer bool
// dereference is true if the candidate obj should be made into *obj.
dereference bool
// imp is the import that needs to be added to this package in order
// for this candidate to be valid. nil if no import needed.
imp *importInfo
@ -1776,6 +1779,15 @@ func (c *completer) matchingCandidate(cand *candidate) bool {
return true
}
// Check if dereferencing cand would match our type inference.
if ptr, ok := cand.obj.Type().Underlying().(*types.Pointer); ok {
if c.matchingCandidate(&candidate{obj: c.fakeObj(ptr.Elem())}) {
// Mark the candidate so we know to prepend "*" when formatting.
cand.dereference = true
return true
}
}
// Check if cand is addressable and a pointer to cand matches our type inference.
if cand.addressable && c.matchingCandidate(&candidate{obj: c.fakeObj(types.NewPointer(candType))}) {
// Mark the candidate so we know to prepend "&" when formatting.

View File

@ -134,7 +134,7 @@ func (c *completer) item(cand candidate) (CompletionItem, error) {
var prefixOp string
if cand.takeAddress {
prefixOp = "&"
} else if cand.makePointer {
} else if cand.makePointer || cand.dereference {
prefixOp = "*"
}

View File

@ -1,6 +1,9 @@
package address
func wantsPtr(*int) {}
func wantsPtr(*int) {}
func wantsVariadicPtr(...*int) {}
func wantsVariadic(...int) {}
type foo struct{ c int } //@item(addrFieldC, "c", "int", "field")
@ -15,6 +18,8 @@ func _() {
wantsPtr() //@rank(")", addrBRef, addrA),snippet(")", addrBRef, "&b", "&b")
wantsPtr(&b) //@snippet(")", addrB, "b", "b")
wantsVariadicPtr() //@rank(")", addrBRef, addrA),snippet(")", addrBRef, "&b", "&b")
var s foo
s.c //@item(addrDeepC, "s.c", "int", "field")
&s.c //@item(addrDeepCRef, "&s.c", "int", "field")
@ -24,6 +29,13 @@ func _() {
// don't add "&" in item (it gets added as an additional edit)
wantsPtr(&s.c) //@snippet(")", addrFieldC, "c", "c")
// check dereferencing as well
var c *int
*c //@item(addrCPtr, "*c", "*int", "var")
var _ int = _ //@rank("_ //", addrCPtr, addrA),snippet("_ //", addrCPtr, "*c", "*c")
wantsVariadic() //@rank(")", addrCPtr, addrA),snippet(")", addrCPtr, "*c", "*c")
}
func (f foo) ptr() *foo { return &f }

View File

@ -34,7 +34,7 @@ func _() {
*deepCircle
}
var circle deepCircle //@item(deepCircle, "circle", "deepCircle", "var")
circle.deepCircle //@item(deepCircleField, "circle.deepCircle", "*deepCircle", "field", "deepCircle is circular.")
*circle.deepCircle //@item(deepCircleField, "*circle.deepCircle", "*deepCircle", "field", "deepCircle is circular.")
var _ deepCircle = circ //@deep(" //", deepCircle, deepCircleField)
}

View File

@ -1,10 +1,10 @@
-- summary --
CompletionsCount = 225
CompletionSnippetCount = 63
CompletionSnippetCount = 66
UnimportedCompletionsCount = 9
DeepCompletionsCount = 5
FuzzyCompletionsCount = 8
RankedCompletionsCount = 63
RankedCompletionsCount = 66
CaseSensitiveCompletionsCount = 4
DiagnosticsCount = 35
FoldingRangesCount = 2