如何解析方法声明? [英] How to parse a method declaration?

查看:134
本文介绍了如何解析方法声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图解析一个方法声明。基本上我需要得到接收器基类型的语法节点(类型hello )和返回类型( notype 错误)。 ast 包似乎很简单,但由于某种原因,我没有得到我需要的数据(即字段被报告为零)。

唯一有用的数据似乎只在 Object中提供 - > Decl 字段的类型是 interface {} ,所以我不认为我可以序列化它。



任何帮助将不胜感激。代码如下:

 包主

导入(
fmt
go / ast
go / parser
go / token


func main(){
// src是我们想要检查AST的输入。
src:=`
包mypack
//类型hello是一个很酷的类型
类型hello字符串

//类型notype不是那么酷
类型notype int

// func printme就像没有别的。
func(x * hello)printme(s string)(notype,error){
return 0,nil
}
`
//通过解析来创建AST SRC。
fset:= token.NewFileSet()//位置相对于fset
f,err:= parser.ParseFile(fset,src.go,src,0)
if err! =无{
恐慌(错误)
}

//检查AST并找到我们的函数
var mf ast.FuncDecl
ast.Inspect f,func(n ast.Node)bool {
switch x:= n。(type){
case * ast.FuncDecl:
mf = * x
}
返回true
})

如果mf.Recv!= nil {
fmt.Printf(\\\
receivers:)
for _,v :=范围mf.Recv.List {
fmt.Printf(,tag%v,v.Tag)
for _,xv:=范围v.Names {
fmt.Printf (name%v,decl%v,data%v,type%v,
xv.Name,xv.Obj.Decl,xv.Obj.Data,xv.Obj.Type)
}
}
}
}

游乐场

$ b $为了得到这个类型,你需要看看 Type 属性,它可能是一个 ast.StarExpr ast.Ident



这个



<$ p






$ b $ go $ / $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ go / token


func main(){
// src是我们要检查AST的输入。
src:=`
包mypack
//类型hello是一个很酷的类型
类型hello字符串

//类型notype不是那么酷
类型notype int

// printme与其他类似。
func(x * hello)printme(s string)(notype,error){
return 0,nil
}
`
//通过解析来创建AST SRC。
fset:= token.NewFileSet()//位置相对于fset
f,err:= parser.ParseFile(fset,src.go,src,0)
if err! =无{
恐慌(错误)
}

//检查AST并找到我们的函数
var mf ast.FuncDecl
ast.Inspect f,func(n ast.Node)bool {
switch x:= n。(type){
case * ast.FuncDecl:
mf = * x
}
返回true
})

if mf.Recv!= nil {
for _,v:= range mf.Recv.List {
fmt.Print (recv type:)
switch xv:= v.Type。(type){
case * ast.StarExpr:
if si,ok:= xv.X。(* ast .Ident); OK {
fmt.Println(si.Name)
}
case * ast.Ident:
fmt.Println(xv.Name)
}
}
}
}


I'm trying to parse a method declaration. Basically I need to get the syntax node of the receiver base type (type hello) and the return types (notype and error). The ast package seems straightforward but for some reason I don't get the data I need (i.e. the fields are reported nil).

The only useful data seems provided only in Object -> Decl field which is of type interface{} so I don't think I can serialize it.

Any help would be appreciated. Code below:

package main

import (
    "fmt"
    "go/ast"
    "go/parser"
    "go/token"
)

func main() {
    // src is the input for which we want to inspect the AST.
    src := `
package mypack
// type hello is a cool type
type hello string

// type notype is not that cool
type notype int

// func printme is like nothing else.
func (x *hello)printme(s string)(notype, error){
    return 0, nil
}
`
    // Create the AST by parsing src.
    fset := token.NewFileSet() // positions are relative to fset
    f, err := parser.ParseFile(fset, "src.go", src, 0)
    if err != nil {
        panic(err)
    }

    // Inspect the AST and find our function
    var mf ast.FuncDecl
    ast.Inspect(f, func(n ast.Node) bool {
        switch x := n.(type) {
        case *ast.FuncDecl:
            mf = *x
        }
        return true
    })

    if mf.Recv != nil {
        fmt.Printf("\n receivers:")
        for _, v := range mf.Recv.List {
            fmt.Printf(",tag %v", v.Tag)
            for _, xv := range v.Names {
                fmt.Printf("name %v, decl %v, data %v, type %v",
                    xv.Name, xv.Obj.Decl, xv.Obj.Data, xv.Obj.Type)
            }
        }
    }
}

Playground

解决方案

To get the type you need to look at the Type attribute which could be an ast.StarExpr or an ast.Ident.

Here take a look at this :

package main

import (
    "fmt"
    "go/ast"
    "go/parser"
    "go/token"
)

func main() {
    // src is the input for which we want to inspect the AST.
    src := `
package mypack
// type hello is a cool type
type hello string

// type notype is not that cool
type notype int

// printme is like nothing else.
func (x *hello)printme(s string)(notype, error){
    return 0, nil
}
`
    // Create the AST by parsing src.
    fset := token.NewFileSet() // positions are relative to fset
    f, err := parser.ParseFile(fset, "src.go", src, 0)
    if err != nil {
        panic(err)
    }

    // Inspect the AST and find our function
    var mf ast.FuncDecl
    ast.Inspect(f, func(n ast.Node) bool {
        switch x := n.(type) {
        case *ast.FuncDecl:
            mf = *x
        }
        return true
    })

    if mf.Recv != nil {
        for _, v := range mf.Recv.List {
            fmt.Print("recv type : ")
            switch xv := v.Type.(type) {
            case *ast.StarExpr:
                if si, ok := xv.X.(*ast.Ident); ok {
                    fmt.Println(si.Name)
                }
            case *ast.Ident:
                fmt.Println(xv.Name)
            }
        }
    }
}

这篇关于如何解析方法声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆