Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1960)

Unified Diff: render/render.go

Issue 1716743002: Better rendering for implicit types. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/go-render.git@master
Patch Set: Normalize copyright Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | render/render_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: render/render.go
diff --git a/render/render.go b/render/render.go
index e070a6b3b58151070bafd171a9f4f5336d4ab39c..bdb307ce9d49be5f2662606dbe61c7e6485edea8 100644
--- a/render/render.go
+++ b/render/render.go
@@ -12,32 +12,46 @@ import (
"strconv"
)
-var implicitTypeMap = map[reflect.Kind]string{
+var builtinTypeMap = map[reflect.Kind]string{
reflect.Bool: "bool",
- reflect.String: "string",
- reflect.Int: "int",
- reflect.Int8: "int8",
+ reflect.Complex128: "complex128",
+ reflect.Complex64: "complex64",
+ reflect.Float32: "float32",
+ reflect.Float64: "float64",
reflect.Int16: "int16",
reflect.Int32: "int32",
reflect.Int64: "int64",
- reflect.Uint: "uint",
- reflect.Uint8: "uint8",
+ reflect.Int8: "int8",
+ reflect.Int: "int",
+ reflect.String: "string",
reflect.Uint16: "uint16",
reflect.Uint32: "uint32",
reflect.Uint64: "uint64",
- reflect.Float32: "float32",
- reflect.Float64: "float64",
- reflect.Complex64: "complex64",
- reflect.Complex128: "complex128",
+ reflect.Uint8: "uint8",
+ reflect.Uint: "uint",
+ reflect.Uintptr: "uintptr",
+}
+
+var builtinTypeSet = map[string]struct{}{}
+
+func init() {
+ for _, v := range builtinTypeMap {
+ builtinTypeSet[v] = struct{}{}
+ }
}
+var typeOfString = reflect.TypeOf("")
+var typeOfInt = reflect.TypeOf(int(1))
+var typeOfUint = reflect.TypeOf(uint(1))
+var typeOfFloat = reflect.TypeOf(10.1)
+
// Render converts a structure to a string representation. Unline the "%#v"
// format string, this resolves pointer types' contents in structs, maps, and
// slices/arrays and prints their field values.
func Render(v interface{}) string {
buf := bytes.Buffer{}
s := (*traverseState)(nil)
- s.render(&buf, 0, reflect.ValueOf(v))
+ s.render(&buf, 0, reflect.ValueOf(v), false)
return buf.String()
}
@@ -72,7 +86,7 @@ func (s *traverseState) forkFor(ptr uintptr) *traverseState {
return fs
}
-func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value) {
+func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value, implicit bool) {
if v.Kind() == reflect.Invalid {
buf.WriteString("nil")
return
@@ -107,49 +121,76 @@ func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value) {
s = s.forkFor(pe)
if s == nil {
buf.WriteString("<REC(")
- writeType(buf, ptrs, vt)
+ if !implicit {
+ writeType(buf, ptrs, vt)
+ }
buf.WriteString(")>")
return
}
}
+ isAnon := func(t reflect.Type) bool {
+ if t.Name() != "" {
+ if _, ok := builtinTypeSet[t.Name()]; !ok {
+ return false
+ }
+ }
+ return t.Kind() != reflect.Interface
+ }
+
switch vk {
case reflect.Struct:
- writeType(buf, ptrs, vt)
+ if !implicit {
+ writeType(buf, ptrs, vt)
+ }
+ structAnon := vt.Name() == ""
buf.WriteRune('{')
for i := 0; i < vt.NumField(); i++ {
if i > 0 {
buf.WriteString(", ")
}
- buf.WriteString(vt.Field(i).Name)
- buf.WriteRune(':')
+ anon := structAnon && isAnon(vt.Field(i).Type)
+
+ if !anon {
+ buf.WriteString(vt.Field(i).Name)
+ buf.WriteRune(':')
+ }
- s.render(buf, 0, v.Field(i))
+ s.render(buf, 0, v.Field(i), anon)
}
buf.WriteRune('}')
case reflect.Slice:
if v.IsNil() {
- writeType(buf, ptrs, vt)
- buf.WriteString("(nil)")
+ if !implicit {
+ writeType(buf, ptrs, vt)
+ buf.WriteString("(nil)")
+ } else {
+ buf.WriteString("nil")
+ }
return
}
fallthrough
case reflect.Array:
- writeType(buf, ptrs, vt)
+ if !implicit {
+ writeType(buf, ptrs, vt)
+ }
+ anon := vt.Name() == "" && isAnon(vt.Elem())
buf.WriteString("{")
for i := 0; i < v.Len(); i++ {
if i > 0 {
buf.WriteString(", ")
}
- s.render(buf, 0, v.Index(i))
+ s.render(buf, 0, v.Index(i), anon)
}
buf.WriteRune('}')
case reflect.Map:
- writeType(buf, ptrs, vt)
+ if !implicit {
+ writeType(buf, ptrs, vt)
+ }
if v.IsNil() {
buf.WriteString("(nil)")
} else {
@@ -158,14 +199,17 @@ func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value) {
mkeys := v.MapKeys()
tryAndSortMapKeys(vt, mkeys)
+ kt := vt.Key()
+ keyAnon := typeOfString.ConvertibleTo(kt) || typeOfInt.ConvertibleTo(kt) || typeOfUint.ConvertibleTo(kt) || typeOfFloat.ConvertibleTo(kt)
+ valAnon := vt.Name() == "" && isAnon(vt.Elem())
for i, mk := range mkeys {
if i > 0 {
buf.WriteString(", ")
}
- s.render(buf, 0, mk)
+ s.render(buf, 0, mk, keyAnon)
buf.WriteString(":")
- s.render(buf, 0, v.MapIndex(mk))
+ s.render(buf, 0, v.MapIndex(mk), valAnon)
}
buf.WriteRune('}')
}
@@ -176,11 +220,9 @@ func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value) {
case reflect.Interface:
if v.IsNil() {
writeType(buf, ptrs, v.Type())
- buf.WriteRune('(')
- fmt.Fprint(buf, "nil")
- buf.WriteRune(')')
+ buf.WriteString("(nil)")
} else {
- s.render(buf, ptrs, v.Elem())
+ s.render(buf, ptrs, v.Elem(), false)
}
case reflect.Chan, reflect.Func, reflect.UnsafePointer:
@@ -191,7 +233,7 @@ func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value) {
default:
tstr := vt.String()
- implicit := ptrs == 0 && implicitTypeMap[vk] == tstr
+ implicit = implicit || (ptrs == 0 && builtinTypeMap[vk] == tstr)
if !implicit {
writeType(buf, ptrs, vt)
buf.WriteRune('(')
@@ -206,7 +248,7 @@ func (s *traverseState) render(buf *bytes.Buffer, ptrs int, v reflect.Value) {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
fmt.Fprintf(buf, "%d", v.Int())
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
fmt.Fprintf(buf, "%d", v.Uint())
case reflect.Float32, reflect.Float64:
« no previous file with comments | « no previous file | render/render_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698