func isStringer(obj types.Object) bool { switch obj := obj.(type) { case *types.Func: if obj.Name() != "String" { return false } sig, ok := obj.Type().(*types.Signature) if !ok { return false } if sig.Recv() == nil { return false } if sig.Params().Len() != 0 { return false } res := sig.Results() if res.Len() != 1 { return false } ret := res.At(0).Type() if ret != types.Universe.Lookup("string").Type() { return false } return true default: return false } return false }
func (f *Function) addParamObj(obj types.Object) *Parameter { name := obj.Name() if name == "" { name = fmt.Sprintf("arg%d", len(f.Params)) } param := f.addParam(name, obj.Type(), obj.Pos()) param.object = obj return param }
// addSpilledParam declares a parameter that is pre-spilled to the // stack; the function body will load/store the spilled location. // Subsequent lifting will eliminate spills where possible. // func (f *Function) addSpilledParam(obj types.Object) { param := f.addParamObj(obj) spill := &Alloc{Comment: obj.Name()} spill.setType(types.NewPointer(obj.Type())) spill.setPos(obj.Pos()) f.objects[obj] = spill f.Locals = append(f.Locals, spill) f.emit(spill) f.emit(&Store{Addr: spill, Val: param}) }
func formatMember(obj types.Object, maxname int) string { var buf bytes.Buffer fmt.Fprintf(&buf, "%-5s %-*s", tokenOf(obj), maxname, obj.Name()) switch obj := obj.(type) { case *types.Const: fmt.Fprintf(&buf, " %s = %s", types.TypeString(obj.Pkg(), obj.Type()), obj.Val().String()) case *types.Func: fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type())) case *types.TypeName: // Abbreviate long aggregate type names. var abbrev string switch t := obj.Type().Underlying().(type) { case *types.Interface: if t.NumMethods() > 1 { abbrev = "interface{...}" } case *types.Struct: if t.NumFields() > 1 { abbrev = "struct{...}" } } if abbrev == "" { fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type().Underlying())) } else { fmt.Fprintf(&buf, " %s", abbrev) } case *types.Var: fmt.Fprintf(&buf, " %s", types.TypeString(obj.Pkg(), obj.Type())) } return buf.String() }
func (p *exporter) obj(obj types.Object) { if trace { p.tracef("object %s {\n", obj.Name()) defer p.tracef("}\n") } switch obj := obj.(type) { case *types.Const: p.int(constTag) p.string(obj.Name()) p.typ(obj.Type()) p.value(obj.Val()) case *types.TypeName: p.int(typeTag) // name is written by corresponding named type p.typ(obj.Type().(*types.Named)) case *types.Var: p.int(varTag) p.string(obj.Name()) p.typ(obj.Type()) case *types.Func: p.int(funcTag) p.string(obj.Name()) p.typ(obj.Type()) default: panic(fmt.Sprintf("unexpected object type %T", obj)) } }
func (p *printer) printObj(obj types.Object) { p.print(obj.Name()) typ, basic := obj.Type().Underlying().(*types.Basic) if basic && typ.Info()&types.IsUntyped != 0 { // don't write untyped types } else { p.print(" ") p.writeType(p.pkg, obj.Type()) } if obj, ok := obj.(*types.Const); ok { floatFmt := basic && typ.Info()&(types.IsFloat|types.IsComplex) != 0 p.print(" = ") p.print(valString(obj.Val(), floatFmt)) } }
func newFuncFrom(p *Package, parent string, obj types.Object, sig *types.Signature) (Func, error) { haserr := false res := sig.Results() var ret types.Type switch res.Len() { case 2: if !isErrorType(res.At(1).Type()) { return Func{}, fmt.Errorf( "bind: second result value must be of type error: %s", obj, ) } haserr = true ret = res.At(0).Type() case 1: if isErrorType(res.At(0).Type()) { haserr = true ret = nil } else { ret = res.At(0).Type() } case 0: ret = nil default: return Func{}, fmt.Errorf("bind: too many results to return: %v", obj) } id := obj.Pkg().Name() + "_" + obj.Name() if parent != "" { id = obj.Pkg().Name() + "_" + parent + "_" + obj.Name() } return Func{ pkg: p, sig: newSignatureFrom(p, sig), typ: obj.Type(), name: obj.Name(), id: id, doc: p.getDoc(parent, obj), ret: ret, err: haserr, }, nil }
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 (g *Grapher) makeDefInfo(obj types.Object) (*DefKey, *defInfo, error) { switch obj := obj.(type) { case *types.Builtin: return &DefKey{"builtin", []string{obj.Name()}}, &defInfo{pkgscope: false, exported: true}, nil case *types.Nil: return &DefKey{"builtin", []string{"nil"}}, &defInfo{pkgscope: false, exported: true}, nil case *types.TypeName: if basic, ok := obj.Type().(*types.Basic); ok { return &DefKey{"builtin", []string{basic.Name()}}, &defInfo{pkgscope: false, exported: true}, nil } if obj.Name() == "error" { return &DefKey{"builtin", []string{obj.Name()}}, &defInfo{pkgscope: false, exported: true}, nil } case *types.PkgName: return &DefKey{obj.Imported().Path(), []string{}}, &defInfo{pkgscope: false, exported: true}, nil case *types.Const: var pkg string if obj.Pkg() == nil { pkg = "builtin" } else { pkg = obj.Pkg().Path() } if obj.Val().Kind() == exact.Bool && pkg == "builtin" { return &DefKey{pkg, []string{obj.Name()}}, &defInfo{pkgscope: false, exported: true}, nil } } if obj.Pkg() == nil { // builtin return &DefKey{"builtin", []string{obj.Name()}}, &defInfo{pkgscope: false, exported: true}, nil } path := g.path(obj) // Handle the case where a dir has 2 main packages that are not // intended to be compiled together and have overlapping def // paths. Prefix the def path with the filename. if obj.Pkg().Name() == "main" { p := g.program.Fset.Position(obj.Pos()) path = append([]string{filepath.Base(p.Filename)}, path...) } return &DefKey{obj.Pkg().Path(), path}, &defInfo{pkgscope: g.pkgscope[obj], exported: g.exported[obj]}, nil }
func (sym *symtab) addSymbol(obj types.Object) { fn := types.ObjectString(obj, nil) n := obj.Name() pkg := obj.Pkg() id := n if pkg != nil { id = pkg.Name() + "_" + n } switch obj.(type) { case *types.Const: sym.syms[fn] = &symbol{ gopkg: pkg, goobj: obj, kind: skConst, id: id, goname: n, cgoname: "cgo_const_" + id, cpyname: "cpy_const_" + id, } sym.addType(obj, obj.Type()) case *types.Var: sym.syms[fn] = &symbol{ gopkg: pkg, goobj: obj, kind: skVar, id: id, goname: n, cgoname: "cgo_var_" + id, cpyname: "cpy_var_" + id, } sym.addType(obj, obj.Type()) case *types.Func: sym.syms[fn] = &symbol{ gopkg: pkg, goobj: obj, kind: skFunc, id: id, goname: n, cgoname: "cgo_func_" + id, cpyname: "cpy_func_" + id, } sig := obj.Type().Underlying().(*types.Signature) sym.processTuple(sig.Params()) sym.processTuple(sig.Results()) case *types.TypeName: sym.addType(obj, obj.Type()) default: panic(fmt.Errorf("gopy: handled object [%#v]", obj)) } }
func isExported(obj types.Object) bool { // https://golang.org/ref/spec#Exported_identifiers // An identifier is exported if both: // the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and // the identifier is declared in the package block or it is a field name or method name. // All other identifiers are not exported. if !obj.Exported() { // does not start with an upper case letter return false } if v, ok := obj.(*types.Var); ok && v.IsField() { // is a field name return true } if sig, ok := obj.Type().(*types.Signature); ok && sig.Recv() != nil { // is a method name return true } // is declared in the package block return obj.Parent() == obj.Pkg().Scope() }
// memberFromObject populates package pkg with a member for the // typechecker object obj. // // For objects from Go source code, syntax is the associated syntax // tree (for funcs and vars only); it will be used during the build // phase. // func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) { name := obj.Name() switch obj := obj.(type) { case *types.TypeName: pkg.Members[name] = &Type{ object: obj, pkg: pkg, } case *types.Const: c := &NamedConst{ object: obj, Value: NewConst(obj.Val(), obj.Type()), pkg: pkg, } pkg.values[obj] = c.Value pkg.Members[name] = c case *types.Var: g := &Global{ Pkg: pkg, name: name, object: obj, typ: types.NewPointer(obj.Type()), // address pos: obj.Pos(), } pkg.values[obj] = g pkg.Members[name] = g case *types.Func: sig := obj.Type().(*types.Signature) if sig.Recv() == nil && name == "init" { pkg.ninit++ name = fmt.Sprintf("init#%d", pkg.ninit) } fn := &Function{ name: name, object: obj, Signature: sig, syntax: syntax, pos: obj.Pos(), Pkg: pkg, Prog: pkg.Prog, } if syntax == nil { fn.Synthetic = "loaded from gc object file" } pkg.values[obj] = fn if sig.Recv() == nil { pkg.Members[name] = fn // package-level function } default: // (incl. *types.Package) panic("unexpected Object type: " + obj.String()) } }
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)) } }
func getEnclosingStruct(object types.Object) types.Type { pkgScope := object.Pkg().Scope() s := pkgScope.Innermost(object.Pos()) if s.Parent() == pkgScope { s = pkgScope } var obj types.Object for _, name := range s.Names() { o := s.Lookup(name) if o.Pos() <= object.Pos() && (obj == nil || o.Pos() > obj.Pos()) { obj = o } } if obj == nil { return nil } if obj == object { return obj.Type() } t := obj.Type().Underlying().(*types.Struct) for { var f types.Object for i := 0; i < t.NumFields(); i++ { field := t.Field(i) if field == object { return t } if field.Pos() <= object.Pos() && (f == nil || field.Pos() > f.Pos()) { f = field } } if fs, ok := f.Type().(*types.Struct); ok { t = fs } else { break } } return t }
// addNamedLocal creates a local variable, adds it to function f and // returns it. Its name and type are taken from obj. Subsequent // calls to f.lookup(obj) will return the same local. // func (f *Function) addNamedLocal(obj types.Object) *Alloc { l := f.addLocal(obj.Type(), obj.Pos()) l.Comment = obj.Name() f.objects[obj] = l return l }
func (w *PkgWalker) LookupObjects(conf *PkgConfig, cursor *FileCursor) { var cursorObj types.Object var cursorSelection *types.Selection var cursorObjIsDef bool //lookup defs var pkg *types.Package var pkgInfo *types.Info if cursor.xtest { pkgInfo = conf.XInfo pkg = conf.XPkg } else { pkgInfo = conf.Info pkg = conf.Pkg } _ = cursorObjIsDef if cursorObj == nil { for sel, obj := range pkgInfo.Selections { if cursor.pos >= sel.Sel.Pos() && cursor.pos <= sel.Sel.End() { cursorObj = obj.Obj() cursorSelection = obj break } } } if cursorObj == nil { for id, obj := range pkgInfo.Defs { if cursor.pos >= id.Pos() && cursor.pos <= id.End() { cursorObj = obj cursorObjIsDef = true break } } } _ = cursorSelection if cursorObj == nil { for id, obj := range pkgInfo.Uses { if cursor.pos >= id.Pos() && cursor.pos <= id.End() { cursorObj = obj break } } } if cursorObj == nil { return } kind, err := parserObjKind(cursorObj) if err != nil { log.Fatalln(err) } if kind == ObjField { if cursorObj.(*types.Var).Anonymous() { typ := orgType(cursorObj.Type()) if named, ok := typ.(*types.Named); ok { cursorObj = named.Obj() } } } cursorPkg := cursorObj.Pkg() cursorPos := cursorObj.Pos() //var fieldTypeInfo *types.Info var fieldTypeObj types.Object // if cursorPkg == pkg { // fieldTypeInfo = pkgInfo // } cursorIsInterfaceMethod := false var cursorInterfaceTypeName string if kind == ObjMethod && cursorSelection != nil && cursorSelection.Recv() != nil { sig := cursorObj.(*types.Func).Type().Underlying().(*types.Signature) if _, ok := sig.Recv().Type().Underlying().(*types.Interface); ok { if named, ok := cursorSelection.Recv().(*types.Named); ok { obj, typ := w.lookupNamedMethod(named, cursorObj.Name()) if obj != nil { cursorObj = obj } if typ != nil { cursorPkg = typ.Obj().Pkg() cursorInterfaceTypeName = typ.Obj().Name() } cursorIsInterfaceMethod = true } } } else if kind == ObjField && cursorSelection != nil { if recv := cursorSelection.Recv(); recv != nil { typ := orgType(recv) if typ != nil { if name, ok := typ.(*types.Named); ok { fieldTypeObj = name.Obj() na := w.lookupNamedField(name, cursorObj.Name()) if na != nil { fieldTypeObj = na.Obj() } } } } } if cursorPkg != nil && cursorPkg != pkg && kind != ObjPkgName && w.isBinaryPkg(cursorPkg.Path()) { conf := &PkgConfig{ IgnoreFuncBodies: true, AllowBinary: true, WithTestFiles: true, Info: &types.Info{ Defs: make(map[*ast.Ident]types.Object), }, } pkg, _ := w.Import("", cursorPkg.Path(), conf) if pkg != nil { if cursorIsInterfaceMethod { for _, obj := range conf.Info.Defs { if obj == nil { continue } if fn, ok := obj.(*types.Func); ok { if fn.Name() == cursorObj.Name() { if sig, ok := fn.Type().Underlying().(*types.Signature); ok { if named, ok := sig.Recv().Type().(*types.Named); ok { if named.Obj() != nil && named.Obj().Name() == cursorInterfaceTypeName { cursorPos = obj.Pos() break } } } } } } } else if kind == ObjField && fieldTypeObj != nil { for _, obj := range conf.Info.Defs { if obj == nil { continue } if _, ok := obj.(*types.TypeName); ok { if IsSameObject(fieldTypeObj, obj) { if t, ok := obj.Type().Underlying().(*types.Struct); ok { for i := 0; i < t.NumFields(); i++ { if t.Field(i).Id() == cursorObj.Id() { cursorPos = t.Field(i).Pos() break } } } break } } } } else { for k, v := range conf.Info.Defs { if k != nil && v != nil && IsSameObject(v, cursorObj) { cursorPos = k.Pos() break } } } } // if kind == ObjField || cursorIsInterfaceMethod { // fieldTypeInfo = conf.Info // } } // if kind == ObjField { // fieldTypeObj = w.LookupStructFromField(fieldTypeInfo, cursorPkg, cursorObj, cursorPos) // } if typesFindDef { fmt.Println(w.fset.Position(cursorPos)) } if typesFindInfo { if kind == ObjField && fieldTypeObj != nil { typeName := fieldTypeObj.Name() if fieldTypeObj.Pkg() != nil && fieldTypeObj.Pkg() != pkg { typeName = fieldTypeObj.Pkg().Name() + "." + fieldTypeObj.Name() } fmt.Println(typeName, simpleObjInfo(cursorObj)) } else if kind == ObjBuiltin { fmt.Println(builtinInfo(cursorObj.Name())) } else if kind == ObjPkgName { fmt.Println(cursorObj.String()) } else if cursorIsInterfaceMethod { fmt.Println(strings.Replace(simpleObjInfo(cursorObj), "(interface)", cursorPkg.Name()+"."+cursorInterfaceTypeName, 1)) } else { fmt.Println(simpleObjInfo(cursorObj)) } } if typesFindDoc && typesFindDef { pos := w.fset.Position(cursorPos) file := w.parsedFileCache[pos.Filename] if file != nil { line := pos.Line var group *ast.CommentGroup for _, v := range file.Comments { lastLine := w.fset.Position(v.End()).Line if lastLine == line || lastLine == line-1 { group = v } else if lastLine > line { break } } if group != nil { fmt.Println(group.Text()) } } } if !typesFindUse { return } var usages []int if kind == ObjPkgName { for id, obj := range pkgInfo.Uses { if obj != nil && obj.Id() == cursorObj.Id() { //!= nil && cursorObj.Pos() == obj.Pos() { usages = append(usages, int(id.Pos())) } } } else { // for id, obj := range pkgInfo.Defs { // if obj == cursorObj { //!= nil && cursorObj.Pos() == obj.Pos() { // usages = append(usages, int(id.Pos())) // } // } for id, obj := range pkgInfo.Uses { if obj == cursorObj { //!= nil && cursorObj.Pos() == obj.Pos() { usages = append(usages, int(id.Pos())) } } } var pkg_path string var xpkg_path string if conf.Pkg != nil { pkg_path = conf.Pkg.Path() } if conf.XPkg != nil { xpkg_path = conf.XPkg.Path() } if cursorPkg != nil && (cursorPkg.Path() == pkg_path || cursorPkg.Path() == xpkg_path) && kind != ObjPkgName { usages = append(usages, int(cursorPos)) } (sort.IntSlice(usages)).Sort() for _, pos := range usages { fmt.Println(w.fset.Position(token.Pos(pos))) } //check look for current pkg.object on pkg_test if typesFindUseAll || IsSamePkg(cursorPkg, conf.Pkg) { var addInfo *types.Info if conf.Cursor.xtest { addInfo = conf.Info } else { addInfo = conf.XInfo } if addInfo != nil && cursorPkg != nil { var usages []int // for id, obj := range addInfo.Defs { // if id != nil && obj != nil && obj.Id() == cursorObj.Id() { // usages = append(usages, int(id.Pos())) // } // } for k, v := range addInfo.Uses { if k != nil && v != nil && IsSameObject(v, cursorObj) { usages = append(usages, int(k.Pos())) } } (sort.IntSlice(usages)).Sort() for _, pos := range usages { fmt.Println(w.fset.Position(token.Pos(pos))) } } } if !typesFindUseAll { return } if cursorPkg == nil { return } var find_def_pkg string var uses_paths []string if cursorPkg.Path() != pkg_path && cursorPkg.Path() != xpkg_path { find_def_pkg = cursorPkg.Path() uses_paths = append(uses_paths, cursorPkg.Path()) } buildutil.ForEachPackage(&build.Default, func(importPath string, err error) { if err != nil { return } if importPath == conf.Pkg.Path() { return } bp, err := w.importPath(importPath, 0) if err != nil { return } find := false if bp.ImportPath == cursorPkg.Path() { find = true } else { for _, v := range bp.Imports { if v == cursorObj.Pkg().Path() { find = true break } } } if find { for _, v := range uses_paths { if v == bp.ImportPath { return } } uses_paths = append(uses_paths, bp.ImportPath) } }) w.imported = make(map[string]*types.Package) for _, v := range uses_paths { conf := &PkgConfig{ IgnoreFuncBodies: false, AllowBinary: true, WithTestFiles: true, Info: &types.Info{ Uses: make(map[*ast.Ident]types.Object), }, XInfo: &types.Info{ Uses: make(map[*ast.Ident]types.Object), }, } w.imported[v] = nil var usages []int vpkg, _ := w.Import("", v, conf) if vpkg != nil && vpkg != pkg { if conf.Info != nil { for k, v := range conf.Info.Uses { if k != nil && v != nil && IsSameObject(v, cursorObj) { usages = append(usages, int(k.Pos())) } } } if conf.XInfo != nil { for k, v := range conf.XInfo.Uses { if k != nil && v != nil && IsSameObject(v, cursorObj) { usages = append(usages, int(k.Pos())) } } } } if v == find_def_pkg { usages = append(usages, int(cursorPos)) } (sort.IntSlice(usages)).Sort() for _, pos := range usages { fmt.Println(w.fset.Position(token.Pos(pos))) } } }
func (g *cpyGen) genStructMemberSetter(cpy Struct, i int, f types.Object) { var ( pkg = cpy.Package() ft = f.Type() self = newVar(pkg, cpy.GoType(), cpy.GoName(), "self", "") ifield = newVar(pkg, ft, f.Name(), "ret", "") cgo_fsetname = fmt.Sprintf("cgo_func_%[1]s_setter_%[2]d", cpy.sym.id, i+1) cpy_fsetname = fmt.Sprintf("cpy_func_%[1]s_setter_%[2]d", cpy.sym.id, i+1) ) g.decl.Printf("\n/* setter for %[1]s.%[2]s.%[3]s */\n", pkg.Name(), cpy.sym.goname, f.Name(), ) g.decl.Printf("static int\n") g.decl.Printf( "%[2]s(%[1]s *self, PyObject *value, void *closure);\n", cpy.sym.cpyname, cpy_fsetname, ) g.impl.Printf("\n/* setter for %[1]s.%[2]s.%[3]s */\n", pkg.Name(), cpy.sym.goname, f.Name(), ) g.impl.Printf("static int\n") g.impl.Printf( "%[2]s(%[1]s *self, PyObject *value, void *closure) {\n", cpy.sym.cpyname, cpy_fsetname, ) g.impl.Indent() ifield.genDecl(g.impl) g.impl.Printf("if (value == NULL) {\n") g.impl.Indent() g.impl.Printf( "PyErr_SetString(PyExc_TypeError, \"cannot delete '%[1]s' attribute\");\n", f.Name(), ) g.impl.Printf("return -1;\n") g.impl.Outdent() g.impl.Printf("}\n\n") g.impl.Printf("if (!%s) {\n", fmt.Sprintf(ifield.sym.pychk, "value")) g.impl.Indent() g.impl.Printf( "PyErr_SetString(PyExc_TypeError, \"invalid type for '%[1]s' attribute\");\n", f.Name(), ) g.impl.Printf("return -1;\n") g.impl.Outdent() g.impl.Printf("}\n\n") g.impl.Printf("if (!%[1]s(value, &c_ret)) {\n", ifield.sym.py2c) g.impl.Indent() g.impl.Printf("return -1;\n") g.impl.Outdent() g.impl.Printf("}\n\n") g.impl.Printf("%[1]s((%[2]s)(self->cgopy), c_%[3]s);\n", cgo_fsetname, self.CGoType(), ifield.Name(), ) g.impl.Printf("return 0;\n") g.impl.Outdent() g.impl.Printf("}\n\n") }
func (g *cpyGen) genStructMemberGetter(cpy Struct, i int, f types.Object) { pkg := cpy.Package() ft := f.Type() var ( cgo_fgetname = fmt.Sprintf("cgo_func_%[1]s_getter_%[2]d", cpy.sym.id, i+1) cpy_fgetname = fmt.Sprintf("cpy_func_%[1]s_getter_%[2]d", cpy.sym.id, i+1) ifield = newVar(pkg, ft, f.Name(), "ret", "") results = []*Var{ifield} ) if needWrapType(ft) { g.decl.Printf("\n/* wrapper for field %s.%s.%s */\n", pkg.Name(), cpy.GoName(), f.Name(), ) g.decl.Printf("typedef void* %[1]s_field_%d;\n", cpy.sym.cgoname, i+1) } g.decl.Printf("\n/* getter for %[1]s.%[2]s.%[3]s */\n", pkg.Name(), cpy.sym.goname, f.Name(), ) g.decl.Printf("static PyObject*\n") g.decl.Printf( "%[2]s(%[1]s *self, void *closure); /* %[3]s */\n", cpy.sym.cpyname, cpy_fgetname, f.Name(), ) g.impl.Printf("\n/* getter for %[1]s.%[2]s.%[3]s */\n", pkg.Name(), cpy.sym.goname, f.Name(), ) g.impl.Printf("static PyObject*\n") g.impl.Printf( "%[2]s(%[1]s *self, void *closure) /* %[3]s */ {\n", cpy.sym.cpyname, cpy_fgetname, f.Name(), ) g.impl.Indent() g.impl.Printf("PyObject *o = NULL;\n") ftname := g.pkg.syms.symtype(ft).cgoname if needWrapType(ft) { ftname = fmt.Sprintf("%[1]s_field_%d", cpy.sym.cgoname, i+1) } g.impl.Printf( "%[1]s c_ret = %[2]s(self->cgopy); /*wrap*/\n", ftname, cgo_fgetname, ) { format := []string{} funcArgs := []string{} switch len(results) { case 1: ret := results[0] ret.name = "ret" pyfmt, pyaddrs := ret.getArgBuildValue() format = append(format, pyfmt) funcArgs = append(funcArgs, pyaddrs...) default: panic("bind: impossible") } g.impl.Printf("o = Py_BuildValue(%q, %s);\n", strings.Join(format, ""), strings.Join(funcArgs, ", "), ) } g.impl.Printf("return o;\n") g.impl.Outdent() g.impl.Printf("}\n\n") }
// getDoc returns the doc string associated with types.Object // parent is the name of the containing scope ("" for global scope) func (p *Package) getDoc(parent string, o types.Object) string { n := o.Name() switch o.(type) { case *types.Const: for _, c := range p.doc.Consts { for _, cn := range c.Names { if n == cn { return c.Doc } } } case *types.Var: for _, v := range p.doc.Vars { for _, vn := range v.Names { if n == vn { return v.Doc } } } case *types.Func: doc := func() string { if o.Parent() == nil || (o.Parent() != nil && parent != "") { for _, typ := range p.doc.Types { if typ.Name != parent { continue } if o.Parent() == nil { for _, m := range typ.Methods { if m.Name == n { return m.Doc } } } else { for _, m := range typ.Funcs { if m.Name == n { return m.Doc } } } } } else { for _, f := range p.doc.Funcs { if n == f.Name { return f.Doc } } } return "" }() sig := o.Type().(*types.Signature) parseFn := func(tup *types.Tuple) []string { params := []string{} if tup == nil { return params } for i := 0; i < tup.Len(); i++ { paramVar := tup.At(i) paramType := p.syms.symtype(paramVar.Type()).pysig if paramVar.Name() != "" { paramType = fmt.Sprintf("%s %s", paramType, paramVar.Name()) } params = append(params, paramType) } return params } params := parseFn(sig.Params()) results := parseFn(sig.Results()) paramString := strings.Join(params, ", ") resultString := strings.Join(results, ", ") //FIXME(sbinet): add receiver for methods? docSig := fmt.Sprintf("%s(%s) %s", o.Name(), paramString, resultString) if doc != "" { doc = fmt.Sprintf("%s\n\n%s", docSig, doc) } else { doc = docSig } return doc case *types.TypeName: for _, t := range p.doc.Types { if n == t.Name { return t.Doc } } default: // TODO(sbinet) panic(fmt.Errorf("not yet supported: %v (%T)", o, o)) } return "" }
func (w *PkgWalker) LookupObjects(pkg *types.Package, pkgInfo *types.Info, cursor *FileCursor) { var cursorObj types.Object var cursorSelection *types.Selection var cursorObjIsDef bool //lookup defs _ = cursorObjIsDef if cursorObj == nil { for sel, obj := range pkgInfo.Selections { if cursor.pos >= sel.Sel.Pos() && cursor.pos <= sel.Sel.End() { cursorObj = obj.Obj() cursorSelection = obj break } } } if cursorObj == nil { for id, obj := range pkgInfo.Defs { if cursor.pos >= id.Pos() && cursor.pos <= id.End() { cursorObj = obj cursorObjIsDef = true break } } } _ = cursorSelection if cursorObj == nil { for id, obj := range pkgInfo.Uses { if cursor.pos >= id.Pos() && cursor.pos <= id.End() { cursorObj = obj break } } } if cursorObj == nil { return } kind, err := parserObjKind(cursorObj) if err != nil { log.Fatalln(err) } if kind == ObjField { if cursorObj.(*types.Var).Anonymous() { if named, ok := cursorObj.Type().(*types.Named); ok { cursorObj = named.Obj() } } } cursorPkg := cursorObj.Pkg() cursorPos := cursorObj.Pos() var fieldTypeInfo *types.Info var fieldTypeObj types.Object if cursorPkg == pkg { fieldTypeInfo = pkgInfo } cursorIsInterfaceMethod := false var cursorInterfaceTypeName string if kind == ObjMethod && cursorSelection != nil && cursorSelection.Recv() != nil { sig := cursorObj.(*types.Func).Type().Underlying().(*types.Signature) if _, ok := sig.Recv().Type().Underlying().(*types.Interface); ok { named := cursorSelection.Recv().(*types.Named) obj, typ := w.lookupNamedMethod(named, cursorObj.Name()) if obj != nil { cursorObj = obj } if typ != nil { cursorPkg = typ.Obj().Pkg() cursorInterfaceTypeName = typ.Obj().Name() } cursorIsInterfaceMethod = true } } if cursorPkg != nil && cursorPkg != pkg && kind != ObjPkgName && w.isBinaryPkg(cursorPkg.Path()) { conf := &PkgConfig{ IgnoreFuncBodies: true, AllowBinary: true, WithTestFiles: true, Info: &types.Info{ Defs: make(map[*ast.Ident]types.Object), }, } pkg, _ := w.Import("", cursorPkg.Path(), conf) if pkg != nil { if cursorIsInterfaceMethod { for _, obj := range conf.Info.Defs { if obj == nil { continue } if fn, ok := obj.(*types.Func); ok { if fn.Name() == cursorObj.Name() { if sig, ok := fn.Type().Underlying().(*types.Signature); ok { if named, ok := sig.Recv().Type().(*types.Named); ok { if named.Obj() != nil && named.Obj().Name() == cursorInterfaceTypeName { cursorPos = obj.Pos() break } } } } } } } else { for _, obj := range conf.Info.Defs { if obj != nil && obj.String() == cursorObj.String() { cursorPos = obj.Pos() break } } } } if kind == ObjField || cursorIsInterfaceMethod { fieldTypeInfo = conf.Info } } if kind == ObjField { fieldTypeObj = w.LookupStructFromField(fieldTypeInfo, cursorPkg, cursorObj, cursorPos) } if typeFindDef { fmt.Println(w.fset.Position(cursorPos)) } if typeFindInfo { if kind == ObjField && fieldTypeObj != nil { typeName := fieldTypeObj.Name() if fieldTypeObj.Pkg() != nil && fieldTypeObj.Pkg() != pkg { typeName = fieldTypeObj.Pkg().Name() + "." + fieldTypeObj.Name() } fmt.Println(typeName, simpleType(cursorObj.String())) } else if kind == ObjBuiltin { fmt.Println(builtinInfo(cursorObj.Name())) } else if kind == ObjPkgName { fmt.Println(cursorObj.String()) } else if cursorIsInterfaceMethod { fmt.Println(strings.Replace(simpleType(cursorObj.String()), "(interface)", cursorPkg.Name()+"."+cursorInterfaceTypeName, 1)) } else { fmt.Println(simpleType(cursorObj.String())) } } //if f, ok := w.parsedFileCache[w.fset.Position(cursorPos).Filename]; ok { // for _, d := range f.Decls { // if inRange(d, cursorPos) { // if fd, ok := d.(*ast.FuncDecl); ok { // fd.Body = nil // } // commentMap := ast.NewCommentMap(w.fset, f, f.Comments) // commentedNode := printer.CommentedNode{Node: d} // if comments := commentMap.Filter(d).Comments(); comments != nil { // commentedNode.Comments = comments // } // var b bytes.Buffer // printer.Fprint(&b, w.fset, &commentedNode) // b.Write([]byte("\n\n")) // Add a blank line between entries if we print documentation. // log.Println(w.nodeString(d)) // } // } //} if !typeFindUse { return } var usages []int if kind == ObjPkgName { for id, obj := range pkgInfo.Uses { if obj != nil && obj.Id() == cursorObj.Id() { //!= nil && cursorObj.Pos() == obj.Pos() { usages = append(usages, int(id.Pos())) } } } else { for id, obj := range pkgInfo.Defs { if obj == cursorObj { //!= nil && cursorObj.Pos() == obj.Pos() { usages = append(usages, int(id.Pos())) } } for id, obj := range pkgInfo.Uses { if obj == cursorObj { //!= nil && cursorObj.Pos() == obj.Pos() { usages = append(usages, int(id.Pos())) } } } (sort.IntSlice(usages)).Sort() for _, pos := range usages { fmt.Println(w.fset.Position(token.Pos(pos))) } }
// 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 }