/
yagi.go
97 lines (85 loc) · 2.28 KB
/
yagi.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// This package holds the command line tool yagi.
// yagi (yet another generics implementation) can be used
// to generate code based on an idomatic, compilable and
// testable Go template.
// It reads this template code, modifies types and names, and
// writes a new concrete implementation of that template.
package main
import (
"bytes"
"flag"
"fmt"
"go/parser"
"go/token"
"os"
"github.com/hneemann/yagi/concrete"
"github.com/hneemann/yagi/generify"
"github.com/hneemann/yagi/names"
"golang.org/x/tools/imports"
)
const message = "// generated by yagi. Don't modify this file!\n// Any changes will be lost if this file is regenerated.\n\n"
func main() {
tem := flag.String("tem", "", "name of the template go file")
out := flag.String("out", "", "name of the new source file")
pac := flag.String("pac", "", "package name in the created file")
gen := flag.String("gen", "", "concrete types e.g string,int;string,double64")
imp := flag.Bool("imp", true, "run go imports")
flag.Parse()
// read the source file
fset := token.NewFileSet()
ast, err := parser.ParseFile(fset, *tem, nil, parser.ParseComments)
if err != nil {
fmt.Println("reading source file: ", err)
return
}
// prepeare the concrete types
c, err := concrete.New(*gen)
if err != nil {
fmt.Println("processing concrete types: ", err)
return
}
// create output name
outName, err := names.CreateOutName(*out, *tem, message)
if err != nil {
fmt.Println(err)
return
}
packageName, err := names.GetPackageName(*pac, outName)
if err != nil {
fmt.Println(err)
return
}
// generify the source file
gener := generify.New(ast, c)
var buffer = new(bytes.Buffer)
buffer.WriteString(message)
err = gener.Do(packageName, buffer)
if err != nil {
fmt.Println(err)
return
}
var output []byte
if *imp {
// run go imports
output, err = imports.Process("", buffer.Bytes(), nil)
if err != nil {
fmt.Println("go imports has an error, try -imp=false: ", err)
return
}
} else {
output = buffer.Bytes()
}
// write the output
file, err := os.Create(outName)
if err != nil {
fmt.Println("error creating output file: ", err)
return
}
defer file.Close()
_, err = file.Write(output)
if err != nil {
fmt.Println("error writing output file: ", err)
return
}
fmt.Println("generated ", outName)
}