-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherrorStack.go
More file actions
127 lines (106 loc) · 2.36 KB
/
errorStack.go
File metadata and controls
127 lines (106 loc) · 2.36 KB
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
package parser
import (
"fmt"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/go-multierror"
"reflect"
"strings"
)
type ErrorStack struct {
prefix string
error error
}
func NewErrorStack(prefix string) *ErrorStack {
return &ErrorStack{
prefix: prefix,
}
}
func (c *ErrorStack) Push(i interface{}) {
var name string
if reflect.TypeOf(i).Comparable() {
name = reflect.TypeOf(i).Elem().Name()
} else {
name = reflect.TypeOf(i).Name()
}
c.prefix = fmt.Sprintf("%s/%s", c.prefix, name)
}
func (c *ErrorStack) getName(field reflect.StructField) string {
if protobuf, ok := field.Tag.Lookup("protobuf"); ok {
arr := strings.Split( protobuf, ",")
var name string
for _, s := range arr {
if strings.HasPrefix(s, "json=") {
return s[5:]
}
if strings.HasPrefix(s, "name=") {
name = s[5:]
}
}
return name
}
if json, ok := field.Tag.Lookup("json"); ok {
i := strings.Index(json, ",")
return json[0:i]
}
return field.Name
}
func (c *ErrorStack) PushMethod(index int, field reflect.StructField) {
name := c.getName(field)
if index >= 0 {
c.prefix = fmt.Sprintf("%s/%s[%v]", c.prefix, name, index)
} else {
c.prefix = fmt.Sprintf("%s/%s", c.prefix, name)
}
}
func (c *ErrorStack) Pop() {
index := strings.LastIndex(c.prefix, "/")
if index >= 0 {
c.prefix = c.prefix[0:index]
}
}
func (c *ErrorStack) path() string {
return c.prefix
}
func (c *ErrorStack) AppendError(err error) {
c.error = multierror.Append(Prefix(err, c.prefix), c.error)
}
func Prefix(err error, prefix string) error {
if err == nil {
return nil
}
format := fmt.Sprintf("%s.{{err}}", prefix)
switch err := err.(type) {
case *multierror.Error:
if err == nil {
err = new(multierror.Error)
}
for i, e := range err.Errors {
err.Errors[i] = e
}
return err
default:
return errwrap.Wrapf(format, err)
}
}
func (c *ErrorStack) Errors() error {
if c.error == nil {
return nil
}
if result, ok := c.error.(*multierror.Error); ok {
if result != nil {
result.ErrorFormat = func(es []error) string {
if len(es) == 1 {
return fmt.Sprintf("1 error occurred:\n\t* %s\n\n", es[0])
}
points := make([]string, len(es))
for i, err := range es {
points[i] = fmt.Sprintf("* %s", err)
}
return fmt.Sprintf(
"%d errors occurred:\n\t%s\n\n",
len(es), strings.Join(points, "\n\t"))
}
}
}
return c.error
}