Skip to content

Commit

Permalink
feat: Hide[T]() completely omits fields of the given type
Browse files Browse the repository at this point in the history
  • Loading branch information
alecthomas committed Oct 3, 2023
1 parent cded7b9 commit 10866c5
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 16 deletions.
28 changes: 14 additions & 14 deletions repr.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,12 @@ func IgnorePrivate() Option { return func(o *Printer) { o.ignorePrivate = true }
// For example, `time.Hour` will be printed as `time.Duration(3600000000000)` rather than `time.Duration(1h0m0s)`.
func ScalarLiterals() Option { return func(o *Printer) { o.useLiterals = true } }

// Hide excludes the given types from representation, instead just printing the name of the type.
func Hide(ts ...any) Option {
// Hide excludes fields of the given type from representation.
func Hide[T any]() Option {
return func(o *Printer) {
for _, t := range ts {
rt := reflect.Indirect(reflect.ValueOf(t)).Type()
o.exclude[rt] = true
}
t := (*T)(nil) // A bit of skulduggery so we can Hide() interfaces.
rt := reflect.TypeOf(t).Elem()
o.exclude[rt] = true
}
}

Expand Down Expand Up @@ -167,10 +166,6 @@ func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent
fmt.Fprint(p.w, "nil")
return
}
if p.exclude[v.Type()] {
fmt.Fprintf(p.w, "%s...", v.Type().Name())
return
}
t := v.Type()

if t == byteSliceType {
Expand All @@ -186,7 +181,7 @@ func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent
}
}
// Attempt to use fmt.GoStringer interface.
if !p.ignoreGoStringer && t.Implements(goStringerType) {
if !p.ignoreGoStringer && t.Implements(goStringerType) && v.CanInterface() {
fmt.Fprint(p.w, v.Interface().(fmt.GoStringer).GoString())
return
}
Expand Down Expand Up @@ -254,8 +249,12 @@ func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent
if p.indent != "" && v.NumField() != 0 {
fmt.Fprintf(p.w, "\n")
}
previous := false
for i := 0; i < v.NumField(); i++ {
t := v.Type().Field(i)
if p.exclude[t.Type] {
continue
}
f := v.Field(i)
// skip private fields
if p.ignorePrivate && !f.CanInterface() {
Expand All @@ -264,6 +263,10 @@ func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent
if p.omitEmpty && f.IsZero() {
continue
}
if previous && p.indent == "" {
fmt.Fprintf(p.w, ", ")
}
previous = true
fmt.Fprintf(p.w, "%s%s: ", ni, t.Name)
p.reprValue(seen, f, ni, true, t.Type == anyType)

Expand Down Expand Up @@ -291,11 +294,8 @@ func (p *Printer) reprValue(seen map[reflect.Value]bool, v reflect.Value, indent
continue
}
}

if p.indent != "" {
fmt.Fprintf(p.w, ",\n")
} else if i < v.NumField()-1 {
fmt.Fprintf(p.w, ", ")
}
}
fmt.Fprintf(p.w, "%s}", indent)
Expand Down
23 changes: 21 additions & 2 deletions repr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package repr

import (
"bytes"
"fmt"
"runtime"
"strings"
"testing"
Expand All @@ -19,12 +20,30 @@ type anotherStruct struct {
A []int
}

func (anotherStruct) String() string { return "anotherStruct" }

type testStruct struct {
S string
I *int
A anotherStruct
}

type testStructWithInterfaceField struct {
S string
I fmt.Stringer
}

func TestHide(t *testing.T) {
actual := testStruct{
S: "str",
A: anotherStruct{A: []int{1}},
}
equal(t, `repr.testStruct{S: "str"}`, String(actual, Hide[anotherStruct]()))
equal(t, "repr.testStruct{\n S: \"str\",\n}", String(actual, Indent(" "), Hide[anotherStruct]()))
equal(t, "repr.testStructWithInterfaceField{S: \"str\"}",
String(testStructWithInterfaceField{S: "str", I: anotherStruct{}}, Hide[fmt.Stringer]()))
}

func TestReprEmptyArray(t *testing.T) {
equal(t, "[]string{}", String([]string{}, OmitEmpty(false)))
}
Expand Down Expand Up @@ -196,7 +215,7 @@ func TestRecursiveIssue3(t *testing.T) {
child := &data{}
root := &data{children: []*data{child}}
child.parent = root
want := "&repr.data{children: []*repr.data{{parent: &..., }}}"
want := "&repr.data{children: []*repr.data{{parent: &...}}}"
have := String(root)
equal(t, want, have)
}
Expand All @@ -217,7 +236,7 @@ func TestReprPrivateBytes(t *testing.T) {
case strings.Contains(v, "go1.10"), strings.Contains(v, "go1.11"):
equal(t, "repr.MyBuffer{buf: &bytes.Buffer{buf: []byte(\"Hi th3re!\"), bootstrap: [64]uint8{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }}", s)
default:
equal(t, "repr.MyBuffer{buf: &bytes.Buffer{buf: []byte(\"Hi th3re!\"), }}", s)
equal(t, "repr.MyBuffer{buf: &bytes.Buffer{buf: []byte(\"Hi th3re!\")}}", s)
}
}

Expand Down

0 comments on commit 10866c5

Please sign in to comment.