aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/api/api.go4
-rw-r--r--internal/api/render.go167
-rw-r--r--internal/api/render_test.go36
-rw-r--r--internal/api/testdata/examples.go14
-rw-r--r--internal/api/testdata/html-examples.golden155
-rw-r--r--internal/api/testdata/html.golden2
-rw-r--r--internal/api/testdata/markdown-examples.golden185
-rw-r--r--internal/api/testdata/markdown.golden30
-rw-r--r--internal/api/testdata/pkg_test.go46
-rw-r--r--internal/api/testdata/text-examples.golden122
10 files changed, 704 insertions, 57 deletions
diff --git a/internal/api/api.go b/internal/api/api.go
index 867d1d1d..cf771e82 100644
--- a/internal/api/api.go
+++ b/internal/api/api.go
@@ -112,7 +112,9 @@ func ServePackage(w http.ResponseWriter, r *http.Request, ds internal.DataSource
default:
return fmt.Errorf("%w: bad doc format: need one of 'text', 'md', 'markdown' or 'html'", derrors.InvalidArgument)
}
- if err := renderDoc(dpkg, r); err != nil {
+ // TODO(jba): add a param to omit examples
+ const includeExamples = true
+ if err := renderDoc(dpkg, r, includeExamples); err != nil {
return fmt.Errorf("%w: %s", derrors.Unknown, err.Error())
}
docs = sb.String()
diff --git a/internal/api/render.go b/internal/api/render.go
index 8654de2c..f8d9dbc7 100644
--- a/internal/api/render.go
+++ b/internal/api/render.go
@@ -37,7 +37,9 @@ type renderer interface {
// emit prints documentation for particular node, like a const
// or function.
emit(comment string, node ast.Node)
- // TODO(jba): support examples
+
+ // emitExample prints an example.
+ emitExample(ex *doc.Example)
}
type textRenderer struct {
@@ -62,8 +64,7 @@ func (r *textRenderer) start(pkg *doc.Package) {
if pkg.Doc != "" {
r.printf("\n")
// The package doc is not indented, so don't use r.printer.
- _, err := r.w.Write(pkg.Text(pkg.Doc))
- if err != nil {
+ if _, err := r.w.Write(pkg.Text(pkg.Doc)); err != nil {
r.err = err
}
}
@@ -90,8 +91,7 @@ func (r *textRenderer) emit(comment string, node ast.Node) {
r.printf("\n")
formatted := r.printer.Text(r.parser.Parse(comment))
if len(formatted) > 0 {
- _, err = r.w.Write(formatted)
- if err != nil {
+ if _, err = r.w.Write(formatted); err != nil {
r.err = err
return
}
@@ -99,13 +99,54 @@ func (r *textRenderer) emit(comment string, node ast.Node) {
r.printf("\n")
}
+func (r *textRenderer) emitExample(ex *doc.Example) {
+ if r.err != nil {
+ return
+ }
+ r.printf("Example")
+ if ex.Suffix != "" {
+ r.printf(" (%s)", ex.Suffix)
+ }
+ r.printf(":\n")
+ if ex.Doc != "" {
+ formatted := r.printer.Text(r.parser.Parse(ex.Doc))
+ if len(formatted) > 0 {
+ if _, err := r.w.Write(formatted); err != nil {
+ r.err = err
+ return
+ }
+ r.printf("\n")
+ }
+ }
+ var buf strings.Builder
+ if err := format.Node(&buf, r.fset, ex.Code); err != nil {
+ r.err = err
+ return
+ }
+ // Indent the code and output.
+ lines := strings.Split(strings.TrimSpace(buf.String()), "\n")
+ for i, line := range lines {
+ // Omit blank line before close brace.
+ if i == len(lines)-2 && line == "" {
+ continue
+ }
+ r.printf("\t%s\n", line)
+ }
+ if ex.Output != "" {
+ r.printf("\n\tOutput:\n")
+ for _, line := range strings.Split(strings.TrimSpace(ex.Output), "\n") {
+ r.printf("\t%s\n", line)
+ }
+ }
+ r.printf("\n")
+}
+
// TODO(jba): consolidate this function to avoid duplication.
func (r *textRenderer) printf(format string, args ...any) {
if r.err != nil {
return
}
- _, err := fmt.Fprintf(r.w, format, args...)
- if err != nil {
+ if _, err := fmt.Fprintf(r.w, format, args...); err != nil {
r.err = err
}
}
@@ -130,8 +171,7 @@ func (r *markdownRenderer) start(pkg *doc.Package) {
r.printf("# package %s\n", pkg.Name)
if pkg.Doc != "" {
r.printf("\n")
- _, err := r.w.Write(r.printer.Markdown(r.parser.Parse(pkg.Doc)))
- if err != nil {
+ if _, err := r.w.Write(r.printer.Markdown(r.parser.Parse(pkg.Doc))); err != nil {
r.err = err
}
}
@@ -153,7 +193,7 @@ func (r *markdownRenderer) emit(comment string, node ast.Node) {
if r.err != nil {
return
}
- r.printf("```\n")
+ r.printf("```go\n")
err := format.Node(r.w, r.fset, node)
if err != nil {
r.err = err
@@ -162,8 +202,7 @@ func (r *markdownRenderer) emit(comment string, node ast.Node) {
r.printf("\n```\n")
formatted := r.printer.Markdown(r.parser.Parse(comment))
if len(formatted) > 0 {
- _, err = r.w.Write(formatted)
- if err != nil {
+ if _, err = r.w.Write(formatted); err != nil {
r.err = err
return
}
@@ -171,13 +210,41 @@ func (r *markdownRenderer) emit(comment string, node ast.Node) {
r.printf("\n")
}
-func (r *markdownRenderer) printf(format string, args ...any) {
+func (r *markdownRenderer) emitExample(ex *doc.Example) {
if r.err != nil {
return
}
- _, err := fmt.Fprintf(r.w, format, args...)
+ r.printf("#### Example")
+ if ex.Suffix != "" {
+ r.printf(" (%s)", ex.Suffix)
+ }
+ r.printf("\n\n")
+ if ex.Doc != "" {
+ if _, err := r.w.Write(r.printer.Markdown(r.parser.Parse(ex.Doc))); err != nil {
+ r.err = err
+ return
+ }
+ r.printf("\n")
+ }
+ r.printf("```go\n")
+ err := format.Node(r.w, r.fset, ex.Code)
if err != nil {
r.err = err
+ return
+ }
+ r.printf("\n```\n")
+ if ex.Output != "" {
+ r.printf("Output:\n\n```\n%s\n```\n", ex.Output)
+ }
+ r.printf("\n")
+}
+
+func (r *markdownRenderer) printf(format string, args ...any) {
+ if r.err != nil {
+ return
+ }
+ if _, err := fmt.Fprintf(r.w, format, args...); err != nil {
+ r.err = err
}
}
@@ -188,6 +255,7 @@ type htmlRenderer struct {
parser *comment.Parser
printer *comment.Printer
caser cases.Caser
+ buf strings.Builder
err error
}
@@ -201,8 +269,7 @@ func (r *htmlRenderer) start(pkg *doc.Package) {
r.printf("<h1>package %s</h1>\n", pkg.Name)
if pkg.Doc != "" {
r.printf("\n")
- _, err := r.w.Write(r.printer.HTML(r.parser.Parse(pkg.Doc)))
- if err != nil {
+ if _, err := r.w.Write(r.printer.HTML(r.parser.Parse(pkg.Doc))); err != nil {
r.err = err
}
}
@@ -224,17 +291,16 @@ func (r *htmlRenderer) emit(comment string, node ast.Node) {
if r.err != nil {
return
}
- var buf strings.Builder
- err := format.Node(&buf, r.fset, node)
+ r.buf.Reset()
+ err := format.Node(&r.buf, r.fset, node)
if err != nil {
r.err = err
return
}
- r.printf("<pre><code>%s</code></pre>\n", html.EscapeString(buf.String()))
+ r.printf("<pre><code>%s</code></pre>\n", html.EscapeString(r.buf.String()))
formatted := r.printer.HTML(r.parser.Parse(comment))
if len(formatted) > 0 {
- _, err = r.w.Write(formatted)
- if err != nil {
+ if _, err = r.w.Write(formatted); err != nil {
r.err = err
return
}
@@ -242,24 +308,57 @@ func (r *htmlRenderer) emit(comment string, node ast.Node) {
r.printf("\n")
}
-func (r *htmlRenderer) printf(format string, args ...any) {
+func (r *htmlRenderer) emitExample(ex *doc.Example) {
if r.err != nil {
return
}
- _, err := fmt.Fprintf(r.w, format, args...)
+ r.printf("<h4>Example")
+ if ex.Suffix != "" {
+ r.printf(" (%s)", ex.Suffix)
+ }
+ r.printf("</h4>\n")
+ r.printf("\n")
+ if ex.Doc != "" {
+ if _, err := r.w.Write(r.printer.Markdown(r.parser.Parse(ex.Doc))); err != nil {
+ r.err = err
+ return
+ }
+ r.printf("\n")
+ }
+ r.printf("<pre><code>\n")
+ err := format.Node(r.w, r.fset, ex.Code)
if err != nil {
r.err = err
+ return
+ }
+ r.printf("\n</code></pre>\n")
+ if ex.Output != "" {
+ r.printf("Output:\n\n<pre><code>\n%s\n</code></pre>\n", html.EscapeString(ex.Output))
+ }
+ r.printf("\n")
+}
+
+func (r *htmlRenderer) printf(format string, args ...any) {
+ if r.err != nil {
+ return
+ }
+ if _, err := fmt.Fprintf(r.w, format, args...); err != nil {
+ r.err = err
}
}
// renderDoc renders the documentation for dpkg using the given renderer.
-// TODO(jba): support examples.
-func renderDoc(dpkg *doc.Package, r renderer) error {
+func renderDoc(dpkg *doc.Package, r renderer, examples bool) error {
r.start(dpkg)
+ if examples {
+ for _, ex := range dpkg.Examples {
+ r.emitExample(ex)
+ }
+ }
renderValues(dpkg.Consts, r, "constants")
renderValues(dpkg.Vars, r, "variables")
- renderFuncs(dpkg.Funcs, r, "functions")
+ renderFuncs(dpkg.Funcs, r, "functions", examples)
started := false
for _, t := range dpkg.Types {
@@ -271,10 +370,15 @@ func renderDoc(dpkg *doc.Package, r renderer) error {
started = true
}
r.emit(t.Doc, t.Decl)
+ if examples {
+ for _, ex := range t.Examples {
+ r.emitExample(ex)
+ }
+ }
renderValues(t.Consts, r, "")
renderValues(t.Vars, r, "")
- renderFuncs(t.Funcs, r, "")
- renderFuncs(t.Methods, r, "")
+ renderFuncs(t.Funcs, r, "", examples)
+ renderFuncs(t.Methods, r, "", examples)
}
if started {
r.endSection()
@@ -301,7 +405,7 @@ func renderValues(vals []*doc.Value, r renderer, section string) {
}
}
-func renderFuncs(funcs []*doc.Func, r renderer, section string) {
+func renderFuncs(funcs []*doc.Func, r renderer, section string, examples bool) {
started := false
for _, f := range funcs {
if !ast.IsExported(f.Name) {
@@ -314,6 +418,11 @@ func renderFuncs(funcs []*doc.Func, r renderer, section string) {
started = true
}
r.emit(f.Doc, f.Decl)
+ if examples {
+ for _, ex := range f.Examples {
+ r.emitExample(ex)
+ }
+ }
}
if started && section != "" {
r.endSection()
diff --git a/internal/api/render_test.go b/internal/api/render_test.go
index 14e06d6d..fdfb8612 100644
--- a/internal/api/render_test.go
+++ b/internal/api/render_test.go
@@ -6,6 +6,7 @@ package api
import (
"context"
+ "fmt"
"go/parser"
"go/token"
"os"
@@ -18,17 +19,24 @@ import (
)
func TestRenderDoc(t *testing.T) {
- src, err := os.ReadFile("testdata/pkg.go")
- if err != nil {
- t.Fatal(err)
- }
+ t.Run("examples", func(t *testing.T) {
+ testRenderDoc(t, true)
+ })
+ t.Run("no examples", func(t *testing.T) {
+ testRenderDoc(t, false)
+ })
+}
+
+func testRenderDoc(t *testing.T, examples bool) {
fset := token.NewFileSet()
- pf, err := parser.ParseFile(fset, "p.go", src, parser.ParseComments)
- if err != nil {
- t.Fatal(err)
- }
docPkg := godoc.NewPackage(fset, nil)
- docPkg.AddFile(pf, true)
+ for _, file := range []string{"pkg.go", "pkg_test.go"} {
+ pf, err := parser.ParseFile(fset, filepath.Join("testdata", file), nil, parser.ParseComments)
+ if err != nil {
+ t.Fatal(err)
+ }
+ docPkg.AddFile(pf, true)
+ }
gpkg, err := docPkg.Encode(context.Background())
if err != nil {
t.Fatal(err)
@@ -48,17 +56,23 @@ func TestRenderDoc(t *testing.T) {
check := func(t *testing.T, name string, r renderer) {
sb.Reset()
t.Run(name, func(t *testing.T) {
- if err := renderDoc(dpkg, r); err != nil {
+ if err := renderDoc(dpkg, r, examples); err != nil {
t.Fatal(err)
}
got := strings.TrimSpace(sb.String())
- wantBytes, err := os.ReadFile(filepath.FromSlash("testdata/" + name + ".golden"))
+ goldenName := name
+ if examples {
+ goldenName += "-examples"
+ }
+ goldenFile := filepath.Join("testdata", goldenName+".golden")
+ wantBytes, err := os.ReadFile(goldenFile)
if err != nil {
t.Fatal(err)
}
want := strings.TrimSpace(string(wantBytes))
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("mismatch (-want +got):\n%s", diff)
+ fmt.Println(got)
}
})
}
diff --git a/internal/api/testdata/examples.go b/internal/api/testdata/examples.go
new file mode 100644
index 00000000..93baaa17
--- /dev/null
+++ b/internal/api/testdata/examples.go
@@ -0,0 +1,14 @@
+// Copyright 2026 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package examples
+
+// F is a function.
+func F() {}
+
+// T is a type.
+type T struct{}
+
+// M is a method.
+func (T) M() {}
diff --git a/internal/api/testdata/html-examples.golden b/internal/api/testdata/html-examples.golden
new file mode 100644
index 00000000..fd6e0682
--- /dev/null
+++ b/internal/api/testdata/html-examples.golden
@@ -0,0 +1,155 @@
+<h1>package pkg</h1>
+
+<p>Package pkg has every form of declaration.
+<h3 id="hdr-Heading">Heading</h3>
+<p>Search <a href="https://google.com">Google</a> for details.
+<h3 id="hdr-Links">Links</h3>
+<ul>
+<li>pkgsite repo, <a href="https://go.googlesource.com/pkgsite">https://go.googlesource.com/pkgsite</a>
+<li>Play with Go, <a href="https://play-with-go.dev">https://play-with-go.dev</a>
+</ul>
+
+<h4>Example</h4>
+
+<pre><code>
+{
+ fmt.Println("Package example")
+
+}
+</code></pre>
+Output:
+
+<pre><code>
+Package example
+
+</code></pre>
+
+<h2>Constants</h2>
+
+<pre><code>const (
+ X = 1
+ Y = 2
+)</code></pre>
+<p>Several constants.
+
+<pre><code>const C = 1</code></pre>
+<p>C is a shorthand for 1.
+
+<h2>Variables</h2>
+
+<pre><code>var V = 2</code></pre>
+<p>V is a variable.
+
+<h2>Functions</h2>
+
+<pre><code>func Add(x int) int</code></pre>
+<p>Add adds 1 to x.
+
+<pre><code>func F()</code></pre>
+<p>F is a function.
+
+<h4>Example</h4>
+
+<pre><code>
+{
+ pkg.F()
+ fmt.Println("F example")
+
+}
+</code></pre>
+Output:
+
+<pre><code>
+F example
+
+</code></pre>
+
+<h4>Example (second)</h4>
+
+<pre><code>
+{
+ pkg.F()
+ fmt.Println("F second example")
+
+}
+</code></pre>
+Output:
+
+<pre><code>
+F second example
+
+</code></pre>
+
+<h2>Types</h2>
+
+<pre><code>type A int</code></pre>
+
+<pre><code>type B bool</code></pre>
+
+<pre><code>type I1 interface {
+ M1()
+}</code></pre>
+<p>I1 is an interface.
+
+<pre><code>type I2 interface {
+ I1
+ M2()
+}</code></pre>
+
+<pre><code>type S1 struct {
+ F int // field
+}</code></pre>
+<p>S1 is a struct.
+
+<pre><code>type S2 struct {
+ S1
+ G int
+}</code></pre>
+<p>S2 is another struct.
+
+<pre><code>type T int</code></pre>
+<p>T is a type.
+
+<h4>Example</h4>
+
+<pre><code>
+{
+ _ = pkg.T(0)
+ fmt.Println("T example")
+
+}
+</code></pre>
+Output:
+
+<pre><code>
+T example
+
+</code></pre>
+
+<pre><code>const CT T = 3</code></pre>
+<p>CT is a typed constant.
+They appear after their type.
+
+<pre><code>func TF() T</code></pre>
+<p>TF is a constructor for T.
+
+<pre><code>func (T) M()</code></pre>
+<p>M is a method of T.
+BUG(xxx): this verifies that notes are rendered.
+
+<h4>Example</h4>
+
+<pre><code>
+{
+ var t pkg.T
+ t.M()
+ fmt.Println("M example")
+
+}
+</code></pre>
+Output:
+
+<pre><code>
+M example
+
+</code></pre>
diff --git a/internal/api/testdata/html.golden b/internal/api/testdata/html.golden
index d77b329c..dac7514b 100644
--- a/internal/api/testdata/html.golden
+++ b/internal/api/testdata/html.golden
@@ -72,4 +72,4 @@ They appear after their type.
<pre><code>func (T) M()</code></pre>
<p>M is a method of T.
-BUG(xxx): this verifies that notes are rendered. \ No newline at end of file
+BUG(xxx): this verifies that notes are rendered.
diff --git a/internal/api/testdata/markdown-examples.golden b/internal/api/testdata/markdown-examples.golden
new file mode 100644
index 00000000..c552629b
--- /dev/null
+++ b/internal/api/testdata/markdown-examples.golden
@@ -0,0 +1,185 @@
+# package pkg
+
+Package pkg has every form of declaration.
+
+### Heading {#hdr-Heading}
+
+Search [Google](https://google.com) for details.
+
+### Links {#hdr-Links}
+
+ - pkgsite repo, [https://go.googlesource.com/pkgsite](https://go.googlesource.com/pkgsite)
+ - Play with Go, [https://play-with-go.dev](https://play-with-go.dev)
+
+#### Example
+
+```go
+{
+ fmt.Println("Package example")
+
+}
+```
+Output:
+
+```
+Package example
+
+```
+
+## Constants
+
+```go
+const (
+ X = 1
+ Y = 2
+)
+```
+Several constants.
+
+```go
+const C = 1
+```
+C is a shorthand for 1.
+
+## Variables
+
+```go
+var V = 2
+```
+V is a variable.
+
+## Functions
+
+```go
+func Add(x int) int
+```
+Add adds 1 to x.
+
+```go
+func F()
+```
+F is a function.
+
+#### Example
+
+```go
+{
+ pkg.F()
+ fmt.Println("F example")
+
+}
+```
+Output:
+
+```
+F example
+
+```
+
+#### Example (second)
+
+```go
+{
+ pkg.F()
+ fmt.Println("F second example")
+
+}
+```
+Output:
+
+```
+F second example
+
+```
+
+## Types
+
+```go
+type A int
+```
+
+```go
+type B bool
+```
+
+```go
+type I1 interface {
+ M1()
+}
+```
+I1 is an interface.
+
+```go
+type I2 interface {
+ I1
+ M2()
+}
+```
+
+```go
+type S1 struct {
+ F int // field
+}
+```
+S1 is a struct.
+
+```go
+type S2 struct {
+ S1
+ G int
+}
+```
+S2 is another struct.
+
+```go
+type T int
+```
+T is a type.
+
+#### Example
+
+```go
+{
+ _ = pkg.T(0)
+ fmt.Println("T example")
+
+}
+```
+Output:
+
+```
+T example
+
+```
+
+```go
+const CT T = 3
+```
+CT is a typed constant. They appear after their type.
+
+```go
+func TF() T
+```
+TF is a constructor for T.
+
+```go
+func (T) M()
+```
+M is a method of T. BUG(xxx): this verifies that notes are rendered.
+
+#### Example
+
+```go
+{
+ var t pkg.T
+ t.M()
+ fmt.Println("M example")
+
+}
+```
+Output:
+
+```
+M example
+
+```
diff --git a/internal/api/testdata/markdown.golden b/internal/api/testdata/markdown.golden
index 205546d0..8e19e5db 100644
--- a/internal/api/testdata/markdown.golden
+++ b/internal/api/testdata/markdown.golden
@@ -13,7 +13,7 @@ Search [Google](https://google.com) for details.
## Constants
-```
+```go
const (
X = 1
Y = 2
@@ -21,62 +21,62 @@ const (
```
Several constants.
-```
+```go
const C = 1
```
C is a shorthand for 1.
## Variables
-```
+```go
var V = 2
```
V is a variable.
## Functions
-```
+```go
func Add(x int) int
```
Add adds 1 to x.
-```
+```go
func F()
```
F is a function.
## Types
-```
+```go
type A int
```
-```
+```go
type B bool
```
-```
+```go
type I1 interface {
M1()
}
```
I1 is an interface.
-```
+```go
type I2 interface {
I1
M2()
}
```
-```
+```go
type S1 struct {
F int // field
}
```
S1 is a struct.
-```
+```go
type S2 struct {
S1
G int
@@ -84,22 +84,22 @@ type S2 struct {
```
S2 is another struct.
-```
+```go
type T int
```
T is a type.
-```
+```go
const CT T = 3
```
CT is a typed constant. They appear after their type.
-```
+```go
func TF() T
```
TF is a constructor for T.
-```
+```go
func (T) M()
```
M is a method of T. BUG(xxx): this verifies that notes are rendered.
diff --git a/internal/api/testdata/pkg_test.go b/internal/api/testdata/pkg_test.go
new file mode 100644
index 00000000..4697bec4
--- /dev/null
+++ b/internal/api/testdata/pkg_test.go
@@ -0,0 +1,46 @@
+// Copyright 2026 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pkg_test
+
+import (
+ "fmt"
+
+ "golang.org/x/pkgsite/internal/api/testdata"
+)
+
+func Example() {
+ fmt.Println("Package example")
+ // Output:
+ // Package example
+}
+
+func ExampleF() {
+ pkg.F()
+ fmt.Println("F example")
+ // Output:
+ // F example
+}
+
+func ExampleF_second() {
+ pkg.F()
+ fmt.Println("F second example")
+ // Output:
+ // F second example
+}
+
+func ExampleT() {
+ _ = pkg.T(0)
+ fmt.Println("T example")
+ // Output:
+ // T example
+}
+
+func ExampleT_M() {
+ var t pkg.T
+ t.M()
+ fmt.Println("M example")
+ // Output:
+ // M example
+}
diff --git a/internal/api/testdata/text-examples.golden b/internal/api/testdata/text-examples.golden
new file mode 100644
index 00000000..c8c10435
--- /dev/null
+++ b/internal/api/testdata/text-examples.golden
@@ -0,0 +1,122 @@
+package pkg
+
+Package pkg has every form of declaration.
+
+# Heading
+
+Search Google for details.
+
+# Links
+
+ - pkgsite repo, https://go.googlesource.com/pkgsite
+ - Play with Go, https://play-with-go.dev
+
+[Google]: https://google.com
+
+Example:
+ {
+ fmt.Println("Package example")
+ }
+
+ Output:
+ Package example
+
+CONSTANTS
+
+const (
+ X = 1
+ Y = 2
+)
+ Several constants.
+
+const C = 1
+ C is a shorthand for 1.
+
+VARIABLES
+
+var V = 2
+ V is a variable.
+
+FUNCTIONS
+
+func Add(x int) int
+ Add adds 1 to x.
+
+func F()
+ F is a function.
+
+Example:
+ {
+ pkg.F()
+ fmt.Println("F example")
+ }
+
+ Output:
+ F example
+
+Example (second):
+ {
+ pkg.F()
+ fmt.Println("F second example")
+ }
+
+ Output:
+ F second example
+
+TYPES
+
+type A int
+
+type B bool
+
+type I1 interface {
+ M1()
+}
+ I1 is an interface.
+
+type I2 interface {
+ I1
+ M2()
+}
+
+type S1 struct {
+ F int // field
+}
+ S1 is a struct.
+
+type S2 struct {
+ S1
+ G int
+}
+ S2 is another struct.
+
+type T int
+ T is a type.
+
+Example:
+ {
+ _ = pkg.T(0)
+ fmt.Println("T example")
+ }
+
+ Output:
+ T example
+
+const CT T = 3
+ CT is a typed constant. They appear after their type.
+
+func TF() T
+ TF is a constructor for T.
+
+func (T) M()
+ M is a method of T. BUG(xxx): this verifies that notes are rendered.
+
+Example:
+ {
+ var t pkg.T
+ t.M()
+ fmt.Println("M example")
+ }
+
+ Output:
+ M example