mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/doc: implement "go doc struct.field"
By analogy with the handling of methods on types, show the documentation
for a single field of a struct.
% go doc ast.structtype.fields
struct StructType {
Fields *FieldList // list of field declarations
}
%
Fixes #19169.
Change-Id: I002f992e4aa64bee667e2e4bccc7082486149842
Reviewed-on: https://go-review.googlesource.com/38438
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
19040ac871
commit
2c47c3e22e
5 changed files with 112 additions and 29 deletions
|
|
@ -390,6 +390,29 @@ var tests = []test{
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Field.
|
||||||
|
{
|
||||||
|
"field",
|
||||||
|
[]string{p, `ExportedType.ExportedField`},
|
||||||
|
[]string{
|
||||||
|
`ExportedField int`,
|
||||||
|
`Comment before exported field.`,
|
||||||
|
`Comment on line with exported field.`,
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Field with -u.
|
||||||
|
{
|
||||||
|
"method with -u",
|
||||||
|
[]string{"-u", p, `ExportedType.unexportedField`},
|
||||||
|
[]string{
|
||||||
|
`unexportedField int`,
|
||||||
|
`Comment on line with unexported field.`,
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
|
||||||
// Case matching off.
|
// Case matching off.
|
||||||
{
|
{
|
||||||
"case matching off",
|
"case matching off",
|
||||||
|
|
|
||||||
|
|
@ -10,18 +10,18 @@
|
||||||
//
|
//
|
||||||
// One argument:
|
// One argument:
|
||||||
// go doc <pkg>
|
// go doc <pkg>
|
||||||
// go doc <sym>[.<method>]
|
// go doc <sym>[.<methodOrField>]
|
||||||
// go doc [<pkg>.]<sym>[.<method>]
|
// go doc [<pkg>.]<sym>[.<methodOrField>]
|
||||||
// go doc [<pkg>.][<sym>.]<method>
|
// go doc [<pkg>.][<sym>.]<methodOrField>
|
||||||
// The first item in this list that succeeds is the one whose documentation
|
// The first item in this list that succeeds is the one whose documentation
|
||||||
// is printed. If there is a symbol but no package, the package in the current
|
// is printed. If there is a symbol but no package, the package in the current
|
||||||
// directory is chosen. However, if the argument begins with a capital
|
// directory is chosen. However, if the argument begins with a capital
|
||||||
// letter it is always assumed to be a symbol in the current directory.
|
// letter it is always assumed to be a symbol in the current directory.
|
||||||
//
|
//
|
||||||
// Two arguments:
|
// Two arguments:
|
||||||
// go doc <pkg> <sym>[.<method>]
|
// go doc <pkg> <sym>[.<methodOrField>]
|
||||||
//
|
//
|
||||||
// Show the documentation for the package, symbol, and method. The
|
// Show the documentation for the package, symbol, and method or field. The
|
||||||
// first argument must be a full package path. This is similar to the
|
// first argument must be a full package path. This is similar to the
|
||||||
// command-line usage for the godoc command.
|
// command-line usage for the godoc command.
|
||||||
//
|
//
|
||||||
|
|
@ -129,6 +129,9 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) {
|
||||||
if pkg.methodDoc(symbol, method) {
|
if pkg.methodDoc(symbol, method) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if pkg.fieldDoc(symbol, method) {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +152,7 @@ func failMessage(paths []string, symbol, method string) error {
|
||||||
if method == "" {
|
if method == "" {
|
||||||
return fmt.Errorf("no symbol %s in package%s", symbol, &b)
|
return fmt.Errorf("no symbol %s in package%s", symbol, &b)
|
||||||
}
|
}
|
||||||
return fmt.Errorf("no method %s.%s in package%s", symbol, method, &b)
|
return fmt.Errorf("no method or field %s.%s in package%s", symbol, method, &b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseArgs analyzes the arguments (if any) and returns the package
|
// parseArgs analyzes the arguments (if any) and returns the package
|
||||||
|
|
|
||||||
|
|
@ -790,7 +790,6 @@ func (pkg *Package) printMethodDoc(symbol, method string) bool {
|
||||||
inter, ok := spec.Type.(*ast.InterfaceType)
|
inter, ok := spec.Type.(*ast.InterfaceType)
|
||||||
if !ok {
|
if !ok {
|
||||||
// Not an interface type.
|
// Not an interface type.
|
||||||
// TODO? Maybe handle struct fields here.
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, iMethod := range inter.Methods.List {
|
for _, iMethod := range inter.Methods.List {
|
||||||
|
|
@ -821,12 +820,68 @@ func (pkg *Package) printMethodDoc(symbol, method string) bool {
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// printFieldDoc prints the docs for matches of symbol.fieldName.
|
||||||
|
// It reports whether it found any field.
|
||||||
|
// Both symbol and fieldName must be non-empty or it returns false.
|
||||||
|
func (pkg *Package) printFieldDoc(symbol, fieldName string) bool {
|
||||||
|
if symbol == "" || fieldName == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer pkg.flush()
|
||||||
|
types := pkg.findTypes(symbol)
|
||||||
|
if types == nil {
|
||||||
|
pkg.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 {
|
||||||
|
// Type must be a struct.
|
||||||
|
spec := pkg.findTypeSpec(typ.Decl, typ.Name)
|
||||||
|
structType, ok := spec.Type.(*ast.StructType)
|
||||||
|
if !ok {
|
||||||
|
// Not a struct type.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, field := range structType.Fields.List {
|
||||||
|
// TODO: Anonymous fields.
|
||||||
|
for _, name := range field.Names {
|
||||||
|
if match(fieldName, name.Name) {
|
||||||
|
if !found {
|
||||||
|
pkg.Printf("struct %s {\n", typ.Name)
|
||||||
|
}
|
||||||
|
if field.Doc != nil {
|
||||||
|
for _, comment := range field.Doc.List {
|
||||||
|
doc.ToText(&pkg.buf, comment.Text, indent, indent, indentedWidth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s := pkg.oneLineNode(field.Type)
|
||||||
|
lineComment := ""
|
||||||
|
if field.Comment != nil {
|
||||||
|
lineComment = fmt.Sprintf(" %s", field.Comment.List[0].Text)
|
||||||
|
}
|
||||||
|
pkg.Printf("%s%s %s%s\n", indent, name, s, lineComment)
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
pkg.Printf("}\n")
|
||||||
|
}
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
|
||||||
// methodDoc prints the docs for matches of symbol.method.
|
// methodDoc prints the docs for matches of symbol.method.
|
||||||
func (pkg *Package) methodDoc(symbol, method string) bool {
|
func (pkg *Package) methodDoc(symbol, method string) bool {
|
||||||
defer pkg.flush()
|
defer pkg.flush()
|
||||||
return pkg.printMethodDoc(symbol, method)
|
return pkg.printMethodDoc(symbol, method)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fieldDoc prints the docs for matches of symbol.field.
|
||||||
|
func (pkg *Package) fieldDoc(symbol, field string) bool {
|
||||||
|
defer pkg.flush()
|
||||||
|
return pkg.printFieldDoc(symbol, field)
|
||||||
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
// The program string must be exported.
|
// The program string must be exported.
|
||||||
|
|
|
||||||
|
|
@ -209,12 +209,13 @@
|
||||||
//
|
//
|
||||||
// Usage:
|
// Usage:
|
||||||
//
|
//
|
||||||
// go doc [-u] [-c] [package|[package.]symbol[.method]]
|
// go doc [-u] [-c] [package|[package.]symbol[.methodOrField]]
|
||||||
//
|
//
|
||||||
// Doc prints the documentation comments associated with the item identified by its
|
// Doc prints the documentation comments associated with the item identified by its
|
||||||
// arguments (a package, const, func, type, var, or method) followed by a one-line
|
// arguments (a package, const, func, type, var, method, or struct field)
|
||||||
// summary of each of the first-level items "under" that item (package-level
|
// followed by a one-line summary of each of the first-level items "under"
|
||||||
// declarations for a package, methods for a type, etc.).
|
// that item (package-level declarations for a package, methods for a type,
|
||||||
|
// etc.).
|
||||||
//
|
//
|
||||||
// Doc accepts zero, one, or two arguments.
|
// Doc accepts zero, one, or two arguments.
|
||||||
//
|
//
|
||||||
|
|
@ -232,9 +233,9 @@
|
||||||
// which is schematically one of these:
|
// which is schematically one of these:
|
||||||
//
|
//
|
||||||
// go doc <pkg>
|
// go doc <pkg>
|
||||||
// go doc <sym>[.<method>]
|
// go doc <sym>[.<methodOrField>]
|
||||||
// go doc [<pkg>.]<sym>[.<method>]
|
// go doc [<pkg>.]<sym>[.<methodOrField>]
|
||||||
// go doc [<pkg>.][<sym>.]<method>
|
// go doc [<pkg>.][<sym>.]<methodOrField>
|
||||||
//
|
//
|
||||||
// The first item in this list matched by the argument is the one whose documentation
|
// The first item in this list matched by the argument is the one whose documentation
|
||||||
// is printed. (See the examples below.) However, if the argument starts with a capital
|
// is printed. (See the examples below.) However, if the argument starts with a capital
|
||||||
|
|
@ -254,10 +255,10 @@
|
||||||
// elements like . and ... are not implemented by go doc.
|
// elements like . and ... are not implemented by go doc.
|
||||||
//
|
//
|
||||||
// When run with two arguments, the first must be a full package path (not just a
|
// When run with two arguments, the first must be a full package path (not just a
|
||||||
// suffix), and the second is a symbol or symbol and method; this is similar to the
|
// suffix), and the second is a symbol, or symbol with method or struct field.
|
||||||
// syntax accepted by godoc:
|
// This is similar to the syntax accepted by godoc:
|
||||||
//
|
//
|
||||||
// go doc <pkg> <sym>[.<method>]
|
// go doc <pkg> <sym>[.<methodOrField>]
|
||||||
//
|
//
|
||||||
// In all forms, when matching symbols, lower-case letters in the argument match
|
// In all forms, when matching symbols, lower-case letters in the argument match
|
||||||
// either case but upper-case letters match exactly. This means that there may be
|
// either case but upper-case letters match exactly. This means that there may be
|
||||||
|
|
@ -308,7 +309,7 @@
|
||||||
// when showing the package's top-level documentation.
|
// when showing the package's top-level documentation.
|
||||||
// -u
|
// -u
|
||||||
// Show documentation for unexported as well as exported
|
// Show documentation for unexported as well as exported
|
||||||
// symbols and methods.
|
// symbols, methods, and fields.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Print Go environment information
|
// Print Go environment information
|
||||||
|
|
|
||||||
|
|
@ -12,14 +12,15 @@ import (
|
||||||
|
|
||||||
var CmdDoc = &base.Command{
|
var CmdDoc = &base.Command{
|
||||||
Run: runDoc,
|
Run: runDoc,
|
||||||
UsageLine: "doc [-u] [-c] [package|[package.]symbol[.method]]",
|
UsageLine: "doc [-u] [-c] [package|[package.]symbol[.methodOrField]]",
|
||||||
CustomFlags: true,
|
CustomFlags: true,
|
||||||
Short: "show documentation for package or symbol",
|
Short: "show documentation for package or symbol",
|
||||||
Long: `
|
Long: `
|
||||||
Doc prints the documentation comments associated with the item identified by its
|
Doc prints the documentation comments associated with the item identified by its
|
||||||
arguments (a package, const, func, type, var, or method) followed by a one-line
|
arguments (a package, const, func, type, var, method, or struct field)
|
||||||
summary of each of the first-level items "under" that item (package-level
|
followed by a one-line summary of each of the first-level items "under"
|
||||||
declarations for a package, methods for a type, etc.).
|
that item (package-level declarations for a package, methods for a type,
|
||||||
|
etc.).
|
||||||
|
|
||||||
Doc accepts zero, one, or two arguments.
|
Doc accepts zero, one, or two arguments.
|
||||||
|
|
||||||
|
|
@ -37,9 +38,9 @@ on what is installed in GOROOT and GOPATH, as well as the form of the argument,
|
||||||
which is schematically one of these:
|
which is schematically one of these:
|
||||||
|
|
||||||
go doc <pkg>
|
go doc <pkg>
|
||||||
go doc <sym>[.<method>]
|
go doc <sym>[.<methodOrField>]
|
||||||
go doc [<pkg>.]<sym>[.<method>]
|
go doc [<pkg>.]<sym>[.<methodOrField>]
|
||||||
go doc [<pkg>.][<sym>.]<method>
|
go doc [<pkg>.][<sym>.]<methodOrField>
|
||||||
|
|
||||||
The first item in this list matched by the argument is the one whose documentation
|
The first item in this list matched by the argument is the one whose documentation
|
||||||
is printed. (See the examples below.) However, if the argument starts with a capital
|
is printed. (See the examples below.) However, if the argument starts with a capital
|
||||||
|
|
@ -59,10 +60,10 @@ path. The go tool's usual package mechanism does not apply: package path
|
||||||
elements like . and ... are not implemented by go doc.
|
elements like . and ... are not implemented by go doc.
|
||||||
|
|
||||||
When run with two arguments, the first must be a full package path (not just a
|
When run with two arguments, the first must be a full package path (not just a
|
||||||
suffix), and the second is a symbol or symbol and method; this is similar to the
|
suffix), and the second is a symbol, or symbol with method or struct field.
|
||||||
syntax accepted by godoc:
|
This is similar to the syntax accepted by godoc:
|
||||||
|
|
||||||
go doc <pkg> <sym>[.<method>]
|
go doc <pkg> <sym>[.<methodOrField>]
|
||||||
|
|
||||||
In all forms, when matching symbols, lower-case letters in the argument match
|
In all forms, when matching symbols, lower-case letters in the argument match
|
||||||
either case but upper-case letters match exactly. This means that there may be
|
either case but upper-case letters match exactly. This means that there may be
|
||||||
|
|
@ -113,7 +114,7 @@ Flags:
|
||||||
when showing the package's top-level documentation.
|
when showing the package's top-level documentation.
|
||||||
-u
|
-u
|
||||||
Show documentation for unexported as well as exported
|
Show documentation for unexported as well as exported
|
||||||
symbols and methods.
|
symbols, methods, and fields.
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue