func objectKind(obj types.Object) string { switch obj := obj.(type) { case *types.PkgName: return "imported package name" case *types.TypeName: return "type" case *types.Var: if obj.IsField() { return "field" } case *types.Func: if obj.Type().(*types.Signature).Recv() != nil { return "method" } } // label, func, var, const return strings.ToLower(strings.TrimPrefix(reflect.TypeOf(obj).String(), "*types.")) }
func defKind(obj types.Object) string { switch obj := obj.(type) { case *types.PkgName: return definfo.Package case *types.Const: return definfo.Const case *types.TypeName: return definfo.Type case *types.Var: if obj.IsField() { return definfo.Field } return definfo.Var case *types.Func: sig := obj.Type().(*types.Signature) if sig.Recv() == nil { return definfo.Func } else { return definfo.Method } default: panic(fmt.Sprintf("unhandled obj type %T", obj)) } }
// NewDef creates a new Def. func (g *Grapher) NewDef(obj types.Object, declIdent *ast.Ident) (*Def, error) { // Find the AST node that declares this def. var declNode ast.Node _, astPath, _ := g.program.PathEnclosingInterval(declIdent.Pos(), declIdent.End()) for _, node := range astPath { switch node.(type) { case *ast.FuncDecl, *ast.GenDecl, *ast.ValueSpec, *ast.TypeSpec, *ast.Field, *ast.DeclStmt, *ast.AssignStmt: declNode = node goto found } } found: if declNode == nil { return nil, fmt.Errorf("On ident %s at %s: no DeclNode found (using PathEnclosingInterval)", declIdent.Name, g.program.Fset.Position(declIdent.Pos())) } key, info, err := g.defInfo(obj) if err != nil { return nil, err } si := definfo.DefInfo{ Exported: info.exported, PkgScope: info.pkgscope, PkgName: obj.Pkg().Name(), Kind: defKind(obj), } if typ := obj.Type(); typ != nil { si.TypeString = typ.String() if utyp := typ.Underlying(); utyp != nil { si.UnderlyingTypeString = utyp.String() } } switch obj := obj.(type) { case *types.Var: if obj.IsField() { if fieldStruct, ok := g.structFields[obj]; ok { if struct_, ok := fieldStruct.parent.(*types.Named); ok { si.FieldOfStruct = struct_.Obj().Name() } } } case *types.Func: sig := obj.Type().(*types.Signature) if recv := sig.Recv(); recv != nil && recv.Type() != nil { // omit package path; just get receiver type name si.Receiver = strings.Replace(recv.Type().String(), obj.Pkg().Path()+".", "", 1) } } return &Def{ Name: obj.Name(), DefKey: key, File: g.program.Fset.Position(declIdent.Pos()).Filename, IdentSpan: makeSpan(g.program.Fset, declIdent), DeclSpan: makeSpan(g.program.Fset, declNode), DefInfo: si, }, nil }