You write custom AST-based code generators in Go by parsing source code into an AST, traversing it to find specific nodes, and emitting new code based on those nodes.
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"go/types"
"os"
)
func main() {
fset := token.NewFileSet()
node, err := parser.ParseFile(fset, "main.go", nil, parser.ParseComments)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// Configure type checker
conf := types.Config{Importer: nil}
_, err = conf.Check("main", fset, []*ast.File{node}, nil)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// Traverse AST and generate code
ast.Inspect(node, func(n ast.Node) bool {
if fn, ok := n.(*ast.FuncDecl); ok {
fmt.Printf("// Generated wrapper for %s\n", fn.Name.Name)
fmt.Printf("func wrap%s() { %s() }\n", fn.Name.Name, fn.Name.Name)
}
return true
})
}