Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gopls/internal: convert variadic arguments from string to []byte/[]rune #512

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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