diff --git a/cmp/cmpopts/ignore.go b/cmp/cmpopts/ignore.go index 016891d..e86554b 100644 --- a/cmp/cmpopts/ignore.go +++ b/cmp/cmpopts/ignore.go @@ -50,7 +50,7 @@ func (tf typeFilter) filter(p cmp.Path) bool { if len(p) < 1 { return false } - t := p[len(p)-1].Type() + t := p.Last().Type() for _, ti := range tf { if t.AssignableTo(ti) { return true @@ -95,7 +95,7 @@ func (tf ifaceFilter) filter(p cmp.Path) bool { if len(p) < 1 { return false } - t := p[len(p)-1].Type() + t := p.Last().Type() for _, ti := range tf { if t.AssignableTo(ti) { return true @@ -131,14 +131,11 @@ func newUnexportedFilter(typs ...interface{}) unexportedFilter { return ux } func (xf unexportedFilter) filter(p cmp.Path) bool { - if len(p) < 2 { - return false - } - sf, ok := p[len(p)-1].(cmp.StructField) + sf, ok := p.Index(-1).(cmp.StructField) if !ok { return false } - return xf.m[p[len(p)-2].Type()] && !isExported(sf.Name()) + return xf.m[p.Index(-2).Type()] && !isExported(sf.Name()) } // isExported reports whether the identifier is exported. diff --git a/cmp/path.go b/cmp/path.go index 76d73f7..13d9c2e 100644 --- a/cmp/path.go +++ b/cmp/path.go @@ -94,10 +94,21 @@ func (pa *Path) pop() { // Last returns the last PathStep in the Path. // If the path is empty, this returns a non-nil PathStep that reports a nil Type. func (pa Path) Last() PathStep { - if len(pa) > 0 { - return pa[len(pa)-1] + return pa.Index(-1) +} + +// Index returns the ith step in the Path and supports negative indexing. +// A negative index starts counting from the tail of the Path such that -1 +// refers to the last step, -2 refers to the second-to-last step, and so on. +// If index is invalid, this returns a non-nil PathStep that reports a nil Type. +func (pa Path) Index(i int) PathStep { + if i < 0 { + i = len(pa) + i + } + if i < 0 || i >= len(pa) { + return pathStep{} } - return pathStep{} + return pa[i] } // String returns the simplified path to a node.