1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
15 // FormatError calls the FormatError method of f with an errors.Printer
16 // configured according to s and verb, and writes the result to s.
17 func FormatError(f Formatter
, s fmt
.State
, verb rune
) {
18 // Assuming this function is only called from the Format method, and given
19 // that FormatError takes precedence over Format, it cannot be called from
20 // any package that supports errors.Formatter. It is therefore safe to
21 // disregard that State may be a specific printer implementation and use one
22 // of our choice instead.
24 // limitations: does not support printing error as Go struct.
27 sep
= " " // separator before next error
35 // Note that this switch must match the preference order
36 // for ordinary string printing (%#v before %+v, and so on).
40 if stringer
, ok
:= err
.(fmt
.GoStringer
); ok
{
41 io
.WriteString(&p
.buf
, stringer
.GoString())
44 // proceed as if it were %v
45 } else if s
.Flag('+') {
51 // Use an intermediate buffer in the rare cases that precision,
52 // truncation, or one of the alternative verbs (q, x, and X) are
57 p
.buf
.WriteString("%!")
62 p
.buf
.WriteString(reflect
.TypeOf(f
).String())
64 p
.buf
.WriteString("<nil>")
73 switch v
:= err
.(type) {
75 err
= v
.FormatError((*printer
)(p
))
80 io
.WriteString(&p
.buf
, v
.Error())
86 if p
.needColon ||
!p
.printDetail
{
90 p
.buf
.WriteString(sep
)
96 width
, okW
:= s
.Width()
97 prec
, okP
:= s
.Precision()
99 if !direct ||
(okW
&& width
> 0) || okP
{
100 // Construct format string from State s.
101 format
:= []byte{'%'}
103 format
= append(format
, '-')
106 format
= append(format
, '+')
109 format
= append(format
, ' ')
112 format
= strconv
.AppendInt(format
, int64(width
), 10)
115 format
= append(format
, '.')
116 format
= strconv
.AppendInt(format
, int64(prec
), 10)
118 format
= append(format
, string(verb
)...)
119 fmt
.Fprintf(s
, string(format
), p
.buf
.String())
125 var detailSep
= []byte("\n ")
127 // state tracks error printing state. It implements fmt.State.
138 func (s
*state
) Write(b
[]byte) (n
int, err error
) {
143 if s
.inDetail
&& s
.needColon
{
150 for i
, c
:= range b
{
152 if s
.inDetail
&& s
.needColon
{
156 s
.buf
.Write(detailSep
)
157 s
.needNewline
= false
169 } else if !s
.inDetail
{
175 // printer wraps a state to implement an xerrors.Printer.
178 func (s
*printer
) Print(args
...interface{}) {
179 if !s
.inDetail || s
.printDetail
{
180 fmt
.Fprint((*state
)(s
), args
...)
184 func (s
*printer
) Printf(format
string, args
...interface{}) {
185 if !s
.inDetail || s
.printDetail
{
186 fmt
.Fprintf((*state
)(s
), format
, args
...)
190 func (s
*printer
) Detail() bool {