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 {