godoc: add a Corpus hook to summarize a package

This lets godoc implementations provide a more efficient means
of getting this information, without reading files and parsing the
package docs.

This is especially important when the files themselves don't
actually exist and the VFS is synthesizing them on demand
(e.g. protocol buffer files -> their generated *.pb.go files).
This means corpus.Init can run quickly, without generating
every protocol file in a large corpus (or fetching it from a
cache).

In the future, this hook could also be used for caching the summaries of
regular packages.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/19440043
This commit is contained in:
Brad Fitzpatrick 2013-10-30 11:34:32 -07:00
parent 99890b82e7
commit 766a70612a
2 changed files with 48 additions and 24 deletions

View File

@ -38,6 +38,18 @@ type Corpus struct {
// The default is 1000.
MaxResults int
// SummarizePackage optionally specifies a function to
// summarize a package. It exists as an optimization to
// avoid reading files to parse package comments.
//
// If SummarizePackage returns false for ok, the caller
// ignores all return values and parses the files in the package
// as if SummarizePackage were nil.
//
// If showList is false, the package is hidden from the
// package listing.
SummarizePackage func(pkg string) (summary string, showList, ok bool)
testDir string // TODO(bradfitz,adg): migrate old godoc flag? looks unused.
// Send a value on this channel to trigger a metadata refresh.

View File

@ -70,13 +70,26 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
}
}
var synopses [3]string // prioritized package documentation (0 == highest priority)
show := true // show in package listing
hasPkgFiles := false
haveSummary := false
if hook := b.c.SummarizePackage; hook != nil {
if summary, show0, ok := hook(strings.TrimPrefix(path, "/src/pkg/")); ok {
hasPkgFiles = true
show = show0
synopses[0] = summary
haveSummary = true
}
}
list, _ := b.c.fs.ReadDir(path)
// determine number of subdirectories and if there are package files
hasPkgFiles := false
var dirchs []chan *Directory
var synopses [3]string // prioritized package documentation (0 == highest priority)
for _, d := range list {
switch {
case isPkgDir(d):
@ -86,11 +99,10 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
name := d.Name()
ch <- b.newDirTree(fset, pathpkg.Join(path, name), name, depth+1)
}(d)
case isPkgFile(d):
case !haveSummary && isPkgFile(d):
// looks like a package file, but may just be a file ending in ".go";
// don't just count it yet (otherwise we may end up with hasPkgFiles even
// though the directory doesn't contain any real package files - was bug)
if synopses[0] == "" {
// no "optimal" package synopsis yet; continue to collect synopses
file, err := b.c.parseFile(fset, pathpkg.Join(path, d.Name()),
parser.ParseComments|parser.PackageClauseOnly)
@ -111,7 +123,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
synopses[i] = doc.Synopsis(file.Doc.Text())
}
}
}
haveSummary = synopses[0] != ""
}
}
}
@ -142,7 +154,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
Depth: depth,
Path: path,
Name: name,
HasPkg: hasPkgFiles,
HasPkg: hasPkgFiles && show, // TODO(bradfitz): add proper Hide field?
Synopsis: synopsis,
Dirs: dirs,
}