Golang静态标识符解析

eri*_*ang 7 static-analysis go

我试图使用go/parse,go/tokengo/ast模块对 Go 项目中的函数调用进行一些静态分析,但我不知道如何确定给定ast.Ident对象的类型。

例如,如果解析这样的内容:

textToContain := bytes.NewBuffer([]byte{})
// lots of other code
text := textToContain.String() // <- I care about this function call
Run Code Online (Sandbox Code Playgroud)

(这是从这里解析的: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  }
Run Code Online (Sandbox Code Playgroud)

但我看不出在哪里可以推断出类型textToContain

我知道很多工具可以做到这一点,例如go 博客中的这个示例,但我认为我走错了方向。

Ala*_*van 6

3of3 是对的;您需要类型检查器,即golang.org/x/tools/go/types. 一般来说,表达式的类型取决于导入依赖项的传递闭包的类型信息,因此您可能需要使用该golang.org/x/tools/go/loader包(我维护的),它会为您处理许多具有挑战性的细节。它stdlib_test.go可能是一个有用的起点。

types.Info一旦您确定了感兴趣的表达,您就可以在AST 包结构内的映射之一中找到其类型。

在本例中,表达式是引用标识符 ( *ast.Ident),因此在Uses映射中查找types.Object它所引用的(命名实体)——在本例中为局部变量 ( *types.Var)。对于标识符以外的表达式,Types映射会告诉您其类型。