-
-
Notifications
You must be signed in to change notification settings - Fork 58
/
is-1.7.go
65 lines (58 loc) · 1.72 KB
/
is-1.7.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//go:build go1.7
// +build go1.7
package is
import (
"regexp"
"runtime"
)
// Helper marks the calling function as a test helper function.
// When printing file and line information, that function will be skipped.
//
// Available with Go 1.7 and later.
func (is *I) Helper() {
is.helpers[callerName(1)] = struct{}{}
}
// callerName gives the function name (qualified with a package path)
// for the caller after skip frames (where 0 means the current function).
func callerName(skip int) string {
// Make room for the skip PC.
var pc [1]uintptr
n := runtime.Callers(skip+2, pc[:]) // skip + runtime.Callers + callerName
if n == 0 {
panic("is: zero callers found")
}
frames := runtime.CallersFrames(pc[:n])
frame, _ := frames.Next()
return frame.Function
}
// The maximum number of stack frames to go through when skipping helper functions for
// the purpose of decorating log messages.
const maxStackLen = 50
var reIsSourceFile = regexp.MustCompile(`is(-1.7)?\.go$`)
func (is *I) callerinfo() (path string, line int, ok bool) {
var pc [maxStackLen]uintptr
// Skip two extra frames to account for this function
// and runtime.Callers itself.
n := runtime.Callers(2, pc[:])
if n == 0 {
panic("is: zero callers found")
}
frames := runtime.CallersFrames(pc[:n])
var firstFrame, frame runtime.Frame
for more := true; more; {
frame, more = frames.Next()
if reIsSourceFile.MatchString(frame.File) {
continue
}
if firstFrame.PC == 0 {
firstFrame = frame
}
if _, ok := is.helpers[frame.Function]; ok {
// Frame is inside a helper function.
continue
}
return frame.File, frame.Line, true
}
// If no "non-helper" frame is found, the first non is frame is returned.
return firstFrame.File, firstFrame.Line, true
}