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
diff --git a/godoc/corpus.go b/godoc/corpus.go
index af9eaee..106c6b6 100644
--- a/godoc/corpus.go
+++ b/godoc/corpus.go
@@ -38,6 +38,18 @@
// 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.
diff --git a/godoc/dirtrees.go b/godoc/dirtrees.go
index dde54de..5d35e10 100644
--- a/godoc/dirtrees.go
+++ b/godoc/dirtrees.go
@@ -70,13 +70,26 @@
}
}
+ 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,32 +99,31 @@
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)
- if err == nil {
- hasPkgFiles = true
- if file.Doc != nil {
- // prioritize documentation
- i := -1
- switch file.Name.Name {
- case name:
- i = 0 // normal case: directory name matches package name
- case "main":
- i = 1 // directory contains a main package
- default:
- i = 2 // none of the above
- }
- if 0 <= i && i < len(synopses) && synopses[i] == "" {
- synopses[i] = doc.Synopsis(file.Doc.Text())
- }
+ // no "optimal" package synopsis yet; continue to collect synopses
+ file, err := b.c.parseFile(fset, pathpkg.Join(path, d.Name()),
+ parser.ParseComments|parser.PackageClauseOnly)
+ if err == nil {
+ hasPkgFiles = true
+ if file.Doc != nil {
+ // prioritize documentation
+ i := -1
+ switch file.Name.Name {
+ case name:
+ i = 0 // normal case: directory name matches package name
+ case "main":
+ i = 1 // directory contains a main package
+ default:
+ i = 2 // none of the above
+ }
+ if 0 <= i && i < len(synopses) && synopses[i] == "" {
+ synopses[i] = doc.Synopsis(file.Doc.Text())
}
}
+ haveSummary = synopses[0] != ""
}
}
}
@@ -142,7 +154,7 @@
Depth: depth,
Path: path,
Name: name,
- HasPkg: hasPkgFiles,
+ HasPkg: hasPkgFiles && show, // TODO(bradfitz): add proper Hide field?
Synopsis: synopsis,
Dirs: dirs,
}