// Member looks for a member with the given name inside // the type. For packages, the member can be any exported // top level declaration inside the package. func (t Type) Member(name string, importer Importer) *ast.Object { debugp("member %v '%s' {", t, name) if t.Pkg != "" && !ast.IsExported(name) { return nil } c := make(chan *ast.Object) go func() { if !Panic { defer func() { if err := recover(); err != nil { log.Printf("panic: %v", err) c <- nil } }() } doMembers(t, name, importer, func(obj *ast.Object) { if obj.Name == name { c <- obj runtime.Goexit() } }) c <- nil }() m := <-c debugp("} -> %v", m) return m }
func done(obj *ast.Object, typ types.Type, importer types.Importer) { defer os.Exit(0) pos := types.FileSet.Position(types.DeclPos(obj)) fmt.Printf("%v\n", pos) if typ.Kind == ast.Bad || !*tflag { return } fmt.Printf("%s\n", strings.Replace(typeStr(obj, typ), "\n", "\n\t", -1)) if *aflag || *Aflag { var m orderedObjects for obj := range typ.Iter(importer) { m = append(m, obj) } sort.Sort(m) for _, obj := range m { // Ignore unexported members unless Aflag is set. if !*Aflag && (typ.Pkg != "" || !ast.IsExported(obj.Name)) { continue } id := ast.NewIdent(obj.Name) id.Obj = obj _, mt := types.ExprType(id, importer) fmt.Printf("\t%s\n", strings.Replace(typeStr(obj, mt), "\n", "\n\t\t", -1)) fmt.Printf("\t\t%v\n", types.FileSet.Position(types.DeclPos(obj))) } } }
// Iter returns a channel, sends on it // all the members of the type, then closes it. // Members at a shallower depth will be // sent first. // func (t Type) Iter(importer Importer) <-chan *ast.Object { // TODO avoid sending members with the same name twice. c := make(chan *ast.Object) go func() { internal := t.Pkg == "" doMembers(t, "", importer, func(obj *ast.Object) { if internal || ast.IsExported(obj.Name) { c <- obj } }) close(c) }() return c }
// doScope iterates through all the functions in the given scope, at // the top level only. func doScope(s *ast.Scope, name string, fn func(*ast.Object), pkg string, importer Importer) { if s == nil { return } if name != "" { if obj := s.Lookup(name); obj != nil { fn(obj) } return } for _, obj := range s.Objects { if obj.Kind == ast.Bad || pkg != "" && !ast.IsExported(obj.Name) { continue } fn(obj) } }