Golang静态标识符解析 [英] Golang static identifier resolution
问题描述
我正在尝试使用 go / parse
, go / token $>对Go项目中的函数调用进行一些静态分析c $ c>和
go / ast
模块,但我无法弄清楚如何确定给定的 ast.Ident
object。
例如,如果解析这样的内容:
textToContain:= bytes.NewBuffer([] byte {})
//很多其他代码
text:= textToContain.String()//< - 我关心这个函数调用
(这是从这里解析的: file )编辑:它花了很多代码来解析这个所以我没有在这里发布,但您可以在 https:// gist上找到它。 github.com/EricChiang/6735340c5fa3d2de2b73
我得到以下代码prin使用 ast.Print
function
0 * ast.CallExpr {
1。有趣:* ast.SelectorExpr {
2。 。 X:* ast.Ident {
4。 。 。名称:textToContain
5。 。 。 Obj:* ast.Object {
6。 。 。 。种类:var
7。 。 。 。名称:textToContain
8。 。 。 。申报:* ast.AssignStmt {
9。 。 。 。 。 Lhs:[] ast.Expr(len = 1){
10。 。 。 。 。 。 0:* ast.Ident {
12。 。 。 。 。 。 。名称:textToContain
13。 。 。 。 。 。 。 Obj:*(obj @ 5)
14。 。 。 。 。 。 }
15。 。 。 。 。 }
17。 。 。 。 。 Tok::=
18。 。 。 。 。 Rhs:[] ast.Expr(len = 1){
19。 。 。 。 。 。 0:* ast.CallExpr {
20。 。 。 。 。 。 。趣味:* ast.SelectorExpr {
21。 。 。 。 。 。 。 。 X:* ast.Ident {
23。 。 。 。 。 。 。 。 。名称:字节
24。 。 。 。 。 。 。 。 }
25。 。 。 。 。 。 。 。 Sel:* ast.Ident {
27。 。 。 。 。 。 。 。 。名称:NewBuffer
28。 。 。 。 。 。 。 。 }
29。 。 。 。 。 。 。 }
31。 。 。 。 。 。 。参数:[] ast.Expr(len = 1){
32。 。 。 。 。 。 。 。 0:* ast.CompositeLit {
33。 。 。 。 。 。 。 。 。类型:* ast.ArrayType {
35。 。 。 。 。 。 。 。 。 。 Elt:* ast.Ident {
37。 。 。 。 。 。 。 。 。 。 。名称:字节
38。 。 。 。 。 。 。 。 。 。 }
39。 。 。 。 。 。 。 。 。 }
42。 。 。 。 。 。 。 。 }
43。 。 。 。 。 。 。 }
44。 。 。 。 。 。 。省略号: -
46。 。 。 。 。 。 }
47。 。 。 。 。 }
48。 。 。 。 }
49。 。 。 }
50。 。 }
51。 。 Sel:* ast.Ident {
53。 。 。名称:字符串
54。 。 }
55。 }
57。省略号: -
59}
但我无法看到哪里可以推断出类型的 textToContain
我知道一堆可以做到这一点的工具,例如这个例子,但我认为我会走错方向。
3of3是对的;你需要类型检查器,它是 golang.org/x/tools/go/types
。通常,表达式的类型取决于导入依赖关系传递闭包的类型信息,因此您可能需要使用 golang.org/x/tools/go/loader
包(我维护),它为您处理许多具有挑战性的细节。它的 stdlib_test.go
可能是一个有用的起点。
一旦确定了感兴趣的表达,可以在AST包的 types.Info
结构中的一个映射中找到它的类型。
情况下,表达式是一个引用标识符( * ast.Ident
),所以查看使用
映射来查找<它引用的code> types.Object (命名实体)---一个局部变量( * types.Var
)案件。对于标识符以外的表达式, Types
映射会告诉你它的类型。
I'm attempting to do some static analysis on function calls in a Go project using the go/parse
, go/token
and go/ast
modules, but I can't figure out how to determine the type of a given ast.Ident
object.
For instance if parse something like this:
textToContain := bytes.NewBuffer([]byte{})
// lots of other code
text := textToContain.String() // <- I care about this function call
(this is parsed from here: file)
EDIT: It took a lot of code to parse this so I didn't post it here, but you can find it as a gist at: https://gist.github.com/EricChiang/6735340c5fa3d2de2b73
I get the following code printed using the ast.Print
function
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 }
But I can't see where I could infer the type of textToContain
I know a bunch of tools that can do this, for instance this example from the go blog, but I think I'm going in the wrong direction.
3of3 is right; you need the type checker, which is golang.org/x/tools/go/types
. In general, the type of an expression depends on type information for the transitive closure of import dependencies, so you will probably want to use the golang.org/x/tools/go/loader
package (which I maintain), which takes care of many challenging details for you. Its stdlib_test.go
may be a useful starting point.
Once you've identified the expression of interest, you can find its type in one of the mappings within the types.Info
structure for the AST's package.
In this case, the expression is a referring identifier (*ast.Ident
) so look in the Uses
mapping to find the types.Object
(named entity) to which it refers---a local variable (*types.Var
) in this case. For expressions other than identifiers, the Types
mapping will tell you its type.
这篇关于Golang静态标识符解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!