From 612aa94f0a93518a2e92739136d6499f3a75b150 Mon Sep 17 00:00:00 2001 From: Arpad Ryszka Date: Thu, 22 Oct 2020 20:55:32 +0200 Subject: [PATCH] wrap lines --- fprint.go | 168 +++++++++++++++++++++++++++ notation.go | 105 +++++++++++++++-- reflect.go | 308 +++++++++++++++++++++++++++++++++++++++++++++++++ reflecttype.go | 129 +++++++++++++++++++++ sprint.go | 271 ------------------------------------------- sprint_test.go | 12 +- type.go | 118 ------------------- 7 files changed, 701 insertions(+), 410 deletions(-) create mode 100644 fprint.go create mode 100644 reflect.go create mode 100644 reflecttype.go delete mode 100644 sprint.go delete mode 100644 type.go diff --git a/fprint.go b/fprint.go new file mode 100644 index 0000000..fbfcedc --- /dev/null +++ b/fprint.go @@ -0,0 +1,168 @@ +package notation + +import ( + "fmt" + "io" +) + +type writer struct { + w io.Writer + n int + err error +} + +func (w *writer) write(o interface{}) { + if w.err != nil { + return + } + + n, err := fmt.Fprint(w.w, o) + w.n += n + w.err = err +} + +func nodeLen(t int, n node) node { + var w int + for i, p := range n.parts { + switch part := p.(type) { + case string: + n.len += len(part) + w += len(part) + case node: + part = nodeLen(t, part) + n.parts[i] = part + n.len += part.len + if part.len == part.wlen { + w += part.len + } else { + w += part.wlen0 + if w > n.wlen { + n.wlen = w + } + + if part.wlen > n.wlen { + n.wlen = part.wlen + } + + if n.wlen0 == 0 { + n.wlen0 = w + } + + w = part.wlenLast + } + case wrapper: + if len(part.items) == 0 { + continue + } + + if w > n.wlen { + n.wlen = w + } + + if n.wlen0 == 0 { + n.wlen0 = w + } + + w = 0 + for j, ni := range part.items { + ni = nodeLen(t, ni) + part.items[j] = ni + n.len += ni.len + wni := t + ni.len + len(part.suffix) + if wni > w { + w = wni + } + } + + if len(part.items) > 0 { + n.len += (len(part.items) - 1) * len(part.sep) + } + + w = 0 + } + } + + if w > n.wlen { + n.wlen = w + } + + if n.wlen0 == 0 { + n.wlen0 = w + } + + n.wlenLast = w + return n +} + +func wrapNode(t, c0, c1 int, n node) node { + if n.len <= c0 || n.wlen == n.len { + return n + } + + if n.len <= c1 && n.len-c0 <= n.wlen { + return n + } + + n.wrap = true + if n.wlen <= c0 { + return n + } + + for i, p := range n.parts { + switch part := p.(type) { + case node: + n.parts[i] = wrapNode(t, c0, c1, part) + case wrapper: + for j := range part.items { + part.items[j] = wrapNode( + t, + c0-t, + c1-t, + part.items[j], + ) + } + } + } + + return n +} + +func fprint(w *writer, t int, n node) { + if w.err != nil { + return + } + + for i := 0; i < t; i++ { + w.write("\t") + } + + for _, p := range n.parts { + switch part := p.(type) { + case node: + fprint(w, 0, part) + case wrapper: + if len(part.items) == 0 { + continue + } + + if n.wrap { + w.write("\n") + } + + for i, ni := range part.items { + if n.wrap { + fprint(w, t+1, ni) + w.write(part.suffix) + w.write("\n") + } else { + fprint(w, 0, ni) + if i < len(part.items)-1 { + w.write(part.sep) + } + } + } + default: + w.write(part) + } + } +} diff --git a/notation.go b/notation.go index 4069f92..6426162 100644 --- a/notation.go +++ b/notation.go @@ -1,7 +1,11 @@ package notation import ( + "bytes" + "io" + "os" "reflect" + "strconv" "strings" ) @@ -16,23 +20,102 @@ const ( allTypes ) -func sprintValues(o opts, v []interface{}) string { - s := make([]string, len(v)) - for i := range v { - if v[i] == nil { - s[i] = "nil" +type node struct { + len, wlen, wlen0, wlenLast int + wrap bool + parts []interface{} +} + +type wrapper struct { + sep, suffix string + items []node +} + +func nodeOf(parts ...interface{}) node { + return node{parts: parts} +} + +func config(name string, dflt int) int { + s := os.Getenv(name) + if s == "" { + s = os.Getenv(strings.ToLower(name)) + } + + if s == "" { + return dflt + } + + v, err := strconv.Atoi(s) + if err != nil { + return dflt + } + + return v +} + +func fprintValues(w io.Writer, o opts, v []interface{}) (int, error) { + tab := config("TABWIDTH", 8) + cols0 := config("LINEWIDTH", 80-8) + cols1 := config("LINEWIDTH1", (cols0+8)*3/2-8) + wr := &writer{w: w} + for i, vi := range v { + if wr.err != nil { + return wr.n, wr.err + } + + if i > 0 { + if o&wrap == 0 { + wr.write(" ") + } else { + wr.write("\n") + } + } + + if vi == nil { + fprint(wr, 0, nodeOf("nil")) continue } - s[i] = sprint(o, reflect.ValueOf(v[i])) + n := reflectValue(o, reflect.ValueOf(vi)) + if o&wrap != 0 { + n = nodeLen(tab, n) + n = wrapNode(tab, cols0, cols1, n) + } + + fprint(wr, 0, n) } - sep := " " - if o&wrap != 0 { - sep = "\n" - } + return wr.n, wr.err +} - return strings.Join(s, sep) +func sprintValues(o opts, v []interface{}) string { + var b bytes.Buffer + fprintValues(&b, o, v) + return b.String() +} + +func Fprint(w io.Writer, v ...interface{}) (int, error) { + return fprintValues(w, none, v) +} + +func Fprintw(w io.Writer, v ...interface{}) (int, error) { + return fprintValues(w, wrap, v) +} + +func Fprintt(w io.Writer, v ...interface{}) (int, error) { + return fprintValues(w, types, v) +} + +func Fprintwt(w io.Writer, v ...interface{}) (int, error) { + return fprintValues(w, wrap|types, v) +} + +func Fprintv(w io.Writer, v ...interface{}) (int, error) { + return fprintValues(w, allTypes, v) +} + +func Fprintwv(w io.Writer, v ...interface{}) (int, error) { + return fprintValues(w, wrap|allTypes, v) } func Sprint(v ...interface{}) string { diff --git a/reflect.go b/reflect.go new file mode 100644 index 0000000..30d5ba8 --- /dev/null +++ b/reflect.go @@ -0,0 +1,308 @@ +package notation + +import ( + "bytes" + "fmt" + "reflect" + "sort" +) + +func withType(o opts) (opts, bool, bool) { + if o&types == 0 && o&allTypes == 0 { + return o, false, false + } + + if o&skipTypes != 0 && o&allTypes == 0 { + return o &^ skipTypes, false, false + } + + return o, true, o&allTypes != 0 +} + +func reflectPrimitive(o opts, r reflect.Value, v interface{}, suppressType ...string) node { + s := fmt.Sprint(v) + if s[0] == '(' && s[len(s)-1] == ')' { + s = s[1 : len(s)-1] + } + + _, t, a := withType(o) + if !t { + return nodeOf(s) + } + + tn := reflectType(r.Type()) + if a { + return nodeOf(tn, "(", s, ")") + } + + for _, suppress := range suppressType { + if tn.parts[0] != suppress { + continue + } + + return nodeOf(s) + } + + return nodeOf(tn, "(", s, ")") +} + +func reflectNil(o opts, r reflect.Value) node { + if _, _, a := withType(o); !a { + return nodeOf("nil") + } + + return nodeOf(reflectType(r.Type()), "(nil)") +} + +func reflectItems(o opts, prefix string, r reflect.Value) node { + items := wrapper{sep: ", ", suffix: ","} + itemOpts := o | skipTypes + for i := 0; i < r.Len(); i++ { + items.items = append( + items.items, + reflectValue(itemOpts, r.Index(i)), + ) + } + + if _, t, _ := withType(o); !t { + return nodeOf(prefix, "{", items, "}") + } + + return nodeOf(reflectType(r.Type()), "{", items, "}") +} + +func reflectHidden(o opts, hidden string, r reflect.Value) node { + if r.IsNil() { + return reflectNil(o, r) + } + + if _, t, _ := withType(o); !t { + return nodeOf(hidden) + } + + return reflectType(r.Type()) +} + +func reflectArray(o opts, r reflect.Value) node { + return reflectItems(o, fmt.Sprintf("[%d]", r.Len()), r) +} + +func reflectChan(o opts, r reflect.Value) node { + return reflectHidden(o, "chan", r) +} + +func reflectFunc(o opts, r reflect.Value) node { + return reflectHidden(o, "func()", r) +} + +func reflectInterface(o opts, r reflect.Value) node { + if r.IsNil() { + return reflectNil(o, r) + } + + e := reflectValue(o, r.Elem()) + if _, t, _ := withType(o); !t { + return e + } + + return nodeOf( + reflectType(r.Type()), + "(", + wrapper{items: []node{e}}, + ")", + ) +} + +func reflectMap(o opts, r reflect.Value) node { + if r.IsNil() { + return reflectNil(o, r) + } + + var ( + nkeys []node + skeys []string + ) + + items := wrapper{sep: ", ", suffix: ","} + itemOpts := o | skipTypes + keys := r.MapKeys() + sv := make(map[string]reflect.Value) + sn := make(map[string]node) + for _, key := range keys { + var b bytes.Buffer + nk := reflectValue(itemOpts, key) + nkeys = append(nkeys, nk) + wr := writer{w: &b} + fprint(&wr, 0, nk) + skey := b.String() + skeys = append(skeys, skey) + sv[skey] = key + sn[skey] = nk + } + + sort.Strings(skeys) + for _, skey := range skeys { + items.items = append( + items.items, + nodeOf( + sn[skey], + ": ", + reflectValue(itemOpts, r.MapIndex(sv[skey])), + ), + ) + } + + if _, t, _ := withType(o); !t { + return nodeOf("map{", items, "}") + } + + return nodeOf(reflectType(r.Type()), "{", items, "}") +} + +func reflectPointer(o opts, r reflect.Value) node { + if r.IsNil() { + return reflectNil(o, r) + } + + e := reflectValue(o, r.Elem()) + if _, t, _ := withType(o); !t { + return e + } + + return nodeOf("*", e) +} + +func reflectList(o opts, r reflect.Value) node { + if r.IsNil() { + return reflectNil(o, r) + } + + return reflectItems(o, "[]", r) +} + +func reflectString(o opts, r reflect.Value) node { + b := []byte(r.String()) + e := make([]byte, 0, len(b)) + for _, c := range b { + switch c { + case '\\': + e = append(e, '\\', '\\') + case '"': + e = append(e, '\\', '"') + case '\b': + e = append(e, '\\', 'b') + case '\f': + e = append(e, '\\', 'f') + case '\n': + e = append(e, '\\', 'n') + case '\r': + e = append(e, '\\', 'r') + case '\t': + e = append(e, '\\', 't') + case '\v': + e = append(e, '\\', 'v') + default: + e = append(e, c) + } + } + + s := fmt.Sprintf("\"%s\"", string(e)) + _, t, a := withType(o) + if !t { + return nodeOf(s) + } + + tn := reflectType(r.Type()) + if !a && tn.parts[0] == "string" { + return nodeOf(s) + } + + return nodeOf(tn, "(", wrapper{items: []node{nodeOf(s)}}, ")") +} + +func reflectStruct(o opts, r reflect.Value) node { + wr := wrapper{sep: ", "} + + fieldOpts := o | skipTypes + rt := r.Type() + for i := 0; i < r.NumField(); i++ { + name := rt.Field(i).Name + wr.items = append( + wr.items, + nodeOf( + name, + ": ", + reflectValue( + fieldOpts, + r.FieldByName(name), + ), + ), + ) + } + + if _, t, _ := withType(o); !t { + return nodeOf("{", wr, "}") + } + + return nodeOf(reflectType(rt), "{", wr, "}") +} + +func reflectUnsafePointer(o opts, r reflect.Value) node { + if r.IsNil() { + return reflectNil(o, r) + } + + if _, _, a := withType(o); !a { + return nodeOf("pointer") + } + + return nodeOf(reflectType(r.Type()), "(pointer)") +} + +func reflectValue(o opts, r reflect.Value) node { + switch r.Kind() { + case reflect.Bool: + return reflectPrimitive(o, r, r.Bool(), "bool") + case + reflect.Int, + reflect.Int8, + reflect.Int16, + reflect.Int32, + reflect.Int64: + return reflectPrimitive(o, r, r.Int(), "int") + case + reflect.Uint, + reflect.Uint8, + reflect.Uint16, + reflect.Uint32, + reflect.Uint64, + reflect.Uintptr: + return reflectPrimitive(o, r, r.Uint()) + case reflect.Float32, reflect.Float64: + return reflectPrimitive(o, r, r.Float()) + case reflect.Complex64, reflect.Complex128: + return reflectPrimitive(o, r, r.Complex()) + case reflect.Array: + return reflectArray(o, r) + case reflect.Chan: + return reflectChan(o, r) + case reflect.Func: + return reflectFunc(o, r) + case reflect.Interface: + return reflectInterface(o, r) + case reflect.Map: + return reflectMap(o, r) + case reflect.Ptr: + return reflectPointer(o, r) + case reflect.Slice: + return reflectList(o, r) + case reflect.String: + return reflectString(o, r) + case reflect.Struct: + return reflectStruct(o, r) + case reflect.UnsafePointer: + return reflectUnsafePointer(o, r) + default: + return nodeOf("") + } +} diff --git a/reflecttype.go b/reflecttype.go new file mode 100644 index 0000000..b37fbb3 --- /dev/null +++ b/reflecttype.go @@ -0,0 +1,129 @@ +package notation + +import ( + "reflect" +) + +func reflectFuncBaseType(t reflect.Type) node { + args := func(num func() int, typ func(int) reflect.Type) []node { + var t []node + for i := 0; i < num(); i++ { + 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: ", ", 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: ", ", 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() != "" { + return nodeOf(t.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) + case reflect.Struct: + return reflectStructType(t) + default: + return nodeOf("") + } +} diff --git a/sprint.go b/sprint.go deleted file mode 100644 index 543ff1e..0000000 --- a/sprint.go +++ /dev/null @@ -1,271 +0,0 @@ -package notation - -import ( - "fmt" - "reflect" - "sort" - "strings" -) - -func withType(o opts) (opts, bool, bool) { - if o&types == 0 && o&allTypes == 0 { - return o, false, false - } - - if o&skipTypes != 0 && o&allTypes == 0 { - return o &^ skipTypes, false, false - } - - return o, true, o&allTypes != 0 -} - -func sprintNil(o opts, r reflect.Value) string { - if _, _, a := withType(o); !a { - return "nil" - } - - return fmt.Sprintf("%s(nil)", sprintType(r.Type())) -} - -func sprintPrimitive(o opts, r reflect.Value, v interface{}, suppressType ...string) string { - s := fmt.Sprint(v) - if s[0] == '(' && s[len(s)-1] == ')' { - s = s[1 : len(s)-1] - } - - _, w, a := withType(o) - if !w { - return s - } - - t := sprintType(r.Type()) - if !a { - for _, suppress := range suppressType { - if t == suppress { - return s - } - } - } - - return fmt.Sprintf("%s(%s)", t, s) -} - -func sprintItems(o opts, prefix string, r reflect.Value) string { - o, w, _ := withType(o) - itemOpts := o | skipTypes - s := make([]string, r.Len()) - for i := 0; i < r.Len(); i++ { - s[i] = sprint(itemOpts, r.Index(i)) - } - - if !w { - return fmt.Sprintf("%s{%s}", prefix, strings.Join(s, ", ")) - } - - return fmt.Sprintf("%s{%s}", sprintType(r.Type()), strings.Join(s, ", ")) -} - -func sprintHidden(o opts, r reflect.Value, hidden string) string { - if r.IsNil() { - return sprintNil(o, r) - } - - _, w, _ := withType(o) - if !w { - return hidden - } - - return sprintType(r.Type()) -} - -func sprintArray(o opts, r reflect.Value) string { - return sprintItems(o, fmt.Sprintf("[%d]", r.Len()), r) -} - -func sprintChan(o opts, r reflect.Value) string { - return sprintHidden(o, r, "chan") -} - -func sprintFunc(o opts, r reflect.Value) string { - return sprintHidden(o, r, "func()") -} - -func sprinterface(o opts, r reflect.Value) string { - if r.IsNil() { - return sprintNil(o, r) - } - - o, w, _ := withType(o) - if !w { - return sprint(o, r.Elem()) - } - - return fmt.Sprintf("%s(%s)", sprintType(r.Type()), sprint(o, r.Elem())) -} - -func sprintMap(o opts, r reflect.Value) string { - if r.IsNil() { - return sprintNil(o, r) - } - - o, w, _ := withType(o) - itemOpts := o | skipTypes - var items []string - for _, key := range r.MapKeys() { - items = append( - items, - fmt.Sprintf( - "%s: %s", - sprint(itemOpts, key), - sprint(itemOpts, r.MapIndex(key)), - ), - ) - } - - sort.Strings(items) - sitems := strings.Join(items, ", ") - if !w { - return fmt.Sprintf("map{%s}", sitems) - } - - return fmt.Sprintf("%s{%s}", sprintType(r.Type()), sitems) -} - -func sprintPointer(o opts, r reflect.Value) string { - if r.IsNil() { - return sprintNil(o, r) - } - - s := sprint(o, r.Elem()) - if _, w, _ := withType(o); !w { - return s - } - - return fmt.Sprintf("*%s", s) -} - -func sprintList(o opts, r reflect.Value) string { - if r.IsNil() { - return sprintNil(o, r) - } - - return sprintItems(o, "[]", r) -} - -func sprintString(o opts, r reflect.Value) string { - b := []byte(r.String()) - e := make([]byte, 0, len(b)) - for _, c := range b { - switch c { - case '\\': - e = append(e, '\\', '\\') - case '"': - e = append(e, '\\', '"') - case '\b': - e = append(e, '\\', 'b') - case '\f': - e = append(e, '\\', 'f') - case '\n': - e = append(e, '\\', 'n') - case '\r': - e = append(e, '\\', 'r') - case '\t': - e = append(e, '\\', 't') - case '\v': - e = append(e, '\\', 'v') - default: - e = append(e, c) - } - } - - s := fmt.Sprintf("\"%s\"", string(e)) - _, w, a := withType(o) - if !w { - return s - } - - t := sprintType(r.Type()) - if !a && t == "string" { - return s - } - - return fmt.Sprintf("%s(%s)", t, s) -} - -func sprintStruct(o opts, r reflect.Value) string { - o, w, _ := withType(o) - fieldOpts := o | skipTypes - rt := r.Type() - f := make([]string, r.NumField()) - for i := 0; i < r.NumField(); i++ { - name := rt.Field(i).Name - f[i] = fmt.Sprintf( - "%s: %s", - name, - sprint(fieldOpts, r.FieldByName(name)), - ) - } - - fs := strings.Join(f, ", ") - if !w { - return fmt.Sprintf("{%s}", fs) - } - - return fmt.Sprintf("%s{%s}", sprintType(rt), fs) -} - -func sprintUnsafePointer(o opts, r reflect.Value) string { - if r.IsNil() { - return sprintNil(o, r) - } - - return "pointer" -} - -func sprint(o opts, r reflect.Value) string { - switch r.Kind() { - case reflect.Bool: - return sprintPrimitive(o, r, r.Bool(), "bool") - case - reflect.Int, - reflect.Int8, - reflect.Int16, - reflect.Int32, - reflect.Int64: - return sprintPrimitive(o, r, r.Int(), "int") - case - reflect.Uint, - reflect.Uint8, - reflect.Uint16, - reflect.Uint32, - reflect.Uint64, - reflect.Uintptr: - return sprintPrimitive(o, r, r.Uint()) - case reflect.Float32, reflect.Float64: - return sprintPrimitive(o, r, r.Float()) - case reflect.Complex64, reflect.Complex128: - return sprintPrimitive(o, r, r.Complex()) - case reflect.Array: - return sprintArray(o, r) - case reflect.Chan: - return sprintChan(o, r) - case reflect.Func: - return sprintFunc(o, r) - case reflect.Interface: - return sprinterface(o, r) - case reflect.Map: - return sprintMap(o, r) - case reflect.Ptr: - return sprintPointer(o, r) - case reflect.Slice: - return sprintList(o, r) - case reflect.String: - return sprintString(o, r) - case reflect.Struct: - return sprintStruct(o, r) - case reflect.UnsafePointer: - return sprintUnsafePointer(o, r) - default: - return "" - } -} diff --git a/sprint_test.go b/sprint_test.go index 389b3b3..35b0505 100644 --- a/sprint_test.go +++ b/sprint_test.go @@ -1,7 +1,6 @@ package notation import ( - "reflect" "testing" "unsafe" ) @@ -243,8 +242,8 @@ func TestSprintv(t *testing.T) { {"structure", struct{ foo int }{42}, "struct{foo int}{foo: int(42)}"}, {"custom structure", myStruct{42}, "myStruct{field: interface{}(int(42))}"}, {"custom structure, nil field", myStruct{}, "myStruct{field: interface{}(nil)}"}, - {"unsafe pointer", unsafe.Pointer(&struct{}{}), "pointer"}, - {"custom unsafe pointer", myUnsafePointer(&struct{}{}), "pointer"}, + {"unsafe pointer", unsafe.Pointer(&struct{}{}), "Pointer(pointer)"}, + {"custom unsafe pointer", myUnsafePointer(&struct{}{}), "myUnsafePointer(pointer)"}, {"unsafe pointer type", struct{ p unsafe.Pointer }{}, "struct{p Pointer}{p: Pointer(nil)}"}, } { t.Run(test.title, func(t *testing.T) { @@ -255,10 +254,3 @@ func TestSprintv(t *testing.T) { }) } } - -func TestSprintInvalid(t *testing.T) { - s := sprint(none, reflect.Value{}) - if s != "" { - t.Fatalf("expected: , got: %s", s) - } -} diff --git a/type.go b/type.go deleted file mode 100644 index 4967135..0000000 --- a/type.go +++ /dev/null @@ -1,118 +0,0 @@ -package notation - -import ( - "fmt" - "reflect" - "strings" -) - -func funcBase(t reflect.Type) string { - args := func(num func() int, typ func(int) reflect.Type) []string { - t := make([]string, num()) - for i := 0; i < num(); i++ { - t[i] = sprintType(typ(i)) - } - - return t - } - - in := args(t.NumIn, t.In) - out := args(t.NumOut, t.Out) - - var outs string - if len(out) == 1 { - outs = out[0] - } else if len(out) > 1 { - outs = fmt.Sprintf("(%s)", strings.Join(out, ", ")) - } - - var s string - if outs == "" { - s = fmt.Sprintf("(%s)", strings.Join(in, ", ")) - } else { - s = fmt.Sprintf("(%s) %s", strings.Join(in, ", "), outs) - } - - return s -} - -func arrayType(t reflect.Type) string { - return fmt.Sprintf("[%d]%s", t.Len(), sprintType(t.Elem())) -} - -func chanType(t reflect.Type) string { - var prefix string - switch t.ChanDir() { - case reflect.RecvDir: - prefix = "<-chan" - case reflect.SendDir: - prefix = "chan<-" - default: - prefix = "chan" - } - - return fmt.Sprintf("%s %s", prefix, sprintType(t.Elem())) -} - -func funcType(t reflect.Type) string { - return fmt.Sprintf("func%s", funcBase(t)) -} - -func interfaceType(t reflect.Type) string { - var m []string - for i := 0; i < t.NumMethod(); i++ { - method := t.Method(i) - m = append(m, fmt.Sprintf("%s%s", method.Name, funcBase(method.Type))) - } - - return fmt.Sprintf("interface{%s}", strings.Join(m, "; ")) -} - -func mapType(t reflect.Type) string { - return fmt.Sprintf("map[%s]%s", sprintType(t.Key()), sprintType(t.Elem())) -} - -func pointerType(t reflect.Type) string { - return fmt.Sprintf("*%s", sprintType(t.Elem())) -} - -func listType(t reflect.Type) string { - return fmt.Sprintf("[]%s", sprintType(t.Elem())) -} - -func structType(t reflect.Type) string { - f := make([]string, t.NumField()) - for i := 0; i < t.NumField(); i++ { - fi := t.Field(i) - f[i] = fmt.Sprintf("%s %s", fi.Name, sprintType(fi.Type)) - } - - return fmt.Sprintf("struct{%s}", strings.Join(f, "; ")) -} - -func sprintType(t reflect.Type) string { - if t.Name() != "" { - return t.Name() - } - - switch t.Kind() { - case reflect.Array: - return arrayType(t) - case reflect.Chan: - return chanType(t) - case reflect.Func: - return funcType(t) - case reflect.Interface: - return interfaceType(t) - case reflect.Map: - return mapType(t) - case reflect.Ptr: - return pointerType(t) - case reflect.Slice: - return listType(t) - case reflect.Struct: - return structType(t) - default: - return "" - } -}