mirror of
https://github.com/golang/go
synced 2024-11-22 07:04:40 -07:00
godoc: report error for directories with multiple packages
Fixes #3922. R=rsc, adg CC=golang-dev https://golang.org/cl/6453094
This commit is contained in:
parent
f087764abc
commit
f597fa67c1
@ -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 @@
|
|||||||
<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
|
|||||||
|
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
*/}}{{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 {
|
|||||||
|
|
||||||
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) {
|
|||||||
// 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
|
|||||||
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
|
|||||||
// 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
|
|||||||
}
|
}
|
||||||
|
|
||||||
} 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
|
|||||||
|
|
||||||
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) {
|
|||||||
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() {
|
|||||||
}
|
}
|
||||||
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() {
|
|||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user