mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/doc: don't stop after first package if the symbol is not found
The test case is go doc rand.Float64 The first package it finds is crypto/rand, which does not have a Float64. Before this change, cmd/doc would stop there even though math/rand has the symbol. After this change, we get: % go doc rand.Float64 package rand // import "math/rand" func Float64() float64 Float64 returns, as a float64, a pseudo-random number in [0.0,1.0) from the default Source. % Another nice consequence is that if a symbol is not found, we might get a longer list of packages that were examined: % go doc rand.Int64 doc: no symbol Int64 in packages crypto/rand, math/rand exit status 1 % This change introduces a coroutine to scan the file system so that if the symbol is not found, the coroutine can deliver another path to try. (This is darned close to the original motivation for coroutines.) Paths are delivered on an unbuffered channel so the scanner does not proceed until candidate paths are needed. The scanner is attached to a new type, called Dirs, that caches the results so if we need to scan a second time, we don't walk the file system again. This is significantly more efficient than the existing code, which could scan the tree multiple times looking for a package with the symbol. Change-Id: I2789505b9992cf04c19376c51ae09af3bc305f7f Reviewed-on: https://go-review.googlesource.com/14921 Reviewed-by: Andrew Gerrand <adg@golang.org>
This commit is contained in:
parent
3f7c3e01db
commit
007fa019a3
4 changed files with 310 additions and 141 deletions
|
|
@ -16,6 +16,8 @@ import (
|
|||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
|
@ -46,6 +48,33 @@ func (p PackageError) Error() string {
|
|||
return string(p)
|
||||
}
|
||||
|
||||
// prettyPath returns a version of the package path that is suitable for an
|
||||
// error message. It obeys the import comment if present. Also, since
|
||||
// pkg.build.ImportPath is sometimes the unhelpful "" or ".", it looks for a
|
||||
// directory name in GOROOT or GOPATH if that happens.
|
||||
func (pkg *Package) prettyPath() string {
|
||||
path := pkg.build.ImportComment
|
||||
if path == "" {
|
||||
path = pkg.build.ImportPath
|
||||
}
|
||||
if path != "." && path != "" {
|
||||
return path
|
||||
}
|
||||
// Conver the source directory into a more useful path.
|
||||
path = filepath.Clean(pkg.build.Dir)
|
||||
// Can we find a decent prefix?
|
||||
goroot := filepath.Join(build.Default.GOROOT, "src")
|
||||
if strings.HasPrefix(path, goroot) {
|
||||
return path[len(goroot)+1:]
|
||||
}
|
||||
for _, gopath := range splitGopath() {
|
||||
if strings.HasPrefix(path, gopath) {
|
||||
return path[len(gopath)+1:]
|
||||
}
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// pkg.Fatalf is like log.Fatalf, but panics so it can be recovered in the
|
||||
// main do function, so it doesn't cause an exit. Allows testing to work
|
||||
// without running a subprocess. The log prefix will be added when
|
||||
|
|
@ -344,7 +373,7 @@ func (pkg *Package) findTypeSpec(decl *ast.GenDecl, symbol string) *ast.TypeSpec
|
|||
// symbolDoc prints the docs for symbol. There may be multiple matches.
|
||||
// If symbol matches a type, output includes its methods factories and associated constants.
|
||||
// If there is no top-level symbol, symbolDoc looks for methods that match.
|
||||
func (pkg *Package) symbolDoc(symbol string) {
|
||||
func (pkg *Package) symbolDoc(symbol string) bool {
|
||||
defer pkg.flush()
|
||||
found := false
|
||||
// Functions.
|
||||
|
|
@ -413,9 +442,10 @@ func (pkg *Package) symbolDoc(symbol string) {
|
|||
if !found {
|
||||
// See if there are methods.
|
||||
if !pkg.printMethodDoc("", symbol) {
|
||||
log.Printf("symbol %s not present in package %s installed in %q", symbol, pkg.name, pkg.build.ImportPath)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// trimUnexportedElems modifies spec in place to elide unexported fields from
|
||||
|
|
@ -493,11 +523,9 @@ func (pkg *Package) printMethodDoc(symbol, method string) bool {
|
|||
}
|
||||
|
||||
// methodDoc prints the docs for matches of symbol.method.
|
||||
func (pkg *Package) methodDoc(symbol, method string) {
|
||||
func (pkg *Package) methodDoc(symbol, method string) bool {
|
||||
defer pkg.flush()
|
||||
if !pkg.printMethodDoc(symbol, method) {
|
||||
pkg.Fatalf("no method %s.%s in package %s installed in %q", symbol, method, pkg.name, pkg.build.ImportPath)
|
||||
}
|
||||
return pkg.printMethodDoc(symbol, method)
|
||||
}
|
||||
|
||||
// match reports whether the user's symbol matches the program's.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue