gpt4 book ai didi

parsing - 如何比较两个源代码文件/ast 树?

转载 作者:IT老高 更新时间:2023-10-28 13:02:22 25 4
gpt4 key购买 nike

我正在使用 templates 生成一些源代码包(有没有更好的方法?)和部分测试我需要检查输出是否与预期的源代码匹配。

  • 我尝试了字符串比较,但由于模板包生成的额外空格/新行而失败。我也试过format.Source没有成功。 (失败)
  • 我试图解析两个来源的 ast(见下文),但即使代码除了新行/空格之外基本相同,ast 也不匹配。 (失败)

    主包

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

    func main() {
    stub1 := `package main
    func myfunc(s string) error {
    return nil
    }`
    stub2 := `package main

    func myfunc(s string) error {

    return nil

    }`
    fset := token.NewFileSet()
    r1, err := parser.ParseFile(fset, "", stub1, parser.AllErrors)
    if err != nil {
    panic(err)
    }
    fset = token.NewFileSet()
    r2, err := parser.ParseFile(fset, "", stub2, parser.AllErrors)
    if err != nil {
    panic(err)
    }
    if !reflect.DeepEqual(r1, r2) {
    fmt.Printf("e %v, r %s, ", r1, r2)
    }
    }

Playground

最佳答案

嗯,实现这一点的一种简单方法是使用 go/printer 库,它可以让您更好地控制输出格式,基本上就像运行 gofmt源,标准化两棵树:

package main
import (
"fmt"
"go/parser"
"go/token"
"go/printer"
//"reflect"
"bytes"
)

func main() {
stub1 := `package main
func myfunc(s string) error {
return nil
}`
stub2 := `package main

func myfunc(s string) error {

return nil

}`

fset1 := token.NewFileSet()
r1, err := parser.ParseFile(fset1, "", stub1, parser.AllErrors)
if err != nil {
panic(err)
}
fset2 := token.NewFileSet()
r2, err := parser.ParseFile(fset1, "", stub2, parser.AllErrors)
if err != nil {
panic(err)
}

// we create two output buffers for each source tree
out1 := bytes.NewBuffer(nil)
out2 := bytes.NewBuffer(nil)

// we use the same printer config for both
conf := &printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}

// print to both outputs
if err := conf.Fprint(out1, fset1, r1); err != nil {
panic(err)
}
if err := conf.Fprint(out2, fset2, r2); err != nil {
panic(err)
}


// they should be identical!
if string(out1.Bytes()) != string(out2.Bytes()) {
panic(string(out1.Bytes()) +"\n" + string(out2.Bytes()))
} else {
fmt.Println("A-OKAY!")
}
}

当然,这段代码需要重构才能看起来不那么愚蠢。另一种方法是不使用 DeepEqual,而是自己创建一个树比较函数,它会跳过不相关的节点。

关于parsing - 如何比较两个源代码文件/ast 树?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30196236/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com