type pkgObject struct { types.Object name string // the final path element; display name srcDir, importPath, pkgName string } func (p pkgObject) fullPath() string { return filepath.Join(p.srcDir, p.importPath) } func (p pkgObject) GetName() string { return p.name } func (p pkgObject) GetPkg() *types.Package { return nil } var ( protoPointer = types.NewTypeName(0, nil, "pointer", nil) protoArray = types.NewTypeName(0, nil, "array", nil) protoSlice = types.NewTypeName(0, nil, "slice", nil) protoMap = types.NewTypeName(0, nil, "map", nil) protoChan = types.NewTypeName(0, nil, "chan", nil) protoFunc = types.NewTypeName(0, nil, "func", nil) protoInterface = types.NewTypeName(0, nil, "interface", nil) protoStruct = types.NewTypeName(0, nil, "struct", nil) ) func newProtoType(t *types.TypeName) types.Type { switch t { case protoPointer: return &types.Pointer{} case protoArray: return &types.Array{}
func (b *browser) KeyPress(event KeyEvent) { if b.options.canFuncAsVal && event.Shift != b.funcAsVal { b.funcAsVal = event.Shift b.refresh() } switch event.Key { case KeyUp: if b.newObj == nil { b.i-- if b.i < 0 { b.i += len(b.objs) } b.refresh() } case KeyDown: if b.newObj == nil { b.i++ if b.i >= len(b.objs) { b.i -= len(b.objs) } b.refresh() } case KeyLeft: if len(b.path) > 0 && b.newObj == nil { parent := b.path[0] b.path = b.path[1:] i := len(b.pathTexts) - 1 b.pathTexts[i].Close() b.pathTexts = b.pathTexts[:i] b.clearText() b.makeCurrent(parent) } case KeyEnter: obj := b.currentObj() if obj == nil { return } if pkg, ok := obj.(*pkgObject); ok && event.Shift && b.options.mutable && b.newObj == nil { Show(b.pkgName) b.pkgName.Accept = func(name string) { if pkg.pkgName != name { pkg.pkgName = name savePackageName(pkg.importPath, name) } b.refresh() SetKeyFocus(b) } b.pkgName.Reject = func() { b.refresh() SetKeyFocus(b) } SetKeyFocus(b.pkgName) return } if event.Command && b.options.mutable && b.newObj == nil { b.newObj = obj b.oldName = obj.GetName() if p, ok := obj.(*pkgObject); ok { delete(pkgs, p.importPath) delete(pkgObjects, p.importPath) } else { if objs := obj.GetPkg().Scope().Objects; objs[obj.GetName()] == obj { delete(objs, obj.GetName()) } else { t, _ := indirect(obj.(*types.Func).Type.(*types.Signature).Recv.Type) n := t.(*types.Named) for i, f2 := range n.Methods { if f2 == obj { n.Methods = append(n.Methods[:i], n.Methods[i+1:]...) break } } } } b.text.SetText(obj.GetName()) return } if obj := b.newObj; obj != nil { if !b.unique(obj.GetName()) { return } b.newObj = nil if p, ok := obj.(*pkgObject); ok { oldImportPath := p.importPath if len(b.path) > 0 { parent := b.path[0].(*pkgObject) p.srcDir = parent.srcDir p.importPath = path.Join(parent.importPath, p.name) } else { dirs := build.Default.SrcDirs() p.srcDir = dirs[len(dirs)-1] p.importPath = p.name } pkgObjects[p.importPath] = p if b.oldName != "" { b.oldName = "" if err := refactor.MovePackage(oldImportPath, p.importPath); err != nil { fmt.Printf("error moving package %s: %s\n", oldImportPath, err) } b.clearText() return } p.pkgName = p.name path := p.fullPath() if err := os.Mkdir(path, 0777); err != nil { fmt.Printf("error creating %s: %s\n", path, err) b.clearText() return } } else { if isMethod(obj) { recv := b.path[0].(*types.TypeName).Type.(*types.Named) recv.Methods = append(recv.Methods, obj.(*types.Func)) } else { pkgs[b.path[0].(*pkgObject).importPath].Scope().Insert(obj) } if b.oldName != "" { newName := obj.GetName() setObjectName(obj, b.oldName) oldPaths := []string{fluxPath(obj)} if t, ok := obj.(*types.TypeName); ok { for _, m := range t.Type.(*types.Named).Methods { oldPaths = append(oldPaths, fluxPath(m)) } } recv := "" if isMethod(obj) { t, _ := indirect(obj.(*types.Func).Type.(*types.Signature).Recv.Type) recv = t.(*types.Named).Obj.Name } if err := refactor.Rename(obj.GetPkg().Path, recv, b.oldName, newName); err != nil { fmt.Printf("error renaming %v to %v: %v\n", b.oldName, newName, err) b.oldName = "" b.clearText() return } setObjectName(obj, newName) newPaths := []string{fluxPath(obj)} if t, ok := obj.(*types.TypeName); ok { for _, m := range t.Type.(*types.Named).Methods { newPaths = append(newPaths, fluxPath(m)) } } for i := range oldPaths { if err := os.Rename(oldPaths[i], newPaths[i]); err != nil { fmt.Println("error renaming files: ", err) } } b.oldName = "" b.clearText() return } } b.makeCurrent(obj) } _, isPkg := obj.(*pkgObject) _, isType := obj.(*types.TypeName) if !(isPkg || isType && !b.options.acceptTypes) { b.finished = true b.accepted(obj) return } fallthrough case KeyRight: if b.newObj == nil { switch obj := b.currentObj().(type) { case *pkgObject, *types.TypeName: if t, ok := obj.(*types.TypeName); ok { if _, ok = t.Type.(*types.Basic); ok || t.Type == nil || !b.options.enterTypes { break } } b.path = append(objects{obj}, b.path...) sep := "." if _, ok := obj.(*pkgObject); ok { sep = "/" } t := NewText(obj.GetName() + sep) t.SetTextColor(color(obj, true, b.funcAsVal)) t.SetBackgroundColor(Color{0, 0, 0, .7}) b.Add(t) x := 0.0 if t, ok := b.lastPathText(); ok { x = Pos(t).X + Width(t) } t.Move(Pt(x, 0)) b.pathTexts = append(b.pathTexts, t) b.clearText() } } case KeyEscape: if b.newObj != nil { if b.oldName != "" { setObjectName(b.newObj, b.oldName) b.oldName = "" if isMethod(b.newObj) { recv := b.path[0].(*types.TypeName).Type.(*types.Named) recv.Methods = append(recv.Methods, b.newObj.(*types.Func)) } else { pkgs[b.path[0].(*pkgObject).importPath].Scope().Insert(b.newObj) } } else if b.i < len(b.objs)-1 { b.i++ } b.newObj = nil b.clearText() } else { b.cancel() } case KeyBackspace: if !event.Command && len(b.text.Text()) > 0 { b.text.KeyPress(event) break } fallthrough case KeyDelete: if event.Command && b.options.mutable && b.newObj == nil { b.clearText() if deleteObj(b.currentObj()) { if b.i > 0 { b.i-- } b.clearText() } } default: if event.Command && (event.Key == KeyN || event.Key == KeyW || event.Key == KeyQ) { b.ViewBase.KeyPress(event) return } if !b.options.mutable { b.text.KeyPress(event) return } makeInPkg := false var pkg *types.Package var recv *types.TypeName if len(b.path) > 0 { switch obj := b.path[0].(type) { case *pkgObject: makeInPkg = true pkg = pkgs[obj.importPath] case *types.TypeName: recv = obj pkg = obj.Pkg } } makePkgInRoot := len(b.path) == 0 && event.Text == "1" makeMethod := recv != nil && event.Text == "3" if b.newObj == nil && event.Command && (makePkgInRoot || makeInPkg || makeMethod) { switch event.Text { case "1": b.newObj = &pkgObject{} case "2": t := types.NewTypeName(0, pkg, "", nil) t.Type = &types.Named{Obj: t} b.newObj = t case "3": sig := &types.Signature{} if recv != nil { sig.Recv = newVar("", &types.Pointer{Elem: recv.Type}) } b.newObj = types.NewFunc(0, pkg, "", sig) case "4": b.newObj = types.NewVar(0, pkg, "", nil) case "5": b.newObj = types.NewConst(0, pkg, "", nil, nil) default: b.text.KeyPress(event) return } b.clearText() } else { b.text.KeyPress(event) } } }
func (r *reader) typ(x ast.Expr) types.Type { switch x := x.(type) { case *ast.Ident: if t, ok := r.scope.LookupParent(x.Name).(*types.TypeName); ok { return t.Type } return types.NewNamed(types.NewTypeName(0, r.pkg, x.Name, nil), types.Typ[types.Invalid], nil) //unknown(t.Obj) == true case *ast.SelectorExpr: pkg := r.scope.LookupParent(name(x.X)).(*types.PkgName).Pkg if t, ok := pkg.Scope().Lookup(x.Sel.Name).(*types.TypeName); ok { return t.Type } return types.NewNamed(types.NewTypeName(0, r.pkg, x.Sel.Name, nil), types.Typ[types.Invalid], nil) //unknown(t.Obj) == true case *ast.StarExpr: return types.NewPointer(r.typ(x.X)) case *ast.ArrayType: elem := r.typ(x.Elt) if x.Len != nil { // TODO: x.Len return types.NewArray(elem, 0) } return types.NewSlice(elem) case *ast.Ellipsis: return types.NewSlice(r.typ(x.Elt)) case *ast.MapType: return types.NewMap(r.typ(x.Key), r.typ(x.Value)) case *ast.ChanType: dir := types.SendRecv if x.Dir&ast.SEND == 0 { dir = types.RecvOnly } if x.Dir&ast.RECV == 0 { dir = types.SendOnly } return types.NewChan(dir, r.typ(x.Value)) case *ast.FuncType: var params, results []*types.Var for _, f := range x.Params.List { t := r.typ(f.Type) if f.Names == nil { params = append(params, types.NewParam(0, r.pkg, "", t)) } for _, n := range f.Names { params = append(params, types.NewParam(0, r.pkg, n.Name, t)) } } variadic := false if x.Results != nil { for _, f := range x.Results.List { t := r.typ(f.Type) if f.Names == nil { results = append(results, types.NewParam(0, r.pkg, "", t)) } for _, n := range f.Names { results = append(results, types.NewParam(0, r.pkg, n.Name, t)) } _, variadic = f.Type.(*ast.Ellipsis) } } return types.NewSignature(nil, nil, params, results, variadic) case *ast.StructType: var fields []*types.Var if x.Fields != nil { for _, f := range x.Fields.List { t := r.typ(f.Type) if f.Names == nil { fields = append(fields, types.NewField(0, r.pkg, "", t, true)) } for _, n := range f.Names { fields = append(fields, types.NewField(0, r.pkg, n.Name, t, false)) } } } return types.NewStruct(fields, nil) case *ast.InterfaceType: var methods []*types.Func var embeddeds []*types.Named if x.Methods != nil { for _, f := range x.Methods.List { switch t := r.typ(f.Type).(type) { case *types.Signature: methods = append(methods, types.NewFunc(0, r.pkg, f.Names[0].Name, t)) case *types.Named: embeddeds = append(embeddeds, t) } } } return types.NewInterface(methods, embeddeds) } panic("unreachable") }