예제 #1
0
파일: reader.go 프로젝트: gordonklaus/flux
func (r *reader) value(b *block, x, y ast.Expr, set bool, s ast.Stmt) {
	if x2, ok := x.(*ast.UnaryExpr); ok {
		x = x2.X
	}
	var obj types.Object
	if _, ok := x.(*ast.StarExpr); !ok { // StarExpr indicates an assignment (*x = y), for which obj must be nil
		obj = r.obj(x)
		if u, ok := obj.(unknownObject); ok {
			if _, ok := s.(*ast.DeclStmt); ok {
				obj = types.NewConst(0, u.pkg, u.name, nil, nil)
			} else {
				var t types.Type
				if set {
					t = r.scope.Lookup(name(y)).(*types.Var).Type
				}
				addr := false
				if s, ok := s.(*ast.AssignStmt); ok {
					if s.Tok == token.DEFINE {
						_, addr = s.Rhs[0].(*ast.UnaryExpr)
					}
				}
				if u.recv != nil {
					obj = field{types.NewVar(0, u.pkg, u.name, t), u.recv, addr} // it may be a method val, but a non-addressable field is close enough
				} else {
					if addr {
						obj = types.NewVar(0, u.pkg, u.name, t)
					} else {
						obj = types.NewFunc(0, u.pkg, u.name, types.NewSignature(nil, newVar("", u.recv), nil, nil, false))
					}
				}
			}
			//unknown(obj) == true
		}
	}
	n := newValueNode(obj, r.pkg, set)
	b.addNode(n)
	switch x := x.(type) {
	case *ast.SelectorExpr:
		r.in(x.X, n.x)
	case *ast.StarExpr:
		r.in(x.X, n.x)
	}
	if set {
		r.in(y, n.y)
	} else {
		r.out(y, n.y)
	}
	r.seq(n, s)
}
예제 #2
0
파일: browser.go 프로젝트: gordonklaus/flux
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)
		}
	}
}