func IsSameObject(a, b types.Object) bool { if a == b { return true } if a == nil || b == nil { return false } var apath string var bpath string if a.Pkg() != nil { apath = a.Pkg().Path() } if b.Pkg() != nil { bpath = b.Pkg().Path() } if apath != bpath { return false } if a.Id() != b.Id() { return false } return a.String() == b.String() }
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 (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))) } }