Home | History | Annotate | Download | only in doc
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package doc
      6 
      7 import "go/ast"
      8 
      9 type Filter func(string) bool
     10 
     11 func matchFields(fields *ast.FieldList, f Filter) bool {
     12 	if fields != nil {
     13 		for _, field := range fields.List {
     14 			for _, name := range field.Names {
     15 				if f(name.Name) {
     16 					return true
     17 				}
     18 			}
     19 		}
     20 	}
     21 	return false
     22 }
     23 
     24 func matchDecl(d *ast.GenDecl, f Filter) bool {
     25 	for _, d := range d.Specs {
     26 		switch v := d.(type) {
     27 		case *ast.ValueSpec:
     28 			for _, name := range v.Names {
     29 				if f(name.Name) {
     30 					return true
     31 				}
     32 			}
     33 		case *ast.TypeSpec:
     34 			if f(v.Name.Name) {
     35 				return true
     36 			}
     37 			switch t := v.Type.(type) {
     38 			case *ast.StructType:
     39 				if matchFields(t.Fields, f) {
     40 					return true
     41 				}
     42 			case *ast.InterfaceType:
     43 				if matchFields(t.Methods, f) {
     44 					return true
     45 				}
     46 			}
     47 		}
     48 	}
     49 	return false
     50 }
     51 
     52 func filterValues(a []*Value, f Filter) []*Value {
     53 	w := 0
     54 	for _, vd := range a {
     55 		if matchDecl(vd.Decl, f) {
     56 			a[w] = vd
     57 			w++
     58 		}
     59 	}
     60 	return a[0:w]
     61 }
     62 
     63 func filterFuncs(a []*Func, f Filter) []*Func {
     64 	w := 0
     65 	for _, fd := range a {
     66 		if f(fd.Name) {
     67 			a[w] = fd
     68 			w++
     69 		}
     70 	}
     71 	return a[0:w]
     72 }
     73 
     74 func filterTypes(a []*Type, f Filter) []*Type {
     75 	w := 0
     76 	for _, td := range a {
     77 		n := 0 // number of matches
     78 		if matchDecl(td.Decl, f) {
     79 			n = 1
     80 		} else {
     81 			// type name doesn't match, but we may have matching consts, vars, factories or methods
     82 			td.Consts = filterValues(td.Consts, f)
     83 			td.Vars = filterValues(td.Vars, f)
     84 			td.Funcs = filterFuncs(td.Funcs, f)
     85 			td.Methods = filterFuncs(td.Methods, f)
     86 			n += len(td.Consts) + len(td.Vars) + len(td.Funcs) + len(td.Methods)
     87 		}
     88 		if n > 0 {
     89 			a[w] = td
     90 			w++
     91 		}
     92 	}
     93 	return a[0:w]
     94 }
     95 
     96 // Filter eliminates documentation for names that don't pass through the filter f.
     97 // TODO(gri): Recognize "Type.Method" as a name.
     98 //
     99 func (p *Package) Filter(f Filter) {
    100 	p.Consts = filterValues(p.Consts, f)
    101 	p.Vars = filterValues(p.Vars, f)
    102 	p.Types = filterTypes(p.Types, f)
    103 	p.Funcs = filterFuncs(p.Funcs, f)
    104 	p.Doc = "" // don't show top-level package doc
    105 }
    106