From 83c7b60f2745e7b0e35e762e3fc2702f59169a7b Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Thu, 14 May 2015 15:45:10 -0700 Subject: [PATCH] cmd/doc: trim unexported methods from interfaces Fixes #10856. Change-Id: I5de65b8dd94eec3451ee0ba9c75698cdd88f5fea Reviewed-on: https://go-review.googlesource.com/10088 Reviewed-by: Andrew Gerrand --- src/cmd/doc/pkg.go | 56 ++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index 835313e902..53f336ff1c 100644 --- a/src/cmd/doc/pkg.go +++ b/src/cmd/doc/pkg.go @@ -345,7 +345,7 @@ func (pkg *Package) symbolDoc(symbol string) { } decl := typ.Decl spec := pkg.findTypeSpec(decl, typ.Name) - trimUnexportedFields(spec) + trimUnexportedElems(spec) // If there are multiple types defined, reduce to just this one. if len(decl.Specs) > 1 { decl.Specs = []ast.Spec{spec} @@ -366,22 +366,26 @@ func (pkg *Package) symbolDoc(symbol string) { } } -// trimUnexportedFields modifies spec in place to elide unexported fields (unless -// the unexported flag is set). If spec is not a structure declartion, nothing happens. -func trimUnexportedFields(spec *ast.TypeSpec) { +// trimUnexportedElems modifies spec in place to elide unexported fields from +// structs and methods from interfaces (unless the unexported flag is set). +func trimUnexportedElems(spec *ast.TypeSpec) { if *unexported { - // We're printing all fields. - return + return fields } - // It must be a struct for us to care. (We show unexported methods in interfaces.) - structType, ok := spec.Type.(*ast.StructType) - if !ok { - return + switch typ := spec.Type.(type) { + case *ast.StructType: + typ.Fields = trimUnexportedFields(typ.Fields, "fields") + case *ast.InterfaceType: + typ.Methods = trimUnexportedFields(typ.Methods, "methods") } +} + +// trimUnexportedFields returns the field list trimmed of unexported fields. +func trimUnexportedFields(fields *ast.FieldList, what string) *ast.FieldList { trimmed := false - list := make([]*ast.Field, 0, len(structType.Fields.List)) - for _, field := range structType.Fields.List { - // Trims if any is unexported. Fine in practice. + list := make([]*ast.Field, 0, len(fields.List)) + for _, field := range fields.List { + // Trims if any is unexported. Good enough in practice. ok := true for _, name := range field.Names { if !isExported(name.Name) { @@ -394,19 +398,23 @@ func trimUnexportedFields(spec *ast.TypeSpec) { list = append(list, field) } } - if trimmed { - unexportedField := &ast.Field{ - Type: ast.NewIdent(""), // Hack: printer will treat this as a field with a named type. - Comment: &ast.CommentGroup{ - List: []*ast.Comment{ - &ast.Comment{ - Text: "// Has unexported fields.\n", - }, + if !trimmed { + return fields + } + unexportedField := &ast.Field{ + Type: ast.NewIdent(""), // Hack: printer will treat this as a field with a named type. + Comment: &ast.CommentGroup{ + List: []*ast.Comment{ + &ast.Comment{ + Text: fmt.Sprintf("// Has unexported %s.\n", what), }, }, - } - list = append(list, unexportedField) - structType.Fields.List = list + }, + } + return &ast.FieldList{ + Opening: fields.Opening, + List: append(list, unexportedField), + Closing: fields.Closing, } }