/
directcaller.go
93 lines (77 loc) · 2.79 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
package gomod
import (
"fmt"
"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)
}
func directCallerPackageE(depth int) (s string, err error) {
defer func() {
if err != nil {
err = xerrors.Errorf("determining current package failed: %w", err)
}
}()
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())
}