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.
 
 
 

255 lines
6.6 KiB

  1. // Copyright 2016 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // Package pretty implements a simple pretty-printer. It is intended for
  15. // debugging the output of tests.
  16. //
  17. // It follows pointers and produces multi-line output for complex values like
  18. // slices, maps and structs.
  19. package pretty
  20. import (
  21. "fmt"
  22. "io"
  23. "reflect"
  24. "sort"
  25. "strings"
  26. "time"
  27. )
  28. // Indent is the string output at each level of indentation.
  29. var Indent = " "
  30. // Value returns a value that will print prettily when used as an
  31. // argument for the %v or %s format specifiers.
  32. // With no flags, struct fields and map keys with default values are omitted.
  33. // With the '+' or '#' flags, all values are displayed.
  34. //
  35. // This package does not detect cycles. Attempting to print a Value that
  36. // contains cycles will result in unbounded recursion.
  37. func Value(v interface{}) val { return val{v: v} }
  38. type val struct{ v interface{} }
  39. // Format implements the fmt.Formatter interface.
  40. func (v val) Format(s fmt.State, c rune) {
  41. if c == 'v' || c == 's' {
  42. fprint(s, reflect.ValueOf(v.v), state{
  43. defaults: s.Flag('+') || s.Flag('#'),
  44. })
  45. } else {
  46. fmt.Fprintf(s, "%%!%c(pretty.Val)", c)
  47. }
  48. }
  49. type state struct {
  50. level int
  51. prefix, suffix string
  52. defaults bool
  53. }
  54. const maxLevel = 100
  55. var typeOfTime = reflect.TypeOf(time.Time{})
  56. func fprint(w io.Writer, v reflect.Value, s state) {
  57. if s.level > maxLevel {
  58. fmt.Fprintln(w, "pretty: max nested depth exceeded")
  59. return
  60. }
  61. indent := strings.Repeat(Indent, s.level)
  62. fmt.Fprintf(w, "%s%s", indent, s.prefix)
  63. if isNil(v) {
  64. fmt.Fprintf(w, "nil%s", s.suffix)
  65. return
  66. }
  67. if v.Type().Kind() == reflect.Interface {
  68. v = v.Elem()
  69. }
  70. if v.Type() == typeOfTime {
  71. fmt.Fprintf(w, "%s%s", v.Interface(), s.suffix)
  72. return
  73. }
  74. for v.Type().Kind() == reflect.Ptr {
  75. fmt.Fprintf(w, "&")
  76. v = v.Elem()
  77. }
  78. switch v.Type().Kind() {
  79. default:
  80. fmt.Fprintf(w, "%s%s", short(v), s.suffix)
  81. case reflect.Array:
  82. fmt.Fprintf(w, "%s{\n", v.Type())
  83. for i := 0; i < v.Len(); i++ {
  84. fprint(w, v.Index(i), state{
  85. level: s.level + 1,
  86. prefix: "",
  87. suffix: ",",
  88. defaults: s.defaults,
  89. })
  90. fmt.Fprintln(w)
  91. }
  92. fmt.Fprintf(w, "%s}", indent)
  93. case reflect.Slice:
  94. fmt.Fprintf(w, "%s{", v.Type())
  95. if v.Len() > 0 {
  96. fmt.Fprintln(w)
  97. for i := 0; i < v.Len(); i++ {
  98. fprint(w, v.Index(i), state{
  99. level: s.level + 1,
  100. prefix: "",
  101. suffix: ",",
  102. defaults: s.defaults,
  103. })
  104. fmt.Fprintln(w)
  105. }
  106. }
  107. fmt.Fprintf(w, "%s}%s", indent, s.suffix)
  108. case reflect.Map:
  109. fmt.Fprintf(w, "%s{", v.Type())
  110. if v.Len() > 0 {
  111. fmt.Fprintln(w)
  112. keys := v.MapKeys()
  113. maybeSort(keys, v.Type().Key())
  114. for _, key := range keys {
  115. val := v.MapIndex(key)
  116. if s.defaults || !isDefault(val) {
  117. fprint(w, val, state{
  118. level: s.level + 1,
  119. prefix: short(key) + ": ",
  120. suffix: ",",
  121. defaults: s.defaults,
  122. })
  123. fmt.Fprintln(w)
  124. }
  125. }
  126. }
  127. fmt.Fprintf(w, "%s}%s", indent, s.suffix)
  128. case reflect.Struct:
  129. t := v.Type()
  130. fmt.Fprintf(w, "%s{\n", t)
  131. for i := 0; i < t.NumField(); i++ {
  132. f := v.Field(i)
  133. if s.defaults || !isDefault(f) {
  134. fprint(w, f, state{
  135. level: s.level + 1,
  136. prefix: t.Field(i).Name + ": ",
  137. suffix: ",",
  138. defaults: s.defaults,
  139. })
  140. fmt.Fprintln(w)
  141. }
  142. }
  143. fmt.Fprintf(w, "%s}%s", indent, s.suffix)
  144. }
  145. }
  146. func isNil(v reflect.Value) bool {
  147. if !v.IsValid() {
  148. return true
  149. }
  150. switch v.Type().Kind() {
  151. case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
  152. return v.IsNil()
  153. default:
  154. return false
  155. }
  156. }
  157. func isDefault(v reflect.Value) bool {
  158. if !v.IsValid() {
  159. return true
  160. }
  161. t := v.Type()
  162. switch t.Kind() {
  163. case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
  164. return v.IsNil()
  165. default:
  166. if !v.CanInterface() {
  167. return false
  168. }
  169. return t.Comparable() && v.Interface() == reflect.Zero(t).Interface()
  170. }
  171. }
  172. // short returns a short, one-line string for v.
  173. func short(v reflect.Value) string {
  174. if !v.IsValid() {
  175. return "nil"
  176. }
  177. if v.Type().Kind() == reflect.String {
  178. return fmt.Sprintf("%q", v)
  179. }
  180. return fmt.Sprintf("%v", v)
  181. }
  182. func indent(w io.Writer, level int) {
  183. for i := 0; i < level; i++ {
  184. io.WriteString(w, Indent) // ignore errors
  185. }
  186. }
  187. func maybeSort(vs []reflect.Value, t reflect.Type) {
  188. if less := lessFunc(t); less != nil {
  189. sort.Sort(&sorter{vs, less})
  190. }
  191. }
  192. // lessFunc returns a function that implements the "<" operator
  193. // for the given type, or nil if the type doesn't support "<" .
  194. func lessFunc(t reflect.Type) func(v1, v2 interface{}) bool {
  195. switch t.Kind() {
  196. case reflect.String:
  197. return func(v1, v2 interface{}) bool { return v1.(string) < v2.(string) }
  198. case reflect.Int:
  199. return func(v1, v2 interface{}) bool { return v1.(int) < v2.(int) }
  200. case reflect.Int8:
  201. return func(v1, v2 interface{}) bool { return v1.(int8) < v2.(int8) }
  202. case reflect.Int16:
  203. return func(v1, v2 interface{}) bool { return v1.(int16) < v2.(int16) }
  204. case reflect.Int32:
  205. return func(v1, v2 interface{}) bool { return v1.(int32) < v2.(int32) }
  206. case reflect.Int64:
  207. return func(v1, v2 interface{}) bool { return v1.(int64) < v2.(int64) }
  208. case reflect.Uint:
  209. return func(v1, v2 interface{}) bool { return v1.(uint) < v2.(uint) }
  210. case reflect.Uint8:
  211. return func(v1, v2 interface{}) bool { return v1.(uint8) < v2.(uint8) }
  212. case reflect.Uint16:
  213. return func(v1, v2 interface{}) bool { return v1.(uint16) < v2.(uint16) }
  214. case reflect.Uint32:
  215. return func(v1, v2 interface{}) bool { return v1.(uint32) < v2.(uint32) }
  216. case reflect.Uint64:
  217. return func(v1, v2 interface{}) bool { return v1.(uint64) < v2.(uint64) }
  218. case reflect.Float32:
  219. return func(v1, v2 interface{}) bool { return v1.(float32) < v2.(float32) }
  220. case reflect.Float64:
  221. return func(v1, v2 interface{}) bool { return v1.(float64) < v2.(float64) }
  222. default:
  223. return nil
  224. }
  225. }
  226. type sorter struct {
  227. vs []reflect.Value
  228. less func(v1, v2 interface{}) bool
  229. }
  230. func (s *sorter) Len() int { return len(s.vs) }
  231. func (s *sorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
  232. func (s *sorter) Less(i, j int) bool { return s.less(s.vs[i].Interface(), s.vs[j].Interface()) }