go/analysis/passes/sortslice: correct diagnostic for sort.Slice(f())

Fixes golang/go#55098

Change-Id: I801279532c448bc4c9d5fce0cc3236e95fb77fdb
Reviewed-on: https://go-review.googlesource.com/c/tools/+/431295
Reviewed-by: Johan Brandhorst-Satzkorn <johan.brandhorst@gmail.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Tim King <taking@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
This commit is contained in:
Cuong Manh Le 2022-09-21 10:25:41 +07:00 committed by Gopher Robot
parent 2f04713366
commit be3ff020ad
2 changed files with 31 additions and 2 deletions

View File

@ -52,11 +52,20 @@ func run(pass *analysis.Pass) (interface{}, error) {
arg := call.Args[0]
typ := pass.TypesInfo.Types[arg].Type
if tuple, ok := typ.(*types.Tuple); ok {
typ = tuple.At(0).Type() // special case for Slice(f(...))
}
switch typ.Underlying().(type) {
case *types.Slice, *types.Interface:
return
}
// Restore typ to the original type, we may unwrap the tuple above,
// typ might not be the type of arg.
typ = pass.TypesInfo.Types[arg].Type
var fixes []analysis.SuggestedFix
switch v := typ.Underlying().(type) {
case *types.Array:

View File

@ -6,8 +6,8 @@ import "sort"
func IncorrectSort() {
i := 5
sortFn := func(i, j int) bool { return false }
sort.Slice(i, sortFn) // want "sort.Slice's argument must be a slice; is called with int"
sort.SliceStable(i, sortFn) // want "sort.SliceStable's argument must be a slice; is called with int"
sort.Slice(i, sortFn) // want "sort.Slice's argument must be a slice; is called with int"
sort.SliceStable(i, sortFn) // want "sort.SliceStable's argument must be a slice; is called with int"
sort.SliceIsSorted(i, sortFn) // want "sort.SliceIsSorted's argument must be a slice; is called with int"
}
@ -62,3 +62,23 @@ func UnderlyingSlice() {
sort.SliceStable(s, sortFn)
sort.SliceIsSorted(s, sortFn)
}
// FunctionResultsAsArguments passes a function which returns two values
// that satisfy sort.Slice signature. It should not produce a diagnostic.
func FunctionResultsAsArguments() {
s := []string{"a", "z", "ooo"}
sort.Slice(less(s))
sort.Slice(lessPtr(s)) // want `sort.Slice's argument must be a slice; is called with \(\*\[\]string,.*`
}
func less(s []string) ([]string, func(i, j int) bool) {
return s, func(i, j int) bool {
return s[i] < s[j]
}
}
func lessPtr(s []string) (*[]string, func(i, j int) bool) {
return &s, func(i, j int) bool {
return s[i] < s[j]
}
}