-
Notifications
You must be signed in to change notification settings - Fork 1
/
directcaller.go
137 lines (114 loc) · 3.64 KB
/
directcaller.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package gomod
import (
"fmt"
"path"
"path/filepath"
"runtime"
"strings"
"golang.org/x/xerrors"
)
// DirectCallerPackageE is same as DirectCallerPackagePanic
// but returns an error instead of panicing once an error occurs.
func DirectCallerPackageE() (s string, err error) {
return directCallerPackageE(3)
}
type callInfo struct {
packageName string
fileName string
funcName string
line int
}
func retrieveCallInfo() *callInfo {
pc, file, line, _ := runtime.Caller(3)
_, fileName := path.Split(file)
parts := strings.Split(runtime.FuncForPC(pc).Name(), ".")
pl := len(parts)
packageName := ""
funcName := parts[pl-1]
fmt.Println("parts:", parts)
// parts: [
// go/gomod/directcallertest/go_default_test
// TestDirectCallerPackage
// ]
if parts[pl-2][0] == '(' {
funcName = parts[pl-2] + "." + funcName
packageName = strings.Join(parts[0:pl-2], ".")
} else {
packageName = strings.Join(parts[0:pl-1], ".")
}
return &callInfo{
packageName: packageName,
fileName: fileName,
funcName: funcName,
line: line,
}
}
func directCallerPackageE(depth int) (s string, err error) {
defer func() {
if err != nil {
err = xerrors.Errorf("determining current package failed: %w", err)
}
}()
call := retrieveCallInfo()
return call.packageName, nil
/*
currentDir := packagePathOfCaller(depth)
ws, err := GetWorkspaceFromWD()
if err != nil {
return
}
gomodDir := filepath.Dir(ws.GomodPath)
if !strings.HasPrefix(currentDir, gomodDir) {
return "", fmt.Errorf("the directory the caller function resides in (%s)"+
"is not under the determined workspace (%s) with Module prefix (%s)"+
"and so package name cannot be determined", currentDir, ws.GomodPath, ws.Module)
}
fmt.Println("currentDir:", currentDir, "gomodDir:", gomodDir)
// Add module path in front, then add current file with root removed.
return strings.ReplaceAll(
ws.Module+"/"+strings.TrimPrefix(strings.TrimSuffix(strings.TrimPrefix(currentDir, gomodDir), string(filepath.Separator)), string(filepath.Separator)),
string(filepath.Separator), "/"), nil
*/
}
// DirectCallerPackagePanic returns the package name the working directory currently points to.
// The function panics if working directory is not inside a workspace.
func DirectCallerPackagePanic() string {
pkg, err := directCallerPackageE(3)
if err != nil {
panic(err)
}
return pkg
}
// DirectCallerPackagePath determines the path to the directory the caller function resides in and returns it.
func DirectCallerPackagePath() string {
return packagePathOfCaller(2)
}
// packagePathOfCaller returns the file callerDepth calls removed from this call.
func packagePathOfCaller(callerDepth int) string {
_, currentFile, _, _ := runtime.Caller(callerDepth)
return filepath.Dir(currentFile)
}
// Source: https://stackoverflow.com/questions/25927660/how-to-get-the-current-function-name
/*
func trace() {
pc := make([]uintptr, 10) // at least 1 entry needed
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
file, line := f.FileLine(pc[0])
fmt.Printf("%s:%d %s\n", file, line, f.Name())
}
*/
// DirectCallerFunctionName determines the function name of the caller and returns it.
func DirectCallerFunctionName() string {
pc := make([]uintptr, 10) // at least 1 entry needed
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return strings.TrimPrefix(filepath.Ext(f.Name()), ".")
}
// DirectCallerFunctionNameWithPackageName returns the caller pkg.function name.
func DirectCallerFunctionNameWithPackageName() string {
pc := make([]uintptr, 10) // at least 1 entry needed
runtime.Callers(2, pc)
f := runtime.FuncForPC(pc[0])
return filepath.Base(f.Name())
}