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 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
package main
import (
"bytes"
"fmt"
"io"
"log"
"os"
"os/exec"
"sort"
"strings"
)
type SourceFile struct {
Pkg string
GoImports []string
GoBody *SourceBody
}
func NewSourceFile(pkg string) *SourceFile {
sf := &SourceFile{
Pkg: pkg,
GoBody: &SourceBody{},
}
return sf
}
func (v *SourceFile) Print() error {
_, err := v.WriteTo(os.Stdout)
return err
}
func (v *SourceFile) Save(filename string) {
f, err := os.Create(filename)
if err != nil {
log.Fatal("fail to create file:", err)
}
defer f.Close()
_, err = v.WriteTo(f)
if err != nil {
log.Fatal("failed to write to file:", err)
}
out, err := exec.Command("goimports", "-w", filename).CombinedOutput()
if err != nil {
log.Printf("%s", out)
log.Fatal("failed to format file:", filename)
}
}
func (v *SourceFile) WriteTo(w io.Writer) (n int64, err error) {
var wn int
cmdline := strings.Join(os.Args, " ")
wn, err = io.WriteString(w, fmt.Sprintf("// Code generated by %q; DO NOT EDIT.\n\n", cmdline))
n += int64(wn)
if err != nil {
return
}
wn, err = io.WriteString(w, "package "+v.Pkg+"\n")
n += int64(wn)
if err != nil {
return
}
sort.Strings(v.GoImports)
for _, imp := range v.GoImports {
wn, err = io.WriteString(w, "import "+imp+"\n")
n += int64(wn)
if err != nil {
return
}
}
wn, err = w.Write(v.GoBody.buf.Bytes())
n += int64(wn)
return
}
// unsafe => "unsafe"
// or x,github.com/path/ => x "path"
func (s *SourceFile) AddGoImport(imp string) {
var importStr string
if strings.Contains(imp, ",") {
parts := strings.SplitN(imp, ",", 2)
importStr = fmt.Sprintf("%s %q", parts[0], parts[1])
} else {
importStr = `"` + imp + `"`
}
for _, imp0 := range s.GoImports {
if imp0 == importStr {
return
}
}
s.GoImports = append(s.GoImports, importStr)
}
type SourceBody struct {
buf bytes.Buffer
}
func (v *SourceBody) writeStr(str string) {
v.buf.WriteString(str)
}
func (v *SourceBody) Pn(format string, a ...interface{}) {
v.P(format, a...)
v.buf.WriteByte('\n')
}
func (v *SourceBody) P(format string, a ...interface{}) {
str := fmt.Sprintf(format, a...)
v.writeStr(str)
}
|