Commit f597fa67 authored by Robert Griesemer's avatar Robert Griesemer

godoc: report error for directories with multiple packages

Fixes #3922.

R=rsc, adg
CC=golang-dev
https://golang.org/cl/6453094
parent f087764a
...@@ -21,9 +21,6 @@ ...@@ -21,9 +21,6 @@
{{if $.Examples}} {{if $.Examples}}
<dd><a href="#pkg-examples">Examples</a></dd> <dd><a href="#pkg-examples">Examples</a></dd>
{{end}} {{end}}
{{if $.PList}}
<dd><a href="#pkg-other-packages">Other packages</a></dd>
{{end}}
{{if $.Dirs}} {{if $.Dirs}}
<dd><a href="#pkg-subdirectories">Subdirectories</a></dd> <dd><a href="#pkg-subdirectories">Subdirectories</a></dd>
{{end}} {{end}}
...@@ -167,16 +164,6 @@ ...@@ -167,16 +164,6 @@
<pre>{{node_html . $.FSet}}</pre> <pre>{{node_html . $.FSet}}</pre>
{{end}} {{end}}
{{with .PList}}
<h2 id="pkg-other-packages">Other packages</h2>
<p>
{{/* PList entries are strings - no need for FSet */}}
{{range .}}
<a href="?p={{urlquery .}}">{{html .}}</a><br />
{{end}}
</p>
{{end}}
{{with .Dirs}} {{with .Dirs}}
{{/* DirList entries are numbers and strings - no need for FSet */}} {{/* DirList entries are numbers and strings - no need for FSet */}}
{{if $.PDoc}} {{if $.PDoc}}
......
...@@ -65,15 +65,6 @@ BUGS ...@@ -65,15 +65,6 @@ BUGS
--------------------------------------- ---------------------------------------
*/}}{{with .PList}}
OTHER PACKAGES
{{range .}}
{{.}}{{end}}
{{end}}{{/*
---------------------------------------
*/}}{{with .Dirs}} */}}{{with .Dirs}}
SUBDIRECTORIES SUBDIRECTORIES
{{if $.DirFlat}}{{range .List}}{{if .HasPkg}} {{if $.DirFlat}}{{range .List}}{{if .HasPkg}}
......
...@@ -810,7 +810,6 @@ func remoteSearchURL(query string, html bool) string { ...@@ -810,7 +810,6 @@ func remoteSearchURL(query string, html bool) string {
type PageInfo struct { type PageInfo struct {
Dirname string // directory containing the package Dirname string // directory containing the package
PList []string // list of package names found
FSet *token.FileSet // corresponding file set FSet *token.FileSet // corresponding file set
PAst *ast.File // nil if no single AST with package exports PAst *ast.File // nil if no single AST with package exports
PDoc *doc.Package // nil if no single package documentation PDoc *doc.Package // nil if no single package documentation
...@@ -876,15 +875,14 @@ func packageExports(fset *token.FileSet, pkg *ast.Package) { ...@@ -876,15 +875,14 @@ func packageExports(fset *token.FileSet, pkg *ast.Package) {
// directories, PageInfo.Dirs is nil. If a directory read error occurred, // directories, PageInfo.Dirs is nil. If a directory read error occurred,
// PageInfo.Err is set to the respective error but the error is not logged. // PageInfo.Err is set to the respective error but the error is not logged.
// //
func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoMode) PageInfo { func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) PageInfo {
var pkgFiles []string var pkgFiles []string
// If we're showing the default package, restrict to the ones // Restrict to the package files
// that would be used when building the package on this // that would be used when building the package on this
// system. This makes sure that if there are separate // system. This makes sure that if there are separate
// implementations for, say, Windows vs Unix, we don't // implementations for, say, Windows vs Unix, we don't
// jumble them all together. // jumble them all together.
if pkgname == "" {
// Note: Uses current binary's GOOS/GOARCH. // Note: Uses current binary's GOOS/GOARCH.
// To use different pair, such as if we allowed the user // To use different pair, such as if we allowed the user
// to choose, set ctxt.GOOS and ctxt.GOARCH before // to choose, set ctxt.GOOS and ctxt.GOARCH before
...@@ -893,11 +891,9 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM ...@@ -893,11 +891,9 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM
ctxt.IsAbsPath = pathpkg.IsAbs ctxt.IsAbsPath = pathpkg.IsAbs
ctxt.ReadDir = fsReadDir ctxt.ReadDir = fsReadDir
ctxt.OpenFile = fsOpenFile ctxt.OpenFile = fsOpenFile
dir, err := ctxt.ImportDir(abspath, 0) if dir, err := ctxt.ImportDir(abspath, 0); err == nil {
if err == nil {
pkgFiles = append(dir.GoFiles, dir.CgoFiles...) pkgFiles = append(dir.GoFiles, dir.CgoFiles...)
} }
}
// filter function to select the desired .go files // filter function to select the desired .go files
filter := func(d os.FileInfo) bool { filter := func(d os.FileInfo) bool {
...@@ -917,15 +913,12 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM ...@@ -917,15 +913,12 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM
// get package ASTs // get package ASTs
fset := token.NewFileSet() fset := token.NewFileSet()
pkgs, err := parseDir(fset, abspath, filter) pkgs, err := parseDir(fset, abspath, filter)
if err != nil && pkgs == nil { if err != nil {
// only report directory read errors, ignore parse errors
// (may be able to extract partial package information)
return PageInfo{Dirname: abspath, Err: err} return PageInfo{Dirname: abspath, Err: err}
} }
// select package // select package
var pkg *ast.Package // selected package var pkg *ast.Package // selected package
var plist []string // list of other package (names), if any
if len(pkgs) == 1 { if len(pkgs) == 1 {
// Exactly one package - select it. // Exactly one package - select it.
for _, p := range pkgs { for _, p := range pkgs {
...@@ -933,49 +926,18 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM ...@@ -933,49 +926,18 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM
} }
} else if len(pkgs) > 1 { } else if len(pkgs) > 1 {
// Multiple packages - select the best matching package: The // More than one package - report an error.
// 1st choice is the package with pkgname, the 2nd choice is var buf bytes.Buffer
// 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 := pathpkg.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 = pathpkg.Split(pathpkg.Clean(dirpath))
}
var choice3 *ast.Package
loop:
for _, p := range pkgs { for _, p := range pkgs {
switch { if buf.Len() > 0 {
case p.Name == pkgname: fmt.Fprintf(&buf, ", ")
pkg = p
break loop // 1st choice; we are done
case p.Name == dirname:
pkg = p // 2nd choice
case p.Name != "main":
choice3 = p
} }
fmt.Fprintf(&buf, p.Name)
} }
if pkg == nil && len(pkgs) == 2 { return PageInfo{
pkg = choice3 Dirname: abspath,
} Err: fmt.Errorf("%s contains more than one package: %s", abspath, buf.Bytes()),
// 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]
sort.Strings(plist)
} }
// get examples from *_test.go files // get examples from *_test.go files
...@@ -1041,7 +1003,6 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM ...@@ -1041,7 +1003,6 @@ func (h *docServer) getPageInfo(abspath, relpath, pkgname string, mode PageInfoM
return PageInfo{ return PageInfo{
Dirname: abspath, Dirname: abspath,
PList: plist,
FSet: fset, FSet: fset,
PAst: past, PAst: past,
PDoc: pdoc, PDoc: pdoc,
...@@ -1065,7 +1026,7 @@ func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { ...@@ -1065,7 +1026,7 @@ func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if relpath == builtinPkgPath { if relpath == builtinPkgPath {
mode = noFiltering mode = noFiltering
} }
info := h.getPageInfo(abspath, relpath, r.FormValue("p"), mode) info := h.getPageInfo(abspath, relpath, mode)
if info.Err != nil { if info.Err != nil {
log.Print(info.Err) log.Print(info.Err)
serveError(w, r, relpath, info.Err) serveError(w, r, relpath, info.Err)
......
...@@ -373,13 +373,11 @@ func main() { ...@@ -373,13 +373,11 @@ func main() {
} }
mode |= showSource mode |= showSource
} }
// TODO(gri): Provide a mechanism (flag?) to select a package
// if there are multiple packages in a directory.
// first, try as package unless forced as command // first, try as package unless forced as command
var info PageInfo var info PageInfo
if !forceCmd { if !forceCmd {
info = pkgHandler.getPageInfo(abspath, relpath, "", mode) info = pkgHandler.getPageInfo(abspath, relpath, mode)
} }
// second, try as command unless the path is absolute // second, try as command unless the path is absolute
...@@ -387,7 +385,7 @@ func main() { ...@@ -387,7 +385,7 @@ func main() {
var cinfo PageInfo var cinfo PageInfo
if !filepath.IsAbs(path) { if !filepath.IsAbs(path) {
abspath = pathpkg.Join(cmdHandler.fsRoot, path) abspath = pathpkg.Join(cmdHandler.fsRoot, path)
cinfo = cmdHandler.getPageInfo(abspath, relpath, "", mode) cinfo = cmdHandler.getPageInfo(abspath, relpath, mode)
} }
// determine what to use // determine what to use
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment