Skip to content

Commit

Permalink
Augment Report to indicate how comparison was determined
Browse files Browse the repository at this point in the history
This is necessary for the upcoming reporter re-implementation so that
it can format the differences with more intelligence.
No tests added in this PR since an upcoming change will heavily test
these code paths.
  • Loading branch information
dsnet committed Feb 26, 2019
1 parent 7586b66 commit 3150040
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 37 deletions.
50 changes: 22 additions & 28 deletions cmp/compare.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ func (s *state) compareAny(step PathStep) {
// TODO: Removing this check allows us FilterPath to operate on missing
// slice elements and map entries.
if !vx.IsValid() || !vy.IsValid() {
s.report(vx.IsValid() == vy.IsValid())
s.report(vx.IsValid() == vy.IsValid(), 0)
return
}

Expand All @@ -236,35 +236,35 @@ func (s *state) compareAny(step PathStep) {
// Rule 3: Recursively descend into each value's underlying kind.
switch t.Kind() {
case reflect.Bool:
s.report(vx.Bool() == vy.Bool())
s.report(vx.Bool() == vy.Bool(), 0)
return
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
s.report(vx.Int() == vy.Int())
s.report(vx.Int() == vy.Int(), 0)
return
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
s.report(vx.Uint() == vy.Uint())
s.report(vx.Uint() == vy.Uint(), 0)
return
case reflect.Float32, reflect.Float64:
s.report(vx.Float() == vy.Float())
s.report(vx.Float() == vy.Float(), 0)
return
case reflect.Complex64, reflect.Complex128:
s.report(vx.Complex() == vy.Complex())
s.report(vx.Complex() == vy.Complex(), 0)
return
case reflect.String:
s.report(vx.String() == vy.String())
s.report(vx.String() == vy.String(), 0)
return
case reflect.Chan, reflect.UnsafePointer:
s.report(vx.Pointer() == vy.Pointer())
s.report(vx.Pointer() == vy.Pointer(), 0)
return
case reflect.Func:
s.report(vx.IsNil() && vy.IsNil())
s.report(vx.IsNil() && vy.IsNil(), 0)
return
case reflect.Struct:
s.compareStruct(t, vx, vy)
return
case reflect.Slice:
if vx.IsNil() || vy.IsNil() {
s.report(vx.IsNil() && vy.IsNil())
s.report(vx.IsNil() && vy.IsNil(), 0)
return
}
fallthrough
Expand All @@ -276,20 +276,20 @@ func (s *state) compareAny(step PathStep) {
return
case reflect.Ptr:
if vx.IsNil() || vy.IsNil() {
s.report(vx.IsNil() && vy.IsNil())
s.report(vx.IsNil() && vy.IsNil(), 0)
return
}
vx, vy = vx.Elem(), vy.Elem()
s.compareAny(&indirect{pathStep{t.Elem(), vx, vy}})
return
case reflect.Interface:
if vx.IsNil() || vy.IsNil() {
s.report(vx.IsNil() && vy.IsNil())
s.report(vx.IsNil() && vy.IsNil(), 0)
return
}
vx, vy = vx.Elem(), vy.Elem()
if vx.Type() != vy.Type() {
s.report(false)
s.report(false, 0)
return
}
s.compareAny(&typeAssertion{pathStep{vx.Type(), vx, vy}})
Expand Down Expand Up @@ -324,7 +324,7 @@ func (s *state) tryMethod(t reflect.Type, vx, vy reflect.Value) bool {
}

eq := s.callTTBFunc(m.Func, vx, vy)
s.report(eq)
s.report(eq, reportByMethod)
return true
}

Expand Down Expand Up @@ -470,7 +470,7 @@ func (s *state) compareSlice(t reflect.Type, vx, vy reflect.Value) {

func (s *state) compareMap(t reflect.Type, vx, vy reflect.Value) {
if vx.IsNil() || vy.IsNil() {
s.report(vx.IsNil() && vy.IsNil())
s.report(vx.IsNil() && vy.IsNil(), 0)
return
}

Expand Down Expand Up @@ -503,24 +503,18 @@ func (s *state) compareMap(t reflect.Type, vx, vy reflect.Value) {
}
}

func (s *state) report(eq bool) {
if eq {
s.result.NumSame++
} else {
s.result.NumDiff++
}
for _, r := range s.reporters {
func (s *state) report(eq bool, rf reportFlags) {
if rf&reportIgnored == 0 {
if eq {
r.Report(reportEqual)
s.result.NumSame++
rf |= reportEqual
} else {
r.Report(reportUnequal)
s.result.NumDiff++
rf |= reportUnequal
}
}
}

func (s *state) reportIgnore() {
for _, r := range s.reporters {
r.Report(reportIgnore)
r.Report(rf)
}
}

Expand Down
25 changes: 16 additions & 9 deletions cmp/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ type ignore struct{ core }

func (ignore) isFiltered() bool { return false }
func (ignore) filter(_ *state, _ reflect.Type, _, _ reflect.Value) applicableOption { return ignore{} }
func (ignore) apply(s *state, _, _ reflect.Value) { s.reportIgnore() }
func (ignore) apply(s *state, _, _ reflect.Value) { s.report(true, reportIgnored) }
func (ignore) String() string { return "Ignore()" }

// validator is a sentinel Option type to indicate that some options could not
Expand All @@ -213,7 +213,7 @@ func (validator) apply(s *state, vx, vy reflect.Value) {
}

// Implies missing slice element or map entry.
s.report(vx.IsValid() == vy.IsValid())
s.report(vx.IsValid() == vy.IsValid(), 0)
}

// identRx represents a valid identifier according to the Go specification.
Expand Down Expand Up @@ -337,7 +337,7 @@ func (cm *comparer) filter(_ *state, t reflect.Type, _, _ reflect.Value) applica

func (cm *comparer) apply(s *state, vx, vy reflect.Value) {
eq := s.callTTBFunc(cm.fnc, vx, vy)
s.report(eq)
s.report(eq, reportByFunc)
}

func (cm comparer) String() string {
Expand Down Expand Up @@ -391,20 +391,27 @@ func (visibleStructs) filter(_ *state, _ reflect.Type, _, _ reflect.Value) appli
panic("not implemented")
}

type reportFlags uint64
// reportFlags is a bit-set representing how a comparison was determined.
type reportFlags uint

const (
_ reportFlags = (1 << iota) / 2

// reportEqual reports whether the node is equal.
// It may not be issued with reportIgnore or reportUnequal.
// This may be ORed with reportByMethod or reportByFunc.
reportEqual
// reportUnequal reports whether the node is not equal.
// It may not be issued with reportIgnore or reportEqual.
// This may be ORed with reportByMethod or reportByFunc.
reportUnequal
// reportIgnore reports whether the node was ignored.
// It may not be issued with reportEqual or reportUnequal.
reportIgnore
// ReportIgnored reports whether the node was ignored.
reportIgnored

// reportByMethod reports whether equality was determined by calling the
// Equal method. This may be ORed with reportEqual or reportUnequal.
reportByMethod
// reportByFunc reports whether equality was determined by calling a custom
// Comparer function. This may be ORed with reportEqual or reportUnequal.
reportByFunc
)

// reporter is an Option that can be passed to Equal. When Equal traverses
Expand Down

0 comments on commit 3150040

Please sign in to comment.