or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

cmp-core.mdcmp-options.mdcmp-path.mdcmpopts.mdindex.md
tile.json

cmp-path.mddocs/

Path Navigation and Reporting

The cmp package provides types for navigating the comparison tree and implementing custom reporting of comparison results.

Import

import (
    "reflect"
    "github.com/google/go-cmp/cmp"
)

Path Types

Path

type Path []PathStep

Path is a list of PathStep describing the sequence of operations to get from some root type to the current position in the value tree. The first Path element is always an operation-less PathStep that exists simply to identify the initial type.

Note: When traversing structs with embedded structs, the embedded struct is always accessed as a field before traversing its fields.

Methods:

func (pa Path) String() string

String returns the simplified path to a node. The simplified path only contains struct field accesses.

Example output: MyMap.MySlices.MyField

func (pa Path) GoString() string

GoString returns the path to a specific node using Go syntax.

Example output: (*root.MyMap["key"].(*mypkg.MyStruct).MySlices)[2][3].MyField

func (pa Path) Index(i int) PathStep

Index returns the ith step in the Path and supports negative indexing. A negative index starts counting from the tail (-1 is last step, -2 is second-to-last, etc.). If index is invalid, returns a non-nil PathStep that reports a nil Type.

Parameters:

  • i int - Index of step to retrieve (supports negative indexing)

Returns:

  • PathStep - The path step at the specified index
func (pa Path) Last() PathStep

Last returns the last PathStep in the Path. If the path is empty, returns a non-nil PathStep that reports a nil Type.

Returns:

  • PathStep - The last path step

PathStep

type PathStep interface {
    String() string
    Type() reflect.Type
    Values() (vx, vy reflect.Value)
}

PathStep is a union-type for specific operations to traverse a value's tree structure. Users never need to implement these types as values are returned by this package.

Implementations:

  • StructField
  • SliceIndex
  • MapIndex
  • Indirect
  • TypeAssertion
  • Transform

Methods:

  • String() string - Returns string representation of the step
  • Type() reflect.Type - Returns resulting type after performing the path step
  • Values() (vx, vy reflect.Value) - Returns resulting values after performing the path step. Type of each valid value is guaranteed identical to Type. In some cases, one or both may be invalid or have restrictions (see specific PathStep implementations).

PathStep Implementations

StructField

type StructField struct {
    // Has unexported fields
}

StructField is a PathStep that represents a struct field access.

Methods:

func (sf StructField) Name() string

Name returns the field name.

func (sf StructField) Index() int

Index returns the index of the field in the parent struct type. See reflect.Type.Field.

func (sf StructField) String() string
func (sf StructField) Type() reflect.Type
func (sf StructField) Values() (vx, vy reflect.Value)

Values returns the field values. Both are not interface-able if the current field is unexported and the struct type is not explicitly permitted by an Exporter to traverse unexported fields.

SliceIndex

type SliceIndex struct {
    // Has unexported fields
}

SliceIndex is a PathStep that represents an index operation on a slice or array.

Methods:

func (si SliceIndex) Key() int

Key returns the index key. May return -1 if in a split state.

func (si SliceIndex) SplitKeys() (ix, iy int)

SplitKeys returns the indexes for indexing into slices in the x and y values, respectively. These indexes may differ due to insertion or removal of an element, causing all indexes to shift. If an index is -1, the element does not exist in the associated slice.

SliceIndex.Key is guaranteed to return -1 if and only if the indexes returned by SplitKeys are not the same. SplitKeys will never return -1 for both indexes.

Returns:

  • ix int - Index in x slice
  • iy int - Index in y slice
func (si SliceIndex) String() string
func (si SliceIndex) Type() reflect.Type
func (si SliceIndex) Values() (vx, vy reflect.Value)

Values returns the element values. One may be invalid if an element is missing from either the x or y slice.

MapIndex

type MapIndex struct {
    // Has unexported fields
}

MapIndex is a PathStep that represents an index operation on a map at some index Key.

Methods:

func (mi MapIndex) Key() reflect.Value

Key returns the value of the map key.

func (mi MapIndex) String() string
func (mi MapIndex) Type() reflect.Type
func (mi MapIndex) Values() (vx, vy reflect.Value)

Values returns the map entry values. One may be invalid if an entry is missing from either the x or y map.

Indirect

type Indirect struct {
    // Has unexported fields
}

Indirect is a PathStep that represents pointer indirection on the parent type.

Methods:

func (in Indirect) String() string
func (in Indirect) Type() reflect.Type
func (in Indirect) Values() (vx, vy reflect.Value)

TypeAssertion

type TypeAssertion struct {
    // Has unexported fields
}

TypeAssertion is a PathStep that represents a type assertion on an interface.

Methods:

func (ta TypeAssertion) String() string
func (ta TypeAssertion) Type() reflect.Type
func (ta TypeAssertion) Values() (vx, vy reflect.Value)

Transform

type Transform struct {
    // Has unexported fields
}

Transform is a PathStep that represents a transformation from the parent type to the current type.

Methods:

func (tf Transform) Name() string

Name returns the name of the Transformer.

func (tf Transform) Func() reflect.Value

Func returns the function pointer to the transformer function.

func (tf Transform) Option() Option

Option returns the originally constructed Transformer option. The == operator can be used to detect the exact option used.

func (tf Transform) String() string
func (tf Transform) Type() reflect.Type
func (tf Transform) Values() (vx, vy reflect.Value)

Custom Reporting

Reporter

func Reporter(r interface {
    PushStep(PathStep)
    Report(Result)
    PopStep()
}) Option

Reporter is an Option that can be passed to Equal. When Equal traverses the value trees, it calls PushStep as it descends into each node and PopStep as it ascends out. Leaf nodes are either compared (equal or not equal) or ignored, reported via the Report method.

Parameters:

  • r interface{} - Must implement the reporter interface with three methods:
    • PushStep(PathStep) - Called when a tree-traversal operation is performed. The PathStep itself is only valid until popped. The PathStep.Values are valid for entire traversal and must not be mutated. Equal always calls PushStep at start with operation-less PathStep for root values. Within a slice, exact set of inserted/removed/modified elements is unspecified. Map entries are iterated in unspecified order.
    • Report(Result) - Called exactly once on leaf nodes to report whether comparison identified the node as equal, unequal, or ignored. A leaf node is immediately preceded and followed by PushStep/PopStep calls.
    • PopStep() - Ascends back up the value tree. Always a matching pop for every push.

Returns:

  • Option - Configuration option

Example:

type DiffReporter struct {
    path  cmp.Path
    diffs []string
}

func (r *DiffReporter) PushStep(ps cmp.PathStep) {
    r.path = append(r.path, ps)
}

func (r *DiffReporter) Report(rs cmp.Result) {
    if !rs.Equal() {
        vx, vy := r.path.Last().Values()
        r.diffs = append(r.diffs, fmt.Sprintf("%s: %v != %v", r.path, vx, vy))
    }
}

func (r *DiffReporter) PopStep() {
    r.path = r.path[:len(r.path)-1]
}

// Usage
reporter := &DiffReporter{}
cmp.Equal(x, y, cmp.Reporter(reporter))
for _, diff := range reporter.diffs {
    fmt.Println(diff)
}

Result

type Result struct {
    // Has unexported fields
}

Result represents the comparison result for a single node. Provided by cmp when calling Report (see Reporter).

Methods:

func (r Result) Equal() bool

Equal reports whether the node was determined to be equal or not. As a special case, ignored nodes are considered equal.

func (r Result) ByIgnore() bool

ByIgnore reports whether the node is equal because it was ignored. Never reports true if Result.Equal reports false.

func (r Result) ByFunc() bool

ByFunc reports whether a Comparer function determined equality.

func (r Result) ByMethod() bool

ByMethod reports whether the Equal method determined equality.

func (r Result) ByCycle() bool

ByCycle reports whether a reference cycle was detected.