本站源代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

329 lines
7.1KB

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