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  }