Print variants
This commit is contained in:
parent
7c66a3e382
commit
f999a77ff9
@ -9,7 +9,7 @@ import (
|
|||||||
func TestDebugNode(t *testing.T) {
|
func TestDebugNode(t *testing.T) {
|
||||||
const expect = `"foobarbaz"`
|
const expect = `"foobarbaz"`
|
||||||
o := "foobarbaz"
|
o := "foobarbaz"
|
||||||
n := reflectValue(none, &pending{values: make(map[valueKey]nodeRef)}, reflect.ValueOf(o))
|
n := reflectValue(none, &pending{values: make(map[uintptr]nodeRef)}, reflect.ValueOf(o))
|
||||||
s := fmt.Sprint(n)
|
s := fmt.Sprint(n)
|
||||||
if s != expect {
|
if s != expect {
|
||||||
t.Fatalf(
|
t.Fatalf(
|
||||||
|
73
notation.go
73
notation.go
@ -26,17 +26,12 @@ type wrapLen struct {
|
|||||||
first, max, last int
|
first, max, last int
|
||||||
}
|
}
|
||||||
|
|
||||||
type valueKey struct {
|
|
||||||
typ reflect.Type
|
|
||||||
ptr uintptr
|
|
||||||
}
|
|
||||||
|
|
||||||
type nodeRef struct {
|
type nodeRef struct {
|
||||||
id, refCount int
|
id, refCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
type pending struct {
|
type pending struct {
|
||||||
values map[valueKey]nodeRef
|
values map[uintptr]nodeRef
|
||||||
idCounter int
|
idCounter int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,6 +70,8 @@ type writer struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stderr io.Writer = os.Stderr
|
||||||
|
|
||||||
func (n node) String() string {
|
func (n node) String() string {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
w := &writer{w: &b}
|
w := &writer{w: &b}
|
||||||
@ -167,7 +164,7 @@ func fprintValues(w io.Writer, o opts, v []interface{}) (int, error) {
|
|||||||
|
|
||||||
n := reflectValue(
|
n := reflectValue(
|
||||||
o,
|
o,
|
||||||
&pending{values: make(map[valueKey]nodeRef)},
|
&pending{values: make(map[uintptr]nodeRef)},
|
||||||
reflect.ValueOf(vi),
|
reflect.ValueOf(vi),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -182,6 +179,20 @@ func fprintValues(w io.Writer, o opts, v []interface{}) (int, error) {
|
|||||||
return wr.n, wr.err
|
return wr.n, wr.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printValues(o opts, v []interface{}) (int, error) {
|
||||||
|
return fprintValues(stderr, o, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printlnValues(o opts, v []interface{}) (int, error) {
|
||||||
|
n, err := fprintValues(stderr, o, v)
|
||||||
|
if err != nil {
|
||||||
|
return n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nn, err := stderr.Write([]byte("\n"))
|
||||||
|
return n + nn, err
|
||||||
|
}
|
||||||
|
|
||||||
func sprintValues(o opts, v []interface{}) string {
|
func sprintValues(o opts, v []interface{}) string {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
fprintValues(&b, o, v)
|
fprintValues(&b, o, v)
|
||||||
@ -212,6 +223,54 @@ func Fprintwv(w io.Writer, v ...interface{}) (int, error) {
|
|||||||
return fprintValues(w, wrap|allTypes, v)
|
return fprintValues(w, wrap|allTypes, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Print(v ...interface{}) (int, error) {
|
||||||
|
return printValues(none, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printw(v ...interface{}) (int, error) {
|
||||||
|
return printValues(wrap, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printt(v ...interface{}) (int, error) {
|
||||||
|
return printValues(types, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printwt(v ...interface{}) (int, error) {
|
||||||
|
return printValues(wrap|types, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printv(v ...interface{}) (int, error) {
|
||||||
|
return printValues(allTypes, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printwv(v ...interface{}) (int, error) {
|
||||||
|
return printValues(wrap|allTypes, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Println(v ...interface{}) (int, error) {
|
||||||
|
return printlnValues(none, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printlnw(v ...interface{}) (int, error) {
|
||||||
|
return printlnValues(wrap, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printlnt(v ...interface{}) (int, error) {
|
||||||
|
return printlnValues(types, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printlnwt(v ...interface{}) (int, error) {
|
||||||
|
return printlnValues(wrap|types, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printlnv(v ...interface{}) (int, error) {
|
||||||
|
return printlnValues(allTypes, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Printlnwv(v ...interface{}) (int, error) {
|
||||||
|
return printlnValues(wrap|allTypes, v)
|
||||||
|
}
|
||||||
|
|
||||||
func Sprint(v ...interface{}) string {
|
func Sprint(v ...interface{}) string {
|
||||||
return sprintValues(none, v)
|
return sprintValues(none, v)
|
||||||
}
|
}
|
||||||
|
153
notation_test.go
Normal file
153
notation_test.go
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
package notation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPrint(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
p func(...interface{}) (int, error)
|
||||||
|
o interface{}
|
||||||
|
e string
|
||||||
|
}{{
|
||||||
|
p: Print,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: `{foo: 42}`,
|
||||||
|
}, {
|
||||||
|
p: Printw,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: `{
|
||||||
|
foo: 42,
|
||||||
|
}`,
|
||||||
|
}, {
|
||||||
|
p: Printt,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: `struct{foo int}{foo: 42}`,
|
||||||
|
}, {
|
||||||
|
p: Printwt,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: `struct{
|
||||||
|
foo int
|
||||||
|
}{
|
||||||
|
foo: 42,
|
||||||
|
}`,
|
||||||
|
}, {
|
||||||
|
p: Printv,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: `struct{foo int}{foo: int(42)}`,
|
||||||
|
}, {
|
||||||
|
p: Printwv,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: `struct{
|
||||||
|
foo int
|
||||||
|
}{
|
||||||
|
foo: int(42),
|
||||||
|
}`,
|
||||||
|
}} {
|
||||||
|
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
|
||||||
|
t.Run("", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
orig := stderr
|
||||||
|
stderr = &b
|
||||||
|
defer func() { stderr = orig }()
|
||||||
|
n, err := test.p(test.o)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(test.e) {
|
||||||
|
t.Fatalf("expected length: %d, got: %d", len(test.e), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := b.String()
|
||||||
|
if s != test.e {
|
||||||
|
t.Fatalf("expected: %s, got: %s", test.e, s)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrintln(t *testing.T) {
|
||||||
|
for _, test := range []struct {
|
||||||
|
p func(...interface{}) (int, error)
|
||||||
|
f bool
|
||||||
|
o interface{}
|
||||||
|
e string
|
||||||
|
}{{
|
||||||
|
p: Println,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: "{foo: 42}\n",
|
||||||
|
}, {
|
||||||
|
p: Printlnw,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: `{
|
||||||
|
foo: 42,
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
p: Printlnt,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: "struct{foo int}{foo: 42}\n",
|
||||||
|
}, {
|
||||||
|
p: Printlnwt,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: `struct{
|
||||||
|
foo int
|
||||||
|
}{
|
||||||
|
foo: 42,
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
p: Printlnv,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: "struct{foo int}{foo: int(42)}\n",
|
||||||
|
}, {
|
||||||
|
p: Printlnwv,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
e: `struct{
|
||||||
|
foo int
|
||||||
|
}{
|
||||||
|
foo: int(42),
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
}, {
|
||||||
|
p: Println,
|
||||||
|
o: struct{foo int}{42},
|
||||||
|
f: true,
|
||||||
|
}} {
|
||||||
|
defer withEnv(t, "TABWIDTH=0", "LINEWIDTH=0", "LINEWIDTH1=0")()
|
||||||
|
t.Run("", func(t *testing.T) {
|
||||||
|
var b bytes.Buffer
|
||||||
|
orig := stderr
|
||||||
|
stderr = &b
|
||||||
|
if test.f {
|
||||||
|
var w failingWriter
|
||||||
|
stderr = &w
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() { stderr = orig }()
|
||||||
|
n, err := test.p(test.o)
|
||||||
|
if test.f && err == nil {
|
||||||
|
t.Fatal("failed to fail")
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.f {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != len(test.e) {
|
||||||
|
t.Fatalf("expected length: %d, got: %d", len(test.e), n)
|
||||||
|
}
|
||||||
|
|
||||||
|
s := b.String()
|
||||||
|
if s != test.e {
|
||||||
|
t.Fatalf("expected: %s, got: %s", test.e, s)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
10
reflect.go
10
reflect.go
@ -118,7 +118,7 @@ func reflectInterface(o opts, p *pending, r reflect.Value) node {
|
|||||||
return reflectNil(o, false, r)
|
return reflectNil(o, false, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
e := reflectValue(o, p, r.Elem())
|
e := reflectValue(o&^skipTypes, p, r.Elem())
|
||||||
if _, t, _ := withType(o); !t {
|
if _, t, _ := withType(o); !t {
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
@ -169,7 +169,11 @@ func reflectMap(o opts, p *pending, r reflect.Value) node {
|
|||||||
nodeOf(
|
nodeOf(
|
||||||
sn[skey],
|
sn[skey],
|
||||||
": ",
|
": ",
|
||||||
reflectValue(itemOpts, p, r.MapIndex(sv[skey])),
|
reflectValue(
|
||||||
|
itemOpts,
|
||||||
|
p,
|
||||||
|
r.MapIndex(sv[skey]),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -301,7 +305,7 @@ func checkPending(p *pending, r reflect.Value) (applyRef func(node) node, ref no
|
|||||||
}
|
}
|
||||||
|
|
||||||
var nr nodeRef
|
var nr nodeRef
|
||||||
key := valueKey{typ: r.Type(), ptr: r.Pointer()}
|
key := r.Pointer()
|
||||||
nr, isPending = p.values[key]
|
nr, isPending = p.values[key]
|
||||||
if isPending {
|
if isPending {
|
||||||
nr.refCount++
|
nr.refCount++
|
||||||
|
@ -1076,3 +1076,12 @@ func TestCyclicReferences(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInterfaceType(t *testing.T) {
|
||||||
|
const expect = `struct{foo interface{}}{foo: *struct{bar int}{bar: 42}}`
|
||||||
|
o := struct{ foo interface{} }{foo: &struct{ bar int }{42}}
|
||||||
|
s := Sprintt(o)
|
||||||
|
if s != expect {
|
||||||
|
t.Fatalf("expected: %s, got: %s", expect, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user