Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / xerrors@v0.0.0-20200804184101-5ec99f83aff1 / fmt.go
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.
4
5 package xerrors
6
7 import (
8         "fmt"
9         "strings"
10         "unicode"
11         "unicode/utf8"
12
13         "golang.org/x/xerrors/internal"
14 )
15
16 const percentBangString = "%!"
17
18 // Errorf formats according to a format specifier and returns the string as a
19 // value that satisfies error.
20 //
21 // The returned error includes the file and line number of the caller when
22 // formatted with additional detail enabled. If the last argument is an error
23 // the returned error's Format method will return it if the format string ends
24 // with ": %s", ": %v", or ": %w". If the last argument is an error and the
25 // format string ends with ": %w", the returned error implements an Unwrap
26 // method returning it.
27 //
28 // If the format specifier includes a %w verb with an error operand in a
29 // position other than at the end, the returned error will still implement an
30 // Unwrap method returning the operand, but the error's Format method will not
31 // return the wrapped error.
32 //
33 // It is invalid to include more than one %w verb or to supply it with an
34 // operand that does not implement the error interface. The %w verb is otherwise
35 // a synonym for %v.
36 func Errorf(format string, a ...interface{}) error {
37         format = formatPlusW(format)
38         // Support a ": %[wsv]" suffix, which works well with xerrors.Formatter.
39         wrap := strings.HasSuffix(format, ": %w")
40         idx, format2, ok := parsePercentW(format)
41         percentWElsewhere := !wrap && idx >= 0
42         if !percentWElsewhere && (wrap || strings.HasSuffix(format, ": %s") || strings.HasSuffix(format, ": %v")) {
43                 err := errorAt(a, len(a)-1)
44                 if err == nil {
45                         return &noWrapError{fmt.Sprintf(format, a...), nil, Caller(1)}
46                 }
47                 // TODO: this is not entirely correct. The error value could be
48                 // printed elsewhere in format if it mixes numbered with unnumbered
49                 // substitutions. With relatively small changes to doPrintf we can
50                 // have it optionally ignore extra arguments and pass the argument
51                 // list in its entirety.
52                 msg := fmt.Sprintf(format[:len(format)-len(": %s")], a[:len(a)-1]...)
53                 frame := Frame{}
54                 if internal.EnableTrace {
55                         frame = Caller(1)
56                 }
57                 if wrap {
58                         return &wrapError{msg, err, frame}
59                 }
60                 return &noWrapError{msg, err, frame}
61         }
62         // Support %w anywhere.
63         // TODO: don't repeat the wrapped error's message when %w occurs in the middle.
64         msg := fmt.Sprintf(format2, a...)
65         if idx < 0 {
66                 return &noWrapError{msg, nil, Caller(1)}
67         }
68         err := errorAt(a, idx)
69         if !ok || err == nil {
70                 // Too many %ws or argument of %w is not an error. Approximate the Go
71                 // 1.13 fmt.Errorf message.
72                 return &noWrapError{fmt.Sprintf("%sw(%s)", percentBangString, msg), nil, Caller(1)}
73         }
74         frame := Frame{}
75         if internal.EnableTrace {
76                 frame = Caller(1)
77         }
78         return &wrapError{msg, err, frame}
79 }
80
81 func errorAt(args []interface{}, i int) error {
82         if i < 0 || i >= len(args) {
83                 return nil
84         }
85         err, ok := args[i].(error)
86         if !ok {
87                 return nil
88         }
89         return err
90 }
91
92 // formatPlusW is used to avoid the vet check that will barf at %w.
93 func formatPlusW(s string) string {
94         return s
95 }
96
97 // Return the index of the only %w in format, or -1 if none.
98 // Also return a rewritten format string with %w replaced by %v, and
99 // false if there is more than one %w.
100 // TODO: handle "%[N]w".
101 func parsePercentW(format string) (idx int, newFormat string, ok bool) {
102         // Loosely copied from golang.org/x/tools/go/analysis/passes/printf/printf.go.
103         idx = -1
104         ok = true
105         n := 0
106         sz := 0
107         var isW bool
108         for i := 0; i < len(format); i += sz {
109                 if format[i] != '%' {
110                         sz = 1
111                         continue
112                 }
113                 // "%%" is not a format directive.
114                 if i+1 < len(format) && format[i+1] == '%' {
115                         sz = 2
116                         continue
117                 }
118                 sz, isW = parsePrintfVerb(format[i:])
119                 if isW {
120                         if idx >= 0 {
121                                 ok = false
122                         } else {
123                                 idx = n
124                         }
125                         // "Replace" the last character, the 'w', with a 'v'.
126                         p := i + sz - 1
127                         format = format[:p] + "v" + format[p+1:]
128                 }
129                 n++
130         }
131         return idx, format, ok
132 }
133
134 // Parse the printf verb starting with a % at s[0].
135 // Return how many bytes it occupies and whether the verb is 'w'.
136 func parsePrintfVerb(s string) (int, bool) {
137         // Assume only that the directive is a sequence of non-letters followed by a single letter.
138         sz := 0
139         var r rune
140         for i := 1; i < len(s); i += sz {
141                 r, sz = utf8.DecodeRuneInString(s[i:])
142                 if unicode.IsLetter(r) {
143                         return i + sz, r == 'w'
144                 }
145         }
146         return len(s), false
147 }
148
149 type noWrapError struct {
150         msg   string
151         err   error
152         frame Frame
153 }
154
155 func (e *noWrapError) Error() string {
156         return fmt.Sprint(e)
157 }
158
159 func (e *noWrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }
160
161 func (e *noWrapError) FormatError(p Printer) (next error) {
162         p.Print(e.msg)
163         e.frame.Format(p)
164         return e.err
165 }
166
167 type wrapError struct {
168         msg   string
169         err   error
170         frame Frame
171 }
172
173 func (e *wrapError) Error() string {
174         return fmt.Sprint(e)
175 }
176
177 func (e *wrapError) Format(s fmt.State, v rune) { FormatError(e, s, v) }
178
179 func (e *wrapError) FormatError(p Printer) (next error) {
180         p.Print(e.msg)
181         e.frame.Format(p)
182         return e.err
183 }
184
185 func (e *wrapError) Unwrap() error {
186         return e.err
187 }