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 }