PR: preserves comments in mapsloop
How I found it
Hanging around in issues.
How to solve it
The solution is quite straight as the issue described. We can simplely collects the comments using allComments
and put the comments before the target line.
As the allComments
function is inside minmax
, we ought to move it out. (Thanks for Alan Donovan
reviewed and recommonded moved it out instead of simplely copied it.)
At first, I just collected all the comments and put it to start
node no matter mrhs
is nil or not. But it behaved wrong when mrhs != nil
.
When mrhs != nil
, the start
node is located as the arrow indicates,
m := make(map[string]string)
^
So we would add the comments at wrong position, to correct it, we should used curPrev.Node()
, which is the node before rng
, instead of rng
node.
So the final changes is,
--- a/gopls/internal/analysis/modernize/maps.go
+++ b/gopls/internal/analysis/modernize/maps.go
@@ -156,16 +156,35 @@ func mapsloop(pass *analysis.Pass) {
start, end token.Pos
)
if mrhs != nil {
- // Replace RHS of preceding m=... assignment (and loop) with expression.
- start, end = mrhs.Pos(), rng.End()
- newText = fmt.Appendf(nil, "%s%s(%s)",
+ // Replace assignment and loop with expression.
+ //
+ // m = make(...)
+ // for k, v := range x { /* comments */ m[k] = v }
+ //
+ // ->
+ //
+ // /* comments */
+ // m = maps.Copy(x)
+ curPrev, _ := curRange.PrevSibling()
+ start, end = curPrev.Node().Pos(), rng.End()
+ newText = fmt.Appendf(nil, "%s%s = %s%s(%s)",
+ allComments(file, start, end),
+ analysisinternal.Format(pass.Fset, m),
prefix,
funcName,
analysisinternal.Format(pass.Fset, x))
} else {
// Replace loop with call statement.
+ //
+ // for k, v := range x { /* comments */ m[k] = v }
+ //
+ // ->
+ //
+ // /* comments */
+ // maps.Copy(m, x)
start, end = rng.Pos(), rng.End()
- newText = fmt.Appendf(nil, "%s%s(%s, %s)",
+ newText = fmt.Appendf(nil, "%s%s%s(%s, %s)",
+ allComments(file, start, end),
prefix,
funcName,
analysisinternal.Format(pass.Fset, m),
What I learnt
- Never repeat yourself.