mirror of
https://github.com/golang/go
synced 2024-10-01 01:08:33 -06: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 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
|
||||
@ -741,8 +744,9 @@ func expectedType(c *completer) typeInference {
|
||||
}
|
||||
|
||||
var (
|
||||
modifiers []typeModifier
|
||||
typ types.Type
|
||||
modifiers []typeModifier
|
||||
typ types.Type
|
||||
convertibleTo types.Type
|
||||
)
|
||||
|
||||
Nodes:
|
||||
@ -774,6 +778,13 @@ Nodes:
|
||||
case *ast.CallExpr:
|
||||
// Only consider CallExpr args if position falls between parens.
|
||||
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 sig, ok := tv.Type.(*types.Signature); ok {
|
||||
if sig.Params().Len() == 0 {
|
||||
@ -860,8 +871,9 @@ Nodes:
|
||||
}
|
||||
|
||||
return typeInference{
|
||||
objType: typ,
|
||||
modifiers: modifiers,
|
||||
objType: typ,
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -139,6 +139,27 @@ func isFunc(obj types.Object) bool {
|
||||
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 {
|
||||
params := make([]string, 0, tup.Len())
|
||||
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