// filterIdentList removes unexported names from list in place // and returns the resulting list. // func filterIdentList(list []*ast.Ident) []*ast.Ident { j := 0 for _, x := range list { if ast.IsExported(x.Name) { list[j] = x j++ } } return list[0:j] }
func (r *reader) filterDecl(decl ast.Decl) bool { switch d := decl.(type) { case *ast.GenDecl: d.Specs = r.filterSpecList(d.Specs) return len(d.Specs) > 0 case *ast.FuncDecl: // ok to filter these methods early because any // conflicting method will be filtered here, too - // thus, removing these methods early will not lead // to the false removal of possible conflicts return ast.IsExported(d.Name.Name) } return false }
// filterFieldList removes unexported fields (field names) from the field list // in place and returns true if fields were removed. Anonymous fields are // recorded with the parent type. filterType is called with the types of // all remaining fields. // func (r *reader) filterFieldList(parent *namedType, fields *ast.FieldList, ityp *ast.InterfaceType) (removedFields bool) { if fields == nil { return } list := fields.List j := 0 for _, field := range list { keepField := false if n := len(field.Names); n == 0 { // anonymous field fname := r.recordAnonymousField(parent, field.Type) if ast.IsExported(fname) { keepField = true } else if ityp != nil && fname == "error" { // possibly the predeclared error interface; keep // it for now but remember this interface so that // it can be fixed if error is also defined locally keepField = true r.remember(ityp) } } else { field.Names = filterIdentList(field.Names) if len(field.Names) < n { removedFields = true } if len(field.Names) > 0 { keepField = true } } if keepField { r.filterType(nil, field.Type) list[j] = field j++ } } if j < len(list) { removedFields = true } fields.List = list[0:j] return }
func (r *reader) filterSpec(spec ast.Spec) bool { switch s := spec.(type) { case *ast.ImportSpec: // always keep imports so we can collect them return true case *ast.ValueSpec: s.Names = filterIdentList(s.Names) if len(s.Names) > 0 { r.filterType(nil, s.Type) return true } case *ast.TypeSpec: if name := s.Name.Name; ast.IsExported(name) { r.filterType(r.lookupType(s.Name.Name), s.Type) return true } else if name == "error" { // special case: remember that error is declared locally r.errorDecl = true } } return false }