Golang静态标识符解析

时间:2015-01-16 02:39:40

标签: go static-analysis

我尝试使用go/parsego/tokengo/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,但我认为我的方向错误。

1 个答案:

答案 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映射将告诉您其类型。