aboutsummaryrefslogtreecommitdiff
path: root/cmp/report_text.go
diff options
context:
space:
mode:
authorJoe Tsai <joetsai@digital-static.net>2020-06-17 17:25:47 -0700
committerGitHub <noreply@github.com>2020-06-17 17:25:47 -0700
commit77ae86f624cb174e21763cffcbbf070eb06cb016 (patch)
treedd32bd59eb58b50d44dee2efa06ac36f8daa92a1 /cmp/report_text.go
parentc49bfce0ac9115b09320b47c3b9534cc5afd4579 (diff)
downloadgo-cmp-77ae86f624cb174e21763cffcbbf070eb06cb016.tar.gz
Improve reporting of values with cycles (#217)
Previously, the reporter could handle formatting values with cycles in that it did not crash with a stack overflow. However, the output was not particularly understandable as it did not surface to the user why a particular value was truncated, and if it was truncated due to a cyclic reference, what was the referent. This change annotates the reporter tree with pointer information so that a later pass can inject reference information if it is needed to produce more understandable output. Consider the following example: map[string]*cmp_test.CycleAlpha{ "Foo": &⟪ref#0⟫{ Name: "Foo", Bravos: map[string]*cmp_test.CycleBravo{ "FooBravo": &{ - ID: 101, + ID: 0, Name: "FooBravo", Mods: 100, Alphas: {"Foo": &⟪ref#0⟫(...)}, }, }, }, } This graph contains a cycle. To ensure that a graph can be formatted, the cycle is truncated as indicated with: &⟪ref#0⟫(...). The referent was identified earlier with: &⟪ref#0⟫{...}.
Diffstat (limited to 'cmp/report_text.go')
-rw-r--r--cmp/report_text.go21
1 files changed, 11 insertions, 10 deletions
diff --git a/cmp/report_text.go b/cmp/report_text.go
index b8ec9d2..8b12c05 100644
--- a/cmp/report_text.go
+++ b/cmp/report_text.go
@@ -94,21 +94,22 @@ type textNode interface {
// textWrap is a wrapper that concatenates a prefix and/or a suffix
// to the underlying node.
type textWrap struct {
- Prefix string // e.g., "bytes.Buffer{"
- Value textNode // textWrap | textList | textLine
- Suffix string // e.g., "}"
+ Prefix string // e.g., "bytes.Buffer{"
+ Value textNode // textWrap | textList | textLine
+ Suffix string // e.g., "}"
+ Metadata interface{} // arbitrary metadata; has no effect on formatting
}
-func (s textWrap) Len() int {
+func (s *textWrap) Len() int {
return len(s.Prefix) + s.Value.Len() + len(s.Suffix)
}
-func (s1 textWrap) Equal(s2 textNode) bool {
- if s2, ok := s2.(textWrap); ok {
+func (s1 *textWrap) Equal(s2 textNode) bool {
+ if s2, ok := s2.(*textWrap); ok {
return s1.Prefix == s2.Prefix && s1.Value.Equal(s2.Value) && s1.Suffix == s2.Suffix
}
return false
}
-func (s textWrap) String() string {
+func (s *textWrap) String() string {
var d diffMode
var n indentMode
_, s2 := s.formatCompactTo(nil, d)
@@ -117,7 +118,7 @@ func (s textWrap) String() string {
b = append(b, '\n') // Trailing newline
return string(b)
}
-func (s textWrap) formatCompactTo(b []byte, d diffMode) ([]byte, textNode) {
+func (s *textWrap) formatCompactTo(b []byte, d diffMode) ([]byte, textNode) {
n0 := len(b) // Original buffer length
b = append(b, s.Prefix...)
b, s.Value = s.Value.formatCompactTo(b, d)
@@ -127,7 +128,7 @@ func (s textWrap) formatCompactTo(b []byte, d diffMode) ([]byte, textNode) {
}
return b, s
}
-func (s textWrap) formatExpandedTo(b []byte, d diffMode, n indentMode) []byte {
+func (s *textWrap) formatExpandedTo(b []byte, d diffMode, n indentMode) []byte {
b = append(b, s.Prefix...)
b = s.Value.formatExpandedTo(b, d, n)
b = append(b, s.Suffix...)
@@ -195,7 +196,7 @@ func (s1 textList) Equal(s2 textNode) bool {
}
func (s textList) String() string {
- return textWrap{"{", s, "}"}.String()
+ return (&textWrap{Prefix: "{", Value: s, Suffix: "}"}).String()
}
func (s textList) formatCompactTo(b []byte, d diffMode) ([]byte, textNode) {