-
Notifications
You must be signed in to change notification settings - Fork 1
/
error.go
157 lines (129 loc) · 3.28 KB
/
error.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package pepperlint
import (
"bytes"
"fmt"
"go/ast"
"go/token"
)
// FileError is an error interface that will represent an error and where it
// occurred.
type FileError interface {
error
LineNumber
Filename
}
// LineNumber is used to return a line number of where an error occurred.
type LineNumber interface {
LineNumber() int
}
// Filename is the filename of where the error occurred.
type Filename interface {
Filename() string
}
// ErrorWrap will extract the line number from the ast.Node provided.
// The prefix usually represents the file name that the lint error was
// found in.
type ErrorWrap struct {
pos token.Position
prefix string
msg string
}
// NewErrorWrap will return a new error and construct a prefix based on the node
// and file set.
// TODO: Wrap all returned errors in visitor.go with line number and file name
func NewErrorWrap(fset *token.FileSet, node ast.Node, msg string) *ErrorWrap {
pos := fset.Position(node.Pos())
prefix := pos.String()
return &ErrorWrap{
pos: pos,
prefix: prefix,
msg: msg,
}
}
func (e *ErrorWrap) Error() string {
return fmt.Sprintf("%s: %s", e.prefix, e.msg)
}
// LineNumber return the line number to which the error occurred
func (e *ErrorWrap) LineNumber() int {
return e.pos.Line
}
// Filename will return the filename of where the error occurred
func (e *ErrorWrap) Filename() string {
return e.pos.Filename
}
// BatchError groups a set of errors together usually to organize
// them by Validator but is not limited to.
type BatchError struct {
errors []error
}
// NewBatchError returns a new BatchError
func NewBatchError(errs ...error) *BatchError {
return &BatchError{
errors: errs,
}
}
// Add will add a new error to the BatchError
func (e *BatchError) Add(errs ...error) {
e.errors = append(e.errors, errs...)
}
// Errors returns the list of errors back
func (e *BatchError) Errors() []error {
return e.errors
}
// Len returns the length of the errors contained in the BatchError
func (e *BatchError) Len() int {
return len(e.errors)
}
// Return will return BatchError if there is at least 1 error in the container.
// If not, nil will be returned
func (e *BatchError) Return() error {
if e.Len() == 0 {
return nil
}
return e
}
func (e BatchError) Error() string {
buf := bytes.Buffer{}
for i := 0; i < len(e.errors); i++ {
buf.WriteString(fmt.Sprintf("%s", e.errors[i].Error()))
if i+1 < len(e.errors) {
buf.WriteString("\n")
}
}
return buf.String()
}
// Errors is a list of errors. This type is mostly used for pretty printing the
// error message.
type Errors []error
// Add will add the series of errors to the list.
func (e *Errors) Add(errs ...error) {
*e = append(*e, errs...)
}
func (e Errors) Error() string {
buf := bytes.Buffer{}
for _, err := range e {
buf.WriteString(err.Error())
buf.WriteString("\n")
}
return buf.String()
}
// Count will return the number of errors in the list. If there are any batch error, this will
// make recursive calls until a non-batch error is found.
func (e Errors) Count() int {
errAmount := 0
for _, err := range e {
errAmount += count(err)
}
return errAmount
}
func count(e error) int {
berr, ok := e.(*BatchError)
if !ok {
return 1
}
errAmount := 0
for _, err := range berr.Errors() {
errAmount += count(err)
}
return errAmount
}