formatRecursive performs a post-order traversal on the chain of errors to collect error details from innermost to outermost. It uses s.buf as an intermediate buffer to collect strings. It populates s.entries as a result. Between each layer of error, s.buf is reset. s.finalBuf is untouched. The con
(err error, isOutermost, withDetail, withDepth bool, depth int)
| 362 | // persisted into the generated entries and used later to display the |
| 363 | // error with increased indentation based in the depth. |
| 364 | func (s *state) formatRecursive(err error, isOutermost, withDetail, withDepth bool, depth int) int { |
| 365 | cause := UnwrapOnce(err) |
| 366 | numChildren := 0 |
| 367 | if cause != nil { |
| 368 | // Recurse first, which populates entries list starting from innermost |
| 369 | // entry. If we've previously seen a multi-cause wrapper, `withDepth` |
| 370 | // will be true, and we'll record the depth below ensuring that extra |
| 371 | // indentation is applied to this inner cause during printing. |
| 372 | // Otherwise, we maintain "straight" vertical formatting by keeping the |
| 373 | // parent callers `withDepth` value of `false` by default. |
| 374 | numChildren += s.formatRecursive(cause, false, withDetail, withDepth, depth+1) |
| 375 | } |
| 376 | |
| 377 | causes := UnwrapMulti(err) |
| 378 | for _, c := range causes { |
| 379 | // Override `withDepth` to true for all child entries ensuring they have |
| 380 | // indentation applied during formatting to distinguish them from |
| 381 | // parents. |
| 382 | numChildren += s.formatRecursive(c, false, withDetail, true, depth+1) |
| 383 | } |
| 384 | // inserted := len(s.entries) - 1 - startChildren |
| 385 | |
| 386 | // Reinitialize the state for this stage of wrapping. |
| 387 | s.wantDetail = withDetail |
| 388 | s.needSpace = false |
| 389 | s.needNewline = 0 |
| 390 | s.multiLine = false |
| 391 | s.notEmpty = false |
| 392 | s.hasDetail = false |
| 393 | s.headBuf = nil |
| 394 | |
| 395 | seenTrace := false |
| 396 | |
| 397 | bufIsRedactable := false |
| 398 | |
| 399 | switch v := err.(type) { |
| 400 | case SafeFormatter: |
| 401 | bufIsRedactable = true |
| 402 | desiredShortening := v.SafeFormatError((*safePrinter)(s)) |
| 403 | if desiredShortening == nil { |
| 404 | // The error wants to elide the short messages from inner causes. |
| 405 | // Read backwards through list of entries up to the number of new |
| 406 | // entries created "under" this one amount and mark `elideShort` |
| 407 | // true. |
| 408 | s.elideShortChildren(numChildren) |
| 409 | } |
| 410 | |
| 411 | case Formatter: |
| 412 | desiredShortening := v.FormatError((*printer)(s)) |
| 413 | if desiredShortening == nil { |
| 414 | // The error wants to elide the short messages from inner |
| 415 | // causes. Do it. |
| 416 | s.elideShortChildren(numChildren) |
| 417 | } |
| 418 | |
| 419 | case fmt.Formatter: |
| 420 | // We can only use a fmt.Formatter when both the following |
| 421 | // conditions are true: |
no test coverage detected