如何使用go/types从方法中获取AST(Golang)

如何使用go/types从方法中获取AST(Golang) 我有一个 *types.Package 并且正在遍历它:

st := pkg.Scope().Lookup("Sprite") // Struct
m := types.NewMethodSet(types.NewPointer(st.Type())).At(0) // Function

如何获取此方法的 *ast.FuncDecl

1 回复

更多关于如何使用go/types从方法中获取AST(Golang)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


你可以通过遍历AST并匹配类型信息来获取对应的*ast.FuncDecl。以下是一个示例实现:

import (
    "go/ast"
    "go/types"
)

func findFuncDecl(file *ast.File, obj types.Object) *ast.FuncDecl {
    for _, decl := range file.Decls {
        if funcDecl, ok := decl.(*ast.FuncDecl); ok {
            // 通过函数名和类型信息匹配
            if funcDecl.Name.Name == obj.Name() {
                return funcDecl
            }
        }
    }
    return nil
}

// 使用示例
func GetMethodAST(pkg *types.Package, file *ast.File, method *types.Func) *ast.FuncDecl {
    // 遍历AST查找匹配的方法声明
    for _, decl := range file.Decls {
        if funcDecl, ok := decl.(*ast.FuncDecl); ok {
            // 检查方法接收器类型
            if funcDecl.Recv != nil && len(funcDecl.Recv.List) > 0 {
                recvType := funcDecl.Recv.List[0].Type
                // 这里需要根据实际情况处理接收器类型匹配
                if funcDecl.Name.Name == method.Name() {
                    return funcDecl
                }
            }
        }
    }
    return nil
}

更完整的实现需要考虑接收器类型匹配:

func findMethodDecl(files []*ast.File, method *types.Func) *ast.FuncDecl {
    for _, file := range files {
        for _, decl := range file.Decls {
            if funcDecl, ok := decl.(*ast.FuncDecl); ok {
                if funcDecl.Recv == nil {
                    continue
                }
                
                // 获取方法全名进行匹配
                if method.FullName() == getMethodFullName(funcDecl) {
                    return funcDecl
                }
            }
        }
    }
    return nil
}

func getMethodFullName(funcDecl *ast.FuncDecl) string {
    if funcDecl.Recv == nil || len(funcDecl.Recv.List) == 0 {
        return ""
    }
    
    // 简化处理:实际使用时需要正确解析接收器类型
    recvType := astToString(funcDecl.Recv.List[0].Type)
    return "(" + recvType + ")." + funcDecl.Name.Name
}

func astToString(expr ast.Expr) string {
    // 实现AST表达式到字符串的转换
    // 这里需要根据实际情况实现
    return ""
}

如果你已经知道方法所属的具体文件,可以这样使用:

// 假设你已经加载了AST
var astFiles []*ast.File
var pkg *types.Package

st := pkg.Scope().Lookup("Sprite")
methodSet := types.NewMethodSet(types.NewPointer(st.Type()))
method := methodSet.At(0).Obj().(*types.Func)

// 查找对应的AST节点
funcDecl := findMethodDecl(astFiles, method)
if funcDecl != nil {
    // 现在你有了方法的*ast.FuncDecl
    fmt.Printf("Found method: %s\n", funcDecl.Name.Name)
}

注意:类型信息和AST节点之间没有直接的引用关系,需要通过名称和类型签名进行匹配。

回到顶部