Code Examples
package main
import (
"fmt"
"go/ast"
"go/doc"
"go/parser"
"go/token"
)
func main() {
// src and test are two source files that make up
// a package whose documentation will be computed.
const src = `
// This is the package comment.
package p
import "fmt"
// This comment is associated with the Greet function.
func Greet(who string) {
fmt.Printf("Hello, %s!\n", who)
}
`
const test = `
package p_test
// This comment is associated with the ExampleGreet_world example.
func ExampleGreet_world() {
Greet("world")
}
`
// Create the AST by parsing src and test.
fset := token.NewFileSet()
files := []*ast.File{
mustParse(fset, "src.go", src),
mustParse(fset, "src_test.go", test),
}
// Compute package documentation with examples.
p, err := doc.NewFromFiles(fset, files, "example.com/p")
if err != nil {
panic(err)
}
fmt.Printf("package %s - %s", p.Name, p.Doc)
fmt.Printf("func %s - %s", p.Funcs[0].Name, p.Funcs[0].Doc)
fmt.Printf(" ⤷ example with suffix %q - %s", p.Funcs[0].Examples[0].Suffix, p.Funcs[0].Examples[0].Doc)
}
func mustParse(fset *token.FileSet, filename, src string) *ast.File {
f, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
if err != nil {
panic(err)
}
return f
}
Package-Level Type Names (total 16, in which 8 are exported)
/* sort exporteds by: | */
An Example represents an example function found in a test source file.
Codeast.NodeComments[]*ast.CommentGroup
// example function doc string
// expect empty output
// name of the item being exemplified (including optional suffix)
// original source code order
// expected output
// a whole program version of the example
// example suffix, without leading '_' (only populated by NewFromFiles)
Unorderedbool
func Examples(testFiles ...*ast.File) []*Example
func classifyExamples(p *Package, examples []*Example)
Func is the documentation for a func declaration.
Decl*ast.FuncDeclDocstring
Examples is a sorted list of examples associated with this
function or method. Examples are extracted from _test.go files
provided to NewFromFiles.
// embedding level; 0 means not embedded
Namestring
// original receiver "T" or "*T"
methods
(for functions, these fields have the respective zero value)
// actual receiver "T" or "*T"
func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func
func filterFuncs(a []*Func, f Filter) []*Func
func sortedFuncs(m methodSet, allMethods bool) []*Func
func customizeRecv(f *Func, recvTypeName string, embeddedIsPtr bool, level int) *Func
func filterFuncs(a []*Func, f Filter) []*Func
A Note represents a marked comment starting with "MARKER(uid): note body".
Any note with a marker of 2 or more upper case [A-Z] letters and a uid of
at least one character is recognized. The ":" following the uid is optional.
Notes are collected in the Package.Notes map indexed by the notes marker.
// note body text
// position range of the comment containing the marker
// position range of the comment containing the marker
// uid found with the marker
func noteBodies(notes []*Note) []string
Package is the documentation for an entire package.
Deprecated: For backward compatibility Bugs is still populated,
but all new code should use Notes instead.
declarations
Docstring
Examples is a sorted list of examples associated with
the package. Examples are extracted from _test.go files
provided to NewFromFiles.
Filenames[]stringFuncs[]*FuncImportPathstringImports[]stringNamestringNotesmap[string][]*NoteTypes[]*TypeVars[]*Value
Filter eliminates documentation for names that don't pass through the filter f.
TODO(gri): Recognize "Type.Method" as a name.
func New(pkg *ast.Package, importPath string, mode Mode) *Package
func NewFromFiles(fset *token.FileSet, files []*ast.File, importPath string, opts ...any) (*Package, error)
func classifyExamples(p *Package, examples []*Example)
Type is the documentation for a type declaration.
associated declarations
// sorted list of constants of (mostly) this type
Decl*ast.GenDeclDocstring
Examples is a sorted list of examples associated with
this type. Examples are extracted from _test.go files
provided to NewFromFiles.
// sorted list of functions returning this type
// sorted list of methods (including embedded ones) of this type
Namestring
// sorted list of variables of (mostly) this type
func filterTypes(a []*Type, f Filter) []*Type
func sortedTypes(m map[string]*namedType, allMethods bool) []*Type
func filterTypes(a []*Type, f Filter) []*Type
A methodSet describes a set of methods. Entries where Decl == nil are conflict
entries (more than one method with the same name at the same embedding level).
add adds method m to the method set; m is ignored if the method set
already contains a method with the same name at the same or a higher
level than m.
set creates the corresponding Func for f and adds it to mset.
If there are multiple f's with the same name, set keeps the first
one with documentation; conflicts are ignored. The boolean
specifies whether to leave the AST untouched.
func sortedFuncs(m methodSet, allMethods bool) []*Func
A namedType represents a named unqualified (package local, or possibly
predeclared) type. The namedType for a type name is always found via
reader.lookupType.
// nil if declaration hasn't been seen yet
// doc comment for type
// true if the embedded type is a pointer
funcsmethodSet
// true if this type is embedded
// true if this type is a struct
methodsmethodSet
// type name
associated declarations
// consts and vars
func sortedTypes(m map[string]*namedType, allMethods bool) []*Type
reader accumulates documentation for a single package.
It modifies the AST: Comments (declaration documentation)
that have been collected by the reader are set to nil
in the respective AST nodes so that they are not printed
twice (once when printing the documentation and once when
printing the corresponding AST node).
package properties
// package documentation, if any
filenames[]stringfixmapmap[string][]*ast.InterfaceTypefuncsmethodSet
// if set, package contains a dot import
declarations
modeModenotesmap[string][]*Note
// sort order of const and var declarations (when we can't use a name)
support for package-local shadowing of predeclared types
typesmap[string]*namedType
// consts and vars
cleanupTypes removes the association of functions and methods with
types that have no declaration. Instead, these functions and methods
are shown at the package level. It also removes types with missing
declarations or which are not visible.
collectEmbeddedMethods collects the embedded methods of typ in mset.
computeMethodSets determines the actual method sets for each type encountered.
fileExports removes unexported declarations from src in place.
(*reader) filterDecl(decl ast.Decl) bool
filterFieldList removes unexported fields (field names) from the field list
in place and reports whether fields were removed. Anonymous fields are
recorded with the parent type. filterType is called with the types of
all remaining fields.
filterParamList applies filterType to each parameter type in fields.
(*reader) filterSpec(spec ast.Spec) bool(*reader) filterSpecList(list []ast.Spec, tok token.Token) []ast.Spec
filterType strips any unexported struct fields or method types from typ
in place. If fields (or methods) have been removed, the corresponding
struct or interface type has the Incomplete field set to true.
isPredeclared reports whether n denotes a predeclared type.
(*reader) isVisible(name string) bool
lookupType returns the base type with the given name.
If the base type has not been encountered yet, a new
type with the given name but no associated declaration
is added to the type map.
(*reader) readDoc(comment *ast.CommentGroup)
readFile adds the AST for a source file to the reader.
readFunc processes a func or method declaration.
readNote collects a single note from a sequence of comments.
readNotes extracts notes from comments.
A note must start at the beginning of a comment with "MARKER(uid):"
and is followed by the note body (e.g., "// BUG(gri): fix this").
The note ends at the end of the comment group or at the start of
another note in the same comment group, whichever comes first.
(*reader) readPackage(pkg *ast.Package, mode Mode)
readType processes a type declaration.
readValue processes a const or var declaration.
recordAnonymousField registers fieldType as the type of an
anonymous field in the parent type. If the field is imported
(qualified name) or the parent is nil, the field is ignored.
The function returns the field name.
(*reader) remember(predecl string, typ *ast.InterfaceType)
Package-Level Functions (total 56, in which 7 are exported)
Examples returns the examples found in testFiles, sorted by Name field.
The Order fields record the order in which the examples were encountered.
The Suffix field is not populated when Examples is called directly, it is
only populated by NewFromFiles for examples it finds in _test.go files.
Playable Examples must be in a package whose name ends in "_test".
An Example is "playable" (the Play field is non-nil) in either of these
circumstances:
- The example function is self-contained: the function references only
identifiers from other packages (or predeclared identifiers, such as
"int") and the test file does not include a dot import.
- The entire test file is the example: the file contains exactly one
example function, zero test, fuzz test, or benchmark function, and at
least one top-level function, type, variable, or constant declaration
other than the example function.
IsPredeclared reports whether s is a predeclared identifier.
New computes the package documentation for the given package AST.
New takes ownership of the AST pkg and may edit or overwrite it.
To have the Examples fields populated, use NewFromFiles and include
the package's _test.go files.
NewFromFiles computes documentation for a package.
The package is specified by a list of *ast.Files and corresponding
file set, which must not be nil.
NewFromFiles uses all provided files when computing documentation,
so it is the caller's responsibility to provide only the files that
match the desired build context. "go/build".Context.MatchFile can
be used for determining whether a file matches a build context with
the desired GOOS and GOARCH values, and other build constraints.
The import path of the package is specified by importPath.
Examples found in _test.go files are associated with the corresponding
type, function, method, or the package, based on their name.
If the example has a suffix in its name, it is set in the
Example.Suffix field. Examples with malformed names are skipped.
Optionally, a single extra argument of type Mode can be provided to
control low-level aspects of the documentation extraction behavior.
NewFromFiles takes ownership of the AST files and may edit them,
unless the PreserveAST Mode bit is on.
Synopsis returns a cleaned version of the first sentence in s.
That sentence ends after the first period followed by space and
not preceded by exactly one uppercase letter. The result string
has no \n, \r, or \t characters and uses only single spaces between
words. If s starts with any of the IllegalPrefixes, the result
is the empty string.
ToHTML converts comment text to formatted HTML.
The comment was prepared by DocReader,
so it is known not to have leading, trailing blank lines
nor to have trailing spaces at the end of lines.
The comment markers have already been removed.
Each span of unindented non-blank lines is converted into
a single paragraph. There is one exception to the rule: a span that
consists of a single line, is followed by another paragraph span,
begins with a capital letter, and contains no punctuation
other than parentheses and commas is formatted as a heading.
A span of indented lines is converted into a <pre> block,
with the common indent prefix removed.
URLs in the comment text are converted into links; if the URL also appears
in the words map, the link is taken from the map (if the corresponding map
value is the empty string, the URL is not converted into a link).
A pair of (consecutive) backticks (`) is converted to a unicode left quote (“), and a pair of (consecutive)
single quotes (') is converted to a unicode right quote (”).
Go identifiers that appear in the words map are italicized; if the corresponding
map value is not the empty string, it is considered a URL and the word is converted
into a link.
ToText prepares comment text for presentation in textual output.
It wraps paragraphs of text to width or fewer Unicode code points
and then prefixes each line with the indent. In preformatted sections
(such as program text), it prefixes each non-blank line with preIndent.
A pair of (consecutive) backticks (`) is converted to a unicode left quote (“), and a pair of (consecutive)
single quotes (') is converted to a unicode right quote (”).
classifyExamples classifies examples and assigns them to the Examples field
of the relevant Func, Type, or Package that the example is associated with.
The classification process is ambiguous in some cases:
- ExampleFoo_Bar matches a type named Foo_Bar
or a method named Foo.Bar.
- ExampleFoo_bar matches a type named Foo_bar
or Foo (with a "bar" suffix).
Examples with malformed names are not associated with anything.
clean replaces each sequence of space, \n, \r, or \t characters
with a single space and removes any trailing and leading spaces.
If the keepNL flag is set, newline characters are passed through
instead of being change to spaces.
Escape comment text for HTML. If nice is set,
also turn `` into “ and '' into ”.
copyConstType returns a copy of typ with position pos.
typ must be a valid constant type.
In practice, only (possibly qualified) identifiers are possible.
Emphasize and escape a line of text for HTML. URLs are converted into links;
if the URL also appears in the words map, the link is taken from the map (if
the corresponding map value is the empty string, the URL is not converted
into a link). Go identifiers that appear in the words map are italicized; if
the corresponding map value is not the empty string, it is considered a URL
and the word is converted into a link. If nice is set, the remaining text's
appearance is improved where it makes sense (e.g., `` is turned into “
and '' into ”).
Extracts the expected output and whether there was a valid output comment
fields returns a struct's fields or an interface's methods.
firstSentenceLen returns the length of the first sentence in s.
The sentence ends after the first period followed by space and
not preceded by exactly one uppercase letter.
hasExportedName reports whether list contains any exported names.
heading returns the trimmed line if it passes as a section heading;
otherwise it returns the empty string.
isTest tells whether name looks like a test, example, fuzz test, or
benchmark. It is a Test (say) if there is a character after Test that is not
a lower-case letter. (We don't want Testiness.)
lastComment returns the last comment inside the provided block.
lookupTypeParam searches for type parameters named name within the tparams
field list, returning the relevant identifier if found, or nil if not.
simpleImporter returns a (dummy) package object named by the last path
component of the provided package path (as is the convention for packages).
This is sufficient to resolve package identifiers without doing an actual
import. It never returns an error.
splitExampleName attempts to split example name s at index i,
and reports if that produces a valid split. The suffix may be
absent. Otherwise, it must start with a lower-case letter and
be preceded by '_'.
One of i == len(s) or s[i] == '_' must be true.
stripOutputComment finds and removes the "Output:" or "Unordered output:"
comment from body and comments, and adjusts the body block's end position.
Package-Level Constants (total 16, in which 3 are exported)
AllDecls says to extract documentation for all package-level
declarations, not just exported ones.
AllMethods says to show all embedded methods, not just the ones of
invisible (unexported) anonymous fields.
PreserveAST says to leave the AST unmodified. Originally, pieces of
the AST such as function bodies were nil-ed out to save memory in
godoc, but not all programs want that behavior.
host (required) e.g. www.example.com or [::1]:8080