使用ast获取一个函数中的所有函数调用
Use ast to get all function calls in a function
我正在尝试使用 ast 列出函数中的所有函数调用。但是无法理解它应该如何使用。我已经走到这一步了。
set := token.NewFileSet()
packs, err := parser.ParseFile(set, serviceFile, nil, 0)
if err != nil {
fmt.Println("Failed to parse package:", err)
os.Exit(1)
}
funcs := []*ast.FuncDecl{}
for _, d := range packs.Decls {
if fn, isFn := d.(*ast.FuncDecl); isFn {
funcs = append(funcs, fn)
}
}
我检查了函数。我到达 funcs[n1].Body.List[n2]
。
但是在这之后我不明白我应该如何阅读底层 data.X.Fun.data.Sel.name
(从 gogland 的评估中得到它)来获取被调用函数的名称。
好的,所以我发现您必须进行大量转换才能实际提取数据。
这里是一个关于如何在函数中提取函数调用的例子。
for _, function := range funcs {
extractFuncCallInFunc(function.Body.List)
}
func extractFuncCallInFunc(stmts []ast.Stmt) {
for _, stmt := range funcs {
if exprStmt, ok := stmt.(*ast.ExprStmt); ok {
if call, ok := exprStmt.X.(*ast.CallExpr); ok {
if fun, ok := call.Fun.(*ast.SelectorExpr); ok {
funcName := fun.Sel.Name
}
}
}
}
}
我还发现这个有助于找出您需要将其投射到的目标。
http://goast.yuroyoro.net/
您可以为此使用 ast.Inspect 并在节点类型上使用开关。
for _, fun := range funcs {
ast.Inspect(fun, func(node ast.Node) bool {
switch n := node.(type) {
case *ast.CallExpr:
fmt.Println(n) // prints every func call expression
}
return true
})
}
我正在尝试使用 ast 列出函数中的所有函数调用。但是无法理解它应该如何使用。我已经走到这一步了。
set := token.NewFileSet()
packs, err := parser.ParseFile(set, serviceFile, nil, 0)
if err != nil {
fmt.Println("Failed to parse package:", err)
os.Exit(1)
}
funcs := []*ast.FuncDecl{}
for _, d := range packs.Decls {
if fn, isFn := d.(*ast.FuncDecl); isFn {
funcs = append(funcs, fn)
}
}
我检查了函数。我到达 funcs[n1].Body.List[n2]
。
但是在这之后我不明白我应该如何阅读底层 data.X.Fun.data.Sel.name
(从 gogland 的评估中得到它)来获取被调用函数的名称。
好的,所以我发现您必须进行大量转换才能实际提取数据。
这里是一个关于如何在函数中提取函数调用的例子。
for _, function := range funcs {
extractFuncCallInFunc(function.Body.List)
}
func extractFuncCallInFunc(stmts []ast.Stmt) {
for _, stmt := range funcs {
if exprStmt, ok := stmt.(*ast.ExprStmt); ok {
if call, ok := exprStmt.X.(*ast.CallExpr); ok {
if fun, ok := call.Fun.(*ast.SelectorExpr); ok {
funcName := fun.Sel.Name
}
}
}
}
}
我还发现这个有助于找出您需要将其投射到的目标。 http://goast.yuroyoro.net/
您可以为此使用 ast.Inspect 并在节点类型上使用开关。
for _, fun := range funcs {
ast.Inspect(fun, func(node ast.Node) bool {
switch n := node.(type) {
case *ast.CallExpr:
fmt.Println(n) // prints every func call expression
}
return true
})
}