-
Notifications
You must be signed in to change notification settings - Fork 5
/
enable.go
89 lines (76 loc) · 1.97 KB
/
enable.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//go:build what || whathappens || whatif || whatfunc || whatis || whatpackage
package what
import (
"os"
"runtime"
"strings"
)
var enabled map[string]bool
func isPackageEnabled() bool {
if len(enabled) == 0 { // all packages enabled
return true
}
pkg, prnt := pkgname(3) // 3 = skip isPackageEnabled and the top-level what.X function
if enabled[pkg] {
return true
}
if enabled[prnt+"/"+pkg] {
return true
}
return false
}
// pkgname returns the package name and the direct parent in the package path
// of the skip'th caller
func pkgname(skip int) (string, string) {
pc, _, _, _ := runtime.Caller(skip)
fn := runtime.FuncForPC(pc).Name()
// possible fn formats:
// * /some/path/to/package.(Receiver).Func
// * /some/path/to/package.Func.func1 (closure)
// * /some/path/to/package.Func
// * pathto/package.Func
// * package.Func (for package main, and if someone hacks
// the stdlib and adds `what` calls there.)
startName, startParent, endName := 0, 0, 0
// Search the last /, it is the beginning of the package name
for i := len(fn) - 1; i >= 0; i-- {
if fn[i] == '/' {
startName = i + 1
break
}
}
// post-loop assert: startName is either 0 (for package main) or i+1
// Search the first dot after the last /, it is the end of the package name
for i := startName; i < len(fn); i++ {
if fn[i] == '.' {
endName = i
break
}
}
// no leading / found means we are probably in package main.
if startName == 0 {
return fn[0:endName], ""
}
// Search the second-last /, it is the beginning of the parent's name
endParent := startName - 1
for i := endParent - 1; i >= 0; i-- {
if fn[i] == '/' {
startParent = i + 1
break
}
}
// startParent is 0 in case of pathto/package.Func
return fn[startName:endName], fn[startParent:endParent]
}
func getenvWhat() {
packages := strings.Split(os.Getenv("WHAT"), ",")
enabled = map[string]bool{}
for _, p := range packages {
if p != "" {
enabled[p] = true
}
}
}
func init() {
getenvWhat()
}