/
util.go
84 lines (69 loc) · 1.65 KB
/
util.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
package main
import (
"bytes"
"fmt"
"go/ast"
"go/format"
"os"
"strings"
"text/template"
"unicode"
)
func typeToString(expr ast.Expr) (string, error) {
switch n := expr.(type) {
case *ast.StarExpr:
s, err := typeToString(n.X)
if err != nil {
return "", err
}
return "*" + s, nil
case *ast.Ident:
return n.Name, nil
case *ast.StructType:
// Handle only empty struct without fields.
return "struct{}", nil
case *ast.SelectorExpr:
pkg, err := typeToString(n.X)
if err != nil {
return "", err
}
typ, err := typeToString(n.Sel)
if err != nil {
return "", err
}
return fmt.Sprintf("%s.%s", pkg, typ), nil
}
return "", fmt.Errorf("unhanled expression %#v", expr)
}
func camelCaseToUnderscore(s string) string {
// Assume we have no more than 3 capital letters except the first one in the
// type name.
buf := strings.Builder{}
buf.Grow(len(s) + 3)
for i, r := range s {
if unicode.IsUpper(r) {
if i != 0 {
buf.WriteRune('_')
}
r = unicode.ToLower(r)
}
buf.WriteRune(r)
}
// Replace common abbreviations.
return strings.ReplaceAll(buf.String(), "a_s_t", "ast")
}
func renderTemplateToFile(tmpl, path string, data interface{}) error {
t, err := template.New("").Parse(tmpl)
if err != nil {
return fmt.Errorf("failed to parse template: %w", err)
}
buf := bytes.NewBuffer(make([]byte, 0, 2048))
if err = t.Execute(buf, data); err != nil {
return fmt.Errorf("failed to execute template: %w", err)
}
code, err := format.Source(buf.Bytes())
if err != nil {
return fmt.Errorf("failed to gofmt: %w", err)
}
return os.WriteFile(path, code, 0644) //nolint:gosec // It's okay, we save a code here.
}