Skip to content

Commit e250a55

Browse files
authored
Use of hotlinking of Go identifiers (#337)
GoDoc now supports hot linking to specific Go identifiers. Use that feature to enhance the usability of cmp docs. Since cmp lacks a direct dependency on cmpopts, you are forced to use the fully-qualified import path to references identifiers in the cmpopts package. It can future improvements to the go/doc to handle this case, either by rendering the doc with short form, or by detecting the use of cmpopts from the unit tests as well (since those can break circular dependencies).
1 parent 8a3e8dd commit e250a55

File tree

8 files changed

+123
-106
lines changed

8 files changed

+123
-106
lines changed

cmp/cmpopts/equate.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ import (
1616

1717
func equateAlways(_, _ interface{}) bool { return true }
1818

19-
// EquateEmpty returns a Comparer option that determines all maps and slices
19+
// EquateEmpty returns a [cmp.Comparer] option that determines all maps and slices
2020
// with a length of zero to be equal, regardless of whether they are nil.
2121
//
22-
// EquateEmpty can be used in conjunction with SortSlices and SortMaps.
22+
// EquateEmpty can be used in conjunction with [SortSlices] and [SortMaps].
2323
func EquateEmpty() cmp.Option {
2424
return cmp.FilterValues(isEmpty, cmp.Comparer(equateAlways))
2525
}
@@ -31,7 +31,7 @@ func isEmpty(x, y interface{}) bool {
3131
(vx.Len() == 0 && vy.Len() == 0)
3232
}
3333

34-
// EquateApprox returns a Comparer option that determines float32 or float64
34+
// EquateApprox returns a [cmp.Comparer] option that determines float32 or float64
3535
// values to be equal if they are within a relative fraction or absolute margin.
3636
// This option is not used when either x or y is NaN or infinite.
3737
//
@@ -45,7 +45,7 @@ func isEmpty(x, y interface{}) bool {
4545
//
4646
// |x-y| ≤ max(fraction*min(|x|, |y|), margin)
4747
//
48-
// EquateApprox can be used in conjunction with EquateNaNs.
48+
// EquateApprox can be used in conjunction with [EquateNaNs].
4949
func EquateApprox(fraction, margin float64) cmp.Option {
5050
if margin < 0 || fraction < 0 || math.IsNaN(margin) || math.IsNaN(fraction) {
5151
panic("margin or fraction must be a non-negative number")
@@ -73,10 +73,10 @@ func (a approximator) compareF32(x, y float32) bool {
7373
return a.compareF64(float64(x), float64(y))
7474
}
7575

76-
// EquateNaNs returns a Comparer option that determines float32 and float64
76+
// EquateNaNs returns a [cmp.Comparer] option that determines float32 and float64
7777
// NaN values to be equal.
7878
//
79-
// EquateNaNs can be used in conjunction with EquateApprox.
79+
// EquateNaNs can be used in conjunction with [EquateApprox].
8080
func EquateNaNs() cmp.Option {
8181
return cmp.Options{
8282
cmp.FilterValues(areNaNsF64s, cmp.Comparer(equateAlways)),
@@ -91,8 +91,8 @@ func areNaNsF32s(x, y float32) bool {
9191
return areNaNsF64s(float64(x), float64(y))
9292
}
9393

94-
// EquateApproxTime returns a Comparer option that determines two non-zero
95-
// time.Time values to be equal if they are within some margin of one another.
94+
// EquateApproxTime returns a [cmp.Comparer] option that determines two non-zero
95+
// [time.Time] values to be equal if they are within some margin of one another.
9696
// If both times have a monotonic clock reading, then the monotonic time
9797
// difference will be used. The margin must be non-negative.
9898
func EquateApproxTime(margin time.Duration) cmp.Option {
@@ -131,8 +131,8 @@ type anyError struct{}
131131
func (anyError) Error() string { return "any error" }
132132
func (anyError) Is(err error) bool { return err != nil }
133133

134-
// EquateErrors returns a Comparer option that determines errors to be equal
135-
// if errors.Is reports them to match. The AnyError error can be used to
134+
// EquateErrors returns a [cmp.Comparer] option that determines errors to be equal
135+
// if [errors.Is] reports them to match. The [AnyError] error can be used to
136136
// match any non-nil error.
137137
func EquateErrors() cmp.Option {
138138
return cmp.FilterValues(areConcreteErrors, cmp.Comparer(compareErrors))

cmp/cmpopts/ignore.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"github.com/google/go-cmp/cmp/internal/function"
1515
)
1616

17-
// IgnoreFields returns an Option that ignores fields of the
17+
// IgnoreFields returns an [cmp.Option] that ignores fields of the
1818
// given names on a single struct type. It respects the names of exported fields
1919
// that are forwarded due to struct embedding.
2020
// The struct type is specified by passing in a value of that type.
@@ -26,7 +26,7 @@ func IgnoreFields(typ interface{}, names ...string) cmp.Option {
2626
return cmp.FilterPath(sf.filter, cmp.Ignore())
2727
}
2828

29-
// IgnoreTypes returns an Option that ignores all values assignable to
29+
// IgnoreTypes returns an [cmp.Option] that ignores all values assignable to
3030
// certain types, which are specified by passing in a value of each type.
3131
func IgnoreTypes(typs ...interface{}) cmp.Option {
3232
tf := newTypeFilter(typs...)
@@ -59,10 +59,10 @@ func (tf typeFilter) filter(p cmp.Path) bool {
5959
return false
6060
}
6161

62-
// IgnoreInterfaces returns an Option that ignores all values or references of
62+
// IgnoreInterfaces returns an [cmp.Option] that ignores all values or references of
6363
// values assignable to certain interface types. These interfaces are specified
6464
// by passing in an anonymous struct with the interface types embedded in it.
65-
// For example, to ignore sync.Locker, pass in struct{sync.Locker}{}.
65+
// For example, to ignore [sync.Locker], pass in struct{sync.Locker}{}.
6666
func IgnoreInterfaces(ifaces interface{}) cmp.Option {
6767
tf := newIfaceFilter(ifaces)
6868
return cmp.FilterPath(tf.filter, cmp.Ignore())
@@ -107,15 +107,15 @@ func (tf ifaceFilter) filter(p cmp.Path) bool {
107107
return false
108108
}
109109

110-
// IgnoreUnexported returns an Option that only ignores the immediate unexported
110+
// IgnoreUnexported returns an [cmp.Option] that only ignores the immediate unexported
111111
// fields of a struct, including anonymous fields of unexported types.
112112
// In particular, unexported fields within the struct's exported fields
113113
// of struct types, including anonymous fields, will not be ignored unless the
114114
// type of the field itself is also passed to IgnoreUnexported.
115115
//
116116
// Avoid ignoring unexported fields of a type which you do not control (i.e. a
117117
// type from another repository), as changes to the implementation of such types
118-
// may change how the comparison behaves. Prefer a custom Comparer instead.
118+
// may change how the comparison behaves. Prefer a custom [cmp.Comparer] instead.
119119
func IgnoreUnexported(typs ...interface{}) cmp.Option {
120120
ux := newUnexportedFilter(typs...)
121121
return cmp.FilterPath(ux.filter, cmp.Ignore())
@@ -148,7 +148,7 @@ func isExported(id string) bool {
148148
return unicode.IsUpper(r)
149149
}
150150

151-
// IgnoreSliceElements returns an Option that ignores elements of []V.
151+
// IgnoreSliceElements returns an [cmp.Option] that ignores elements of []V.
152152
// The discard function must be of the form "func(T) bool" which is used to
153153
// ignore slice elements of type V, where V is assignable to T.
154154
// Elements are ignored if the function reports true.
@@ -176,7 +176,7 @@ func IgnoreSliceElements(discardFunc interface{}) cmp.Option {
176176
}, cmp.Ignore())
177177
}
178178

179-
// IgnoreMapEntries returns an Option that ignores entries of map[K]V.
179+
// IgnoreMapEntries returns an [cmp.Option] that ignores entries of map[K]V.
180180
// The discard function must be of the form "func(T, R) bool" which is used to
181181
// ignore map entries of type K and V, where K and V are assignable to T and R.
182182
// Entries are ignored if the function reports true.

cmp/cmpopts/sort.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"github.com/google/go-cmp/cmp/internal/function"
1414
)
1515

16-
// SortSlices returns a Transformer option that sorts all []V.
16+
// SortSlices returns a [cmp.Transformer] option that sorts all []V.
1717
// The less function must be of the form "func(T, T) bool" which is used to
1818
// sort any slice with element type V that is assignable to T.
1919
//
@@ -25,7 +25,7 @@ import (
2525
// The less function does not have to be "total". That is, if !less(x, y) and
2626
// !less(y, x) for two elements x and y, their relative order is maintained.
2727
//
28-
// SortSlices can be used in conjunction with EquateEmpty.
28+
// SortSlices can be used in conjunction with [EquateEmpty].
2929
func SortSlices(lessFunc interface{}) cmp.Option {
3030
vf := reflect.ValueOf(lessFunc)
3131
if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {
@@ -82,21 +82,21 @@ func (ss sliceSorter) less(v reflect.Value, i, j int) bool {
8282
return ss.fnc.Call([]reflect.Value{vx, vy})[0].Bool()
8383
}
8484

85-
// SortMaps returns a Transformer option that flattens map[K]V types to be a
85+
// SortMaps returns a [cmp.Transformer] option that flattens map[K]V types to be a
8686
// sorted []struct{K, V}. The less function must be of the form
8787
// "func(T, T) bool" which is used to sort any map with key K that is
8888
// assignable to T.
8989
//
90-
// Flattening the map into a slice has the property that cmp.Equal is able to
91-
// use Comparers on K or the K.Equal method if it exists.
90+
// Flattening the map into a slice has the property that [cmp.Equal] is able to
91+
// use [cmp.Comparer] options on K or the K.Equal method if it exists.
9292
//
9393
// The less function must be:
9494
// - Deterministic: less(x, y) == less(x, y)
9595
// - Irreflexive: !less(x, x)
9696
// - Transitive: if !less(x, y) and !less(y, z), then !less(x, z)
9797
// - Total: if x != y, then either less(x, y) or less(y, x)
9898
//
99-
// SortMaps can be used in conjunction with EquateEmpty.
99+
// SortMaps can be used in conjunction with [EquateEmpty].
100100
func SortMaps(lessFunc interface{}) cmp.Option {
101101
vf := reflect.ValueOf(lessFunc)
102102
if !function.IsType(vf.Type(), function.Less) || vf.IsNil() {

cmp/cmpopts/xform.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ func (xf xformFilter) filter(p cmp.Path) bool {
1919
return true
2020
}
2121

22-
// AcyclicTransformer returns a Transformer with a filter applied that ensures
22+
// AcyclicTransformer returns a [cmp.Transformer] with a filter applied that ensures
2323
// that the transformer cannot be recursively applied upon its own output.
2424
//
2525
// An example use case is a transformer that splits a string by lines:
@@ -28,7 +28,7 @@ func (xf xformFilter) filter(p cmp.Path) bool {
2828
// return strings.Split(s, "\n")
2929
// })
3030
//
31-
// Had this been an unfiltered Transformer instead, this would result in an
31+
// Had this been an unfiltered [cmp.Transformer] instead, this would result in an
3232
// infinite cycle converting a string to []string to [][]string and so on.
3333
func AcyclicTransformer(name string, xformFunc interface{}) cmp.Option {
3434
xf := xformFilter{cmp.Transformer(name, xformFunc)}

cmp/compare.go

+20-18
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Package cmp determines equality of values.
66
//
77
// This package is intended to be a more powerful and safer alternative to
8-
// reflect.DeepEqual for comparing whether two values are semantically equal.
8+
// [reflect.DeepEqual] for comparing whether two values are semantically equal.
99
// It is intended to only be used in tests, as performance is not a goal and
1010
// it may panic if it cannot compare the values. Its propensity towards
1111
// panicking means that its unsuitable for production environments where a
@@ -18,16 +18,17 @@
1818
// For example, an equality function may report floats as equal so long as
1919
// they are within some tolerance of each other.
2020
//
21-
// - Types with an Equal method may use that method to determine equality.
22-
// This allows package authors to determine the equality operation
23-
// for the types that they define.
21+
// - Types with an Equal method (e.g., [time.Time.Equal]) may use that method
22+
// to determine equality. This allows package authors to determine
23+
// the equality operation for the types that they define.
2424
//
2525
// - If no custom equality functions are used and no Equal method is defined,
2626
// equality is determined by recursively comparing the primitive kinds on
27-
// both values, much like reflect.DeepEqual. Unlike reflect.DeepEqual,
27+
// both values, much like [reflect.DeepEqual]. Unlike [reflect.DeepEqual],
2828
// unexported fields are not compared by default; they result in panics
29-
// unless suppressed by using an Ignore option (see cmpopts.IgnoreUnexported)
30-
// or explicitly compared using the Exporter option.
29+
// unless suppressed by using an [Ignore] option
30+
// (see [github.com/google/go-cmp/cmp/cmpopts.IgnoreUnexported])
31+
// or explicitly compared using the [Exporter] option.
3132
package cmp
3233

3334
import (
@@ -45,14 +46,14 @@ import (
4546
// Equal reports whether x and y are equal by recursively applying the
4647
// following rules in the given order to x and y and all of their sub-values:
4748
//
48-
// - Let S be the set of all Ignore, Transformer, and Comparer options that
49+
// - Let S be the set of all [Ignore], [Transformer], and [Comparer] options that
4950
// remain after applying all path filters, value filters, and type filters.
50-
// If at least one Ignore exists in S, then the comparison is ignored.
51-
// If the number of Transformer and Comparer options in S is non-zero,
51+
// If at least one [Ignore] exists in S, then the comparison is ignored.
52+
// If the number of [Transformer] and [Comparer] options in S is non-zero,
5253
// then Equal panics because it is ambiguous which option to use.
53-
// If S contains a single Transformer, then use that to transform
54+
// If S contains a single [Transformer], then use that to transform
5455
// the current values and recursively call Equal on the output values.
55-
// If S contains a single Comparer, then use that to compare the current values.
56+
// If S contains a single [Comparer], then use that to compare the current values.
5657
// Otherwise, evaluation proceeds to the next rule.
5758
//
5859
// - If the values have an Equal method of the form "(T) Equal(T) bool" or
@@ -66,21 +67,22 @@ import (
6667
// Functions are only equal if they are both nil, otherwise they are unequal.
6768
//
6869
// Structs are equal if recursively calling Equal on all fields report equal.
69-
// If a struct contains unexported fields, Equal panics unless an Ignore option
70-
// (e.g., cmpopts.IgnoreUnexported) ignores that field or the Exporter option
71-
// explicitly permits comparing the unexported field.
70+
// If a struct contains unexported fields, Equal panics unless an [Ignore] option
71+
// (e.g., [github.com/google/go-cmp/cmp/cmpopts.IgnoreUnexported]) ignores that field
72+
// or the [Exporter] option explicitly permits comparing the unexported field.
7273
//
7374
// Slices are equal if they are both nil or both non-nil, where recursively
7475
// calling Equal on all non-ignored slice or array elements report equal.
7576
// Empty non-nil slices and nil slices are not equal; to equate empty slices,
76-
// consider using cmpopts.EquateEmpty.
77+
// consider using [github.com/google/go-cmp/cmp/cmpopts.EquateEmpty].
7778
//
7879
// Maps are equal if they are both nil or both non-nil, where recursively
7980
// calling Equal on all non-ignored map entries report equal.
8081
// Map keys are equal according to the == operator.
81-
// To use custom comparisons for map keys, consider using cmpopts.SortMaps.
82+
// To use custom comparisons for map keys, consider using
83+
// [github.com/google/go-cmp/cmp/cmpopts.SortMaps].
8284
// Empty non-nil maps and nil maps are not equal; to equate empty maps,
83-
// consider using cmpopts.EquateEmpty.
85+
// consider using [github.com/google/go-cmp/cmp/cmpopts.EquateEmpty].
8486
//
8587
// Pointers and interfaces are equal if they are both nil or both non-nil,
8688
// where they have the same underlying concrete type and recursively

cmp/example_test.go

+9-5
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ func ExampleDiff_testing() {
6161
// comparer on floats that determines two values to be equal if they are within
6262
// some range of each other.
6363
//
64-
// This example is for demonstrative purposes; use cmpopts.EquateApprox instead.
64+
// This example is for demonstrative purposes;
65+
// use [github.com/google/go-cmp/cmp/cmpopts.EquateApprox] instead.
6566
func ExampleOption_approximateFloats() {
6667
// This Comparer only operates on float64.
6768
// To handle float32s, either define a similar function for that type
@@ -89,7 +90,8 @@ func ExampleOption_approximateFloats() {
8990
// Normal floating-point arithmetic defines == to be false when comparing
9091
// NaN with itself. In certain cases, this is not the desired property.
9192
//
92-
// This example is for demonstrative purposes; use cmpopts.EquateNaNs instead.
93+
// This example is for demonstrative purposes;
94+
// use [github.com/google/go-cmp/cmp/cmpopts.EquateNaNs] instead.
9395
func ExampleOption_equalNaNs() {
9496
// This Comparer only operates on float64.
9597
// To handle float32s, either define a similar function for that type
@@ -117,7 +119,7 @@ func ExampleOption_equalNaNs() {
117119
// to restrict the scope of the comparison so that they are composable.
118120
//
119121
// This example is for demonstrative purposes;
120-
// use cmpopts.EquateNaNs and cmpopts.EquateApprox instead.
122+
// use [github.com/google/go-cmp/cmp/cmpopts.EquateApprox] instead.
121123
func ExampleOption_equalNaNsAndApproximateFloats() {
122124
alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
123125

@@ -156,7 +158,8 @@ func ExampleOption_equalNaNsAndApproximateFloats() {
156158
// Sometimes, an empty map or slice is considered equal to an allocated one
157159
// of zero length.
158160
//
159-
// This example is for demonstrative purposes; use cmpopts.EquateEmpty instead.
161+
// This example is for demonstrative purposes;
162+
// use [github.com/google/go-cmp/cmp/cmpopts.EquateEmpty] instead.
160163
func ExampleOption_equalEmpty() {
161164
alwaysEqual := cmp.Comparer(func(_, _ interface{}) bool { return true })
162165

@@ -190,7 +193,8 @@ func ExampleOption_equalEmpty() {
190193
// regardless of the order that they appear in. Transformations can be used
191194
// to sort the slice.
192195
//
193-
// This example is for demonstrative purposes; use cmpopts.SortSlices instead.
196+
// This example is for demonstrative purposes;
197+
// use [github.com/google/go-cmp/cmp/cmpopts.SortSlices] instead.
194198
func ExampleOption_sortedSlice() {
195199
// This Transformer sorts a []int.
196200
trans := cmp.Transformer("Sort", func(in []int) []int {

0 commit comments

Comments
 (0)