Skip to content

Commit e48606b

Browse files
committed
gopls/internal/analysis/modernize: invalid code produced by fmtappendf modernizer
The fmtappendf produces invalid code when the byte[] conversion contains a comma like T(x,). The fix involves adding an additional text edit to remove the comma (or any whitespace before the right parenthesis) in this case. There still exists some strange formatting from white space left over, but it's hard to remove this without also removing comments. Fixes golang/go#74709 Change-Id: I80c5a88c590897fa40809718beeb1d3d295da86b Reviewed-on: https://go-review.googlesource.com/c/tools/+/697342 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Peter Weinberger <[email protected]>
1 parent 52b7d1c commit e48606b

File tree

3 files changed

+75
-46
lines changed

3 files changed

+75
-46
lines changed

gopls/internal/analysis/modernize/fmtappendf.go

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -45,34 +45,49 @@ func fmtappendf(pass *analysis.Pass) {
4545
}
4646

4747
old, new := fn.Name(), strings.Replace(fn.Name(), "Sprint", "Append", 1)
48+
edits := []analysis.TextEdit{
49+
{
50+
// delete "[]byte("
51+
Pos: conv.Pos(),
52+
End: conv.Lparen + 1,
53+
},
54+
{
55+
// remove ")"
56+
Pos: conv.Rparen,
57+
End: conv.Rparen + 1,
58+
},
59+
{
60+
Pos: id.Pos(),
61+
End: id.End(),
62+
NewText: []byte(new),
63+
},
64+
{
65+
Pos: call.Lparen + 1,
66+
NewText: []byte("nil, "),
67+
},
68+
}
69+
if len(conv.Args) == 1 {
70+
arg := conv.Args[0]
71+
// Determine if we have T(fmt.SprintX(...)<non-args,
72+
// like a space or a comma>). If so, delete the non-args
73+
// that come before the right parenthesis. Leaving an
74+
// extra comma here produces invalid code. (See
75+
// golang/go#74709)
76+
if arg.End() < conv.Rparen {
77+
edits = append(edits, analysis.TextEdit{
78+
Pos: arg.End(),
79+
End: conv.Rparen,
80+
})
81+
}
82+
}
4883
pass.Report(analysis.Diagnostic{
4984
Pos: conv.Pos(),
5085
End: conv.End(),
5186
Category: "fmtappendf",
5287
Message: fmt.Sprintf("Replace []byte(fmt.%s...) with fmt.%s", old, new),
5388
SuggestedFixes: []analysis.SuggestedFix{{
54-
Message: fmt.Sprintf("Replace []byte(fmt.%s...) with fmt.%s", old, new),
55-
TextEdits: []analysis.TextEdit{
56-
{
57-
// delete "[]byte("
58-
Pos: conv.Pos(),
59-
End: conv.Lparen + 1,
60-
},
61-
{
62-
// remove ")"
63-
Pos: conv.Rparen,
64-
End: conv.Rparen + 1,
65-
},
66-
{
67-
Pos: id.Pos(),
68-
End: id.End(),
69-
NewText: []byte(new),
70-
},
71-
{
72-
Pos: call.Lparen + 1,
73-
NewText: []byte("nil, "),
74-
},
75-
},
89+
Message: fmt.Sprintf("Replace []byte(fmt.%s...) with fmt.%s", old, new),
90+
TextEdits: edits,
7691
}},
7792
})
7893
}

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

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,36 @@ func two() string {
99
}
1010

1111
func bye() {
12-
bye := []byte(fmt.Sprintf("bye %d", 1)) // want "Replace .*Sprintf.* with fmt.Appendf"
13-
print(bye)
12+
_ = []byte(fmt.Sprintf("bye %d", 1)) // want "Replace .*Sprintf.* with fmt.Appendf"
1413
}
1514

1615
func funcsandvars() {
1716
one := "one"
18-
bye := []byte(fmt.Sprintf("bye %d %s %s", 1, two(), one)) // want "Replace .*Sprintf.* with fmt.Appendf"
19-
print(bye)
17+
_ = []byte(fmt.Sprintf("bye %d %s %s", 1, two(), one)) // want "Replace .*Sprintf.* with fmt.Appendf"
2018
}
2119

2220
func typealias() {
2321
type b = byte
2422
type bt = []byte
25-
bye := []b(fmt.Sprintf("bye %d", 1)) // want "Replace .*Sprintf.* with fmt.Appendf"
26-
print(bye)
27-
bye = bt(fmt.Sprintf("bye %d", 1)) // want "Replace .*Sprintf.* with fmt.Appendf"
28-
print(bye)
23+
_ = []b(fmt.Sprintf("bye %d", 1)) // want "Replace .*Sprintf.* with fmt.Appendf"
24+
_ = bt(fmt.Sprintf("bye %d", 1)) // want "Replace .*Sprintf.* with fmt.Appendf"
2925
}
3026

3127
func otherprints() {
32-
sprint := []byte(fmt.Sprint("bye %d", 1)) // want "Replace .*Sprint.* with fmt.Append"
33-
print(sprint)
34-
sprintln := []byte(fmt.Sprintln("bye %d", 1)) // want "Replace .*Sprintln.* with fmt.Appendln"
35-
print(sprintln)
28+
_ = []byte(fmt.Sprint("bye %d", 1)) // want "Replace .*Sprint.* with fmt.Append"
29+
_ = []byte(fmt.Sprintln("bye %d", 1)) // want "Replace .*Sprintln.* with fmt.Appendln"
30+
}
31+
32+
func comma() {
33+
type S struct{ Bytes []byte }
34+
var _ = struct{ A S }{
35+
A: S{
36+
Bytes: []byte( // want "Replace .*Sprint.* with fmt.Appendf"
37+
fmt.Sprintf("%d", 0),
38+
),
39+
},
40+
}
41+
_ = []byte( // want "Replace .*Sprint.* with fmt.Appendf"
42+
fmt.Sprintf("%d", 0),
43+
)
3644
}

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

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,34 @@ func two() string {
99
}
1010

1111
func bye() {
12-
bye := fmt.Appendf(nil, "bye %d", 1) // want "Replace .*Sprintf.* with fmt.Appendf"
13-
print(bye)
12+
_ = fmt.Appendf(nil, "bye %d", 1) // want "Replace .*Sprintf.* with fmt.Appendf"
1413
}
1514

1615
func funcsandvars() {
1716
one := "one"
18-
bye := fmt.Appendf(nil, "bye %d %s %s", 1, two(), one) // want "Replace .*Sprintf.* with fmt.Appendf"
19-
print(bye)
17+
_ = fmt.Appendf(nil, "bye %d %s %s", 1, two(), one) // want "Replace .*Sprintf.* with fmt.Appendf"
2018
}
2119

2220
func typealias() {
2321
type b = byte
2422
type bt = []byte
25-
bye := fmt.Appendf(nil, "bye %d", 1) // want "Replace .*Sprintf.* with fmt.Appendf"
26-
print(bye)
27-
bye = fmt.Appendf(nil, "bye %d", 1) // want "Replace .*Sprintf.* with fmt.Appendf"
28-
print(bye)
23+
_ = fmt.Appendf(nil, "bye %d", 1) // want "Replace .*Sprintf.* with fmt.Appendf"
24+
_ = fmt.Appendf(nil, "bye %d", 1) // want "Replace .*Sprintf.* with fmt.Appendf"
2925
}
3026

3127
func otherprints() {
32-
sprint := fmt.Append(nil, "bye %d", 1) // want "Replace .*Sprint.* with fmt.Append"
33-
print(sprint)
34-
sprintln := fmt.Appendln(nil, "bye %d", 1) // want "Replace .*Sprintln.* with fmt.Appendln"
35-
print(sprintln)
28+
_ = fmt.Append(nil, "bye %d", 1) // want "Replace .*Sprint.* with fmt.Append"
29+
_ = fmt.Appendln(nil, "bye %d", 1) // want "Replace .*Sprintln.* with fmt.Appendln"
30+
}
31+
32+
func comma() {
33+
type S struct{ Bytes []byte }
34+
var _ = struct{ A S }{
35+
A: S{
36+
Bytes: // want "Replace .*Sprint.* with fmt.Appendf"
37+
fmt.Appendf(nil, "%d", 0),
38+
},
39+
}
40+
_ = // want "Replace .*Sprint.* with fmt.Appendf"
41+
fmt.Appendf(nil, "%d", 0)
3642
}

0 commit comments

Comments
 (0)