我用过去/解析器 https://golang.org/pkg/go/parser/解析 golang 文件并检查它的 AST。我有一个特定的问题,我想使用 go/parser,但遇到了障碍。
考虑 GOPATH/src 中存在以下文件
$GOPATH/src/
example.go
example_package/
example_package.go
以下是上面文件的内容
示例.go
package main
import (
"example_package"
)
type MyObject struct {
base *example_package.BaseObject
}
func DoMyThing(arg *example_package.FirstArg) {
arg.Write(10)
}
func DoMyAnotherThing() {
}
func main() {
example_package.GetItStarted(&MyObject{})
}
示例_package.go
package example_package
func GetItStarted(obj interface{}) {
}
type FirstArg interface {
Read() int
Write(x int)
}
type BaseObject struct {
}
func (p *BaseObject) DoSomething(arg *FirstArg, a int) {
arg.Write(arg.Read() + a)
}
我的目的是编写一个名为gen_structure
像这样使用
$ gen_structure example.go
输出将是
> MyObject
- DoMyThing(arg)
- base
- DoSomething(arg, a)
gen_struct 做了什么?
它解析 example.go 和
- 从该行中提取“MyObject”
example_package.GetItStarted(&MyObject{})
从 main() 函数内部。
- 寻找方法
MyObject
至少有一个参数,第一个参数是类型*package_example.FirstArg
。它发现DoMyThing
(并忽略DoMyAnotherThing
).
- 识别会员身份
base
并窥视内部(通过打开example_package
).
- 应用与上面相同的过程来查找方法并找到
DoSomething
- 使用收集到的信息,它打印所需的输出。
我知道我可以使用其中的功能解析同一目录中的单个文件或一堆文件go/parser
。但是,我无法弄清楚如何跨包解析符号(在这种情况下,example_package
).
我该怎么做呢?
Call 新建包 http://godoc.org/go/ast#NewPackage解析包名称。您需要提供一个importer http://godoc.org/go/ast#Importer返回一个*ast.对象 http://godoc.org/go/ast#Object对于给定的导入路径。如果您只想将名称解析为路径,导入器只需返回一个*ast.对象 http://godoc.org/go/ast#Object与Kind http://godoc.org/go/ast#Object.Kind set to ast.Pkg http://godoc.org/go/ast#Pkg和Name http://godoc.org/go/ast#Object.Name设置为包的名称。进口商的大部分繁重工作都可以通过go/build http://godoc.org/go/build包裹。如果想要解析目标包的 AST,则需要解析包并返回包的 ast.Object。为了防止多次加载相同的包,请使用导入器的映射参数作为先前加载的包的缓存。
这是一些未经测试的代码,用于从*ast.SelectorExpr
se
:
if x, _ := se.X.(*ast.Ident); x != nil {
if obj := x.Obj; obj != nil && obj.Kind == ast.Pkg {
if spec, _ := obj.Decl.(*ast.ImportSpec); spec != nil {
if path, err := strconv.Unquote(spec.Path.Value); err == nil {
// path is resolved path for selector expression se.
}
}
}
}
The go/types http://godoc.org/go/types包也可用于获取此信息及更多信息。我建议使用 go/types 而不是直接使用 go/ast。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)