]> Cypherpunks repositories - gostls13.git/commitdiff
go/doc: recognize methods on generic types as Funcs
authorKeith Randall <khr@golang.org>
Wed, 9 Nov 2022 23:29:09 +0000 (15:29 -0800)
committerKeith Randall <khr@google.com>
Thu, 10 Nov 2022 06:33:18 +0000 (06:33 +0000)
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 <khr@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/go/doc/comment_test.go
src/go/doc/doc.go
src/go/doc/testdata/pkgdoc/doc.go

index e1e5f15bdf502e5e3f34d8f773e96a5e92d0cb5e..004ae9d13d6de6e213efc7050dabcd56ac7bbff0 100644 (file)
@@ -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        = `<p><a href="#T">T</a> and <a href="#U">U</a> are types, and <a href="#T.M">T.M</a> is a method, but [V] is a broken link. <a href="/math/rand#Int">rand.Int</a> and <a href="/crypto/rand#Reader">crand.Reader</a> are things.` + "\n"
-               wantOldHTML     = "<p>[T] and [U] are <i>types</i>, 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        = `<p><a href="#T">T</a> and <a href="#U">U</a> are types, and <a href="#T.M">T.M</a> is a method, but [V] is a broken link. <a href="/math/rand#Int">rand.Int</a> and <a href="/crypto/rand#Reader">crand.Reader</a> are things. <a href="#G.M1">G.M1</a> and <a href="#G.M2">G.M2</a> are generic methods.` + "\n"
+               wantOldHTML     = "<p>[T] and [U] are <i>types</i>, 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."
        )
index 651a2c1f6c83b02c7c89e8b41f1a97fb5c233f78..eefadfa9329e181dea34e7d1fe17bad278aa38f8 100644 (file)
@@ -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
                }
index 61bd4e32f932859f1aa13a356a1ce9164908e97f..3f822c75546c637bf5c03bbe0acc8d16c4a878bd 100644 (file)
@@ -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() {}