From 2c47c3e22e0d4f238a844da6904ce4e98bb4efd1 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Tue, 21 Mar 2017 20:27:47 -0700 Subject: 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 Run-TryBot: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/cmd/doc/pkg.go | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) (limited to 'src/cmd/doc/pkg.go') 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. -- cgit v1.3-5-g9baa