}
+func filterFieldList(list []*Field, f Filter) []*Field {
+ j := 0
+ for _, field := range list {
+ field.Names = filterIdentList(field.Names, f)
+ if len(field.Names) > 0 {
+ list[j] = field
+ j++
+ }
+ }
+ return list[0:j]
+}
+
+
+func filterFields(fields *FieldList, f Filter) bool {
+ if fields == nil {
+ return false
+ }
+ fields.List = filterFieldList(fields.List, f)
+ return len(fields.List) > 0
+}
+
+
func filterSpec(spec Spec, f Filter) bool {
switch s := spec.(type) {
case *ValueSpec:
s.Names = filterIdentList(s.Names, f)
return len(s.Names) > 0
case *TypeSpec:
- return f(s.Name.Name)
+ if f(s.Name.Name) {
+ return true
+ }
+ switch t := s.Type.(type) {
+ case *StructType:
+ return filterFields(t.Fields, f)
+ case *InterfaceType:
+ return filterFields(t.Methods, f)
+ }
}
return false
}
}
-func filterDecl(decl Decl, f Filter) bool {
+// FilterDecl trims the AST for a Go declaration in place by removing
+// all names (including struct field and interface method names, but
+// not from parameter lists) that don't pass through the filter f.
+//
+// FilterDecl returns true if there are any declared names left after
+// filtering; it returns false otherwise.
+//
+func FilterDecl(decl Decl, f Filter) bool {
switch d := decl.(type) {
case *GenDecl:
d.Specs = filterSpecList(d.Specs, f)
// FilterFile trims the AST for a Go file in place by removing all
-// names from top-level declarations (but not from parameter lists
-// or inside types) that don't pass through the filter f. If the
-// declaration is empty afterwards, the declaration is removed from
-// the AST.
+// names from top-level declarations (including struct field and
+// interface method names, but not from parameter lists) that don't
+// pass through the filter f. If the declaration is empty afterwards,
+// the declaration is removed from the AST.
// The File.comments list is not changed.
//
// FilterFile returns true if there are any top-level declarations
func FilterFile(src *File, f Filter) bool {
j := 0
for _, d := range src.Decls {
- if filterDecl(d, f) {
+ if FilterDecl(d, f) {
src.Decls[j] = d
j++
}
// FilterPackage trims the AST for a Go package in place by removing all
-// names from top-level declarations (but not from parameter lists
-// or inside types) that don't pass through the filter f. If the
-// declaration is empty afterwards, the declaration is removed from
-// the AST.
+// names from top-level declarations (including struct field and
+// interface method names, but not from parameter lists) that don't
+// pass through the filter f. If the declaration is empty afterwards,
+// the declaration is removed from the AST.
// The pkg.Files list is not changed, so that file names and top-level
// package comments don't get lost.
//
// ----------------------------------------------------------------------------
// Filtering by name
-type Filter func(string) bool
-
-
-func matchDecl(d *ast.GenDecl, f Filter) bool {
- for _, d := range d.Specs {
- switch v := d.(type) {
- case *ast.ValueSpec:
- for _, name := range v.Names {
- if f(name.Name) {
- return true
- }
- }
- case *ast.TypeSpec:
- if f(v.Name.Name) {
- return true
- }
- }
- }
- return false
-}
-
-
-func filterValueDocs(a []*ValueDoc, f Filter) []*ValueDoc {
+func filterValueDocs(a []*ValueDoc, f ast.Filter) []*ValueDoc {
w := 0
for _, vd := range a {
- if matchDecl(vd.Decl, f) {
+ if ast.FilterDecl(vd.Decl, f) {
a[w] = vd
w++
}
}
-func filterFuncDocs(a []*FuncDoc, f Filter) []*FuncDoc {
+func filterFuncDocs(a []*FuncDoc, f ast.Filter) []*FuncDoc {
w := 0
for _, fd := range a {
if f(fd.Name) {
}
-func filterTypeDocs(a []*TypeDoc, f Filter) []*TypeDoc {
+func filterTypeDocs(a []*TypeDoc, f ast.Filter) []*TypeDoc {
w := 0
for _, td := range a {
n := 0 // number of matches
- if matchDecl(td.Decl, f) {
+ if ast.FilterDecl(td.Decl, f) {
n = 1
} else {
// type name doesn't match, but we may have matching consts, vars, factories or methods
// Filter eliminates documentation for names that don't pass through the filter f.
// TODO: Recognize "Type.Method" as a name.
//
-func (p *PackageDoc) Filter(f Filter) {
+func (p *PackageDoc) Filter(f ast.Filter) {
p.Consts = filterValueDocs(p.Consts, f)
p.Vars = filterValueDocs(p.Vars, f)
p.Types = filterTypeDocs(p.Types, f)