mirror of
https://github.com/golang/go
synced 2024-11-18 18:04:46 -07:00
internal/lsp: improve completion support for type conversions
Now when completing in code like: foo := int64(<>) we prefer candidates whose type is convertible to int64. Change-Id: Iadc6cdc7de097ac30d8807d6f5aa21d83f89d756 GitHub-Last-Rev: a86dd72496ba752a1f20877c0594ec6a0ed8160e GitHub-Pull-Request: golang/tools#127 Reviewed-on: https://go-review.googlesource.com/c/tools/+/183941 Reviewed-by: Rebecca Stambler <rstambler@golang.org> Run-TryBot: Rebecca Stambler <rstambler@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
970b2b065d
commit
30f1cf78d7
@ -727,6 +727,9 @@ type typeInference struct {
|
|||||||
|
|
||||||
// assertableFrom is a type that must be assertable to our candidate type.
|
// assertableFrom is a type that must be assertable to our candidate type.
|
||||||
assertableFrom types.Type
|
assertableFrom types.Type
|
||||||
|
|
||||||
|
// convertibleTo is a type our candidate type must be convertible to.
|
||||||
|
convertibleTo types.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
// expectedType returns information about the expected type for an expression at
|
// expectedType returns information about the expected type for an expression at
|
||||||
@ -741,8 +744,9 @@ func expectedType(c *completer) typeInference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
modifiers []typeModifier
|
modifiers []typeModifier
|
||||||
typ types.Type
|
typ types.Type
|
||||||
|
convertibleTo types.Type
|
||||||
)
|
)
|
||||||
|
|
||||||
Nodes:
|
Nodes:
|
||||||
@ -774,6 +778,13 @@ 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 {
|
||||||
|
// For type conversions like "int64(foo)" we can only infer our
|
||||||
|
// desired type is convertible to int64.
|
||||||
|
if typ := typeConversion(node, c.info); typ != nil {
|
||||||
|
convertibleTo = typ
|
||||||
|
break Nodes
|
||||||
|
}
|
||||||
|
|
||||||
if tv, ok := c.info.Types[node.Fun]; ok {
|
if tv, ok := c.info.Types[node.Fun]; ok {
|
||||||
if sig, ok := tv.Type.(*types.Signature); ok {
|
if sig, ok := tv.Type.(*types.Signature); ok {
|
||||||
if sig.Params().Len() == 0 {
|
if sig.Params().Len() == 0 {
|
||||||
@ -860,8 +871,9 @@ Nodes:
|
|||||||
}
|
}
|
||||||
|
|
||||||
return typeInference{
|
return typeInference{
|
||||||
objType: typ,
|
objType: typ,
|
||||||
modifiers: modifiers,
|
modifiers: modifiers,
|
||||||
|
convertibleTo: convertibleTo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1045,6 +1057,10 @@ func (c *completer) matchingType(cand *candidate) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.expectedType.convertibleTo != nil {
|
||||||
|
return types.ConvertibleTo(objType, c.expectedType.convertibleTo)
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +139,27 @@ func isFunc(obj types.Object) bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// typeConversion returns the type being converted to if call is a type
|
||||||
|
// conversion expression.
|
||||||
|
func typeConversion(call *ast.CallExpr, info *types.Info) types.Type {
|
||||||
|
var ident *ast.Ident
|
||||||
|
switch expr := call.Fun.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
ident = expr
|
||||||
|
case *ast.SelectorExpr:
|
||||||
|
ident = expr.Sel
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type conversion (e.g. "float64(foo)").
|
||||||
|
if fun, _ := info.ObjectOf(ident).(*types.TypeName); fun != nil {
|
||||||
|
return fun.Type()
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func formatParams(tup *types.Tuple, variadic bool, qf types.Qualifier) []string {
|
func formatParams(tup *types.Tuple, variadic bool, qf types.Qualifier) []string {
|
||||||
params := make([]string, 0, tup.Len())
|
params := make([]string, 0, tup.Len())
|
||||||
for i := 0; i < tup.Len(); i++ {
|
for i := 0; i < tup.Len(); i++ {
|
||||||
|
12
internal/lsp/testdata/rank/convert_rank.go.in
vendored
Normal file
12
internal/lsp/testdata/rank/convert_rank.go.in
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package rank
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
type strList []string
|
||||||
|
wantsStrList := func(strList) {}
|
||||||
|
|
||||||
|
var (
|
||||||
|
convA string //@item(convertA, "convA", "string", "var")
|
||||||
|
convB []string //@item(convertB, "convB", "[]string", "var")
|
||||||
|
)
|
||||||
|
wantsStrList(strList(conv)) //@complete("))", convertB, convertA)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user