go/ast/astutil: fix panic when rewriting multi-argument type instances
Use the typeparams helper package to fix AST rewriting in go/ast/astutil
when encountering the new ListExpr type.
This is liable to break in the future when the go/ast API changes, but
at least it will be easy to find by virtue of using internal/typeparams.
Fixes golang/vscode-go#1551
Change-Id: Id34bbcdede9024ed9818bef6d73a19e993dd76a8
Reviewed-on: https://go-review.googlesource.com/c/tools/+/326131
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
diff --git a/go/ast/astutil/rewrite.go b/go/ast/astutil/rewrite.go
index cf72ea9..b949fc8 100644
--- a/go/ast/astutil/rewrite.go
+++ b/go/ast/astutil/rewrite.go
@@ -9,6 +9,8 @@
"go/ast"
"reflect"
"sort"
+
+ "golang.org/x/tools/internal/typeparams"
)
// An ApplyFunc is invoked by Apply for each node n, even if n is nil,
@@ -437,7 +439,11 @@
}
default:
- panic(fmt.Sprintf("Apply: unexpected node type %T", n))
+ if typeparams.IsListExpr(n) {
+ a.applyList(n, "ElemList")
+ } else {
+ panic(fmt.Sprintf("Apply: unexpected node type %T", n))
+ }
}
if a.post != nil && !a.post(&a.cursor) {
diff --git a/go/ast/astutil/rewrite_test.go b/go/ast/astutil/rewrite_test.go
index 1c86970..3a74afa 100644
--- a/go/ast/astutil/rewrite_test.go
+++ b/go/ast/astutil/rewrite_test.go
@@ -13,13 +13,16 @@
"testing"
"golang.org/x/tools/go/ast/astutil"
+ "golang.org/x/tools/internal/typeparams"
)
-var rewriteTests = [...]struct {
+type rewriteTest struct {
name string
orig, want string
pre, post astutil.ApplyFunc
-}{
+}
+
+var rewriteTests = []rewriteTest{
{name: "nop", orig: "package p\n", want: "package p\n"},
{name: "replace",
@@ -190,6 +193,34 @@
},
}
+func init() {
+ if typeparams.Enabled {
+ rewriteTests = append(rewriteTests, rewriteTest{
+ name: "replace",
+ orig: `package p
+
+type T[P1, P2 any] int
+
+type R T[int, string]
+`,
+ want: `package p
+
+type T[P1, P2 any] int32
+
+type R T[int32, string]
+`,
+ post: func(c *astutil.Cursor) bool {
+ if ident, ok := c.Node().(*ast.Ident); ok {
+ if ident.Name == "int" {
+ c.Replace(ast.NewIdent("int32"))
+ }
+ }
+ return true
+ },
+ })
+ }
+}
+
func valspec(name, typ string) *ast.ValueSpec {
return &ast.ValueSpec{Names: []*ast.Ident{ast.NewIdent(name)},
Type: ast.NewIdent(typ),
diff --git a/internal/typeparams/typeparams.go b/internal/typeparams/typeparams.go
index 624ce37..6b7958a 100644
--- a/internal/typeparams/typeparams.go
+++ b/internal/typeparams/typeparams.go
@@ -101,5 +101,5 @@
return nil, nil
}
inf := info.Inferred[e]
- return inf.Targs, inf.Sig
+ return inf.TArgs, inf.Sig
}