Skip to content

Commit a0304e6

Browse files
adonovangopherbot
authored andcommitted
[gopls-release-branch.0.18] gopls/internal/analysis/modernize: sortslice: fix crash
The sole statement of a comparison func body is not necessarily a return statement. + Test Fixes golang/go#71786 Change-Id: Ic002035fc9fa303b62ed1828c13f3bdfb8bc6950 Reviewed-on: https://go-review.googlesource.com/c/tools/+/650215 Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> (cherry picked from commit 776604a) Reviewed-on: https://go-review.googlesource.com/c/tools/+/650495 Reviewed-by: Alan Donovan <[email protected]> Auto-Submit: Robert Findley <[email protected]>
1 parent bcc48d6 commit a0304e6

File tree

3 files changed

+60
-39
lines changed

3 files changed

+60
-39
lines changed

gopls/internal/analysis/modernize/sortslice.go

+38-37
Original file line numberDiff line numberDiff line change
@@ -57,45 +57,46 @@ func sortslice(pass *analysis.Pass) {
5757
i := sig.Params().At(0)
5858
j := sig.Params().At(1)
5959

60-
ret := lit.Body.List[0].(*ast.ReturnStmt)
61-
if compare, ok := ret.Results[0].(*ast.BinaryExpr); ok && compare.Op == token.LSS {
62-
// isIndex reports whether e is s[v].
63-
isIndex := func(e ast.Expr, v *types.Var) bool {
64-
index, ok := e.(*ast.IndexExpr)
65-
return ok &&
66-
equalSyntax(index.X, s) &&
67-
is[*ast.Ident](index.Index) &&
68-
info.Uses[index.Index.(*ast.Ident)] == v
69-
}
70-
if isIndex(compare.X, i) && isIndex(compare.Y, j) {
71-
// Have: sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
60+
if ret, ok := lit.Body.List[0].(*ast.ReturnStmt); ok {
61+
if compare, ok := ret.Results[0].(*ast.BinaryExpr); ok && compare.Op == token.LSS {
62+
// isIndex reports whether e is s[v].
63+
isIndex := func(e ast.Expr, v *types.Var) bool {
64+
index, ok := e.(*ast.IndexExpr)
65+
return ok &&
66+
equalSyntax(index.X, s) &&
67+
is[*ast.Ident](index.Index) &&
68+
info.Uses[index.Index.(*ast.Ident)] == v
69+
}
70+
if isIndex(compare.X, i) && isIndex(compare.Y, j) {
71+
// Have: sort.Slice(s, func(i, j int) bool { return s[i] < s[j] })
7272

73-
_, prefix, importEdits := analysisinternal.AddImport(
74-
info, file, "slices", "slices", "Sort", call.Pos())
73+
_, prefix, importEdits := analysisinternal.AddImport(
74+
info, file, "slices", "slices", "Sort", call.Pos())
7575

76-
pass.Report(analysis.Diagnostic{
77-
// Highlight "sort.Slice".
78-
Pos: call.Fun.Pos(),
79-
End: call.Fun.End(),
80-
Category: "sortslice",
81-
Message: fmt.Sprintf("sort.Slice can be modernized using slices.Sort"),
82-
SuggestedFixes: []analysis.SuggestedFix{{
83-
Message: fmt.Sprintf("Replace sort.Slice call by slices.Sort"),
84-
TextEdits: append(importEdits, []analysis.TextEdit{
85-
{
86-
// Replace sort.Slice with slices.Sort.
87-
Pos: call.Fun.Pos(),
88-
End: call.Fun.End(),
89-
NewText: []byte(prefix + "Sort"),
90-
},
91-
{
92-
// Eliminate FuncLit.
93-
Pos: call.Args[0].End(),
94-
End: call.Rparen,
95-
},
96-
}...),
97-
}},
98-
})
76+
pass.Report(analysis.Diagnostic{
77+
// Highlight "sort.Slice".
78+
Pos: call.Fun.Pos(),
79+
End: call.Fun.End(),
80+
Category: "sortslice",
81+
Message: fmt.Sprintf("sort.Slice can be modernized using slices.Sort"),
82+
SuggestedFixes: []analysis.SuggestedFix{{
83+
Message: fmt.Sprintf("Replace sort.Slice call by slices.Sort"),
84+
TextEdits: append(importEdits, []analysis.TextEdit{
85+
{
86+
// Replace sort.Slice with slices.Sort.
87+
Pos: call.Fun.Pos(),
88+
End: call.Fun.End(),
89+
NewText: []byte(prefix + "Sort"),
90+
},
91+
{
92+
// Eliminate FuncLit.
93+
Pos: call.Args[0].End(),
94+
End: call.Rparen,
95+
},
96+
}...),
97+
}},
98+
})
99+
}
99100
}
100101
}
101102
}

gopls/internal/analysis/modernize/testdata/src/sortslice/sortslice.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,16 @@ func _(s []int) {
2020
sort.Slice(s, func(i, j int) bool { return s[j] < s[i] }) // nope: wrong index var
2121
}
2222

23-
func _(s2 []struct{ x int }) {
23+
func _(sense bool, s2 []struct{ x int }) {
2424
sort.Slice(s2, func(i, j int) bool { return s2[i].x < s2[j].x }) // nope: not a simple index operation
25+
26+
// Regression test for a crash: the sole statement of a
27+
// comparison func body is not necessarily a return!
28+
sort.Slice(s2, func(i, j int) bool {
29+
if sense {
30+
return s2[i].x < s2[j].x
31+
} else {
32+
return s2[i].x > s2[j].x
33+
}
34+
})
2535
}

gopls/internal/analysis/modernize/testdata/src/sortslice/sortslice.go.golden

+11-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ func _(s []int) {
2222
sort.Slice(s, func(i, j int) bool { return s[j] < s[i] }) // nope: wrong index var
2323
}
2424

25-
func _(s2 []struct{ x int }) {
25+
func _(sense bool, s2 []struct{ x int }) {
2626
sort.Slice(s2, func(i, j int) bool { return s2[i].x < s2[j].x }) // nope: not a simple index operation
27+
28+
// Regression test for a crash: the sole statement of a
29+
// comparison func body is not necessarily a return!
30+
sort.Slice(s2, func(i, j int) bool {
31+
if sense {
32+
return s2[i].x < s2[j].x
33+
} else {
34+
return s2[i].x > s2[j].x
35+
}
36+
})
2737
}

0 commit comments

Comments
 (0)