gopls/internal: check for variadic arguments from string to []byte/[]rune

gopls will correctly convert a string argument to a []byte/[]rune argument,
however it will not check if the the target is also variadic.
This commit is contained in:
Hamza Ali 2024-08-27 14:07:51 +05:00
Родитель 0734f6249f
Коммит 8e231bc34e
3 изменённых файлов: 17 добавлений и 7 удалений

Просмотреть файл

@ -52,7 +52,6 @@ import (
// A CompletionItem represents a possible completion suggested by the algorithm.
type CompletionItem struct {
// Invariant: CompletionItem does not refer to syntax or types.
// Label is the primary text the user sees for this completion item.
@ -2965,6 +2964,13 @@ func (ci *candidateInference) candTypeMatches(cand *candidate) bool {
// If candType doesn't otherwise match, consider if we can
// convert candType directly to expType.
if considerTypeConversion(candType, expType, cand.path) {
// special case: a string to a variadic []byte/[]rune
typ := deslice(expType)
isBytesOrRunes := typ != nil && (isBasicKind(typ, types.Byte) || isBasicKind(typ, types.Rune))
if isBasicType(candType, types.IsString) && isBytesOrRunes && expType == variadicType {
cand.mods = append(cand.mods, takeDotDotDot)
}
cand.convertTo = expType
// Give a major score penalty so we always prefer directly
// assignable candidates, all else equal.
@ -3045,7 +3051,7 @@ func considerTypeConversion(from, to types.Type, path []types.Object) bool {
// Don't offer to convert ints to strings since that probably
// doesn't do what the user wants.
if isBasicKind(from, types.IsInteger) && isBasicKind(to, types.IsString) {
if isBasicType(from, types.IsInteger) && isBasicType(to, types.IsString) {
return false
}

Просмотреть файл

@ -182,7 +182,6 @@ Suffixes:
// add the additional text edits needed.
if cand.imp != nil {
addlEdits, err := c.importEdits(cand.imp)
if err != nil {
return CompletionItem{}, err
}
@ -214,7 +213,7 @@ Suffixes:
}
prefix = typeName + "(" + prefix
suffix = ")"
suffix = ")" + suffix
}
if prefix != "" {

Просмотреть файл

@ -300,10 +300,15 @@ func formatZeroValue(T types.Type, qf types.Qualifier) string {
}
}
// isBasicKind returns whether t is a basic type of kind k.
func isBasicKind(t types.Type, k types.BasicInfo) bool {
// isBasicType returns whether t has property information i.
func isBasicType(t types.Type, i types.BasicInfo) bool {
b, _ := t.Underlying().(*types.Basic)
return b != nil && b.Info()&k > 0
return b != nil && b.Info()&i > 0
}
func isBasicKind(t types.Type, k types.BasicKind) bool {
b, _ := t.Underlying().(*types.Basic)
return b != nil && b.Kind() == k
}
func (c *completer) editText(from, to token.Pos, newText string) ([]protocol.TextEdit, error) {