func loadFunc(obj types.Object) *funcNode { f := newFuncNode(obj, nil) fset := token.NewFileSet() file, err := parser.ParseFile(fset, fluxPath(obj), nil, parser.ParseComments) if err == nil { r := &reader{fset, obj.GetPkg(), types.NewScope(obj.GetPkg().Scope()), map[string]*port{}, map[string][]*connection{}, ast.NewCommentMap(fset, file, file.Comments), map[int]node{}} for _, i := range file.Imports { path, _ := strconv.Unquote(i.Path.Value) pkg, err := getPackage(path) if err != nil { fmt.Printf("error importing %s: %s\n", i.Path.Value, err) continue } name := pkg.Name if i.Name != nil { name = i.Name.Name } r.scope.Insert(types.NewPkgName(0, pkg, name)) } decl := file.Decls[len(file.Decls)-1].(*ast.FuncDecl) // get param and result var names from the source, as the obj names might not match if decl.Recv != nil { r.out(decl.Recv.List[0].Names[0], f.inputsNode.newOutput(obj.GetType().(*types.Signature).Recv)) } r.fun(f, decl.Type, decl.Body) } else { // this is a new func; save it if isMethod(obj) { f.inputsNode.newOutput(obj.GetType().(*types.Signature).Recv) } saveFunc(f) } return f }
func isMakeableType(obj types.Object) bool { switch obj { case protoSlice, protoMap, protoChan: return true } if obj, ok := obj.(*types.TypeName); ok { switch underlying(obj.GetType()).(type) { case *types.Slice, *types.Map, *types.Chan: return true } } return false }
func isCompositeType(obj types.Object) bool { switch obj { case protoArray, protoSlice, protoMap, protoStruct: return true } if obj, ok := obj.(*types.TypeName); ok { switch underlying(obj.GetType()).(type) { case *types.Array, *types.Slice, *types.Map, *types.Struct: return true } } return false }
func isGoDeferrable(obj types.Object) bool { switch obj := obj.(type) { case special: return obj.Name == "call" case *types.Builtin: switch obj.Name { case "close", "copy", "delete", "panic", "recover": return true } case *types.Func: return !isOperator(obj) case *types.TypeName: _, ok := obj.GetType().(*types.Named) return ok } return false }
func fluxPath(obj types.Object) string { pkg, err := build.Import(obj.GetPkg().Path, "", build.FindOnly) if err != nil { fmt.Println("error importing \"%s\": %s\n", obj.GetPkg().Path, err) return "" } name := obj.GetName() if !obj.IsExported() { // unexported names are suffixed with "-" to avoid possible conflicts on case-insensitive systems name += "-" } if isMethod(obj) { t, _ := indirect(obj.GetType().(*types.Signature).Recv.Type) recv := t.(*types.Named).Obj typeName := recv.Name if !recv.IsExported() { typeName += "-" } name = typeName + "." + name } return filepath.Join(pkg.Dir, name+".flux.go") }
func newCallNode(obj types.Object, currentPkg *types.Package, godefer string) node { if obj == nil { n := &callNode{} n.nodeBase = newGoDeferNodeBase(n, godefer) if godefer == "" { n.text.SetText("call") } else { n.text.SetText("") //trigger TextChanged } n.text.SetTextColor(color(special{}, true, false)) n.addSeqPorts() in := n.newInput(nil) in.connsChanged = func() { t := inputType(in) in.setType(t) // TODO: add/remove/modify only the affected ports. beware: t == in.obj.Type because portsNode mutates the signature in place. for _, p := range append(ins(n)[1:], outs(n)...) { n.removePortBase(p) } if t != nil { n.addPorts(underlying(t).(*types.Signature)) } } return n } if sig, ok := obj.GetType().(*types.Signature); ok { n := &callNode{obj: obj} n.nodeBase = newGoDeferNodeBase(n, godefer) name := obj.GetName() if sig.Recv != nil { name = "." + name } else if p := obj.GetPkg(); p != currentPkg && p != nil { n.pkg.setPkg(obj.GetPkg()) } n.text.SetText(name) n.text.SetTextColor(color(&types.Func{}, true, false)) n.addSeqPorts() n.addPorts(sig) return n } switch name := obj.GetName(); name { case "append": return newAppendNode() case "close": return newCloseNode(godefer) case "complex": return newComplexNode() case "copy": return newCopyNode(godefer) case "delete": return newDeleteNode(godefer) case "len", "cap": return newLenCapNode(name) case "make": return newMakeNode(currentPkg) case "new": return newNewNode(currentPkg) case "panic", "recover": return newPanicRecoverNode(name, godefer) case "real", "imag": return newRealImagNode(name) default: panic("unknown builtin: " + name) } }