Skip to content

Commit 68caf84

Browse files
committed
gopls/internal/golang: don't lose ... when split/joining variadics
We wrap the last argument f(x...) in an explicit Ellipsis to record that it was a variadic call, and add the "..." back with corresponding logic when creating the edits. Fixes golang/go#70519 Change-Id: I1fdfa5f3ccb000c9622f856ed7703b31d7911620 Reviewed-on: https://go-review.googlesource.com/c/tools/+/631335 Auto-Submit: Alan Donovan <[email protected]> Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 1e0d4ee commit 68caf84

File tree

3 files changed

+78
-1
lines changed

3 files changed

+78
-1
lines changed

gopls/internal/golang/fix.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ import (
3535
// The supplied token positions (start, end) must belong to
3636
// pkg.FileSet(), and the returned positions
3737
// (SuggestedFix.TextEdits[*].{Pos,End}) must belong to the returned
38-
// FileSet.
38+
// FileSet, which is not necessarily the same.
39+
// (See [insertDeclsAfter] for explanation.)
3940
//
4041
// A fixer may return (nil, nil) if no fix is available.
4142
type fixer func(ctx context.Context, s *cache.Snapshot, pkg *cache.Package, pgf *parsego.File, start, end token.Pos) (*token.FileSet, *analysis.SuggestedFix, error)

gopls/internal/golang/lines.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,15 @@ func processLines(fset *token.FileSet, items []ast.Node, comments []*ast.Comment
151151
}
152152

153153
edits = append(edits, analysis.TextEdit{Pos: pos, End: end, NewText: []byte(sep + indent)})
154+
155+
// Print the Ellipsis if we synthesized one earlier.
156+
if is[*ast.Ellipsis](nodes[i]) {
157+
edits = append(edits, analysis.TextEdit{
158+
Pos: nodes[i].End(),
159+
End: nodes[i].End(),
160+
NewText: []byte("..."),
161+
})
162+
}
154163
}
155164

156165
return &analysis.SuggestedFix{TextEdits: edits}
@@ -205,6 +214,18 @@ func findSplitJoinTarget(fset *token.FileSet, file *ast.File, src []byte, start,
205214
for _, arg := range node.Args {
206215
items = append(items, arg)
207216
}
217+
218+
// Preserve "..." by wrapping the last
219+
// argument in an Ellipsis node
220+
// with the same Pos/End as the argument.
221+
// See corresponding logic in processLines.
222+
if node.Ellipsis.IsValid() {
223+
last := &items[len(items)-1]
224+
*last = &ast.Ellipsis{
225+
Ellipsis: (*last).Pos(), // determines Ellipsis.Pos()
226+
Elt: (*last).(ast.Expr), // determines Ellipsis.End()
227+
}
228+
}
208229
case *ast.CompositeLit:
209230
for _, arg := range node.Elts {
210231
items = append(items, arg)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
This is a regression test for #70519, in which the ellipsis
2+
of a variadic call would go missing after split/join lines.
3+
4+
-- go.mod --
5+
module example.com
6+
go 1.18
7+
8+
-- a/a.go --
9+
package a
10+
11+
var a, b, c []any
12+
func f(any, any, ...any)
13+
14+
func _() {
15+
f(a, b, c...) //@codeaction("a", "refactor.rewrite.splitLines", result=split)
16+
17+
f(
18+
a,
19+
b,
20+
c..., /*@codeaction("c", "refactor.rewrite.joinLines", result=joined)*/
21+
)
22+
}
23+
24+
-- @split/a/a.go --
25+
package a
26+
27+
var a, b, c []any
28+
func f(any, any, ...any)
29+
30+
func _() {
31+
f(
32+
a,
33+
b,
34+
c...,
35+
) //@codeaction("a", "refactor.rewrite.splitLines", result=split)
36+
37+
f(
38+
a,
39+
b,
40+
c..., /*@codeaction("c", "refactor.rewrite.joinLines", result=joined)*/
41+
)
42+
}
43+
44+
-- @joined/a/a.go --
45+
package a
46+
47+
var a, b, c []any
48+
func f(any, any, ...any)
49+
50+
func _() {
51+
f(a, b, c...) //@codeaction("a", "refactor.rewrite.splitLines", result=split)
52+
53+
f(a, b, c..., /*@codeaction("c", "refactor.rewrite.joinLines", result=joined)*/)
54+
}
55+

0 commit comments

Comments
 (0)