Browse Source

make nil maps appear different than empty maps

deads2k 11 years ago
parent
commit
1aaf839fb0
4 changed files with 25 additions and 0 deletions
  1. 6 0
      spew/dump.go
  2. 8 0
      spew/dump_test.go
  3. 6 0
      spew/format.go
  4. 5 0
      spew/format_test.go

+ 6 - 0
spew/dump.go

@@ -367,6 +367,12 @@ func (d *dumpState) dump(v reflect.Value) {
 		// been handled above.
 
 	case reflect.Map:
+		// nil maps should be indicated as different than empty maps
+		if v.IsNil() {
+			d.w.Write(nilAngleBytes)
+			break
+		}
+
 		d.w.Write(openBraceNewlineBytes)
 		d.depth++
 		if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) {

+ 8 - 0
spew/dump_test.go

@@ -547,6 +547,7 @@ func addMapDumpTests() {
 	klen := fmt.Sprintf("%d", len(k)) // not kLen to shut golint up
 	kkLen := fmt.Sprintf("%d", len(kk))
 	mLen := fmt.Sprintf("%d", len(m))
+	nilMap := map[string]int(nil)
 	nm := (*map[string]int)(nil)
 	pm := &m
 	mAddr := fmt.Sprintf("%p", pm)
@@ -566,6 +567,7 @@ func addMapDumpTests() {
 	addDumpTest(&pm, "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms+")\n",
 		"(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms2+")\n")
 	addDumpTest(nm, "(*"+mt+")(<nil>)\n")
+	addDumpTest(nilMap, "("+mt+") <nil>\n")
 
 	// Map with custom formatter type on pointer receiver only keys and vals.
 	k2 := pstringer("one")
@@ -574,6 +576,7 @@ func addMapDumpTests() {
 	k2Len := fmt.Sprintf("%d", len(k2))
 	v2Len := fmt.Sprintf("%d", len(v2))
 	m2Len := fmt.Sprintf("%d", len(m2))
+	nilMap2 := map[pstringer]pstringer(nil)
 	nm2 := (*map[pstringer]pstringer)(nil)
 	pm2 := &m2
 	m2Addr := fmt.Sprintf("%p", pm2)
@@ -587,12 +590,14 @@ func addMapDumpTests() {
 	addDumpTest(pm2, "(*"+m2t+")("+m2Addr+")("+m2s+")\n")
 	addDumpTest(&pm2, "(**"+m2t+")("+pm2Addr+"->"+m2Addr+")("+m2s+")\n")
 	addDumpTest(nm2, "(*"+m2t+")(<nil>)\n")
+	addDumpTest(nilMap2, "("+m2t+") <nil>\n")
 
 	// Map with interface keys and values.
 	k3 := "one"
 	k3Len := fmt.Sprintf("%d", len(k3))
 	m3 := map[interface{}]interface{}{k3: 1}
 	m3Len := fmt.Sprintf("%d", len(m3))
+	nilMap3 := map[interface{}]interface{}(nil)
 	nm3 := (*map[interface{}]interface{})(nil)
 	pm3 := &m3
 	m3Addr := fmt.Sprintf("%p", pm3)
@@ -606,12 +611,14 @@ func addMapDumpTests() {
 	addDumpTest(pm3, "(*"+m3t+")("+m3Addr+")("+m3s+")\n")
 	addDumpTest(&pm3, "(**"+m3t+")("+pm3Addr+"->"+m3Addr+")("+m3s+")\n")
 	addDumpTest(nm3, "(*"+m3t+")(<nil>)\n")
+	addDumpTest(nilMap3, "("+m3t+") <nil>\n")
 
 	// Map with nil interface value.
 	k4 := "nil"
 	k4Len := fmt.Sprintf("%d", len(k4))
 	m4 := map[string]interface{}{k4: nil}
 	m4Len := fmt.Sprintf("%d", len(m4))
+	nilMap4 := map[string]interface{}(nil)
 	nm4 := (*map[string]interface{})(nil)
 	pm4 := &m4
 	m4Addr := fmt.Sprintf("%p", pm4)
@@ -625,6 +632,7 @@ func addMapDumpTests() {
 	addDumpTest(pm4, "(*"+m4t+")("+m4Addr+")("+m4s+")\n")
 	addDumpTest(&pm4, "(**"+m4t+")("+pm4Addr+"->"+m4Addr+")("+m4s+")\n")
 	addDumpTest(nm4, "(*"+m4t+")(<nil>)\n")
+	addDumpTest(nilMap4, "("+m4t+") <nil>\n")
 }
 
 func addStructDumpTests() {

+ 6 - 0
spew/format.go

@@ -296,6 +296,12 @@ func (f *formatState) format(v reflect.Value) {
 		// been handled above.
 
 	case reflect.Map:
+		// nil maps should be indicated as different than empty maps
+		if v.IsNil() {
+			f.fs.Write(nilAngleBytes)
+			break
+		}
+
 		f.fs.Write(openMapBytes)
 		f.depth++
 		if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) {

+ 5 - 0
spew/format_test.go

@@ -762,6 +762,7 @@ func addInterfaceFormatterTests() {
 func addMapFormatterTests() {
 	// Map with string keys and int vals.
 	v := map[string]int{"one": 1, "two": 2}
+	nilMap := map[string]int(nil)
 	nv := (*map[string]int)(nil)
 	pv := &v
 	vAddr := fmt.Sprintf("%p", pv)
@@ -772,21 +773,25 @@ func addMapFormatterTests() {
 	addFormatterTest("%v", v, vs, vs2)
 	addFormatterTest("%v", pv, "<*>"+vs, "<*>"+vs2)
 	addFormatterTest("%v", &pv, "<**>"+vs, "<**>"+vs2)
+	addFormatterTest("%+v", nilMap, "<nil>")
 	addFormatterTest("%+v", nv, "<nil>")
 	addFormatterTest("%+v", v, vs, vs2)
 	addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs, "<*>("+vAddr+")"+vs2)
 	addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs,
 		"<**>("+pvAddr+"->"+vAddr+")"+vs2)
+	addFormatterTest("%+v", nilMap, "<nil>")
 	addFormatterTest("%+v", nv, "<nil>")
 	addFormatterTest("%#v", v, "("+vt+")"+vs, "("+vt+")"+vs2)
 	addFormatterTest("%#v", pv, "(*"+vt+")"+vs, "(*"+vt+")"+vs2)
 	addFormatterTest("%#v", &pv, "(**"+vt+")"+vs, "(**"+vt+")"+vs2)
+	addFormatterTest("%#v", nilMap, "("+vt+")"+"<nil>")
 	addFormatterTest("%#v", nv, "(*"+vt+")"+"<nil>")
 	addFormatterTest("%#+v", v, "("+vt+")"+vs, "("+vt+")"+vs2)
 	addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs,
 		"(*"+vt+")("+vAddr+")"+vs2)
 	addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs,
 		"(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs2)
+	addFormatterTest("%#+v", nilMap, "("+vt+")"+"<nil>")
 	addFormatterTest("%#+v", nv, "(*"+vt+")"+"<nil>")
 
 	// Map with custom formatter type on pointer receiver only keys and vals.