如何在AST解析器中将类型解析为原语



我想提取函数的签名,以便能够在它们上面生成一些包装器方法。为此,我使用golang.org/x/tools/go/packages为我提供了读取AST的可能性。

例如,对于函数func MyFunc(param int)定义,您会收到一些

ast.FuncDecl{
Type: *FieldList{
List: []*Field{
{
Names: []*Ident{ /*...*/ },
Type:  nil, /*...*/
},
},
},
}

其中Type表示类型。

我想为所有int参数生成一些特殊的代码,但是int也可以用一些类型声明隐藏

type MyType int

我如何将ast类型转换为编译器具有的真实类型?

添加packages.NeedTypespackages.NeedTypesInfo为加载模式。这样,每个加载的包将初始化其TypesInfo字段,并且该字段的类型*types.Info有一个名为Types的字段,该字段将最后的表达式映射到类型。你可以这样使用它:

func main() {
loadConfig := new(packages.Config)
loadConfig.Mode = packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo
loadConfig.Fset = token.NewFileSet()
pkgs, err := packages.Load(loadConfig, "syscall")
if err != nil {
panic(err)
}
for _, pkg := range pkgs {
for _, syn := range pkg.Syntax {
for _, dec := range syn.Decls {
if fd, ok := dec.(*ast.FuncDecl); ok && fd.Name.Name == "Kill" {
x1 := fd.Type.Params.List[0].Type // int
x2 := fd.Type.Params.List[1].Type // syscall.Signal
tv1 := pkg.TypesInfo.Types[x1]
tv2 := pkg.TypesInfo.Types[x2]
if basic, ok := tv1.Type.(*types.Basic); ok {
fmt.Printf("%#vn", basic) // int
}
if named, ok := tv2.Type.(*types.Named); ok {
fmt.Printf("%vn", named.Obj())         // *types.TypeName (Signal)
fmt.Printf("%#vn", named.Underlying()) // *types.Basic (int)
}
}
}
}
}
}

最新更新