Last active
November 2, 2017 17:57
-
-
Save travisjeffery/07ef25b7e90bae64c4b9928ed8a2a27f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // error.go | |
| // Copyright 2016 The Upspin Authors. All rights reserved. | |
| // populateStack uses the runtime to populate the Error's stack struct with | |
| // information about the current stack. | |
| func (e *Error) populateStack() { | |
| e.Stack = &Stack{Callers: callers()} | |
| } | |
| // printStack formats and prints the stack for this Error to the given buffer. | |
| // It should be called from the Error's Error method. | |
| func (e *Error) printStack(b *bytes.Buffer) { | |
| if e.Stack == nil { | |
| return | |
| } | |
| printCallers := callers() | |
| // Iterate backward through e.Stack.Callers (the last in the stack is the | |
| // earliest call, such as main) skipping over the PCs that are shared | |
| // by the error stack and by this function call stack, printing the | |
| // names of the functions and their file names and line numbers. | |
| var prev string // the name of the last-seen function | |
| var diff bool // do the print and error call stacks differ now? | |
| for i := 0; i < len(e.Stack.Callers); i++ { | |
| thisFrame := frame(e.Stack.Callers, i) | |
| name := thisFrame.Func.Name() | |
| if !diff && i < len(printCallers) { | |
| if name == frame(printCallers, i).Func.Name() { | |
| // both stacks share this PC, skip it. | |
| continue | |
| } | |
| // No match, don't consider printCallers again. | |
| diff = true | |
| } | |
| // Don't print the same function twice. | |
| // (Can happen when multiple error stacks have been coalesced.) | |
| if name == prev { | |
| continue | |
| } | |
| // Find the uncommon prefix between this and the previous | |
| // function name, separating by dots and slashes. | |
| trim := 0 | |
| for { | |
| j := strings.IndexAny(name[trim:], "./") | |
| if j < 0 { | |
| break | |
| } | |
| if !strings.HasPrefix(prev, name[:j+trim]) { | |
| break | |
| } | |
| trim += j + 1 // skip over the separator | |
| } | |
| // Do the printing. | |
| pad(b, separator) | |
| fmt.Fprintf(b, "%v:%d: ", thisFrame.File, thisFrame.Line) | |
| if trim > 0 { | |
| b.WriteString("...") | |
| } | |
| b.WriteString(name[trim:]) | |
| prev = name | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment