github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/base/fill/error_collector.go (about) 1 package fill 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // ErrorCollector collects errors, merging them into one, while noting the path where they happen 9 type ErrorCollector struct { 10 errs []error 11 fields []string 12 } 13 14 // NewErrorCollector creates a new ErrorCollector 15 func NewErrorCollector() *ErrorCollector { 16 return &ErrorCollector{ 17 errs: make([]error, 0), 18 fields: make([]string, 0), 19 } 20 } 21 22 // Add adds a non-nil error to the ErrorCollector, noting the path where the error happened 23 func (c *ErrorCollector) Add(err error) bool { 24 if err == nil { 25 return false 26 } 27 if len(c.fields) > 0 { 28 c.errs = append(c.errs, fmt.Errorf("at \"%s\": %s", strings.Join(c.fields, "."), err.Error())) 29 return true 30 } 31 c.errs = append(c.errs, err) 32 return true 33 } 34 35 // AsSingleError returns the collected errors as a single error, or nil if there are none 36 func (c *ErrorCollector) AsSingleError() error { 37 if len(c.errs) == 0 { 38 return nil 39 } else if len(c.errs) == 1 { 40 return c.errs[0] 41 } 42 collect := make([]string, 0) 43 for _, err := range c.errs { 44 collect = append(collect, err.Error()) 45 } 46 return fmt.Errorf("%s", strings.Join(collect, "\n")) 47 } 48 49 // PushField adds a field to the current path 50 func (c *ErrorCollector) PushField(fieldName string) { 51 c.fields = append(c.fields, fieldName) 52 } 53 54 // PopField removes the most recent field from the current path 55 func (c *ErrorCollector) PopField() { 56 c.fields = c.fields[:len(c.fields)-1] 57 }