forked from LS6-Events/astra
-
Notifications
You must be signed in to change notification settings - Fork 0
/
collector.go
130 lines (118 loc) · 2.88 KB
/
collector.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
package astra
import (
"errors"
"fmt"
"go/ast"
"go/parser"
"go/token"
"log"
"os"
"path/filepath"
"regexp"
)
type MethodInfo struct {
MethodName string
FileName string
Line int
MethodReceiver string
PkgName string
}
func (m *MethodInfo) Id() string {
return fmt.Sprintf("%s-%s-%s", m.PkgName, m.MethodReceiver, m.MethodName)
}
func Collector(rootPath string) map[string]MethodInfo {
directory := rootPath
methodsMap := make(map[string]MethodInfo)
err := parseDirectoryRecursively(directory, func(path string) {
fileMethods := ParseAndStoreMethods(path)
for k, v := range fileMethods {
methodsMap[k] = v
}
})
if err != nil {
log.Println(err)
}
return methodsMap
}
func parseDirectoryRecursively(directory string, processFile func(string)) error {
return filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() && filepath.Ext(path) == ".go" {
processFile(path)
}
return nil
})
}
func ParseAndStoreMethods(filename string) map[string]MethodInfo {
result := make(map[string]MethodInfo)
// 解析源码
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
if err != nil {
log.Fatal(err)
}
// 遍历AST
ast.Inspect(node, func(n ast.Node) bool {
switch x := n.(type) {
// case *ast.TypeSpec:
// // 找到struct
// if st, ok := x.Type.(*ast.StructType); ok {
// // 遍历struct的方法
// for _, f := range st.Fields.List {
// if f.Names != nil {
// for _, fieldName := range f.Names {
// fmt.Println("Found struct field:", fieldName.Name)
// }
// }
// }
// }
case *ast.FuncDecl:
// 找到方法
if x.Recv != nil {
methodName := x.Name.Name
pos := fset.Position(x.Pos())
methodReceiver := ""
if len(x.Recv.List) > 0 {
switch nn := x.Recv.List[0].Type.(type) {
case *ast.StarExpr:
switch nnn := nn.X.(type) {
case *ast.Ident:
recvIdent := nnn
methodReceiver = "*" + recvIdent.Name
}
case *ast.IndexExpr:
recvIdent := nn.X.(*ast.Ident)
methodReceiver = recvIdent.Name
case *ast.Ident:
recvIdent := nn
methodReceiver = recvIdent.Name
}
}
pkgName := node.Name.Name
methodInfo := MethodInfo{
MethodName: methodName,
FileName: pos.Filename,
Line: pos.Line,
MethodReceiver: methodReceiver,
PkgName: pkgName,
}
result[methodInfo.Id()] = methodInfo
}
}
return true
})
return result
}
func ExtraMethodAndName(testString string) (string, string, error) {
re := regexp.MustCompile(`\((.*?)\)\.(.*)-fm`)
matches := re.FindStringSubmatch(testString)
if len(matches) == 3 {
receiver := matches[1]
functionName := matches[2]
return receiver, functionName, nil
} else {
return "", "", errors.New("fail")
}
}