Skip to content

Commit

Permalink
add printer.clone and test code
Browse files Browse the repository at this point in the history
  • Loading branch information
alingse committed Apr 21, 2023
1 parent e2a49b7 commit b801321
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
21 changes: 17 additions & 4 deletions formatter.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type formatter struct {
// breaks and tabs. Object f responds to the "%v" formatting verb when both the
// "#" and " " (space) flags are set, for example:
//
// fmt.Sprintf("%# v", Formatter(x))
// fmt.Sprintf("%# v", Formatter(x))
//
// If one of these two flags is not set, or any other verb is used, f will
// format x according to the usual rules of package fmt.
Expand Down Expand Up @@ -69,8 +69,21 @@ type printer struct {
depth int
}

func (p *printer) clone() printer {
visited := make(map[visit]int, len(p.visited))
for k, v := range p.visited {
visited[k] = v
}
return printer{
Writer: p.Writer,
tw: p.tw,
visited: visited,
depth: p.depth,
}
}

func (p *printer) indent() *printer {
q := *p
q := p.clone()
q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0)
q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'})
return &q
Expand Down Expand Up @@ -223,7 +236,7 @@ func (p *printer) printValue(v reflect.Value, showType, quote bool) {
case e.Kind() == reflect.Invalid:
io.WriteString(p, "nil")
case e.IsValid():
pp := *p
pp := p.clone()
pp.depth++
pp.printValue(e, showType, true)
default:
Expand Down Expand Up @@ -270,7 +283,7 @@ func (p *printer) printValue(v reflect.Value, showType, quote bool) {
io.WriteString(p, v.Type().String())
io.WriteString(p, ")(nil)")
} else {
pp := *p
pp := p.clone()
pp.depth++
writeByte(pp, '&')
pp.printValue(e, true, true)
Expand Down
32 changes: 32 additions & 0 deletions formatter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,3 +364,35 @@ func TestReuseVisitMap(t *testing.T) {
t.Error("there should not cycle in ComplexValue ", s)
}
}

type Tree struct {
Left *Tree
Value interface{}
Right *Tree
}

func TestCycleRefer(t *testing.T) {
var tree = &Tree{
Left: nil,
Value: 1,
Right: &Tree{
Left: nil,
Value: 2,
Right: nil,
},
}
var s = Sprint(tree)
if strings.Contains(s, "CYCLIC") {
t.Error("tree should have no cycle in Tree", s)
}

tree.Right.Value = []interface{}{
map[string]interface{}{
"refer": tree,
},
}
var s2 = Sprint(tree)
if !strings.Contains(s2, "CYCLIC") {
t.Error("tree should have no cycle in Tree", s2)
}
}

0 comments on commit b801321

Please sign in to comment.