mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 01:53:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			122 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			122 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2019, The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package cmp
 | 
						|
 | 
						|
import "reflect"
 | 
						|
 | 
						|
// valueNode represents a single node within a report, which is a
 | 
						|
// structured representation of the value tree, containing information
 | 
						|
// regarding which nodes are equal or not.
 | 
						|
type valueNode struct {
 | 
						|
	parent *valueNode
 | 
						|
 | 
						|
	Type   reflect.Type
 | 
						|
	ValueX reflect.Value
 | 
						|
	ValueY reflect.Value
 | 
						|
 | 
						|
	// NumSame is the number of leaf nodes that are equal.
 | 
						|
	// All descendants are equal only if NumDiff is 0.
 | 
						|
	NumSame int
 | 
						|
	// NumDiff is the number of leaf nodes that are not equal.
 | 
						|
	NumDiff int
 | 
						|
	// NumIgnored is the number of leaf nodes that are ignored.
 | 
						|
	NumIgnored int
 | 
						|
	// NumCompared is the number of leaf nodes that were compared
 | 
						|
	// using an Equal method or Comparer function.
 | 
						|
	NumCompared int
 | 
						|
	// NumTransformed is the number of non-leaf nodes that were transformed.
 | 
						|
	NumTransformed int
 | 
						|
	// NumChildren is the number of transitive descendants of this node.
 | 
						|
	// This counts from zero; thus, leaf nodes have no descendants.
 | 
						|
	NumChildren int
 | 
						|
	// MaxDepth is the maximum depth of the tree. This counts from zero;
 | 
						|
	// thus, leaf nodes have a depth of zero.
 | 
						|
	MaxDepth int
 | 
						|
 | 
						|
	// Records is a list of struct fields, slice elements, or map entries.
 | 
						|
	Records []reportRecord // If populated, implies Value is not populated
 | 
						|
 | 
						|
	// Value is the result of a transformation, pointer indirect, of
 | 
						|
	// type assertion.
 | 
						|
	Value *valueNode // If populated, implies Records is not populated
 | 
						|
 | 
						|
	// TransformerName is the name of the transformer.
 | 
						|
	TransformerName string // If non-empty, implies Value is populated
 | 
						|
}
 | 
						|
type reportRecord struct {
 | 
						|
	Key   reflect.Value // Invalid for slice element
 | 
						|
	Value *valueNode
 | 
						|
}
 | 
						|
 | 
						|
func (parent *valueNode) PushStep(ps PathStep) (child *valueNode) {
 | 
						|
	vx, vy := ps.Values()
 | 
						|
	child = &valueNode{parent: parent, Type: ps.Type(), ValueX: vx, ValueY: vy}
 | 
						|
	switch s := ps.(type) {
 | 
						|
	case StructField:
 | 
						|
		assert(parent.Value == nil)
 | 
						|
		parent.Records = append(parent.Records, reportRecord{Key: reflect.ValueOf(s.Name()), Value: child})
 | 
						|
	case SliceIndex:
 | 
						|
		assert(parent.Value == nil)
 | 
						|
		parent.Records = append(parent.Records, reportRecord{Value: child})
 | 
						|
	case MapIndex:
 | 
						|
		assert(parent.Value == nil)
 | 
						|
		parent.Records = append(parent.Records, reportRecord{Key: s.Key(), Value: child})
 | 
						|
	case Indirect:
 | 
						|
		assert(parent.Value == nil && parent.Records == nil)
 | 
						|
		parent.Value = child
 | 
						|
	case TypeAssertion:
 | 
						|
		assert(parent.Value == nil && parent.Records == nil)
 | 
						|
		parent.Value = child
 | 
						|
	case Transform:
 | 
						|
		assert(parent.Value == nil && parent.Records == nil)
 | 
						|
		parent.Value = child
 | 
						|
		parent.TransformerName = s.Name()
 | 
						|
		parent.NumTransformed++
 | 
						|
	default:
 | 
						|
		assert(parent == nil) // Must be the root step
 | 
						|
	}
 | 
						|
	return child
 | 
						|
}
 | 
						|
 | 
						|
func (r *valueNode) Report(rs Result) {
 | 
						|
	assert(r.MaxDepth == 0) // May only be called on leaf nodes
 | 
						|
 | 
						|
	if rs.ByIgnore() {
 | 
						|
		r.NumIgnored++
 | 
						|
	} else {
 | 
						|
		if rs.Equal() {
 | 
						|
			r.NumSame++
 | 
						|
		} else {
 | 
						|
			r.NumDiff++
 | 
						|
		}
 | 
						|
	}
 | 
						|
	assert(r.NumSame+r.NumDiff+r.NumIgnored == 1)
 | 
						|
 | 
						|
	if rs.ByMethod() {
 | 
						|
		r.NumCompared++
 | 
						|
	}
 | 
						|
	if rs.ByFunc() {
 | 
						|
		r.NumCompared++
 | 
						|
	}
 | 
						|
	assert(r.NumCompared <= 1)
 | 
						|
}
 | 
						|
 | 
						|
func (child *valueNode) PopStep() (parent *valueNode) {
 | 
						|
	if child.parent == nil {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	parent = child.parent
 | 
						|
	parent.NumSame += child.NumSame
 | 
						|
	parent.NumDiff += child.NumDiff
 | 
						|
	parent.NumIgnored += child.NumIgnored
 | 
						|
	parent.NumCompared += child.NumCompared
 | 
						|
	parent.NumTransformed += child.NumTransformed
 | 
						|
	parent.NumChildren += child.NumChildren + 1
 | 
						|
	if parent.MaxDepth < child.MaxDepth+1 {
 | 
						|
		parent.MaxDepth = child.MaxDepth + 1
 | 
						|
	}
 | 
						|
	return parent
 | 
						|
}
 |