github.com/haraldrudell/parl@v0.4.176/perrors/errorglue/list-error.go (about)

     1  /*
     2  © 2024–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package errorglue
     7  
     8  import (
     9  	"errors"
    10  	"fmt"
    11  	"strings"
    12  
    13  	"github.com/haraldrudell/parl/perrors/panicdetector"
    14  	"github.com/haraldrudell/parl/pruntime"
    15  	"golang.org/x/exp/slices"
    16  )
    17  
    18  func ListError(err error) (s string) {
    19  	if err == nil {
    20  		s = "ListError: OK"
    21  		return
    22  	}
    23  	// the linked-list error chain needs to be traversed oldest error first
    24  	//	- subsequent errors will report the same stack
    25  	var errs []error
    26  	for e := err; e != nil; e = errors.Unwrap(e) {
    27  		errs = append(errs, e)
    28  	}
    29  	// errs now oldest first
    30  	slices.Reverse(errs)
    31  	// error texts, newest error first
    32  	var sL = make([]string, len(errs))
    33  	for i, e := range errs {
    34  		if false {
    35  			FirstPanicStack(err)
    36  		}
    37  		var stack pruntime.Stack
    38  		var isPanicS string
    39  		if errWithStack, ok := e.(ErrorCallStacker); ok {
    40  			stack = errWithStack.StackTrace()
    41  			if isPanic, recoveryIndex, panicIndex := panicdetector.Indices(stack); isPanic {
    42  				isPanicS = " PANIC"
    43  				_ = recoveryIndex
    44  				_ = panicIndex
    45  			}
    46  		}
    47  		var line = fmt.Sprintf(
    48  			"ListError:%d(%d) %s%T “%s”",
    49  			len(sL)-i, len(errs),
    50  			isPanicS,
    51  			e, e.Error(),
    52  		)
    53  		if stack != nil {
    54  			line += "\n" + stack.String()
    55  		}
    56  		sL[len(sL)-i-1] = line
    57  	}
    58  	s = strings.Join(sL, "\n") + "\n— — —"
    59  	return
    60  }