Skip to content

Commit 1eec830

Browse files
neildgopherbot
authored andcommitted
go/doc: linkify interface methods
Create doc links for references to interface methods, such as "[Context.Err]". This does not attempt to handle embedded interfaces: The linked-to method must be declared within the named type. Fixes golang#54033 Change-Id: I4d7a132affe682c85958ca785bcc96571404e6c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/687395 Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Damien Neil <[email protected]> Reviewed-by: Sean Liao <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 7bba745 commit 1eec830

File tree

3 files changed

+39
-7
lines changed

3 files changed

+39
-7
lines changed

src/go/doc/comment_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ func TestComment(t *testing.T) {
2424
pkg := New(pkgs["pkgdoc"], "testdata/pkgdoc", 0)
2525

2626
var (
27-
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"
28-
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"
29-
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"
30-
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"
31-
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"
32-
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"
27+
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. [I.F] is an interface method and [I.V] is a broken link.\n"
28+
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. <a href="#I.F">I.F</a> is an interface method and [I.V] is a broken link.` + "\n"
29+
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. [I.F] is an interface method and [I.V] is a broken link.\n"
30+
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. [I.F](#I.F) is an interface method and \\[I.V] is a broken link.\n"
31+
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. I.F is an interface\nmethod and [I.V] is a broken link.\n"
32+
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[I.F] is an interface method and [I.V] is a broken link.\n"
3333
wantSynopsis = "T and U are types, and T.M is a method, but [V] is a broken link."
3434
wantOldSynopsis = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link."
3535
)

src/go/doc/doc.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ func (p *Package) collectTypes(types []*Type) {
167167
p.collectValues(t.Vars)
168168
p.collectFuncs(t.Funcs)
169169
p.collectFuncs(t.Methods)
170+
p.collectInterfaceMethods(t)
170171
}
171172
}
172173

@@ -184,6 +185,33 @@ func (p *Package) collectFuncs(funcs []*Func) {
184185
}
185186
}
186187

188+
// collectInterfaceMethods adds methods of interface types within t to p.syms.
189+
// Note that t.Methods will contain methods of non-interface types, but not interface types.
190+
// Adding interface methods to t.Methods might make sense, but would cause us to
191+
// include those methods in the documentation index. Adding interface methods to p.syms
192+
// here allows us to linkify references like [io.Reader.Read] without making any other
193+
// changes to the documentation formatting at this time.
194+
//
195+
// If we do start adding interface methods to t.Methods in the future,
196+
// collectInterfaceMethods can be dropped as redundant with collectFuncs(t.Methods).
197+
func (p *Package) collectInterfaceMethods(t *Type) {
198+
for _, s := range t.Decl.Specs {
199+
spec, ok := s.(*ast.TypeSpec)
200+
if !ok {
201+
continue
202+
}
203+
list, isStruct := fields(spec.Type)
204+
if isStruct {
205+
continue
206+
}
207+
for _, field := range list {
208+
for _, name := range field.Names {
209+
p.syms[t.Name+"."+name.Name] = true
210+
}
211+
}
212+
}
213+
}
214+
187215
// NewFromFiles computes documentation for a package.
188216
//
189217
// The package is specified by a list of *ast.Files and corresponding

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,9 @@ var _ = crand.Reader
2020

2121
type G[T any] struct{ x T }
2222

23-
func (g G[T]) M1() {}
23+
func (g G[T]) M1() {}
2424
func (g *G[T]) M2() {}
25+
26+
type I interface {
27+
F()
28+
}

0 commit comments

Comments
 (0)