下面的测试try 使用AST向 struct 中添加字段.字段添加正确,但注释添加顺序混乱.我想这个职位可能需要手动指定,但到目前为止,我还没有找到答案.

这里有个不及格的测试:http://play.golang.org/p/RID4N30FZK

以下是代码:

package generator

import (
    "bytes"
    "fmt"
    "go/ast"
    "go/parser"
    "go/printer"
    "go/token"
    "testing"
)

func TestAst(t *testing.T) {

    source := `package a

// B comment
type B struct {
    // C comment
    C string
}`

    fset := token.NewFileSet()
    file, err := parser.ParseFile(fset, "", []byte(source), parser.ParseComments)
    if err != nil {
        t.Error(err)
    }

    v := &visitor{
        file: file,
    }
    ast.Walk(v, file)

    var output []byte
    buf := bytes.NewBuffer(output)
    if err := printer.Fprint(buf, fset, file); err != nil {
        t.Error(err)
    }

    expected := `package a

// B comment
type B struct {
    // C comment
    C string
    // D comment
    D int
    // E comment
    E float64
}
`

    if buf.String() != expected {
        t.Error(fmt.Sprintf("Test failed. Expected:\n%s\nGot:\n%s", expected, buf.String()))
    }

    /*
    actual output = `package a

// B comment
type B struct {
    // C comment
    // D comment
    // E comment
    C   string
    D   int
    E   float64
}
`
    */

}

type visitor struct {
    file *ast.File
}

func (v *visitor) Visit(node ast.Node) (w ast.Visitor) {

    if node == nil {
        return v
    }

    switch n := node.(type) {
    case *ast.GenDecl:
        if n.Tok != token.TYPE {
            break
        }
        ts := n.Specs[0].(*ast.TypeSpec)
        if ts.Name.Name == "B" {
            fields := ts.Type.(*ast.StructType).Fields
            addStructField(fields, v.file, "int", "D", "D comment")
            addStructField(fields, v.file, "float64", "E", "E comment")
        }
    }

    return v
}

func addStructField(fields *ast.FieldList, file *ast.File, typ string, name string, comment string) {
    c := &ast.Comment{Text: fmt.Sprint("// ", comment)}
    cg := &ast.CommentGroup{List: []*ast.Comment{c}}
    f := &ast.Field{
        Doc:   cg,
        Names: []*ast.Ident{ast.NewIdent(name)},
        Type:  ast.NewIdent(typ),
    }
    fields.List = append(fields.List, f)
    file.Comments = append(file.Comments, cg)
}

推荐答案

我知道这个答案可能有点晚了.但是为了其他人的利益,我在下面这期GitHub中找到了对这个库的引用

https://github.com/golang/go/issues/20744

这个库被称为dst,它可以将围棋ast转换为dst,反之亦然.

https://github.com/dave/dst

ast中,注释按其字节偏移量存储,而不是附加到 node .Dst通过将注释附加到其各自的 node 来解决这个问题,这样重新排列 node 就不会 destruct 输出/树.

图书馆的工作方式和广告一样,到目前为止我还没有发现任何问题.

注意:还有一个名为dst/dstutil的子包,它与golang.org/x/tools/go/ast/astutil兼容

Go相关问答推荐

语法-for循环中的initit陈述是否允许分配?

使用GO从RDPMC获得价值

即使HTTP服务器正在使用GO和Protobuf、SQL Server启动,请求也不返回结果

mockgen不创建模拟

如何使用工作区方法扩展克隆的Golang库

如果values.yaml文件中不存在某个属性,如何返回默认的FALSE?

如何模拟go的Elastic search SDK?

Golang在不写入磁盘的情况下为jpeg图像生成一致的哈希

使用Dockertest进行Golang SQL单元测试的基本设置

Golang 发送Post请求出现400错误

Global Thread-local Storage 在 Go 中的可行性和最佳实践

有没有办法在 Golang 中使用带有 go-simple-mail lib 的代理?

Golang 到 wasm 编译使用 tinygo.使用 wasmtime 执行

更改多对多连接表的名称

为什么不同的 Wireguard 私钥会产生相同的公钥?

使用 oklog/run 来自 Go 编译器的错误(无值)用作值

GOLANG 如何使用 http.FileServer 从模板目录加载某个 html 文件

防止在 Go 公用文件夹中列出目录

行之间的模板交替设计

(如何)我可以基于接口抽象地实现Stringer吗?