github.com/neugram/ng@v0.0.0-20180309130942-d472ff93d872/format/tipe.go (about) 1 // Copyright 2017 The Neugram Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package format 6 7 import ( 8 "bytes" 9 "fmt" 10 "sort" 11 12 "neugram.io/ng/syntax/tipe" 13 ) 14 15 func (p *printer) tipe(t tipe.Type) { 16 if t == nil { 17 p.buf.WriteString("<nil>") 18 return 19 } 20 switch t := t.(type) { 21 case tipe.Basic: 22 p.buf.WriteString(string(t)) 23 case *tipe.Struct: 24 if len(t.Fields) == 0 { 25 p.buf.WriteString("struct{}") 26 return 27 } 28 p.buf.WriteString("struct {") 29 p.indent++ 30 maxlen := 0 31 for _, sf := range t.Fields { 32 if len(sf.Name) > maxlen { 33 maxlen = len(sf.Name) 34 } 35 } 36 for _, sf := range t.Fields { 37 p.newline() 38 name := sf.Name 39 if name == "" { 40 name = "*ERROR*No*Name*" 41 } 42 p.buf.WriteString(name) 43 for i := len(name); i <= maxlen; i++ { 44 p.buf.WriteByte(' ') 45 } 46 p.tipe(sf.Type) 47 } 48 p.indent-- 49 p.newline() 50 p.buf.WriteByte('}') 51 case *tipe.Named: 52 p.buf.WriteString(t.Name) 53 case *tipe.Pointer: 54 p.buf.WriteByte('*') 55 p.tipe(t.Elem) 56 case *tipe.Unresolved: 57 if t.Package != "" { 58 p.buf.WriteString(t.Package) 59 p.buf.WriteByte('.') 60 } 61 p.buf.WriteString(t.Name) 62 case *tipe.Array: 63 if t.Ellipsis { 64 p.buf.WriteString("[...]") 65 } else { 66 fmt.Fprintf(p.buf, "[%d]", t.Len) 67 } 68 p.tipe(t.Elem) 69 case *tipe.Slice: 70 p.buf.WriteString("[]") 71 p.tipe(t.Elem) 72 case *tipe.Table: 73 p.buf.WriteString("[|]") 74 p.tipe(t.Type) 75 case *tipe.Interface: 76 if len(t.Methods) == 0 { 77 p.buf.WriteString("interface{}") 78 return 79 } 80 p.buf.WriteString("interface {") 81 p.indent++ 82 names := make([]string, 0, len(t.Methods)) 83 for name := range t.Methods { 84 names = append(names, name) 85 } 86 sort.Strings(names) 87 for _, name := range names { 88 p.newline() 89 p.buf.WriteString(name) 90 p.tipeFuncSig(t.Methods[name]) 91 } 92 p.indent-- 93 p.newline() 94 p.buf.WriteByte('}') 95 case *tipe.Map: 96 p.buf.WriteString("map[") 97 p.tipe(t.Key) 98 p.buf.WriteByte(']') 99 p.tipe(t.Value) 100 case *tipe.Chan: 101 if t.Direction == tipe.ChanRecv { 102 p.buf.WriteString("<-") 103 } 104 p.buf.WriteString("chan") 105 if t.Direction == tipe.ChanSend { 106 p.buf.WriteString("<-") 107 } 108 p.buf.WriteByte(' ') 109 p.tipe(t.Elem) 110 case *tipe.Func: 111 p.buf.WriteString("func") 112 p.tipeFuncSig(t) 113 case *tipe.Alias: 114 p.buf.WriteString(t.Name) 115 case *tipe.Tuple: 116 p.buf.WriteString("(") 117 for i, elt := range t.Elems { 118 if i > 0 { 119 p.buf.WriteString(", ") 120 } 121 p.tipe(elt) 122 } 123 p.buf.WriteString(")") 124 case *tipe.Ellipsis: 125 p.buf.WriteString("...") 126 p.tipe(t.Elem) 127 default: 128 p.buf.WriteString("format: unknown type: ") 129 WriteDebug(p.buf, t) 130 } 131 } 132 133 func (p *printer) tipeFuncSig(t *tipe.Func) { 134 p.buf.WriteByte('(') 135 if t.Params != nil { 136 for i, elem := range t.Params.Elems { 137 if i > 0 { 138 p.buf.WriteString(", ") 139 } 140 p.tipe(elem) 141 } 142 } 143 p.buf.WriteByte(')') 144 if t.Results != nil && len(t.Results.Elems) > 0 { 145 p.buf.WriteByte(' ') 146 if len(t.Results.Elems) > 1 { 147 p.buf.WriteByte('(') 148 } 149 for i, elem := range t.Results.Elems { 150 if i > 0 { 151 p.buf.WriteString(", ") 152 } 153 p.tipe(elem) 154 } 155 if len(t.Results.Elems) > 1 { 156 p.buf.WriteByte(')') 157 } 158 } 159 } 160 161 func WriteType(buf *bytes.Buffer, t tipe.Type) { 162 p := &printer{ 163 buf: buf, 164 } 165 p.tipe(t) 166 } 167 168 func Type(t tipe.Type) string { 169 buf := new(bytes.Buffer) 170 WriteType(buf, t) 171 return buf.String() 172 }