diff options
| author | Rob Pike <r@golang.org> | 2017-03-21 20:27:47 -0700 |
|---|---|---|
| committer | Rob Pike <r@golang.org> | 2017-03-22 05:37:50 +0000 |
| commit | 2c47c3e22e0d4f238a844da6904ce4e98bb4efd1 (patch) | |
| tree | 2eb3c3ca79ce5ca8537b43a5092e4a04b04fbf2d /src/cmd/doc | |
| parent | 19040ac871bb6873b7fa4747f0ffe479a2ce0ef9 (diff) | |
| download | go-2c47c3e22e0d4f238a844da6904ce4e98bb4efd1.tar.xz | |
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>
Diffstat (limited to 'src/cmd/doc')
| -rw-r--r-- | src/cmd/doc/doc_test.go | 23 | ||||
| -rw-r--r-- | src/cmd/doc/main.go | 15 | ||||
| -rw-r--r-- | src/cmd/doc/pkg.go | 57 |
3 files changed, 88 insertions, 7 deletions
diff --git a/src/cmd/doc/doc_test.go b/src/cmd/doc/doc_test.go index 454a0d6415..e534bfead3 100644 --- a/src/cmd/doc/doc_test.go +++ b/src/cmd/doc/doc_test.go @@ -390,6 +390,29 @@ var tests = []test{ 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", diff --git a/src/cmd/doc/main.go b/src/cmd/doc/main.go index df1890fe71..76c7dba2d9 100644 --- a/src/cmd/doc/main.go +++ b/src/cmd/doc/main.go @@ -10,18 +10,18 @@ // // One argument: // go doc <pkg> -// go doc <sym>[.<method>] -// go doc [<pkg>.]<sym>[.<method>] -// go doc [<pkg>.][<sym>.]<method> +// go doc <sym>[.<methodOrField>] +// go doc [<pkg>.]<sym>[.<methodOrField>] +// go doc [<pkg>.][<sym>.]<methodOrField> // 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 // directory is chosen. However, if the argument begins with a capital // letter it is always assumed to be a symbol in the current directory. // // 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 // 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) { return } + if pkg.fieldDoc(symbol, method) { + return + } } } } @@ -149,7 +152,7 @@ func failMessage(paths []string, symbol, method string) error { if method == "" { 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 diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index b59fcbbd03..7b0f9de775 100644 --- a/src/cmd/doc/pkg.go +++ b/src/cmd/doc/pkg.go @@ -790,7 +790,6 @@ func (pkg *Package) printMethodDoc(symbol, method string) bool { inter, ok := spec.Type.(*ast.InterfaceType) if !ok { // Not an interface type. - // TODO? Maybe handle struct fields here. continue } for _, iMethod := range inter.Methods.List { @@ -821,12 +820,68 @@ func (pkg *Package) printMethodDoc(symbol, method string) bool { 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. func (pkg *Package) methodDoc(symbol, method string) bool { defer pkg.flush() 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. // A lower-case character in the user's string matches either case in the program's. // The program string must be exported. |
