xref: /aosp_15_r20/external/go-cmp/cmp/report_value.go (revision 88d15eac089d7f20c739ff1001d56b91872b21a1)
1*88d15eacSSasha Smundak// Copyright 2019, The Go Authors. All rights reserved.
2*88d15eacSSasha Smundak// Use of this source code is governed by a BSD-style
3*88d15eacSSasha Smundak// license that can be found in the LICENSE file.
4*88d15eacSSasha Smundak
5*88d15eacSSasha Smundakpackage cmp
6*88d15eacSSasha Smundak
7*88d15eacSSasha Smundakimport "reflect"
8*88d15eacSSasha Smundak
9*88d15eacSSasha Smundak// valueNode represents a single node within a report, which is a
10*88d15eacSSasha Smundak// structured representation of the value tree, containing information
11*88d15eacSSasha Smundak// regarding which nodes are equal or not.
12*88d15eacSSasha Smundaktype valueNode struct {
13*88d15eacSSasha Smundak	parent *valueNode
14*88d15eacSSasha Smundak
15*88d15eacSSasha Smundak	Type   reflect.Type
16*88d15eacSSasha Smundak	ValueX reflect.Value
17*88d15eacSSasha Smundak	ValueY reflect.Value
18*88d15eacSSasha Smundak
19*88d15eacSSasha Smundak	// NumSame is the number of leaf nodes that are equal.
20*88d15eacSSasha Smundak	// All descendants are equal only if NumDiff is 0.
21*88d15eacSSasha Smundak	NumSame int
22*88d15eacSSasha Smundak	// NumDiff is the number of leaf nodes that are not equal.
23*88d15eacSSasha Smundak	NumDiff int
24*88d15eacSSasha Smundak	// NumIgnored is the number of leaf nodes that are ignored.
25*88d15eacSSasha Smundak	NumIgnored int
26*88d15eacSSasha Smundak	// NumCompared is the number of leaf nodes that were compared
27*88d15eacSSasha Smundak	// using an Equal method or Comparer function.
28*88d15eacSSasha Smundak	NumCompared int
29*88d15eacSSasha Smundak	// NumTransformed is the number of non-leaf nodes that were transformed.
30*88d15eacSSasha Smundak	NumTransformed int
31*88d15eacSSasha Smundak	// NumChildren is the number of transitive descendants of this node.
32*88d15eacSSasha Smundak	// This counts from zero; thus, leaf nodes have no descendants.
33*88d15eacSSasha Smundak	NumChildren int
34*88d15eacSSasha Smundak	// MaxDepth is the maximum depth of the tree. This counts from zero;
35*88d15eacSSasha Smundak	// thus, leaf nodes have a depth of zero.
36*88d15eacSSasha Smundak	MaxDepth int
37*88d15eacSSasha Smundak
38*88d15eacSSasha Smundak	// Records is a list of struct fields, slice elements, or map entries.
39*88d15eacSSasha Smundak	Records []reportRecord // If populated, implies Value is not populated
40*88d15eacSSasha Smundak
41*88d15eacSSasha Smundak	// Value is the result of a transformation, pointer indirect, of
42*88d15eacSSasha Smundak	// type assertion.
43*88d15eacSSasha Smundak	Value *valueNode // If populated, implies Records is not populated
44*88d15eacSSasha Smundak
45*88d15eacSSasha Smundak	// TransformerName is the name of the transformer.
46*88d15eacSSasha Smundak	TransformerName string // If non-empty, implies Value is populated
47*88d15eacSSasha Smundak}
48*88d15eacSSasha Smundaktype reportRecord struct {
49*88d15eacSSasha Smundak	Key   reflect.Value // Invalid for slice element
50*88d15eacSSasha Smundak	Value *valueNode
51*88d15eacSSasha Smundak}
52*88d15eacSSasha Smundak
53*88d15eacSSasha Smundakfunc (parent *valueNode) PushStep(ps PathStep) (child *valueNode) {
54*88d15eacSSasha Smundak	vx, vy := ps.Values()
55*88d15eacSSasha Smundak	child = &valueNode{parent: parent, Type: ps.Type(), ValueX: vx, ValueY: vy}
56*88d15eacSSasha Smundak	switch s := ps.(type) {
57*88d15eacSSasha Smundak	case StructField:
58*88d15eacSSasha Smundak		assert(parent.Value == nil)
59*88d15eacSSasha Smundak		parent.Records = append(parent.Records, reportRecord{Key: reflect.ValueOf(s.Name()), Value: child})
60*88d15eacSSasha Smundak	case SliceIndex:
61*88d15eacSSasha Smundak		assert(parent.Value == nil)
62*88d15eacSSasha Smundak		parent.Records = append(parent.Records, reportRecord{Value: child})
63*88d15eacSSasha Smundak	case MapIndex:
64*88d15eacSSasha Smundak		assert(parent.Value == nil)
65*88d15eacSSasha Smundak		parent.Records = append(parent.Records, reportRecord{Key: s.Key(), Value: child})
66*88d15eacSSasha Smundak	case Indirect:
67*88d15eacSSasha Smundak		assert(parent.Value == nil && parent.Records == nil)
68*88d15eacSSasha Smundak		parent.Value = child
69*88d15eacSSasha Smundak	case TypeAssertion:
70*88d15eacSSasha Smundak		assert(parent.Value == nil && parent.Records == nil)
71*88d15eacSSasha Smundak		parent.Value = child
72*88d15eacSSasha Smundak	case Transform:
73*88d15eacSSasha Smundak		assert(parent.Value == nil && parent.Records == nil)
74*88d15eacSSasha Smundak		parent.Value = child
75*88d15eacSSasha Smundak		parent.TransformerName = s.Name()
76*88d15eacSSasha Smundak		parent.NumTransformed++
77*88d15eacSSasha Smundak	default:
78*88d15eacSSasha Smundak		assert(parent == nil) // Must be the root step
79*88d15eacSSasha Smundak	}
80*88d15eacSSasha Smundak	return child
81*88d15eacSSasha Smundak}
82*88d15eacSSasha Smundak
83*88d15eacSSasha Smundakfunc (r *valueNode) Report(rs Result) {
84*88d15eacSSasha Smundak	assert(r.MaxDepth == 0) // May only be called on leaf nodes
85*88d15eacSSasha Smundak
86*88d15eacSSasha Smundak	if rs.ByIgnore() {
87*88d15eacSSasha Smundak		r.NumIgnored++
88*88d15eacSSasha Smundak	} else {
89*88d15eacSSasha Smundak		if rs.Equal() {
90*88d15eacSSasha Smundak			r.NumSame++
91*88d15eacSSasha Smundak		} else {
92*88d15eacSSasha Smundak			r.NumDiff++
93*88d15eacSSasha Smundak		}
94*88d15eacSSasha Smundak	}
95*88d15eacSSasha Smundak	assert(r.NumSame+r.NumDiff+r.NumIgnored == 1)
96*88d15eacSSasha Smundak
97*88d15eacSSasha Smundak	if rs.ByMethod() {
98*88d15eacSSasha Smundak		r.NumCompared++
99*88d15eacSSasha Smundak	}
100*88d15eacSSasha Smundak	if rs.ByFunc() {
101*88d15eacSSasha Smundak		r.NumCompared++
102*88d15eacSSasha Smundak	}
103*88d15eacSSasha Smundak	assert(r.NumCompared <= 1)
104*88d15eacSSasha Smundak}
105*88d15eacSSasha Smundak
106*88d15eacSSasha Smundakfunc (child *valueNode) PopStep() (parent *valueNode) {
107*88d15eacSSasha Smundak	if child.parent == nil {
108*88d15eacSSasha Smundak		return nil
109*88d15eacSSasha Smundak	}
110*88d15eacSSasha Smundak	parent = child.parent
111*88d15eacSSasha Smundak	parent.NumSame += child.NumSame
112*88d15eacSSasha Smundak	parent.NumDiff += child.NumDiff
113*88d15eacSSasha Smundak	parent.NumIgnored += child.NumIgnored
114*88d15eacSSasha Smundak	parent.NumCompared += child.NumCompared
115*88d15eacSSasha Smundak	parent.NumTransformed += child.NumTransformed
116*88d15eacSSasha Smundak	parent.NumChildren += child.NumChildren + 1
117*88d15eacSSasha Smundak	if parent.MaxDepth < child.MaxDepth+1 {
118*88d15eacSSasha Smundak		parent.MaxDepth = child.MaxDepth + 1
119*88d15eacSSasha Smundak	}
120*88d15eacSSasha Smundak	return parent
121*88d15eacSSasha Smundak}
122