我尝试使用go/parse
,go/token
和go/ast
模块对Go项目中的函数调用进行静态分析,但我无法理解如何确定给定ast.Ident
对象的类型。
例如,如果解析这样的东西:
textToContain := bytes.NewBuffer([]byte{})
// lots of other code
text := textToContain.String() // <- I care about this function call
(这是从这里解析的:file)
编辑:需要大量代码来解析这个,所以我没有在这里发布,但你可以在https://gist.github.com/EricChiang/6735340c5fa3d2de2b73
找到它的要点我使用ast.Print
函数
0 *ast.CallExpr {
1 . Fun: *ast.SelectorExpr {
2 . . X: *ast.Ident {
4 . . . Name: "textToContain"
5 . . . Obj: *ast.Object {
6 . . . . Kind: var
7 . . . . Name: "textToContain"
8 . . . . Decl: *ast.AssignStmt {
9 . . . . . Lhs: []ast.Expr (len = 1) {
10 . . . . . . 0: *ast.Ident {
12 . . . . . . . Name: "textToContain"
13 . . . . . . . Obj: *(obj @ 5)
14 . . . . . . }
15 . . . . . }
17 . . . . . Tok: :=
18 . . . . . Rhs: []ast.Expr (len = 1) {
19 . . . . . . 0: *ast.CallExpr {
20 . . . . . . . Fun: *ast.SelectorExpr {
21 . . . . . . . . X: *ast.Ident {
23 . . . . . . . . . Name: "bytes"
24 . . . . . . . . }
25 . . . . . . . . Sel: *ast.Ident {
27 . . . . . . . . . Name: "NewBuffer"
28 . . . . . . . . }
29 . . . . . . . }
31 . . . . . . . Args: []ast.Expr (len = 1) {
32 . . . . . . . . 0: *ast.CompositeLit {
33 . . . . . . . . . Type: *ast.ArrayType {
35 . . . . . . . . . . Elt: *ast.Ident {
37 . . . . . . . . . . . Name: "byte"
38 . . . . . . . . . . }
39 . . . . . . . . . }
42 . . . . . . . . }
43 . . . . . . . }
44 . . . . . . . Ellipsis: -
46 . . . . . . }
47 . . . . . }
48 . . . . }
49 . . . }
50 . . }
51 . . Sel: *ast.Ident {
53 . . . Name: "String"
54 . . }
55 . }
57 . Ellipsis: -
59 }
但我无法确定在哪里可以推断出textToContain
我知道可以执行此操作的一系列工具,例如来自go博客的this example,但我认为我的方向错误。
答案 0 :(得分:3)
3of3是对的;你需要类型检查器,golang.org/x/tools/go/types
。通常,表达式的类型取决于导入依赖关系的传递闭包的类型信息,因此您可能希望使用golang.org/x/tools/go/loader
包(我维护),它会为您处理许多具有挑战性的细节。它的stdlib_test.go
可能是一个有用的起点。
一旦确定了感兴趣的表达式,就可以在AST包的types.Info
结构中的一个映射中找到它的类型。
在这种情况下,表达式是引用标识符(*ast.Ident
),因此请查看Uses
映射以查找它引用的types.Object
(命名实体) - a在这种情况下,局部变量(*types.Var
)。对于除标识符以外的表达式,Types
映射将告诉您其类型。