mirror of
https://github.com/golang/go
synced 2024-11-21 20:14:52 -07:00
godoc: support for multiple packages in a directory
- smartly select the "right" package - provide a list of other packages R=rsc CC=golang-dev https://golang.org/cl/466042
This commit is contained in:
parent
1a5cd2c0e1
commit
226c2ec256
@ -80,6 +80,14 @@
|
|||||||
{.end}
|
{.end}
|
||||||
{.end}
|
{.end}
|
||||||
{.end}
|
{.end}
|
||||||
|
{.section PList}
|
||||||
|
<h2>Other packages</h2>
|
||||||
|
<p>
|
||||||
|
{.repeated section @}
|
||||||
|
<a href="?p={@|html}">{@|html}</a><br />
|
||||||
|
{.end}
|
||||||
|
</p>
|
||||||
|
{.end}
|
||||||
{.section Dirs}
|
{.section Dirs}
|
||||||
<h2 id="Subdirectories">Subdirectories</h2>
|
<h2 id="Subdirectories">Subdirectories</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -75,6 +75,14 @@ BUGS
|
|||||||
{.end}
|
{.end}
|
||||||
{.end}
|
{.end}
|
||||||
{.end}
|
{.end}
|
||||||
|
{.section PList}
|
||||||
|
|
||||||
|
OTHER PACKAGES
|
||||||
|
|
||||||
|
{.repeated section @}
|
||||||
|
{@}
|
||||||
|
{.end}
|
||||||
|
{.end}
|
||||||
{.section Dirs}
|
{.section Dirs}
|
||||||
{.section Dirs}
|
{.section Dirs}
|
||||||
|
|
||||||
|
@ -1087,8 +1087,9 @@ const fakePkgName = "documentation"
|
|||||||
|
|
||||||
type PageInfo struct {
|
type PageInfo struct {
|
||||||
Dirname string // directory containing the package
|
Dirname string // directory containing the package
|
||||||
PAst *ast.File // nil if no AST with package exports
|
PList []string // list of package names found
|
||||||
PDoc *doc.PackageDoc // nil if no package documentation
|
PAst *ast.File // nil if no single AST with package exports
|
||||||
|
PDoc *doc.PackageDoc // nil if no single package documentation
|
||||||
Dirs *DirList // nil if no directory information
|
Dirs *DirList // nil if no directory information
|
||||||
IsPkg bool // false if this is not documenting a real package
|
IsPkg bool // false if this is not documenting a real package
|
||||||
}
|
}
|
||||||
@ -1101,7 +1102,7 @@ type httpHandler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// getPageInfo returns the PageInfo for a package directory dirname. If the
|
// getPageInfo returns the PageInfo for a package directory abspath. If the
|
||||||
// parameter genAST is set, an AST containing only the package exports is
|
// parameter genAST is set, an AST containing only the package exports is
|
||||||
// computed (PageInfo.PAst), otherwise package documentation (PageInfo.Doc)
|
// computed (PageInfo.PAst), otherwise package documentation (PageInfo.Doc)
|
||||||
// is extracted from the AST. If the parameter try is set, no errors are
|
// is extracted from the AST. If the parameter try is set, no errors are
|
||||||
@ -1109,7 +1110,7 @@ type httpHandler struct {
|
|||||||
// directory, PageInfo.PDoc and PageInfo.PExp are nil. If there are no sub-
|
// directory, PageInfo.PDoc and PageInfo.PExp are nil. If there are no sub-
|
||||||
// directories, PageInfo.Dirs is nil.
|
// directories, PageInfo.Dirs is nil.
|
||||||
//
|
//
|
||||||
func (h *httpHandler) getPageInfo(dirname, relpath string, genAST, try bool) PageInfo {
|
func (h *httpHandler) getPageInfo(abspath, relpath, pkgname string, genAST, try bool) PageInfo {
|
||||||
// filter function to select the desired .go files
|
// filter function to select the desired .go files
|
||||||
filter := func(d *os.Dir) bool {
|
filter := func(d *os.Dir) bool {
|
||||||
// If we are looking at cmd documentation, only accept
|
// If we are looking at cmd documentation, only accept
|
||||||
@ -1118,30 +1119,64 @@ func (h *httpHandler) getPageInfo(dirname, relpath string, genAST, try bool) Pag
|
|||||||
}
|
}
|
||||||
|
|
||||||
// get package ASTs
|
// get package ASTs
|
||||||
pkgs, err := parser.ParseDir(dirname, filter, parser.ParseComments)
|
pkgs, err := parser.ParseDir(abspath, filter, parser.ParseComments)
|
||||||
if err != nil && !try {
|
if err != nil && !try {
|
||||||
// TODO: errors should be shown instead of an empty directory
|
// TODO: errors should be shown instead of an empty directory
|
||||||
log.Stderrf("parser.parseDir: %s", err)
|
log.Stderrf("parser.parseDir: %s", err)
|
||||||
}
|
}
|
||||||
if len(pkgs) != 1 && !try {
|
|
||||||
// TODO: should handle multiple packages,
|
|
||||||
// error reporting disabled for now
|
|
||||||
// log.Stderrf("parser.parseDir: found %d packages", len(pkgs))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the best matching package: either the first one, or the
|
// select package
|
||||||
// first one whose package name matches the directory name.
|
var pkg *ast.Package // selected package
|
||||||
// The package name is the directory name within its parent.
|
var plist []string // list of other package (names), if any
|
||||||
_, pkgname := pathutil.Split(dirname)
|
if len(pkgs) == 1 {
|
||||||
var pkg *ast.Package
|
// Exactly one package - select it.
|
||||||
for _, p := range pkgs {
|
for _, p := range pkgs {
|
||||||
switch {
|
|
||||||
case pkg == nil:
|
|
||||||
pkg = p
|
pkg = p
|
||||||
case p.Name == pkgname:
|
|
||||||
pkg = p
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if len(pkgs) > 1 {
|
||||||
|
// Multiple packages - select the best matching package: The
|
||||||
|
// 1st choice is the package with pkgname, the 2nd choice is
|
||||||
|
// the package with dirname, and the 3rd choice is a package
|
||||||
|
// that is not called "main" if there is exactly one such
|
||||||
|
// package. Otherwise, don't select a package.
|
||||||
|
dirpath, dirname := pathutil.Split(abspath)
|
||||||
|
|
||||||
|
// If the dirname is "go" we might be in a sub-directory for
|
||||||
|
// .go files - use the outer directory name instead for better
|
||||||
|
// results.
|
||||||
|
if dirname == "go" {
|
||||||
|
_, dirname = pathutil.Split(pathutil.Clean(dirpath))
|
||||||
|
}
|
||||||
|
|
||||||
|
var choice3 *ast.Package
|
||||||
|
loop:
|
||||||
|
for _, p := range pkgs {
|
||||||
|
switch {
|
||||||
|
case p.Name == pkgname:
|
||||||
|
pkg = p
|
||||||
|
break loop // 1st choice; we are done
|
||||||
|
case p.Name == dirname:
|
||||||
|
pkg = p // 2nd choice
|
||||||
|
case p.Name != "main":
|
||||||
|
choice3 = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if pkg == nil && len(pkgs) == 2 {
|
||||||
|
pkg = choice3
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the list of other packages
|
||||||
|
// (excluding the selected package, if any).
|
||||||
|
plist = make([]string, len(pkgs))
|
||||||
|
i := 0
|
||||||
|
for name, _ := range pkgs {
|
||||||
|
if pkg == nil || name != pkg.Name {
|
||||||
|
plist[i] = name
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plist = plist[0:i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute package documentation
|
// compute package documentation
|
||||||
@ -1163,16 +1198,16 @@ func (h *httpHandler) getPageInfo(dirname, relpath string, genAST, try bool) Pag
|
|||||||
// (may still fail if the file system was updated and the
|
// (may still fail if the file system was updated and the
|
||||||
// new directory tree has not yet been computed)
|
// new directory tree has not yet been computed)
|
||||||
// TODO(gri) Need to build directory tree for fsMap entries
|
// TODO(gri) Need to build directory tree for fsMap entries
|
||||||
dir = tree.(*Directory).lookup(dirname)
|
dir = tree.(*Directory).lookup(abspath)
|
||||||
}
|
}
|
||||||
if dir == nil {
|
if dir == nil {
|
||||||
// no directory tree present (either early after startup
|
// no directory tree present (either early after startup
|
||||||
// or command-line mode, or we don't build a tree for the
|
// or command-line mode, or we don't build a tree for the
|
||||||
// directory; e.g. google3); compute one level for this page
|
// directory; e.g. google3); compute one level for this page
|
||||||
dir = newDirectory(dirname, 1)
|
dir = newDirectory(abspath, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return PageInfo{dirname, past, pdoc, dir.listing(true), h.isPkg}
|
return PageInfo{abspath, plist, past, pdoc, dir.listing(true), h.isPkg}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1183,7 +1218,7 @@ func (h *httpHandler) ServeHTTP(c *http.Conn, r *http.Request) {
|
|||||||
|
|
||||||
relpath := r.URL.Path[len(h.pattern):]
|
relpath := r.URL.Path[len(h.pattern):]
|
||||||
abspath := absolutePath(relpath, h.fsRoot)
|
abspath := absolutePath(relpath, h.fsRoot)
|
||||||
info := h.getPageInfo(abspath, relpath, r.FormValue("m") == "src", false)
|
info := h.getPageInfo(abspath, relpath, r.FormValue("p"), r.FormValue("m") == "src", false)
|
||||||
|
|
||||||
if r.FormValue("f") == "text" {
|
if r.FormValue("f") == "text" {
|
||||||
contents := applyTemplate(packageText, "packageText", info)
|
contents := applyTemplate(packageText, "packageText", info)
|
||||||
|
@ -241,14 +241,16 @@ func main() {
|
|||||||
relpath = relativePath(path)
|
relpath = relativePath(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
info := pkgHandler.getPageInfo(abspath, relpath, *genAST, true)
|
// TODO(gri): Provide a mechanism (flag?) to select a package
|
||||||
|
// if there are multiple packages in a directory.
|
||||||
|
info := pkgHandler.getPageInfo(abspath, relpath, "", *genAST, true)
|
||||||
|
|
||||||
if info.PAst == nil && info.PDoc == nil && info.Dirs == nil {
|
if info.PAst == nil && info.PDoc == nil && info.Dirs == nil {
|
||||||
// try again, this time assume it's a command
|
// try again, this time assume it's a command
|
||||||
if len(path) > 0 && path[0] != '/' {
|
if len(path) > 0 && path[0] != '/' {
|
||||||
abspath = absolutePath(path, cmdHandler.fsRoot)
|
abspath = absolutePath(path, cmdHandler.fsRoot)
|
||||||
}
|
}
|
||||||
info = cmdHandler.getPageInfo(abspath, relpath, false, false)
|
info = cmdHandler.getPageInfo(abspath, relpath, "", false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
if info.PDoc != nil && flag.NArg() > 1 {
|
if info.PDoc != nil && flag.NArg() > 1 {
|
||||||
|
Loading…
Reference in New Issue
Block a user