formatter.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. package pretty
  2. import (
  3. "fmt"
  4. "io"
  5. "reflect"
  6. "strconv"
  7. "text/tabwriter"
  8. "github.com/kr/text"
  9. )
  10. const (
  11. limit = 50
  12. )
  13. type formatter struct {
  14. x interface{}
  15. force bool
  16. quote bool
  17. }
  18. // Formatter makes a wrapper, f, that will format x as go source with line
  19. // breaks and tabs. Object f responds to the "%v" formatting verb when both the
  20. // "#" and " " (space) flags are set, for example:
  21. //
  22. // fmt.Sprintf("%# v", Formatter(x))
  23. //
  24. // If one of these two flags is not set, or any other verb is used, f will
  25. // format x according to the usual rules of package fmt.
  26. // In particular, if x satisfies fmt.Formatter, then x.Format will be called.
  27. func Formatter(x interface{}) (f fmt.Formatter) {
  28. return formatter{x: x, quote: true}
  29. }
  30. func (fo formatter) String() string {
  31. return fmt.Sprint(fo.x) // unwrap it
  32. }
  33. func (fo formatter) passThrough(f fmt.State, c rune) {
  34. s := "%"
  35. for i := 0; i < 128; i++ {
  36. if f.Flag(i) {
  37. s += string(i)
  38. }
  39. }
  40. if w, ok := f.Width(); ok {
  41. s += fmt.Sprintf("%d", w)
  42. }
  43. if p, ok := f.Precision(); ok {
  44. s += fmt.Sprintf(".%d", p)
  45. }
  46. s += string(c)
  47. fmt.Fprintf(f, s, fo.x)
  48. }
  49. func (fo formatter) Format(f fmt.State, c rune) {
  50. if fo.force || c == 'v' && f.Flag('#') && f.Flag(' ') {
  51. w := tabwriter.NewWriter(f, 4, 4, 1, ' ', 0)
  52. p := &printer{tw: w, Writer: w, visited: make(map[visit]int)}
  53. p.printValue(reflect.ValueOf(fo.x), true, fo.quote)
  54. w.Flush()
  55. return
  56. }
  57. fo.passThrough(f, c)
  58. }
  59. type printer struct {
  60. io.Writer
  61. tw *tabwriter.Writer
  62. visited map[visit]int
  63. depth int
  64. }
  65. func (p *printer) indent() *printer {
  66. q := *p
  67. q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0)
  68. q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'})
  69. return &q
  70. }
  71. func (p *printer) printInline(v reflect.Value, x interface{}, showType bool) {
  72. if showType {
  73. io.WriteString(p, v.Type().String())
  74. fmt.Fprintf(p, "(%#v)", x)
  75. } else {
  76. fmt.Fprintf(p, "%#v", x)
  77. }
  78. }
  79. // printValue must keep track of already-printed pointer values to avoid
  80. // infinite recursion.
  81. type visit struct {
  82. v uintptr
  83. typ reflect.Type
  84. }
  85. func (p *printer) printValue(v reflect.Value, showType, quote bool) {
  86. if p.depth > 10 {
  87. io.WriteString(p, "!%v(DEPTH EXCEEDED)")
  88. return
  89. }
  90. switch v.Kind() {
  91. case reflect.Bool:
  92. p.printInline(v, v.Bool(), showType)
  93. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  94. p.printInline(v, v.Int(), showType)
  95. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  96. p.printInline(v, v.Uint(), showType)
  97. case reflect.Float32, reflect.Float64:
  98. p.printInline(v, v.Float(), showType)
  99. case reflect.Complex64, reflect.Complex128:
  100. fmt.Fprintf(p, "%#v", v.Complex())
  101. case reflect.String:
  102. p.fmtString(v.String(), quote)
  103. case reflect.Map:
  104. t := v.Type()
  105. if showType {
  106. io.WriteString(p, t.String())
  107. }
  108. writeByte(p, '{')
  109. if nonzero(v) {
  110. expand := !canInline(v.Type())
  111. pp := p
  112. if expand {
  113. writeByte(p, '\n')
  114. pp = p.indent()
  115. }
  116. keys := v.MapKeys()
  117. for i := 0; i < v.Len(); i++ {
  118. showTypeInStruct := true
  119. k := keys[i]
  120. mv := v.MapIndex(k)
  121. pp.printValue(k, false, true)
  122. writeByte(pp, ':')
  123. if expand {
  124. writeByte(pp, '\t')
  125. }
  126. showTypeInStruct = t.Elem().Kind() == reflect.Interface
  127. pp.printValue(mv, showTypeInStruct, true)
  128. if expand {
  129. io.WriteString(pp, ",\n")
  130. } else if i < v.Len()-1 {
  131. io.WriteString(pp, ", ")
  132. }
  133. }
  134. if expand {
  135. pp.tw.Flush()
  136. }
  137. }
  138. writeByte(p, '}')
  139. case reflect.Struct:
  140. t := v.Type()
  141. if v.CanAddr() {
  142. addr := v.UnsafeAddr()
  143. vis := visit{addr, t}
  144. if vd, ok := p.visited[vis]; ok && vd < p.depth {
  145. p.fmtString(t.String()+"{(CYCLIC REFERENCE)}", false)
  146. break // don't print v again
  147. }
  148. p.visited[vis] = p.depth
  149. }
  150. if showType {
  151. io.WriteString(p, t.String())
  152. }
  153. writeByte(p, '{')
  154. if nonzero(v) {
  155. expand := !canInline(v.Type())
  156. pp := p
  157. if expand {
  158. writeByte(p, '\n')
  159. pp = p.indent()
  160. }
  161. for i := 0; i < v.NumField(); i++ {
  162. showTypeInStruct := true
  163. if f := t.Field(i); f.Name != "" {
  164. io.WriteString(pp, f.Name)
  165. writeByte(pp, ':')
  166. if expand {
  167. writeByte(pp, '\t')
  168. }
  169. showTypeInStruct = labelType(f.Type)
  170. }
  171. pp.printValue(getField(v, i), showTypeInStruct, true)
  172. if expand {
  173. io.WriteString(pp, ",\n")
  174. } else if i < v.NumField()-1 {
  175. io.WriteString(pp, ", ")
  176. }
  177. }
  178. if expand {
  179. pp.tw.Flush()
  180. }
  181. }
  182. writeByte(p, '}')
  183. case reflect.Interface:
  184. switch e := v.Elem(); {
  185. case e.Kind() == reflect.Invalid:
  186. io.WriteString(p, "nil")
  187. case e.IsValid():
  188. pp := *p
  189. pp.depth++
  190. pp.printValue(e, showType, true)
  191. default:
  192. io.WriteString(p, v.Type().String())
  193. io.WriteString(p, "(nil)")
  194. }
  195. case reflect.Array, reflect.Slice:
  196. t := v.Type()
  197. if showType {
  198. io.WriteString(p, t.String())
  199. }
  200. if v.Kind() == reflect.Slice && v.IsNil() && showType {
  201. io.WriteString(p, "(nil)")
  202. break
  203. }
  204. if v.Kind() == reflect.Slice && v.IsNil() {
  205. io.WriteString(p, "nil")
  206. break
  207. }
  208. writeByte(p, '{')
  209. expand := !canInline(v.Type())
  210. pp := p
  211. if expand {
  212. writeByte(p, '\n')
  213. pp = p.indent()
  214. }
  215. for i := 0; i < v.Len(); i++ {
  216. showTypeInSlice := t.Elem().Kind() == reflect.Interface
  217. pp.printValue(v.Index(i), showTypeInSlice, true)
  218. if expand {
  219. io.WriteString(pp, ",\n")
  220. } else if i < v.Len()-1 {
  221. io.WriteString(pp, ", ")
  222. }
  223. }
  224. if expand {
  225. pp.tw.Flush()
  226. }
  227. writeByte(p, '}')
  228. case reflect.Ptr:
  229. e := v.Elem()
  230. if !e.IsValid() {
  231. writeByte(p, '(')
  232. io.WriteString(p, v.Type().String())
  233. io.WriteString(p, ")(nil)")
  234. } else {
  235. pp := *p
  236. pp.depth++
  237. writeByte(pp, '&')
  238. pp.printValue(e, true, true)
  239. }
  240. case reflect.Chan:
  241. x := v.Pointer()
  242. if showType {
  243. writeByte(p, '(')
  244. io.WriteString(p, v.Type().String())
  245. fmt.Fprintf(p, ")(%#v)", x)
  246. } else {
  247. fmt.Fprintf(p, "%#v", x)
  248. }
  249. case reflect.Func:
  250. io.WriteString(p, v.Type().String())
  251. io.WriteString(p, " {...}")
  252. case reflect.UnsafePointer:
  253. p.printInline(v, v.Pointer(), showType)
  254. case reflect.Invalid:
  255. io.WriteString(p, "nil")
  256. }
  257. }
  258. func canInline(t reflect.Type) bool {
  259. switch t.Kind() {
  260. case reflect.Map:
  261. return !canExpand(t.Elem())
  262. case reflect.Struct:
  263. for i := 0; i < t.NumField(); i++ {
  264. if canExpand(t.Field(i).Type) {
  265. return false
  266. }
  267. }
  268. return true
  269. case reflect.Interface:
  270. return false
  271. case reflect.Array, reflect.Slice:
  272. return !canExpand(t.Elem())
  273. case reflect.Ptr:
  274. return false
  275. case reflect.Chan, reflect.Func, reflect.UnsafePointer:
  276. return false
  277. }
  278. return true
  279. }
  280. func canExpand(t reflect.Type) bool {
  281. switch t.Kind() {
  282. case reflect.Map, reflect.Struct,
  283. reflect.Interface, reflect.Array, reflect.Slice,
  284. reflect.Ptr:
  285. return true
  286. }
  287. return false
  288. }
  289. func labelType(t reflect.Type) bool {
  290. switch t.Kind() {
  291. case reflect.Interface, reflect.Struct:
  292. return true
  293. }
  294. return false
  295. }
  296. func (p *printer) fmtString(s string, quote bool) {
  297. if quote {
  298. s = strconv.Quote(s)
  299. }
  300. io.WriteString(p, s)
  301. }
  302. func tryDeepEqual(a, b interface{}) bool {
  303. defer func() { recover() }()
  304. return reflect.DeepEqual(a, b)
  305. }
  306. func writeByte(w io.Writer, b byte) {
  307. w.Write([]byte{b})
  308. }
  309. func getField(v reflect.Value, i int) reflect.Value {
  310. val := v.Field(i)
  311. if val.Kind() == reflect.Interface && !val.IsNil() {
  312. val = val.Elem()
  313. }
  314. return val
  315. }