diff --git a/go/analysis/passes/hostport/hostport.go b/go/analysis/passes/hostport/hostport.go
index d41a0e4..46c9319 100644
--- a/go/analysis/passes/hostport/hostport.go
+++ b/go/analysis/passes/hostport/hostport.go
@@ -170,6 +170,10 @@
} {
for curCall := range index.Calls(callee) {
call := curCall.Node().(*ast.CallExpr)
+ if len(call.Args) < 2 {
+ // A multi-valued call may supply the complete argument list.
+ continue
+ }
switch address := call.Args[1].(type) {
case *ast.CallExpr:
if len(call.Args) == 2 { // avoid spread-call edge case
diff --git a/go/analysis/passes/hostport/testdata/src/a/a.go b/go/analysis/passes/hostport/testdata/src/a/a.go
index 708fef3..9a7f8f3 100644
--- a/go/analysis/passes/hostport/testdata/src/a/a.go
+++ b/go/analysis/passes/hostport/testdata/src/a/a.go
@@ -52,3 +52,12 @@
const port = 0x7B
_, _ = net.Dial("tcp", fmt.Sprintf("%s:%d", "localhost", port)) // want `address format "%s:%d" does not work with IPv6`
}
+
+func dialArgs() (string, string) {
+ return "tcp", "localhost:80"
+}
+
+func multiValueDial() {
+ // A multi-valued call may supply the complete argument list.
+ _, _ = net.Dial(dialArgs())
+}
diff --git a/go/analysis/passes/hostport/testdata/src/a/a.go.golden b/go/analysis/passes/hostport/testdata/src/a/a.go.golden
index 93a89dc..165269e 100644
--- a/go/analysis/passes/hostport/testdata/src/a/a.go.golden
+++ b/go/analysis/passes/hostport/testdata/src/a/a.go.golden
@@ -52,3 +52,12 @@
const port = 0x7B
_, _ = net.Dial("tcp", net.JoinHostPort("localhost", fmt.Sprintf("%d", port))) // want `address format "%s:%d" does not work with IPv6`
}
+
+func dialArgs() (string, string) {
+ return "tcp", "localhost:80"
+}
+
+func multiValueDial() {
+ // A multi-valued call may supply the complete argument list.
+ _, _ = net.Dial(dialArgs())
+}
diff --git a/go/analysis/passes/modernize/sortslice.go b/go/analysis/passes/modernize/sortslice.go
index 08d8667..ecfe99e 100644
--- a/go/analysis/passes/modernize/sortslice.go
+++ b/go/analysis/passes/modernize/sortslice.go
@@ -64,6 +64,10 @@
)
for curCall := range index.Calls(sortSlice) {
call := curCall.Node().(*ast.CallExpr)
+ if len(call.Args) != 2 {
+ // A multi-valued call may supply the complete argument list.
+ continue
+ }
if lit, ok := call.Args[1].(*ast.FuncLit); ok && len(lit.Body.List) == 1 {
sig := info.Types[lit.Type].Type.(*types.Signature)
diff --git a/go/analysis/passes/modernize/stringscut.go b/go/analysis/passes/modernize/stringscut.go
index daa6a67..8013ef3 100644
--- a/go/analysis/passes/modernize/stringscut.go
+++ b/go/analysis/passes/modernize/stringscut.go
@@ -136,6 +136,10 @@
continue // strings.Index not available in this file
}
indexCall := curCall.Node().(*ast.CallExpr) // the call to strings.Index, etc.
+ if len(indexCall.Args) != 2 {
+ // A multi-valued call may supply the complete argument list.
+ continue
+ }
obj := typeutil.Callee(info, indexCall)
if obj == nil {
continue
@@ -396,6 +400,14 @@
for _, obj := range []types.Object{stringsSplit, stringsSplitN} {
for curCall := range index.Calls(obj) {
callExpr := curCall.Node().(*ast.CallExpr)
+ expectedArgs := 2
+ if obj.Name() == "SplitN" {
+ expectedArgs = 3
+ }
+ if len(callExpr.Args) != expectedArgs {
+ // A multi-valued call may supply the complete argument list.
+ continue
+ }
// For SplitN, the third argument must be the integer constant 2.
if obj.Name() == "SplitN" && !isIntLiteral(info, callExpr.Args[2], 2) {
diff --git a/go/analysis/passes/modernize/stringscutprefix.go b/go/analysis/passes/modernize/stringscutprefix.go
index 6e28545..0a80b4a 100644
--- a/go/analysis/passes/modernize/stringscutprefix.go
+++ b/go/analysis/passes/modernize/stringscutprefix.go
@@ -74,6 +74,10 @@
// pattern1
if call, ok := ifStmt.Cond.(*ast.CallExpr); ok && ifStmt.Init == nil && len(ifStmt.Body.List) > 0 {
+ if len(call.Args) != 2 {
+ // A multi-valued call may supply the complete argument list.
+ continue
+ }
obj := typeutil.Callee(info, call)
if !typesinternal.IsFunctionNamed(obj, "strings", "HasPrefix", "HasSuffix") &&
@@ -87,6 +91,9 @@
firstStmt := curIfStmt.Child(ifStmt.Body).Child(ifStmt.Body.List[0])
for curCall := range firstStmt.Preorder((*ast.CallExpr)(nil)) {
call1 := curCall.Node().(*ast.CallExpr)
+ if len(call1.Args) != 2 {
+ continue
+ }
obj1 := typeutil.Callee(info, call1)
// bytesTrimPrefix or stringsTrimPrefix might be nil if the file doesn't import it,
// so we need to ensure the obj1 is not nil otherwise the call1 is not TrimPrefix and cause a panic (ditto Suffix).
@@ -180,6 +187,9 @@
isSimpleAssign(ifStmt.Init) {
assign := ifStmt.Init.(*ast.AssignStmt)
if call, ok := assign.Rhs[0].(*ast.CallExpr); ok && assign.Tok == token.DEFINE {
+ if len(call.Args) != 2 {
+ continue
+ }
lhs := assign.Lhs[0]
obj := typeutil.Callee(info, call)
diff --git a/go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go b/go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go
index 50c9021..3b690bd 100644
--- a/go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go
+++ b/go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go
@@ -2,6 +2,16 @@
import "sort"
+func sortArgs() ([]int, func(int, int) bool) {
+ s := []int{2, 1}
+ return s, func(i, j int) bool { return s[i] < s[j] }
+}
+
+func multiValueSort() {
+ // A multi-valued call may supply the complete argument list.
+ sort.Slice(sortArgs())
+}
+
type myint int
func _(s []myint) {
diff --git a/go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go.golden b/go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go.golden
index 58be9ab..e2990c2 100644
--- a/go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go.golden
+++ b/go/analysis/passes/modernize/testdata/src/slicessort/slicessort.go.golden
@@ -4,6 +4,16 @@
import "sort"
+func sortArgs() ([]int, func(int, int) bool) {
+ s := []int{2, 1}
+ return s, func(i, j int) bool { return s[i] < s[j] }
+}
+
+func multiValueSort() {
+ // A multi-valued call may supply the complete argument list.
+ sort.Slice(sortArgs())
+}
+
type myint int
func _(s []myint) {
diff --git a/go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go b/go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go
index 472b2f8..6f1df43 100644
--- a/go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go
+++ b/go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go
@@ -5,6 +5,15 @@
"strings"
)
+func indexArgs() (string, string) {
+ return "abc", "b"
+}
+
+func multiValueIndex() bool {
+ i := strings.Index(indexArgs())
+ return i >= 0
+}
+
func basic() bool {
s := "value"
i := strings.Index(s, "=") // want "strings.Index can be simplified using strings.Cut"
diff --git a/go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go.golden b/go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go.golden
index 9dd053e..52776bf 100644
--- a/go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go.golden
+++ b/go/analysis/passes/modernize/testdata/src/stringscut/stringscut.go.golden
@@ -5,6 +5,15 @@
"strings"
)
+func indexArgs() (string, string) {
+ return "abc", "b"
+}
+
+func multiValueIndex() bool {
+ i := strings.Index(indexArgs())
+ return i >= 0
+}
+
func basic() bool {
s := "value"
before, _, ok := strings.Cut(s, "=") // want "strings.Index can be simplified using strings.Cut"
diff --git a/go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go b/go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go
index c9ea96e..4dbf11e 100644
--- a/go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go
+++ b/go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go
@@ -8,6 +8,16 @@
s, pre, suf string
)
+func prefixArgs() (string, string) {
+ return "abc", "a"
+}
+
+func multiValuePrefix() {
+ if strings.HasPrefix(prefixArgs()) {
+ _ = strings.TrimPrefix("abc", "a")
+ }
+}
+
// test supported cases of pattern 1 - CutPrefix
func _() {
if strings.HasPrefix(s, pre) { // want "HasPrefix \\+ TrimPrefix can be simplified to CutPrefix"
diff --git a/go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go.golden b/go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go.golden
index 9699cbe..84dad2a 100644
--- a/go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go.golden
+++ b/go/analysis/passes/modernize/testdata/src/stringscutprefix/stringscutprefix.go.golden
@@ -8,6 +8,16 @@
s, pre, suf string
)
+func prefixArgs() (string, string) {
+ return "abc", "a"
+}
+
+func multiValuePrefix() {
+ if strings.HasPrefix(prefixArgs()) {
+ _ = strings.TrimPrefix("abc", "a")
+ }
+}
+
// test supported cases of pattern 1 - CutPrefix
func _() {
if after, ok := strings.CutPrefix(s, pre); ok { // want "HasPrefix \\+ TrimPrefix can be simplified to CutPrefix"