mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/doc: print documentation for all matches in a package, not just the first
Change-Id: Id0d4ac7169f741dfeec7b1e67bdc21e49ae37b9e Reviewed-on: https://go-review.googlesource.com/9430 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
a88994c137
commit
d3bd6b6ae7
3 changed files with 62 additions and 53 deletions
|
|
@ -218,89 +218,89 @@ func (pkg *Package) typeSummary() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// findValue finds the doc.Value that describes the symbol.
|
// findValues finds the doc.Values that describe the symbol.
|
||||||
func (pkg *Package) findValue(symbol string, values []*doc.Value) *doc.Value {
|
func (pkg *Package) findValues(symbol string, docValues []*doc.Value) (values []*doc.Value) {
|
||||||
for _, value := range values {
|
for _, value := range docValues {
|
||||||
for _, name := range value.Names {
|
for _, name := range value.Names {
|
||||||
if match(symbol, name) {
|
if match(symbol, name) {
|
||||||
return value
|
values = append(values, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// findType finds the doc.Func that describes the symbol.
|
// findFuncs finds the doc.Funcs that describes the symbol.
|
||||||
func (pkg *Package) findFunc(symbol string) *doc.Func {
|
func (pkg *Package) findFuncs(symbol string) (funcs []*doc.Func) {
|
||||||
for _, fun := range pkg.doc.Funcs {
|
for _, fun := range pkg.doc.Funcs {
|
||||||
if match(symbol, fun.Name) {
|
if match(symbol, fun.Name) {
|
||||||
return fun
|
funcs = append(funcs, fun)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// findType finds the doc.Type that describes the symbol.
|
// findTypes finds the doc.Types that describes the symbol.
|
||||||
func (pkg *Package) findType(symbol string) *doc.Type {
|
func (pkg *Package) findTypes(symbol string) (types []*doc.Type) {
|
||||||
for _, typ := range pkg.doc.Types {
|
for _, typ := range pkg.doc.Types {
|
||||||
if match(symbol, typ.Name) {
|
if match(symbol, typ.Name) {
|
||||||
return typ
|
types = append(types, typ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// findTypeSpec returns the ast.TypeSpec within the declaration that defines the symbol.
|
// findTypeSpec returns the ast.TypeSpec within the declaration that defines the symbol.
|
||||||
|
// The name must match exactly.
|
||||||
func (pkg *Package) findTypeSpec(decl *ast.GenDecl, symbol string) *ast.TypeSpec {
|
func (pkg *Package) findTypeSpec(decl *ast.GenDecl, symbol string) *ast.TypeSpec {
|
||||||
for _, spec := range decl.Specs {
|
for _, spec := range decl.Specs {
|
||||||
typeSpec := spec.(*ast.TypeSpec) // Must succeed.
|
typeSpec := spec.(*ast.TypeSpec) // Must succeed.
|
||||||
if match(symbol, typeSpec.Name.Name) {
|
if symbol == typeSpec.Name.Name {
|
||||||
return typeSpec
|
return typeSpec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// symbolDoc prints the doc for symbol. If it is a type, this includes its methods,
|
// symbolDoc prints the docs for symbol. There may be multiple matches.
|
||||||
// factories (TODO) and associated constants.
|
// If symbol matches a type, output includes its methods factories and associated constants.
|
||||||
func (pkg *Package) symbolDoc(symbol string) {
|
func (pkg *Package) symbolDoc(symbol string) {
|
||||||
// TODO: resolve ambiguity in doc foo vs. doc Foo.
|
found := false
|
||||||
// Functions.
|
// Functions.
|
||||||
if fun := pkg.findFunc(symbol); fun != nil {
|
for _, fun := range pkg.findFuncs(symbol) {
|
||||||
// Symbol is a function.
|
// Symbol is a function.
|
||||||
decl := fun.Decl
|
decl := fun.Decl
|
||||||
decl.Body = nil
|
decl.Body = nil
|
||||||
pkg.emit(fun.Doc, decl)
|
pkg.emit(fun.Doc, decl)
|
||||||
return
|
found = true
|
||||||
}
|
}
|
||||||
// Constants and variables behave the same.
|
// Constants and variables behave the same.
|
||||||
value := pkg.findValue(symbol, pkg.doc.Consts)
|
values := pkg.findValues(symbol, pkg.doc.Consts)
|
||||||
if value == nil {
|
values = append(values, pkg.findValues(symbol, pkg.doc.Vars)...)
|
||||||
value = pkg.findValue(symbol, pkg.doc.Vars)
|
for _, value := range values {
|
||||||
}
|
|
||||||
if value != nil {
|
|
||||||
pkg.emit(value.Doc, value.Decl)
|
pkg.emit(value.Doc, value.Decl)
|
||||||
return
|
found = true
|
||||||
}
|
}
|
||||||
// Types.
|
// Types.
|
||||||
typ := pkg.findType(symbol)
|
for _, typ := range pkg.findTypes(symbol) {
|
||||||
if typ == nil {
|
|
||||||
log.Fatalf("symbol %s not present in package %s installed in %q", symbol, pkg.name, pkg.build.ImportPath)
|
|
||||||
}
|
|
||||||
decl := typ.Decl
|
decl := typ.Decl
|
||||||
spec := pkg.findTypeSpec(decl, symbol)
|
spec := pkg.findTypeSpec(decl, typ.Name)
|
||||||
trimUnexportedFields(spec)
|
trimUnexportedFields(spec)
|
||||||
// If there are multiple types defined, reduce to just this one.
|
// If there are multiple types defined, reduce to just this one.
|
||||||
if len(decl.Specs) > 1 {
|
if len(decl.Specs) > 1 {
|
||||||
decl.Specs = []ast.Spec{spec}
|
decl.Specs = []ast.Spec{spec}
|
||||||
}
|
}
|
||||||
pkg.emit(typ.Doc, decl)
|
pkg.emit(typ.Doc, decl)
|
||||||
// TODO: Show factory functions.
|
|
||||||
// Show associated methods, constants, etc.
|
// Show associated methods, constants, etc.
|
||||||
pkg.valueSummary(typ.Consts)
|
pkg.valueSummary(typ.Consts)
|
||||||
pkg.valueSummary(typ.Vars)
|
pkg.valueSummary(typ.Vars)
|
||||||
pkg.funcSummary(typ.Funcs)
|
pkg.funcSummary(typ.Funcs)
|
||||||
pkg.funcSummary(typ.Methods)
|
pkg.funcSummary(typ.Methods)
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
log.Fatalf("symbol %s not present in package %s installed in %q", symbol, pkg.name, pkg.build.ImportPath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// trimUnexportedFields modifies spec in place to elide unexported fields (unless
|
// trimUnexportedFields modifies spec in place to elide unexported fields (unless
|
||||||
|
|
@ -347,22 +347,27 @@ func trimUnexportedFields(spec *ast.TypeSpec) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// methodDoc prints the doc for symbol.method.
|
// methodDoc prints the docs for matches of symbol.method.
|
||||||
func (pkg *Package) methodDoc(symbol, method string) {
|
func (pkg *Package) methodDoc(symbol, method string) {
|
||||||
typ := pkg.findType(symbol)
|
types := pkg.findTypes(symbol)
|
||||||
if typ == nil {
|
if types == nil {
|
||||||
log.Fatalf("symbol %s is not a type in package %s installed in %q", symbol, pkg.name, pkg.build.ImportPath)
|
log.Fatalf("symbol %s is not a type in package %s installed in %q", symbol, pkg.name, pkg.build.ImportPath)
|
||||||
}
|
}
|
||||||
|
found := false
|
||||||
|
for _, typ := range types {
|
||||||
for _, meth := range typ.Methods {
|
for _, meth := range typ.Methods {
|
||||||
if match(method, meth.Name) {
|
if match(method, meth.Name) {
|
||||||
decl := meth.Decl
|
decl := meth.Decl
|
||||||
decl.Body = nil
|
decl.Body = nil
|
||||||
pkg.emit(meth.Doc, decl)
|
pkg.emit(meth.Doc, decl)
|
||||||
return
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
log.Fatalf("no method %s.%s in package %s installed in %q", symbol, method, pkg.name, pkg.build.ImportPath)
|
log.Fatalf("no method %s.%s in package %s installed in %q", symbol, method, pkg.name, pkg.build.ImportPath)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// match reports whether the user's symbol matches the program's.
|
// match reports whether the user's symbol matches the program's.
|
||||||
// A lower-case character in the user's string matches either case in the program's.
|
// A lower-case character in the user's string matches either case in the program's.
|
||||||
|
|
|
||||||
|
|
@ -220,7 +220,9 @@ The package paths must be either a qualified path or a proper suffix of a path
|
||||||
path elements like . and ... are not implemented by go doc.
|
path elements like . and ... are not implemented by go doc.
|
||||||
|
|
||||||
When matching symbols, lower-case letters match either case but upper-case letters
|
When matching symbols, lower-case letters match either case but upper-case letters
|
||||||
match exactly.
|
match exactly. This means that there may be multiple matches in a package if
|
||||||
|
different symbols have different cases. If this occurs, documentation for all
|
||||||
|
matches is printed.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
go doc
|
go doc
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,9 @@ The package paths must be either a qualified path or a proper suffix of a path
|
||||||
path elements like . and ... are not implemented by go doc.
|
path elements like . and ... are not implemented by go doc.
|
||||||
|
|
||||||
When matching symbols, lower-case letters match either case but upper-case letters
|
When matching symbols, lower-case letters match either case but upper-case letters
|
||||||
match exactly.
|
match exactly. This means that there may be multiple matches in a package if
|
||||||
|
different symbols have different cases. If this occurs, documentation for all
|
||||||
|
matches is printed.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
go doc
|
go doc
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue