From a11cd6f69aec5c783656601fbc7b493e0d63f605 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Wed, 9 Nov 2022 15:29:09 -0800 Subject: [PATCH] go/doc: recognize methods on generic types as Funcs When writing markdown for godoc, we can reference a method M of a type T as [T.M]. This doesn't currently work for methods on generic types because the declaration of the type parameter gets in the way. (You'd have to write [T[P].M] and that doesn't parse, and even if it did you'd have to spell "P" correctly.) Get rid of the type parameter when building the list of Funcs so [T.M] works in godoc if T is generic. Change-Id: I8ef5264124a944967df3ce20ddd40a2447ff4187 Reviewed-on: https://go-review.googlesource.com/c/go/+/449236 Reviewed-by: Keith Randall Reviewed-by: Robert Griesemer Run-TryBot: Keith Randall TryBot-Result: Gopher Robot --- src/go/doc/comment_test.go | 12 ++++++------ src/go/doc/doc.go | 8 ++++++-- src/go/doc/testdata/pkgdoc/doc.go | 5 +++++ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/go/doc/comment_test.go b/src/go/doc/comment_test.go index e1e5f15bdf..004ae9d13d 100644 --- a/src/go/doc/comment_test.go +++ b/src/go/doc/comment_test.go @@ -24,12 +24,12 @@ func TestComment(t *testing.T) { pkg := New(pkgs["pkgdoc"], "testdata/pkgdoc", 0) var ( - input = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link. [rand.Int] and [crand.Reader] are things.\n" - wantHTML = `

T and U are types, and T.M is a method, but [V] is a broken link. rand.Int and crand.Reader are things.` + "\n" - wantOldHTML = "

[T] and [U] are types, and [T.M] is a method, but [V] is a broken link. [rand.Int] and [crand.Reader] are things.\n" - wantMarkdown = "[T](#T) and [U](#U) are types, and [T.M](#T.M) is a method, but \\[V] is a broken link. [rand.Int](/math/rand#Int) and [crand.Reader](/crypto/rand#Reader) are things.\n" - wantText = "T and U are types, and T.M is a method, but [V] is a broken link. rand.Int and\ncrand.Reader are things.\n" - wantOldText = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link.\n[rand.Int] and [crand.Reader] are things.\n" + input = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link. [rand.Int] and [crand.Reader] are things. [G.M1] and [G.M2] are generic methods.\n" + wantHTML = `

T and U are types, and T.M is a method, but [V] is a broken link. rand.Int and crand.Reader are things. G.M1 and G.M2 are generic methods.` + "\n" + wantOldHTML = "

[T] and [U] are types, and [T.M] is a method, but [V] is a broken link. [rand.Int] and [crand.Reader] are things. [G.M1] and [G.M2] are generic methods.\n" + wantMarkdown = "[T](#T) and [U](#U) are types, and [T.M](#T.M) is a method, but \\[V] is a broken link. [rand.Int](/math/rand#Int) and [crand.Reader](/crypto/rand#Reader) are things. [G.M1](#G.M1) and [G.M2](#G.M2) are generic methods.\n" + wantText = "T and U are types, and T.M is a method, but [V] is a broken link. rand.Int and\ncrand.Reader are things. G.M1 and G.M2 are generic methods.\n" + wantOldText = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link.\n[rand.Int] and [crand.Reader] are things. [G.M1] and [G.M2] are generic methods.\n" wantSynopsis = "T and U are types, and T.M is a method, but [V] is a broken link." wantOldSynopsis = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link." ) diff --git a/src/go/doc/doc.go b/src/go/doc/doc.go index 651a2c1f6c..eefadfa932 100644 --- a/src/go/doc/doc.go +++ b/src/go/doc/doc.go @@ -76,7 +76,7 @@ type Func struct { // methods // (for functions, these fields have the respective zero value) - Recv string // actual receiver "T" or "*T" + Recv string // actual receiver "T" or "*T" possibly followed by type parameters [P1, ..., Pn] Orig string // original receiver "T" or "*T" Level int // embedding level; 0 means not embedded @@ -173,7 +173,11 @@ func (p *Package) collectTypes(types []*Type) { func (p *Package) collectFuncs(funcs []*Func) { for _, f := range funcs { if f.Recv != "" { - p.syms[strings.TrimPrefix(f.Recv, "*")+"."+f.Name] = true + r := strings.TrimPrefix(f.Recv, "*") + if i := strings.IndexByte(r, '['); i >= 0 { + r = r[:i] // remove type parameters + } + p.syms[r+"."+f.Name] = true } else { p.syms[f.Name] = true } diff --git a/src/go/doc/testdata/pkgdoc/doc.go b/src/go/doc/testdata/pkgdoc/doc.go index 61bd4e32f9..3f822c7554 100644 --- a/src/go/doc/testdata/pkgdoc/doc.go +++ b/src/go/doc/testdata/pkgdoc/doc.go @@ -17,3 +17,8 @@ func (T) M() {} var _ = rand.Int var _ = crand.Reader + +type G[T any] struct{ x T } + +func (g G[T]) M1() {} +func (g *G[T]) M2() {} -- 2.50.0