Skip to content

Commit

Permalink
gopls/internal: check for variadic arguments from string to []byte/[]…
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
hhhapz committed Aug 27, 2024
1 parent 0734f62 commit 8e231bc
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 7 deletions.
10 changes: 8 additions & 2 deletions gopls/internal/golang/completion/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}

Expand Down
3 changes: 1 addition & 2 deletions gopls/internal/golang/completion/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -214,7 +213,7 @@ Suffixes:
}

prefix = typeName + "(" + prefix
suffix = ")"
suffix = ")" + suffix
}

if prefix != "" {
Expand Down
11 changes: 8 additions & 3 deletions gopls/internal/golang/completion/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 8e231bc

Please sign in to comment.