package notation import "reflect" func reflectFuncBaseType(t reflect.Type) node { isVariadic := t.IsVariadic() args := func(num func() int, typ func(int) reflect.Type) []node { var t []node for i := 0; i < num(); i++ { if i == num()-1 && isVariadic { t = append(t, nodeOf("...", reflectType(typ(i).Elem()))) continue } t = append(t, reflectType(typ(i))) } return t } in := args(t.NumIn, t.In) out := args(t.NumOut, t.Out) n := nodeOf("(") if len(in) == 1 { n.parts = append(n.parts, in[0]) } else if len(in) > 1 { n.parts = append(n.parts, wrapper{sep: ", ", suffix: ",", items: in}) } n.parts = append(n.parts, ")") if len(out) == 1 { n.parts = append(n.parts, " ", out[0]) } else if len(out) > 1 { n.parts = append(n.parts, " (", wrapper{sep: ", ", suffix: ",", items: out}, ")") } return n } func reflectArrayType(t reflect.Type) node { return nodeOf("[", t.Len(), "]", reflectType(t.Elem())) } func reflectChanType(t reflect.Type) node { var prefix string switch t.ChanDir() { case reflect.RecvDir: prefix = "<-chan " case reflect.SendDir: prefix = "chan<- " default: prefix = "chan " } return nodeOf(prefix, reflectType(t.Elem())) } func reflectFuncType(t reflect.Type) node { return nodeOf("func", reflectFuncBaseType(t)) } func reflectInterfaceType(t reflect.Type) node { wr := wrapper{sep: "; "} for i := 0; i < t.NumMethod(); i++ { method := t.Method(i) wr.items = append( wr.items, nodeOf( method.Name, reflectFuncBaseType(method.Type), ), ) } return nodeOf("interface{", wr, "}") } func reflectMapType(t reflect.Type) node { return nodeOf("map[", reflectType(t.Key()), "]", reflectType(t.Elem())) } func reflectPointerType(t reflect.Type) node { return nodeOf("*", reflectType(t.Elem())) } func reflectListType(t reflect.Type) node { return nodeOf("[]", reflectType(t.Elem())) } func reflectStructType(t reflect.Type) node { wr := wrapper{sep: "; "} for i := 0; i < t.NumField(); i++ { fi := t.Field(i) wr.items = append( wr.items, nodeOf( fi.Name, " ", reflectType(fi.Type), ), ) } return nodeOf("struct{", wr, "}") } func reflectType(t reflect.Type) node { if t.Name() != "" { name := t.Name() if name == "uint8" { name = "byte" } return nodeOf(name) } switch t.Kind() { case reflect.Array: return reflectArrayType(t) case reflect.Chan: return reflectChanType(t) case reflect.Func: return reflectFuncType(t) case reflect.Interface: return reflectInterfaceType(t) case reflect.Map: return reflectMapType(t) case reflect.Ptr: return reflectPointerType(t) case reflect.Slice: return reflectListType(t) default: return reflectStructType(t) } }