Skip to content

Commit f397877

Browse files
committed
feat: generate custom label code to configs directory #4
1 parent 29f9efb commit f397877

File tree

2 files changed

+101
-21
lines changed

2 files changed

+101
-21
lines changed

generator.go

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ import (
66
"text/template"
77
)
88

9+
type IndexesInfo struct {
10+
Comment string
11+
Field string
12+
Label string
13+
SearchItem string // TODO `前方一致` や `部分一致` など (5/7 unused)
14+
}
15+
916
type generator struct {
1017
PackageName string
1118
GeneratedFileName string
@@ -20,17 +27,8 @@ type generator struct {
2027
KeyFieldType string
2128

2229
KeyValueName string // lower camel case
23-
}
24-
25-
func (g *generator) generate(writer io.Writer) {
26-
g.setting()
27-
t := template.Must(template.New("tmpl").Parse(tmpl))
28-
29-
err := t.Execute(writer, g)
3030

31-
if err != nil {
32-
log.Printf("failed to execute template: %+v", err)
33-
}
31+
ConstMapForIndexes []IndexesInfo
3432
}
3533

3634
func (g *generator) setting() {
@@ -49,6 +47,39 @@ func (g *generator) setRepositoryStructName() {
4947
g.RepositoryStructName = prefix + name[1:]
5048
}
5149

50+
func (g *generator) generate(writer io.Writer) {
51+
g.setting()
52+
t := template.Must(template.New("tmpl").Parse(tmpl))
53+
54+
err := t.Execute(writer, g)
55+
56+
if err != nil {
57+
log.Printf("failed to execute template: %+v", err)
58+
}
59+
}
60+
61+
func (g *generator) generateConstant(writer io.Writer) {
62+
g.setting()
63+
t := template.Must(template.New("tmpl").Parse(tmplConst))
64+
65+
err := t.Execute(writer, g)
66+
67+
if err != nil {
68+
log.Printf("failed to execute template: %+v", err)
69+
}
70+
}
71+
72+
const tmplConst = `// THIS FILE IS A GENERATED CODE. EDIT OK
73+
package configs
74+
75+
const (
76+
{{- range .ConstMapForIndexes }}
77+
// {{ .Comment }}検索用ラベル
78+
{{ .Field }} = "{{ .Label }}"
79+
{{- end }}
80+
)
81+
`
82+
5283
// nolint:lll
5384
const tmpl = `// THIS FILE IS A GENERATED CODE. DO NOT EDIT
5485
package {{.PackageName}}

main.go

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/fatih/structtag"
1414
"github.com/iancoleman/strcase"
15+
"golang.org/x/xerrors"
1516
)
1617

1718
func main() {
@@ -87,9 +88,26 @@ func traverse(pkg *ast.Package, fs *token.FileSet, structName string) error {
8788
return fmt.Errorf("no such struct: %s", structName)
8889
}
8990

91+
func uppercaseExtraction(name string) (lower string) {
92+
for _, x := range name {
93+
if 65 <= x && x <= 90 {
94+
lower += string(x + 32)
95+
}
96+
}
97+
return
98+
}
99+
100+
const queryLabel = "QueryLabel"
101+
90102
func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) error {
103+
dupMap := make(map[string]int)
104+
filedLabel := gen.StructName + queryLabel
91105
for _, field := range structType.Fields.List {
92106
// structの各fieldを調査
107+
if len(field.Names) != 1 {
108+
return xerrors.New("`field.Names` must have only one element")
109+
}
110+
name := field.Names[0].Name
93111

94112
if field.Tag == nil {
95113
continue
@@ -102,7 +120,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err
102120
if err != nil {
103121
log.Printf(
104122
"%s: tag for %s in struct %s in %s",
105-
pos, field.Names[0].Name, gen.StructName, gen.GeneratedFileName+".go",
123+
pos, name, gen.StructName, gen.GeneratedFileName+".go",
106124
)
107125

108126
continue
@@ -111,6 +129,19 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err
111129
_, err = tags.Get("datastore_key")
112130

113131
if err != nil {
132+
u := uppercaseExtraction(name)
133+
if _, ok := dupMap[u]; !ok {
134+
dupMap[u] = 1
135+
} else {
136+
dupMap[u]++
137+
u = fmt.Sprintf("%s%d", u, dupMap[u])
138+
}
139+
idx := IndexesInfo{
140+
Field: filedLabel + name,
141+
Label: u,
142+
}
143+
idx.Comment = fmt.Sprintf("%s %s", idx.Field, name) // TODO `前方一致` や `部分一致` など
144+
gen.ConstMapForIndexes = append(gen.ConstMapForIndexes, idx)
114145
continue
115146
}
116147

@@ -125,7 +156,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err
125156
return fmt.Errorf("%s: datastore_key tag can be set to only one field", pos)
126157
}
127158

128-
gen.KeyFieldName = field.Names[0].Name
159+
gen.KeyFieldName = name
129160
gen.KeyFieldType = getTypeName(field.Type)
130161

131162
if gen.KeyFieldType != "int64" &&
@@ -134,20 +165,38 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err
134165
return fmt.Errorf("%s: supported key types are int64, string, *datastore.Key", pos)
135166
}
136167

137-
gen.KeyValueName = strcase.ToLowerCamel(field.Names[0].Name)
168+
gen.KeyValueName = strcase.ToLowerCamel(name)
138169
}
139170

140-
fp, err := os.Create(gen.GeneratedFileName + ".go")
171+
{
172+
fp, err := os.Create(gen.GeneratedFileName + ".go")
173+
if err != nil {
174+
panic(err)
175+
}
176+
defer fp.Close()
141177

142-
if err != nil {
143-
panic(err)
178+
gen.generate(fp)
144179
}
145180

146-
gen.generate(
147-
fp,
148-
)
149-
150-
fp.Close()
181+
{
182+
if !exists("configs") {
183+
if err := os.Mkdir("configs", 0777); err != nil {
184+
return err
185+
}
186+
}
187+
path := "configs/" + strcase.ToLowerCamel(gen.StructName) + "_const.go"
188+
fp, err := os.Create(path)
189+
if err != nil {
190+
panic(err)
191+
}
192+
defer fp.Close()
193+
gen.generateConstant(fp)
194+
}
151195

152196
return nil
153197
}
198+
199+
func exists(filename string) bool {
200+
_, err := os.Stat(filename)
201+
return err == nil
202+
}

0 commit comments

Comments
 (0)