dstとはDecorated Syntax Treeの略で、GOの構文木(go/astパッケージ)にファイルの情報を付加したものである。
go/astパッケージではスペースやコメントの情報を持たないので、コードを生成するという目的には適さない。
例えば以下の例の場合、コメントの位置情報を持たないので順序が保存されずに出力の際に壊れてしまう。
code := `package a
func main(){
var a int // foo
var b string // bar
}
`
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, "", code, parser.ParseComments)
if err != nil {
panic(err)
}
list := f.Decls[0].(*ast.FuncDecl).Body.List
list[0], list[1] = list[1], list[0]
if err := format.Node(os.Stdout, fset, f); err != nil {
panic(err)
}
//Output:
//package a
//
//func main() {
// // foo
// var b string
// var a int
// // bar
//}
この例をdstなら以下のように出力できてコメントとソースの順序も保存されいてる。
code := `package a
func main(){
var a int // foo
var b string // bar
}
`
f, err := decorator.Parse(code)
if err != nil {
panic(err)
}
list := f.Decls[0].(*dst.FuncDecl).Body.List
list[0], list[1] = list[1], list[0]
if err := decorator.Print(f); err != nil {
panic(err)
}
//Output:
//package a
//
//func main() {
// var b string // bar
// var a int // foo
//}
astからdstへ
dstはastのほぼ互換なので構文木に関するものはastをdstに置き換えれば大体いける
decorator.ParseFileを使ってdst.Fileを取得します
func (d *[Decorator](https://pkg.go.dev/github.com/dave/dst/decorator#Decorator)) ParseFile(filename [string](https://pkg.go.dev/builtin#string), src interface{}, mode [parser](https://pkg.go.dev/go/parser).[Mode](https://pkg.go.dev/go/parser#Mode)) (*[dst](https://pkg.go.dev/github.com/dave/dst@v0.27.2).[File](https://pkg.go.dev/github.com/dave/dst@v0.27.2#File), [error](https://pkg.go.dev/builtin#error))
ParseFile uses parser.ParseFile to parse and decorate a Go source file. The ParseComments flag is added to mode if it doesn't exist.
f, err := decorator.ParseFile(fset, "postback_strategy.go", nil, parser.DeclarationErrors|parser.AllErrors|parser.ParseComments)
if err != nil {
switch err := err.(type) {
case scanner.ErrorList:
for _, e := range err {
fmt.Printf("%s:%d:%d %s\n", e.Pos.Filename, e.Pos.Line, e.Pos.Column, e.Msg)
}
default:
fmt.Println(err)
}
return
}
このfを使って、ast.
とされてる箇所をdst.
に置き換えれば大体いける。
なのでgolangでコード生成する必要があれば、こちらを使った方がいいかもしれない。