From f397877e18cdbbdaf578f9ecd44e84b56e3e2bd5 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Thu, 7 May 2020 15:37:11 +0900 Subject: [PATCH 01/77] feat: generate custom label code to configs directory #4 --- generator.go | 51 +++++++++++++++++++++++++++++-------- main.go | 71 ++++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 101 insertions(+), 21 deletions(-) diff --git a/generator.go b/generator.go index 996d0b9..ff2152d 100644 --- a/generator.go +++ b/generator.go @@ -6,6 +6,13 @@ import ( "text/template" ) +type IndexesInfo struct { + Comment string + Field string + Label string + SearchItem string // TODO `前方一致` や `部分一致` など (5/7 unused) +} + type generator struct { PackageName string GeneratedFileName string @@ -20,17 +27,8 @@ type generator struct { KeyFieldType string KeyValueName string // lower camel case -} - -func (g *generator) generate(writer io.Writer) { - g.setting() - t := template.Must(template.New("tmpl").Parse(tmpl)) - - err := t.Execute(writer, g) - if err != nil { - log.Printf("failed to execute template: %+v", err) - } + ConstMapForIndexes []IndexesInfo } func (g *generator) setting() { @@ -49,6 +47,39 @@ func (g *generator) setRepositoryStructName() { g.RepositoryStructName = prefix + name[1:] } +func (g *generator) generate(writer io.Writer) { + g.setting() + t := template.Must(template.New("tmpl").Parse(tmpl)) + + err := t.Execute(writer, g) + + if err != nil { + log.Printf("failed to execute template: %+v", err) + } +} + +func (g *generator) generateConstant(writer io.Writer) { + g.setting() + t := template.Must(template.New("tmpl").Parse(tmplConst)) + + err := t.Execute(writer, g) + + if err != nil { + log.Printf("failed to execute template: %+v", err) + } +} + +const tmplConst = `// THIS FILE IS A GENERATED CODE. EDIT OK +package configs + +const ( +{{- range .ConstMapForIndexes }} + // {{ .Comment }}検索用ラベル + {{ .Field }} = "{{ .Label }}" +{{- end }} +) +` + // nolint:lll const tmpl = `// THIS FILE IS A GENERATED CODE. DO NOT EDIT package {{.PackageName}} diff --git a/main.go b/main.go index f9919c6..e671ca5 100644 --- a/main.go +++ b/main.go @@ -12,6 +12,7 @@ import ( "github.com/fatih/structtag" "github.com/iancoleman/strcase" + "golang.org/x/xerrors" ) func main() { @@ -87,9 +88,26 @@ func traverse(pkg *ast.Package, fs *token.FileSet, structName string) error { return fmt.Errorf("no such struct: %s", structName) } +func uppercaseExtraction(name string) (lower string) { + for _, x := range name { + if 65 <= x && x <= 90 { + lower += string(x + 32) + } + } + return +} + +const queryLabel = "QueryLabel" + func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) error { + dupMap := make(map[string]int) + filedLabel := gen.StructName + queryLabel for _, field := range structType.Fields.List { // structの各fieldを調査 + if len(field.Names) != 1 { + return xerrors.New("`field.Names` must have only one element") + } + name := field.Names[0].Name if field.Tag == nil { continue @@ -102,7 +120,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err if err != nil { log.Printf( "%s: tag for %s in struct %s in %s", - pos, field.Names[0].Name, gen.StructName, gen.GeneratedFileName+".go", + pos, name, gen.StructName, gen.GeneratedFileName+".go", ) continue @@ -111,6 +129,19 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err _, err = tags.Get("datastore_key") if err != nil { + u := uppercaseExtraction(name) + if _, ok := dupMap[u]; !ok { + dupMap[u] = 1 + } else { + dupMap[u]++ + u = fmt.Sprintf("%s%d", u, dupMap[u]) + } + idx := IndexesInfo{ + Field: filedLabel + name, + Label: u, + } + idx.Comment = fmt.Sprintf("%s %s", idx.Field, name) // TODO `前方一致` や `部分一致` など + gen.ConstMapForIndexes = append(gen.ConstMapForIndexes, idx) continue } @@ -125,7 +156,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err return fmt.Errorf("%s: datastore_key tag can be set to only one field", pos) } - gen.KeyFieldName = field.Names[0].Name + gen.KeyFieldName = name gen.KeyFieldType = getTypeName(field.Type) if gen.KeyFieldType != "int64" && @@ -134,20 +165,38 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err return fmt.Errorf("%s: supported key types are int64, string, *datastore.Key", pos) } - gen.KeyValueName = strcase.ToLowerCamel(field.Names[0].Name) + gen.KeyValueName = strcase.ToLowerCamel(name) } - fp, err := os.Create(gen.GeneratedFileName + ".go") + { + fp, err := os.Create(gen.GeneratedFileName + ".go") + if err != nil { + panic(err) + } + defer fp.Close() - if err != nil { - panic(err) + gen.generate(fp) } - gen.generate( - fp, - ) - - fp.Close() + { + if !exists("configs") { + if err := os.Mkdir("configs", 0777); err != nil { + return err + } + } + path := "configs/" + strcase.ToLowerCamel(gen.StructName) + "_const.go" + fp, err := os.Create(path) + if err != nil { + panic(err) + } + defer fp.Close() + gen.generateConstant(fp) + } return nil } + +func exists(filename string) bool { + _, err := os.Stat(filename) + return err == nil +} From 6bff3cd9b5823fe5fdb98a08a59393778bdbe681 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Thu, 7 May 2020 15:37:32 +0900 Subject: [PATCH 02/77] add: name.go --- testfiles/a/name.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 testfiles/a/name.go diff --git a/testfiles/a/name.go b/testfiles/a/name.go new file mode 100644 index 0000000..ac01fb0 --- /dev/null +++ b/testfiles/a/name.go @@ -0,0 +1,14 @@ +package task + +import ( + "time" +) + +//go:generate repo_generator Name + +type Name struct { + Desc string `datastore:"description"` + Created time.Time `datastore:"created"` + Done bool `datastore:"done"` + ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key +} From d107f29932d53952107f3bb427df3ef0792cd32c Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Thu, 7 May 2020 15:37:44 +0900 Subject: [PATCH 03/77] add: configs/ #4 --- testfiles/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testfiles/.gitignore b/testfiles/.gitignore index 529f624..928f4a4 100644 --- a/testfiles/.gitignore +++ b/testfiles/.gitignore @@ -1,2 +1,3 @@ +mock_*/ +configs/ *_gen.go -mock_*/ \ No newline at end of file From 9f553a686ffd27e59347ff0211a90ed3dc753304 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 16:55:11 +0900 Subject: [PATCH 04/77] feat: add funcMap #4 --- generator.go | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/generator.go b/generator.go index ff2152d..b5d5349 100644 --- a/generator.go +++ b/generator.go @@ -49,7 +49,20 @@ func (g *generator) setRepositoryStructName() { func (g *generator) generate(writer io.Writer) { g.setting() - t := template.Must(template.New("tmpl").Parse(tmpl)) + funcMap := template.FuncMap{ + "Parse": func(field, fieldType string) string { + fn := ".Int()" + switch fieldType { + case "int": + case "int64": + fn = ".Int64()" + default: + panic("invalid types") + } + return field + fn + }, + } + t := template.Must(template.New("tmpl").Funcs(funcMap).Parse(tmpl)) err := t.Execute(writer, g) From 1d0214a757b063fbe9cff9fec1b0a4ed4b254c39 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 16:57:49 +0900 Subject: [PATCH 05/77] feat: consider time.Time #4 --- generator.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/generator.go b/generator.go index b5d5349..9f46fdd 100644 --- a/generator.go +++ b/generator.go @@ -35,6 +35,16 @@ func (g *generator) setting() { g.GoGenerate = "go:generate" g.RepositoryInterfaceName = g.StructName + "Repository" g.setRepositoryStructName() + g.buildConditions() +} + +func (g *generator) buildConditions() { + for _, field := range g.FieldInfos { + switch field.FieldType { + case "time.Time": + g.ImportList = append(g.ImportList, ImportInfo{"time"}) + } + } } func (g *generator) setRepositoryStructName() { @@ -99,6 +109,9 @@ package {{.PackageName}} import ( "context" +{{- range .ImportList }} + "{{ .Name }}" +{{- end }} "cloud.google.com/go/datastore" "golang.org/x/xerrors" From 5e72de80e58547e996406987972a0ecb20f386f8 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:02:59 +0900 Subject: [PATCH 06/77] clean: refactoring --- generator.go | 192 +++++++++++++++++++++++++-------------------------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/generator.go b/generator.go index 9f46fdd..b5d1661 100644 --- a/generator.go +++ b/generator.go @@ -105,7 +105,7 @@ const ( // nolint:lll const tmpl = `// THIS FILE IS A GENERATED CODE. DO NOT EDIT -package {{.PackageName}} +package {{ .PackageName }} import ( "context" @@ -117,15 +117,15 @@ import ( "golang.org/x/xerrors" ) -//{{.GoGenerate}} mockgen -source {{.GeneratedFileName}}.go -destination mock_{{.GeneratedFileName}}/mock_{{.GeneratedFileName}}.go +//{{ .GoGenerate }} mockgen -source {{ .GeneratedFileName }}.go -destination mock_{{ .GeneratedFileName }}/mock_{{ .GeneratedFileName }}.go -type {{.RepositoryInterfaceName}} interface { +type {{ .RepositoryInterfaceName }} interface { // Single - Get(ctx context.Context, {{.KeyValueName}} {{.KeyFieldType}}) (*{{.StructName}}, error) - Insert(ctx context.Context, subject *{{.StructName}}) ({{.KeyFieldType}}, error) - Update(ctx context.Context, subject *{{.StructName}}) error - Delete(ctx context.Context, subject *{{.StructName}}) error - DeleteBy{{.KeyFieldName}}(ctx context.Context, {{.KeyValueName}} {{.KeyFieldType}}) error + Get(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) (*{{ .StructName }}, error) + Insert(ctx context.Context, subject *{{ .StructName }}) ({{ .KeyFieldType }}, error) + Update(ctx context.Context, subject *{{ .StructName }}) error + Delete(ctx context.Context, subject *{{ .StructName }}) error + DeleteBy{{ .KeyFieldName }}(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) error // Multiple GetMulti(ctx context.Context, {{.KeyValueName}}s []{{.KeyFieldType}}) ([]*{{.StructName}}, error) InsertMulti(ctx context.Context, subjects []*{{.StructName}}) ([]{{.KeyFieldType}}, error) @@ -134,14 +134,14 @@ type {{.RepositoryInterfaceName}} interface { DeleteMultiBy{{.KeyFieldName}}s(ctx context.Context, {{.KeyValueName}}s []{{.KeyFieldType}}) error } -type {{.RepositoryStructName}} struct { +type {{ .RepositoryStructName }} struct { kind string datastoreClient *datastore.Client } -func New{{.RepositoryInterfaceName}}(datastoreClient *datastore.Client) {{.RepositoryInterfaceName}} { - return &{{.RepositoryStructName}}{ - kind: "{{.StructName}}", +func New{{ .RepositoryInterfaceName }}(datastoreClient *datastore.Client) {{ .RepositoryInterfaceName }} { + return &{{ .RepositoryStructName }}{ + kind: "{{ .StructName }}", datastoreClient: datastoreClient, } } @@ -149,59 +149,59 @@ func New{{.RepositoryInterfaceName}}(datastoreClient *datastore.Client) {{.Repos func (repo *{{.RepositoryStructName}}) getKeys(subjects ...*{{.StructName}}) ([]*datastore.Key, error) { keys := make([]*datastore.Key, 0, len(subjects)) for _, subject := range subjects { - key := subject.{{.KeyFieldName}} -{{- if eq .KeyFieldType "int64"}} + key := subject.{{ .KeyFieldName }} +{{- if eq .KeyFieldType "int64" }} if key == 0 { return nil, xerrors.New("ID must be set") } keys = append(keys, datastore.IDKey(repo.kind, key, nil)) -{{- else if eq .KeyFieldType "string"}} +{{- else if eq .KeyFieldType "string" }} if key == "" { return nil, xerrors.New("ID must be set") } keys = append(keys, datastore.NameKey(repo.kind, key, nil)) -{{- else}} +{{- else }} if key == nil { key = datastore.IncompleteKey(repo.kind, nil) } keys = append(keys, key) -{{- end}} +{{- end }} } return keys, nil } -func (repo *{{.RepositoryStructName}}) Get(ctx context.Context, {{.KeyValueName}} {{.KeyFieldType}}) (*{{.StructName}}, error) { -{{- if eq .KeyFieldType "int64"}} - key := datastore.IDKey(repo.kind, {{.KeyValueName}}, nil) -{{else if eq .KeyFieldType "string"}} - key := datastore.NameKey(repo.kind, {{.KeyValueName}}, nil) -{{else}} - key := {{.KeyValueName}} -{{end}} - subject := new({{.StructName}}) +func (repo *{{ .RepositoryStructName }}) Get(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) (*{{ .StructName }}, error) { +{{- if eq .KeyFieldType "int64" }} + key := datastore.IDKey(repo.kind, {{ .KeyValueName }}, nil) +{{ else if eq .KeyFieldType "string" }} + key := datastore.NameKey(repo.kind, {{ .KeyValueName }}, nil) +{{ else }} + key := {{ .KeyValueName }} +{{ end }} + subject := new({{ .StructName }}) err := repo.datastoreClient.Get(ctx, key, subject) if err != nil { return nil, err } -{{if eq .KeyFieldType "int64"}} - subject.{{.KeyFieldName}} = key.ID -{{else if eq .KeyFieldType "string"}} - subject.{{.KeyFieldName}} = key.Name -{{else}} - subject.{{.KeyFieldName}} = key -{{end}} +{{if eq .KeyFieldType "int64" }} + subject.{{ .KeyFieldName }} = key.ID +{{ else if eq .KeyFieldType "string" }} + subject.{{ .KeyFieldName }} = key.Name +{{ else }} + subject.{{ .KeyFieldName }} = key +{{ end }} return subject, nil } -func (repo *{{.RepositoryStructName}}) Insert(ctx context.Context, subject *{{.StructName}}) ({{.KeyFieldType}}, error) { -{{- if eq .KeyFieldType "int64"}} +func (repo *{{ .RepositoryStructName }}) Insert(ctx context.Context, subject *{{ .StructName }}) ({{ .KeyFieldType }}, error) { +{{- if eq .KeyFieldType "int64" }} zero := int64(0) -{{else if eq .KeyFieldType "string"}} +{{ else if eq .KeyFieldType "string" }} zero := "" -{{else}} - var zero {{.KeyFieldType}} -{{end}} +{{ else }} + var zero {{ .KeyFieldType }} +{{ end }} keys, err := repo.getKeys(subject) if err != nil { return zero, xerrors.Errorf("error in getKeys method: %w", err) @@ -211,17 +211,17 @@ func (repo *{{.RepositoryStructName}}) Insert(ctx context.Context, subject *{{.S if err != nil { return zero, err } -{{if eq .KeyFieldType "int64"}} +{{if eq .KeyFieldType "int64" }} return key.ID, nil -{{else if eq .KeyFieldType "string"}} +{{ else if eq .KeyFieldType "string" }} return key.Name, nil -{{else}} +{{ else }} return key, nil -{{end -}} +{{- end }} } -func (repo *{{.RepositoryStructName}}) Update(ctx context.Context, subject *{{.StructName}}) error { - if _, err := repo.Get(ctx, subject.{{.KeyFieldName}}); err == datastore.ErrNoSuchEntity { +func (repo *{{ .RepositoryStructName }}) Update(ctx context.Context, subject *{{ .StructName }}) error { + if _, err := repo.Get(ctx, subject.{{ .KeyFieldName }}); err == datastore.ErrNoSuchEntity { return err } @@ -237,7 +237,7 @@ func (repo *{{.RepositoryStructName}}) Update(ctx context.Context, subject *{{.S return nil } -func (repo *{{.RepositoryStructName}}) Delete(ctx context.Context, subject *{{.StructName}}) error { +func (repo *{{ .RepositoryStructName }}) Delete(ctx context.Context, subject *{{ .StructName }}) error { keys, err := repo.getKeys(subject) if err != nil { return xerrors.Errorf("error in getKeys method: %w", err) @@ -246,59 +246,59 @@ func (repo *{{.RepositoryStructName}}) Delete(ctx context.Context, subject *{{.S return repo.datastoreClient.Delete(ctx, keys[0]) } -func (repo *{{.RepositoryStructName}}) DeleteBy{{.KeyFieldName}}(ctx context.Context, {{.KeyValueName}} {{.KeyFieldType}}) error { -{{- if eq .KeyFieldType "int64"}} - key := datastore.IDKey(repo.kind, {{.KeyValueName}}, nil) -{{- else if eq .KeyFieldType "string"}} - key := datastore.NameKey(repo.kind, {{.KeyValueName}}, nil) -{{- else}} - key := {{.KeyValueName}} -{{end}} +func (repo *{{ .RepositoryStructName }}) DeleteBy{{ .KeyFieldName }}(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) error { +{{- if eq .KeyFieldType "int64" }} + key := datastore.IDKey(repo.kind, {{ .KeyValueName }}, nil) +{{- else if eq .KeyFieldType "string" }} + key := datastore.NameKey(repo.kind, {{ .KeyValueName }}, nil) +{{- else }} + key := {{ .KeyValueName }} +{{ end }} return repo.datastoreClient.Delete(ctx, key) } -func (repo *{{.RepositoryStructName}}) GetMulti(ctx context.Context, {{.KeyValueName}}s []{{.KeyFieldType}}) ([]*{{.StructName}}, error) { -{{- if eq .KeyFieldType "int64"}} - keys := make([]*datastore.Key, 0, len({{.KeyValueName}}s)) +func (repo *{{ .RepositoryStructName }}) GetMulti(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) ([]*{{ .StructName }}, error) { +{{- if eq .KeyFieldType "int64" }} + keys := make([]*datastore.Key, 0, len({{ .KeyValueName }}s)) - for i := range {{.KeyValueName}}s { - keys = append(keys, datastore.IDKey(repo.kind, {{.KeyValueName}}s[i], nil)) + for i := range {{ .KeyValueName }}s { + keys = append(keys, datastore.IDKey(repo.kind, {{ .KeyValueName }}s[i], nil)) } -{{else if eq .KeyFieldType "string"}} - keys := make([]*datastore.Key, 0, len({{.KeyValueName}}s)) +{{ else if eq .KeyFieldType "string" }} + keys := make([]*datastore.Key, 0, len({{ .KeyValueName }}s)) - for i := range {{.KeyValueName}}s { - keys = append(keys, datastore.NameKey(repo.kind, {{.KeyValueName}}s[i], nil)) + for i := range {{ .KeyValueName }}s { + keys = append(keys, datastore.NameKey(repo.kind, {{ .KeyValueName }}s[i], nil)) } -{{else}} - keys := {{.KeyValueName}}s -{{end}} - vessels := make([]*{{.StructName}}, len({{.KeyValueName}}s)) +{{ else }} + keys := {{ .KeyValueName }}s +{{ end }} + vessels := make([]*{{ .StructName }}, len({{ .KeyValueName }}s)) err := repo.datastoreClient.GetMulti(ctx, keys, vessels) for i := range vessels { if vessels[i] != nil { -{{- if eq .KeyFieldType "int64"}} - vessels[i].{{.KeyFieldName}} = keys[i].ID -{{- else if eq .KeyFieldType "string"}} - vessels[i].{{.KeyFieldName}} = keys[i].Name -{{- else}} - vessels[i].{{.KeyFieldName}} = keys[i] -{{- end}} +{{- if eq .KeyFieldType "int64" }} + vessels[i].{{ .KeyFieldName }} = keys[i].ID +{{- else if eq .KeyFieldType "string" }} + vessels[i].{{ .KeyFieldName }} = keys[i].Name +{{- else }} + vessels[i].{{ .KeyFieldName }} = keys[i] +{{- end }} } } return vessels, err } -func (repo *{{.RepositoryStructName}}) InsertMulti(ctx context.Context, subjects []*{{.StructName}}) ([]{{.KeyFieldType}}, error) { +func (repo *{{ .RepositoryStructName }}) InsertMulti(ctx context.Context, subjects []*{{ .StructName }}) ([]{{ .KeyFieldType }}, error) { keys, err := repo.getKeys(subjects...) if err != nil { return nil, xerrors.Errorf("error in getKeys method: %w", err) } var cnt int - if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{.StructName}}, 0, len(subjects))); err != nil { + if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{ .StructName }}, 0, len(subjects))); err != nil { if errs, ok := err.(datastore.MultiError); ok { for _, err := range errs { if err == datastore.ErrNoSuchEntity { @@ -317,29 +317,29 @@ func (repo *{{.RepositoryStructName}}) InsertMulti(ctx context.Context, subjects return nil, err } - vessels := make([]{{.KeyFieldType}}, 0, len(resKeys)) + vessels := make([]{{ .KeyFieldType }}, 0, len(resKeys)) for i := range resKeys { if keys[i] != nil { -{{- if eq .KeyFieldType "int64"}} +{{- if eq .KeyFieldType "int64" }} vessels[i] = resKeys[i].ID -{{- else if eq .KeyFieldType "string"}} +{{- else if eq .KeyFieldType "string" }} vessels[i] = resKeys[i].Name -{{- else}} +{{- else }} vessels[i] = resKeys[i] -{{- end}} +{{- end }} } } return vessels, err } -func (repo *{{.RepositoryStructName}}) UpdateMulti(ctx context.Context, subjects []*{{.StructName}}) error { +func (repo *{{ .RepositoryStructName }}) UpdateMulti(ctx context.Context, subjects []*{{ .StructName }}) error { keys, err := repo.getKeys(subjects...) if err != nil { return xerrors.Errorf("error in getKeys method: %w", err) } - if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{.StructName}}, 0, len(subjects))); err != nil { + if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{ .StructName }}, 0, len(subjects))); err != nil { if _, ok := err.(datastore.MultiError); ok { return err } @@ -353,7 +353,7 @@ func (repo *{{.RepositoryStructName}}) UpdateMulti(ctx context.Context, subjects return nil } -func (repo *{{.RepositoryStructName}}) DeleteMulti(ctx context.Context, subjects []*{{.StructName}}) error { +func (repo *{{ .RepositoryStructName }}) DeleteMulti(ctx context.Context, subjects []*{{ .StructName }}) error { keys, err := repo.getKeys(subjects...) if err != nil { return xerrors.Errorf("error in getKeys method: %w", err) @@ -362,22 +362,22 @@ func (repo *{{.RepositoryStructName}}) DeleteMulti(ctx context.Context, subjects return repo.datastoreClient.DeleteMulti(ctx, keys) } -func (repo *{{.RepositoryStructName}}) DeleteMultiBy{{.KeyFieldName}}s(ctx context.Context, {{.KeyValueName}}s []{{.KeyFieldType}}) error { -{{- if eq .KeyFieldType "int64"}} - keys := make([]*datastore.Key, 0, len({{.KeyValueName}}s)) +func (repo *{{ .RepositoryStructName }}) DeleteMultiBy{{ .KeyFieldName }}s(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) error { +{{- if eq .KeyFieldType "int64" }} + keys := make([]*datastore.Key, 0, len({{ .KeyValueName }}s)) - for i := range {{.KeyValueName}}s { - keys = append(keys, datastore.IDKey(repo.kind, {{.KeyValueName}}s[i], nil)) + for i := range {{ .KeyValueName }}s { + keys = append(keys, datastore.IDKey(repo.kind, {{ .KeyValueName }}s[i], nil)) } -{{else if eq .KeyFieldType "string"}} - keys := make([]*datastore.Key, 0, len({{.KeyValueName}}s)) +{{ else if eq .KeyFieldType "string" }} + keys := make([]*datastore.Key, 0, len({{ .KeyValueName }}s)) - for i := range {{.KeyValueName}}s { - keys = append(keys, datastore.NameKey(repo.kind, {{.KeyValueName}}s[i], nil)) + for i := range {{ .KeyValueName }}s { + keys = append(keys, datastore.NameKey(repo.kind, {{ .KeyValueName }}s[i], nil)) } -{{else}} - keys := {{.KeyValueName}}s -{{end}} +{{ else }} + keys := {{ .KeyValueName }}s +{{ end }} return repo.datastoreClient.DeleteMulti(ctx, keys) } ` From 8457d61c310d3f8512e201f134abbe1d15803d69 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:05:37 +0900 Subject: [PATCH 07/77] feat: add ExtraFilters #4 --- generator.go | 267 +++++++++++++++++++++++++++++++++++++++++++++++---- main.go | 90 ++++++++++++++--- 2 files changed, 323 insertions(+), 34 deletions(-) diff --git a/generator.go b/generator.go index b5d1661..0bedea7 100644 --- a/generator.go +++ b/generator.go @@ -7,17 +7,30 @@ import ( ) type IndexesInfo struct { - Comment string - Field string - Label string - SearchItem string // TODO `前方一致` や `部分一致` など (5/7 unused) + Comment string + ConstName string + Label string + Method string +} + +type FieldInfo struct { + Field string + FieldType string + Indexes []*IndexesInfo +} + +type ImportInfo struct { + Name string } type generator struct { PackageName string + ImportName string + ImportList []ImportInfo GeneratedFileName string FileName string StructName string + LowerStructName string GoGenerate string RepositoryStructName string @@ -28,10 +41,14 @@ type generator struct { KeyValueName string // lower camel case - ConstMapForIndexes []IndexesInfo + FieldInfos []*FieldInfo + + EnableIndexes bool + BoolCriteriaCnt int } func (g *generator) setting() { + g.ImportName = ImportName g.GoGenerate = "go:generate" g.RepositoryInterfaceName = g.StructName + "Repository" g.setRepositoryStructName() @@ -81,9 +98,18 @@ func (g *generator) generate(writer io.Writer) { } } +func (g *generator) generateLabel(writer io.Writer) { + t := template.Must(template.New("tmplLabel").Parse(tmplLabel)) + + err := t.Execute(writer, g) + + if err != nil { + log.Printf("failed to execute template: %+v", err) + } +} + func (g *generator) generateConstant(writer io.Writer) { - g.setting() - t := template.Must(template.New("tmpl").Parse(tmplConst)) + t := template.Must(template.New("tmplConst").Parse(tmplConst)) err := t.Execute(writer, g) @@ -92,13 +118,55 @@ func (g *generator) generateConstant(writer io.Writer) { } } -const tmplConst = `// THIS FILE IS A GENERATED CODE. EDIT OK +const tmplConst = `// THIS FILE IS A GENERATED CODE. DO NOT EDIT package configs +import "strconv" + +type BoolCriteria string + const ( -{{- range .ConstMapForIndexes }} - // {{ .Comment }}検索用ラベル - {{ .Field }} = "{{ .Label }}" + BoolCriteriaEmpty BoolCriteria = "" + BoolCriteriaTrue BoolCriteria = "true" + BoolCriteriaFalse BoolCriteria = "false" +) + +func (src BoolCriteria) Bool() bool { + return src == BoolCriteriaTrue +} + +type IntegerCriteria string + +const ( + IntegerCriteriaEmpty IntegerCriteria = "" +) + +func (str IntegerCriteria) Int() int { + i32, err := strconv.Atoi(string(str)) + if err != nil { + return -1 + } + return i32 +} + +func (str IntegerCriteria) Int64() int64 { + i64, err := strconv.ParseInt(string(str), 10, 64) + if err != nil { + return -1 + } + return i64 +} +` + +const tmplLabel = `// THIS FILE IS A GENERATED CODE. EDIT OK +package configs + +const ( +{{- range $fi := .FieldInfos }} + {{- range $idx := $fi.Indexes }} + // {{ $idx.Comment }}検索用ラベル + {{ $idx.ConstName }} = "{{ $idx.Label }}" + {{- end }} {{- end }} ) ` @@ -114,6 +182,7 @@ import ( {{- end }} "cloud.google.com/go/datastore" + "{{ .ImportName }}/configs" "golang.org/x/xerrors" ) @@ -127,11 +196,15 @@ type {{ .RepositoryInterfaceName }} interface { Delete(ctx context.Context, subject *{{ .StructName }}) error DeleteBy{{ .KeyFieldName }}(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) error // Multiple - GetMulti(ctx context.Context, {{.KeyValueName}}s []{{.KeyFieldType}}) ([]*{{.StructName}}, error) - InsertMulti(ctx context.Context, subjects []*{{.StructName}}) ([]{{.KeyFieldType}}, error) - UpdateMulti(ctx context.Context, subjects []*{{.StructName}}) error - DeleteMulti(ctx context.Context, subjects []*{{.StructName}}) error - DeleteMultiBy{{.KeyFieldName}}s(ctx context.Context, {{.KeyValueName}}s []{{.KeyFieldType}}) error + GetMulti(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) ([]*{{ .StructName }}, error) + InsertMulti(ctx context.Context, subjects []*{{ .StructName }}) ([]{{ .KeyFieldType }}, error) + UpdateMulti(ctx context.Context, subjects []*{{ .StructName }}) error + DeleteMulti(ctx context.Context, subjects []*{{ .StructName }}) error + DeleteMultiBy{{ .KeyFieldName }}s(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) error + // List + List(ctx context.Context, req *{{ .StructName }}ListReq, q *datastore.Query) ([]*{{ .StructName }}, error) + // misc + GetKindName() string } type {{ .RepositoryStructName }} struct { @@ -146,7 +219,12 @@ func New{{ .RepositoryInterfaceName }}(datastoreClient *datastore.Client) {{ .Re } } -func (repo *{{.RepositoryStructName}}) getKeys(subjects ...*{{.StructName}}) ([]*datastore.Key, error) { +func (repo *{{ .RepositoryStructName }}) GetKindName() string { + return repo.kind +} + +// getKeys Entityからkeyを取得する +func (repo *{{ .RepositoryStructName }}) getKeys(subjects ...*{{ .StructName }}) ([]*datastore.Key, error) { keys := make([]*datastore.Key, 0, len(subjects)) for _, subject := range subjects { key := subject.{{ .KeyFieldName }} @@ -170,6 +248,137 @@ func (repo *{{.RepositoryStructName}}) getKeys(subjects ...*{{.StructName}}) ([] return keys, nil } +{{ if eq .EnableIndexes true }} +// saveIndexes 拡張フィルタを保存する +func (repo *{{ .RepositoryStructName }}) saveIndexes(subjects ...*{{ .StructName }}) error { + for _, subject := range subjects { + idx := xian.NewIndexes({{ .LowerStructName }}IndexesConfig) +{{- range $fi := .FieldInfos }} +{{- range $idx := $fi.Indexes }} +{{- if eq $fi.FieldType "bool" }} + idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}) +{{- else if eq $fi.FieldType "string" }} +{{- if eq $idx.Method "AddPrefix" }} + idx.{{ $idx.Method }}es(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}) +{{- else }} + idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}) +{{- end }} +{{- else if eq $fi.FieldType "int" }} + idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}) +{{- else if eq $fi.FieldType "time.Time" }} + idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}.Unix()) +{{- end }} +{{- end }} +{{- end }} + built, err := idx.Build() + if err != nil { + return err + } + subject.Indexes = built + } + + return nil +} + +var {{ .LowerStructName }}IndexesConfig = &xian.Config{ + IgnoreCase: true, // Case insensitive + SaveNoFiltersIndex: true, // https://qiita.com/hogedigo/items/02dcce80f6197faae1fb#savenofiltersindex +} +{{- end }} + +// {{ .StructName }}ListReq List取得時に渡すリクエスト +// └─ bool/int(64) は stringで渡す(configs.BoolCriteria | configs.IntegerCriteria) +type {{ .StructName }}ListReq struct { +{{- range .FieldInfos }} +{{- if eq .FieldType "bool" }} + {{ .Field }} configs.BoolCriteria +{{- else if or (eq .FieldType "int") (eq .FieldType "int64") }} + {{ .Field }} configs.IntegerCriteria +{{- else }} + {{ .Field }} {{ .FieldType }} +{{- end }} +{{- end }} +} + +// List datastore.Queryを使用し条件抽出をする +// └─ 第3引数はNOT/OR/IN/RANGEなど、より複雑な条件を適用したいときにつける +// └─ 基本的にnilを渡せば良い +// BUG(54mch4n) 潜在的なバグがあるかもしれない +func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .StructName }}ListReq, q *datastore.Query) ([]*{{ .StructName }}, error) { + if q == nil { + q = datastore.NewQuery(repo.kind) + } +{{ $Enable := .EnableIndexes }} +{{- if eq $Enable true }} + filters := xian.NewFilters({{ .LowerStructName }}IndexesConfig) +{{- end }} +{{- range $fi := .FieldInfos }} +{{- if eq $fi.FieldType "bool" }} + if req.{{ $fi.Field }} != "" { +{{- if eq $Enable true }} +{{- range $idx := $fi.Indexes }} + filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}) +{{- end }} +{{- else }} + q = q.Filter("{{ $fi.Field }}", req.{{ $fi.Field }}.Bool()) +{{- end }} + } +{{- else if eq $fi.FieldType "string" }} + if req.{{ $fi.Field }} != "" { +{{- if eq $Enable true }} +{{- range $idx := $fi.Indexes }} + filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}) +{{- end }} +{{- else }} + q = q.Filter("{{ $fi.Field }}", req.{{ $fi.Field }}) +{{- end }} + } +{{- else if or (eq $fi.FieldType "int") (eq $fi.FieldType "int64") }} + if req.{{ $fi.Field }} != configs.IntegerCriteriaEmpty { +{{- if eq $Enable true }} +{{- range $idx := $fi.Indexes }} + filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ Parse $fi.Field $fi.FieldType }}) +{{- end }} +{{- else }} + q = q.Filter("{{ $fi.Field }}", req.{{ Parse $fi.Field $fi.FieldType }}) +{{- end }} + } +{{- else if eq $fi.FieldType "time.Time" }} + if !req.{{ $fi.Field }}.IsZero() { +{{- if eq $Enable true }} +{{- range $idx := $fi.Indexes }} + filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}.Unix()) +{{- end }} +{{- else }} + q = q.Filter("{{ $fi.Field }}", req.{{ $fi.Field }}) +{{- end }} + } +{{- end }} +{{- end }} +{{ if eq $Enable true }} + built, err := filters.Build() + if err != nil { + return nil, err + } + + for _, f := range built { + q = q.Filter("Indexes =", f) + } +{{- end }} + subjects := make([]*{{ .StructName }}, 0) + keys, err := repo.datastoreClient.GetAll(ctx, q, &subjects) + if err != nil { + return nil, err + } + + for i, k := range keys { + if k != nil { + subjects[i].ID = k.ID + } + } + + return subjects, nil +} func (repo *{{ .RepositoryStructName }}) Get(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) (*{{ .StructName }}, error) { {{- if eq .KeyFieldType "int64" }} @@ -206,7 +415,11 @@ func (repo *{{ .RepositoryStructName }}) Insert(ctx context.Context, subject *{{ if err != nil { return zero, xerrors.Errorf("error in getKeys method: %w", err) } - +{{ if eq .EnableIndexes true }} + if err := repo.saveIndexes(subject); err != nil { + return zero, xerrors.Errorf("error in saveIndexes method: %w", err) + } +{{ end }} key, err := repo.datastoreClient.Put(ctx, keys[0], subject) if err != nil { return zero, err @@ -229,7 +442,11 @@ func (repo *{{ .RepositoryStructName }}) Update(ctx context.Context, subject *{{ if err != nil { return xerrors.Errorf("error in getKeys method: %w", err) } - +{{ if eq .EnableIndexes true }} + if err := repo.saveIndexes(subject); err != nil { + return xerrors.Errorf("error in saveIndexes method: %w", err) + } +{{ end }} if _, err := repo.datastoreClient.Put(ctx, keys[0], subject); err != nil { return err } @@ -311,7 +528,11 @@ func (repo *{{ .RepositoryStructName }}) InsertMulti(ctx context.Context, subjec if len(subjects) != cnt { return nil, xerrors.Errorf("already exist. (%d)", len(subjects)-cnt) } - +{{ if eq .EnableIndexes true }} + if err := repo.saveIndexes(subjects...); err != nil { + return nil, xerrors.Errorf("error in saveIndexes method: %w", err) + } +{{ end }} resKeys, err := repo.datastoreClient.PutMulti(ctx, keys, subjects) if err != nil { return nil, err @@ -344,7 +565,11 @@ func (repo *{{ .RepositoryStructName }}) UpdateMulti(ctx context.Context, subjec return err } } - +{{ if eq .EnableIndexes true }} + if err := repo.saveIndexes(subjects...); err != nil { + return xerrors.Errorf("error in saveIndexes method: %w", err) + } +{{ end }} _, err = repo.datastoreClient.PutMulti(ctx, keys, subjects) if err != nil { return err diff --git a/main.go b/main.go index e671ca5..063be44 100644 --- a/main.go +++ b/main.go @@ -15,13 +15,17 @@ import ( "golang.org/x/xerrors" ) +var ImportName string + func main() { l := len(os.Args) - if l < 2 { + if l < 3 { fmt.Println("You have to specify the struct name of target") os.Exit(1) } + ImportName = os.Args[2] + if err := run(os.Args[1]); err != nil { log.Fatal(err.Error()) } @@ -79,6 +83,7 @@ func traverse(pkg *ast.Package, fs *token.FileSet, structName string) error { continue } gen.StructName = name + gen.LowerStructName = strcase.ToLowerCamel(name) return generate(gen, fs, structType) } @@ -126,22 +131,72 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err continue } + if name == "Indexes" { + gen.EnableIndexes = true + continue + } + _, err = tags.Get("datastore_key") if err != nil { - u := uppercaseExtraction(name) - if _, ok := dupMap[u]; !ok { - dupMap[u] = 1 - } else { - dupMap[u]++ - u = fmt.Sprintf("%s%d", u, dupMap[u]) + f := func() string { + u := uppercaseExtraction(name) + if _, ok := dupMap[u]; !ok { + dupMap[u] = 1 + } else { + dupMap[u]++ + u = fmt.Sprintf("%s%d", u, dupMap[u]) + } + return u + } + field := &FieldInfo{ + Field: name, + FieldType: getTypeName(field.Type), + Indexes: make([]*IndexesInfo, 0), } - idx := IndexesInfo{ - Field: filedLabel + name, - Label: u, + ft, err := tags.Get("filter") + if err != nil || field.FieldType != "string" { + idx := &IndexesInfo{ + ConstName: filedLabel + name, + Label: f(), + Method: "Add", + } + idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) + if field.FieldType != "string" { + idx.Method += "Something" + } + field.Indexes = append(field.Indexes, idx) + } else { + filters := strings.Split(ft.Value(), ",") + for _, fil := range filters { + idx := &IndexesInfo{ + ConstName: filedLabel + name, + Label: f(), + Method: "Add", + } + switch fil { + case "p", "prefix": // 前方一致 (AddPrefix) + idx.Method += "Prefix" + idx.ConstName += "Prefix" + idx.Comment = fmt.Sprintf("%s %s前方一致", idx.ConstName, name) + case "s", "suffix": /* TODO 後方一致 + idx.Method += "Suffix" + idx.ConstName += "Suffix" + idx.Comment = fmt.Sprintf("%s %s後方一致", idx.ConstName, name)*/ + case "m", "matching": // 完全一致 (Add) Default + idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) + case "l", "like": // 部分一致 + idx.Method += "Biunigrams" + idx.ConstName += "Like" + idx.Comment = fmt.Sprintf("%s %s部分一致", idx.ConstName, name) + default: + continue + } + field.Indexes = append(field.Indexes, idx) + } } - idx.Comment = fmt.Sprintf("%s %s", idx.Field, name) // TODO `前方一致` や `部分一致` など - gen.ConstMapForIndexes = append(gen.ConstMapForIndexes, idx) + + gen.FieldInfos = append(gen.FieldInfos, field) continue } @@ -184,12 +239,21 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err return err } } - path := "configs/" + strcase.ToLowerCamel(gen.StructName) + "_const.go" + path := "configs/" + strcase.ToLowerCamel(gen.StructName) + "_label.go" fp, err := os.Create(path) if err != nil { panic(err) } defer fp.Close() + gen.generateLabel(fp) + } + + { + fp, err := os.Create("configs/constant.go") + if err != nil { + panic(err) + } + defer fp.Close() gen.generateConstant(fp) } From 65c997ba269beb173958f4fc8f5f7109de13e9fe Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:06:00 +0900 Subject: [PATCH 08/77] clean: delete unnecessary things --- main.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/main.go b/main.go index 063be44..c7bb2fe 100644 --- a/main.go +++ b/main.go @@ -207,10 +207,6 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err return fmt.Errorf("%s: key field for datastore should have datastore:\"-\" tag", pos) } - if len(field.Names) != 1 { - return fmt.Errorf("%s: datastore_key tag can be set to only one field", pos) - } - gen.KeyFieldName = name gen.KeyFieldType = getTypeName(field.Type) From 2490f793d11d9f8238d1ac73e272b5046ade27d0 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:08:43 +0900 Subject: [PATCH 09/77] update: add args --- testfiles/a/name.go | 2 +- testfiles/a/task.go | 2 +- testfiles/b/task.go | 2 +- testfiles/c/task.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testfiles/a/name.go b/testfiles/a/name.go index ac01fb0..86556d3 100644 --- a/testfiles/a/name.go +++ b/testfiles/a/name.go @@ -4,7 +4,7 @@ import ( "time" ) -//go:generate repo_generator Name +//go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/a type Name struct { Desc string `datastore:"description"` diff --git a/testfiles/a/task.go b/testfiles/a/task.go index fe53f38..10ce78d 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -4,7 +4,7 @@ import ( "time" ) -//go:generate repo_generator Task +//go:generate repo_generator Task github.com/go-generalize/repo_generator/testfiles/a type Task struct { Desc string `datastore:"description"` diff --git a/testfiles/b/task.go b/testfiles/b/task.go index a3393d8..a376ff6 100644 --- a/testfiles/b/task.go +++ b/testfiles/b/task.go @@ -4,7 +4,7 @@ import ( "time" ) -//go:generate repo_generator Task +//go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/b type Task struct { Desc string `datastore:"description"` diff --git a/testfiles/c/task.go b/testfiles/c/task.go index b3715ce..f67c8d6 100644 --- a/testfiles/c/task.go +++ b/testfiles/c/task.go @@ -6,7 +6,7 @@ import ( "cloud.google.com/go/datastore" ) -//go:generate repo_generator Task +//go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/c type Task struct { Desc string `datastore:"description"` From dc95259c247510cc994f870ca216995334d1a400 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:09:52 +0900 Subject: [PATCH 10/77] update: go generate gofmt --- testfiles/a/name.go | 1 + testfiles/a/task.go | 1 + testfiles/b/task.go | 1 + testfiles/c/task.go | 1 + 4 files changed, 4 insertions(+) diff --git a/testfiles/a/name.go b/testfiles/a/name.go index 86556d3..eb6eb2a 100644 --- a/testfiles/a/name.go +++ b/testfiles/a/name.go @@ -5,6 +5,7 @@ import ( ) //go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/a +//go:generate gofmt -w ./ type Name struct { Desc string `datastore:"description"` diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 10ce78d..263da07 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -5,6 +5,7 @@ import ( ) //go:generate repo_generator Task github.com/go-generalize/repo_generator/testfiles/a +//go:generate gofmt -w ./ type Task struct { Desc string `datastore:"description"` diff --git a/testfiles/b/task.go b/testfiles/b/task.go index a376ff6..c93a1b8 100644 --- a/testfiles/b/task.go +++ b/testfiles/b/task.go @@ -5,6 +5,7 @@ import ( ) //go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/b +//go:generate gofmt -w ./ type Task struct { Desc string `datastore:"description"` diff --git a/testfiles/c/task.go b/testfiles/c/task.go index f67c8d6..97da911 100644 --- a/testfiles/c/task.go +++ b/testfiles/c/task.go @@ -7,6 +7,7 @@ import ( ) //go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/c +//go:generate gofmt -w ./ type Task struct { Desc string `datastore:"description"` From 3b60d2494c3158da346753d78ad45bad60d8ba12 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:11:25 +0900 Subject: [PATCH 11/77] update: modifications related to changes #4 --- testfiles/a/name.go | 5 +++-- testfiles/a/task.go | 8 ++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/testfiles/a/name.go b/testfiles/a/name.go index eb6eb2a..d352afd 100644 --- a/testfiles/a/name.go +++ b/testfiles/a/name.go @@ -8,8 +8,9 @@ import ( //go:generate gofmt -w ./ type Name struct { - Desc string `datastore:"description"` + ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key Created time.Time `datastore:"created"` + Desc string `datastore:"description"` Done bool `datastore:"done"` - ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key + Count int `datastore:"count"` } diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 263da07..3d58422 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -8,8 +8,12 @@ import ( //go:generate gofmt -w ./ type Task struct { - Desc string `datastore:"description"` + ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key + Desc string `datastore:"description" filter:"l"` // supported word: m/matching(Default), l/like, p/prefix, TODO s/suffix Created time.Time `datastore:"created"` Done bool `datastore:"done"` - ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key + Done2 bool `datastore:"done2"` + Count int `datastore:"count"` + Count64 int64 `datastore:"count64"` + Indexes []string `datastore:"indexes"` // for XIAN } From 838c6384fb0a74b5982b1e1f06648657a55f2e52 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:57:37 +0900 Subject: [PATCH 12/77] hotfix: fix fatal mistake #4 --- generator.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/generator.go b/generator.go index 0bedea7..315e2ea 100644 --- a/generator.go +++ b/generator.go @@ -320,7 +320,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}) {{- end }} {{- else }} - q = q.Filter("{{ $fi.Field }}", req.{{ $fi.Field }}.Bool()) + q = q.Filter("{{ $fi.Field }} =", req.{{ $fi.Field }}.Bool()) {{- end }} } {{- else if eq $fi.FieldType "string" }} @@ -330,7 +330,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}) {{- end }} {{- else }} - q = q.Filter("{{ $fi.Field }}", req.{{ $fi.Field }}) + q = q.Filter("{{ $fi.Field }} =", req.{{ $fi.Field }}) {{- end }} } {{- else if or (eq $fi.FieldType "int") (eq $fi.FieldType "int64") }} @@ -340,7 +340,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ Parse $fi.Field $fi.FieldType }}) {{- end }} {{- else }} - q = q.Filter("{{ $fi.Field }}", req.{{ Parse $fi.Field $fi.FieldType }}) + q = q.Filter("{{ $fi.Field }} =", req.{{ Parse $fi.Field $fi.FieldType }}) {{- end }} } {{- else if eq $fi.FieldType "time.Time" }} @@ -350,7 +350,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}.Unix()) {{- end }} {{- else }} - q = q.Filter("{{ $fi.Field }}", req.{{ $fi.Field }}) + q = q.Filter("{{ $fi.Field }} =", req.{{ $fi.Field }}) {{- end }} } {{- end }} @@ -515,7 +515,7 @@ func (repo *{{ .RepositoryStructName }}) InsertMulti(ctx context.Context, subjec } var cnt int - if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{ .StructName }}, 0, len(subjects))); err != nil { + if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{ .StructName }}, len(subjects))); err != nil { if errs, ok := err.(datastore.MultiError); ok { for _, err := range errs { if err == datastore.ErrNoSuchEntity { @@ -538,7 +538,7 @@ func (repo *{{ .RepositoryStructName }}) InsertMulti(ctx context.Context, subjec return nil, err } - vessels := make([]{{ .KeyFieldType }}, 0, len(resKeys)) + vessels := make([]{{ .KeyFieldType }}, len(resKeys)) for i := range resKeys { if keys[i] != nil { {{- if eq .KeyFieldType "int64" }} @@ -560,7 +560,7 @@ func (repo *{{ .RepositoryStructName }}) UpdateMulti(ctx context.Context, subjec return xerrors.Errorf("error in getKeys method: %w", err) } - if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{ .StructName }}, 0, len(subjects))); err != nil { + if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{ .StructName }}, len(subjects))); err != nil { if _, ok := err.(datastore.MultiError); ok { return err } From 380965b176feb28f77fdb59fa2d3d3897f172a7d Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:58:12 +0900 Subject: [PATCH 13/77] tests: add List Search #4 --- testfiles/a/tests/task_test.go | 53 ++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 5d5ed7b..3c28cb8 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -1,15 +1,15 @@ -// +build internal - package tests import ( "context" + "fmt" "os" "testing" "time" "cloud.google.com/go/datastore" task "github.com/go-generalize/repo_generator/testfiles/a" + "github.com/go-generalize/repo_generator/testfiles/a/configs" ) func initDatastoreClient(t *testing.T) *datastore.Client { @@ -53,6 +53,55 @@ func compareTask(t *testing.T, expected, actual *task.Task) { } } +func TestDatastoreList(t *testing.T) { + client := initDatastoreClient(t) + + taskRepo := task.NewNameRepository(client) + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + var ids []int64 + defer func() { + defer cancel() + if err := taskRepo.DeleteMultiByIDs(ctx, ids); err != nil { + t.Fatal(err) + } + }() + + now := time.Unix(time.Now().Unix(), 0) + desc := "Hello, World." + + tks := make([]*task.Name, 0) + for i := int64(1); i <= 10; i++ { + tk := &task.Name{ + ID: i, + Created: now, + Desc: fmt.Sprintf("%s%d", desc, i), + Done: true, + Count: int(i), + } + tks = append(tks, tk) + } + ids, err := taskRepo.InsertMulti(ctx, tks) + if err != nil { + t.Fatalf("%+v", err) + } + + req := &task.NameListReq{ + Done: configs.BoolCriteriaTrue, // FIXME 1 これがだけ指定したら条件に引っかかるものが抽出できるはずなのに現状できない + //Count: configs.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい + } + + tasks, err := taskRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + // FIXME 1 + _ = tasks + //if len(tasks) != len(ids) { + // t.Fatal("not match") + //} +} + func TestDatastore(t *testing.T) { client := initDatastoreClient(t) From 6b5432e92ae4b6c640ff9a3a694adecdd783d05f Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:59:26 +0900 Subject: [PATCH 14/77] add: xian #4 --- go.mod | 2 ++ 1 file changed, 2 insertions(+) diff --git a/go.mod b/go.mod index bc47618..0871d9a 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,8 @@ require ( github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.4.1 // indirect github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 + github.com/knightso/xian v0.1.0 + github.com/pkg/errors v0.9.1 // indirect golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 // indirect golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8 From 3f0811e532345eee61fbe4add786d80873d132f0 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 17:59:41 +0900 Subject: [PATCH 15/77] update: go.sum --- go.sum | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/go.sum b/go.sum index e07099c..6c1925f 100644 --- a/go.sum +++ b/go.sum @@ -105,9 +105,13 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1 github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knightso/xian v0.1.0 h1:tbSxtKEB0jMK9M4U6ftbh33LwLDASQqknR0pTodRNBQ= +github.com/knightso/xian v0.1.0/go.mod h1:awKIZpjAL+4BI/y7lanh65Qf2uz2lwQGK8mK+gW+QUo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= From 552ab082978ca7f674e287adad4450f3e7da0084 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 18:10:26 +0900 Subject: [PATCH 16/77] add: *_label.go --- testfiles/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testfiles/.gitignore b/testfiles/.gitignore index 928f4a4..9856778 100644 --- a/testfiles/.gitignore +++ b/testfiles/.gitignore @@ -1,3 +1,3 @@ mock_*/ -configs/ *_gen.go +*_label.go \ No newline at end of file From 61c49d0aef792993ec6c4b6abc3b3e0da37b6b47 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 18:11:06 +0900 Subject: [PATCH 17/77] add: configs/constant.go --- testfiles/a/configs/constant.go | 38 +++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 testfiles/a/configs/constant.go diff --git a/testfiles/a/configs/constant.go b/testfiles/a/configs/constant.go new file mode 100644 index 0000000..8bc439b --- /dev/null +++ b/testfiles/a/configs/constant.go @@ -0,0 +1,38 @@ +// THIS FILE IS A GENERATED CODE. DO NOT EDIT +package configs + +import "strconv" + +type BoolCriteria string + +const ( + BoolCriteriaEmpty BoolCriteria = "" + BoolCriteriaTrue BoolCriteria = "true" + BoolCriteriaFalse BoolCriteria = "false" +) + +func (src BoolCriteria) Bool() bool { + return src == BoolCriteriaTrue +} + +type IntegerCriteria string + +const ( + IntegerCriteriaEmpty IntegerCriteria = "" +) + +func (str IntegerCriteria) Int() int { + i32, err := strconv.Atoi(string(str)) + if err != nil { + return -1 + } + return i32 +} + +func (str IntegerCriteria) Int64() int64 { + i64, err := strconv.ParseInt(string(str), 10, 64) + if err != nil { + return -1 + } + return i64 +} From cabd9000505a63f3eb7d3291c7aa2bfc333f4cb9 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 18:34:34 +0900 Subject: [PATCH 18/77] chore: +build internal --- testfiles/a/tests/task_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 3c28cb8..0d02508 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -1,3 +1,5 @@ +// +build internal + package tests import ( From f2c13dc1eeaa1c9a652accdf2b15050f269957c8 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 19:44:50 +0900 Subject: [PATCH 19/77] hotfix: omission of correction #4 --- generator.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/generator.go b/generator.go index 315e2ea..b631422 100644 --- a/generator.go +++ b/generator.go @@ -183,6 +183,9 @@ import ( "cloud.google.com/go/datastore" "{{ .ImportName }}/configs" +{{- if eq .EnableIndexes true }} + "github.com/knightso/xian" +{{- end }} "golang.org/x/xerrors" ) From a47cb373bea4cf41d241e9b018cf6005ab8416c9 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 19:45:51 +0900 Subject: [PATCH 20/77] hotfix: supports DataStore tags #4 --- generator.go | 9 +++++---- main.go | 6 ++++++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/generator.go b/generator.go index b631422..6c29ccc 100644 --- a/generator.go +++ b/generator.go @@ -14,6 +14,7 @@ type IndexesInfo struct { } type FieldInfo struct { + DsTag string Field string FieldType string Indexes []*IndexesInfo @@ -323,7 +324,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}) {{- end }} {{- else }} - q = q.Filter("{{ $fi.Field }} =", req.{{ $fi.Field }}.Bool()) + q = q.Filter("{{ $fi.DsTag }} =", req.{{ $fi.Field }}.Bool()) {{- end }} } {{- else if eq $fi.FieldType "string" }} @@ -333,7 +334,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}) {{- end }} {{- else }} - q = q.Filter("{{ $fi.Field }} =", req.{{ $fi.Field }}) + q = q.Filter("{{ $fi.DsTag }} =", req.{{ $fi.Field }}) {{- end }} } {{- else if or (eq $fi.FieldType "int") (eq $fi.FieldType "int64") }} @@ -343,7 +344,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ Parse $fi.Field $fi.FieldType }}) {{- end }} {{- else }} - q = q.Filter("{{ $fi.Field }} =", req.{{ Parse $fi.Field $fi.FieldType }}) + q = q.Filter("{{ $fi.DsTag }} =", req.{{ Parse $fi.Field $fi.FieldType }}) {{- end }} } {{- else if eq $fi.FieldType "time.Time" }} @@ -353,7 +354,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}.Unix()) {{- end }} {{- else }} - q = q.Filter("{{ $fi.Field }} =", req.{{ $fi.Field }}) + q = q.Filter("{{ $fi.DsTag }} =", req.{{ $fi.Field }}) {{- end }} } {{- end }} diff --git a/main.go b/main.go index c7bb2fe..9f481e4 100644 --- a/main.go +++ b/main.go @@ -154,6 +154,12 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err FieldType: getTypeName(field.Type), Indexes: make([]*IndexesInfo, 0), } + dsTag, err := tags.Get("datastore") + if err != nil { + fieldInfo.DsTag = fieldInfo.Field + } else { + fieldInfo.DsTag = strings.Split(dsTag.Value(), ",")[0] + } ft, err := tags.Get("filter") if err != nil || field.FieldType != "string" { idx := &IndexesInfo{ From efb87d2c0c5eaa813d3695388311babdfd7531fb Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 19:46:15 +0900 Subject: [PATCH 21/77] fix: mistake #4 --- generator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator.go b/generator.go index 6c29ccc..88afee0 100644 --- a/generator.go +++ b/generator.go @@ -366,7 +366,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru } for _, f := range built { - q = q.Filter("Indexes =", f) + q = q.Filter("indexes =", f) } {{- end }} subjects := make([]*{{ .StructName }}, 0) From 33cd472b2c256bc5224fe3238c4498b7af0c65ce Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 19:47:03 +0900 Subject: [PATCH 22/77] clean: refactoring --- main.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/main.go b/main.go index 9f481e4..ce246a9 100644 --- a/main.go +++ b/main.go @@ -137,7 +137,6 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } _, err = tags.Get("datastore_key") - if err != nil { f := func() string { u := uppercaseExtraction(name) @@ -149,7 +148,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } return u } - field := &FieldInfo{ + fieldInfo := &FieldInfo{ Field: name, FieldType: getTypeName(field.Type), Indexes: make([]*IndexesInfo, 0), @@ -161,17 +160,17 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err fieldInfo.DsTag = strings.Split(dsTag.Value(), ",")[0] } ft, err := tags.Get("filter") - if err != nil || field.FieldType != "string" { + if err != nil || fieldInfo.FieldType != "string" { idx := &IndexesInfo{ ConstName: filedLabel + name, Label: f(), Method: "Add", } idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) - if field.FieldType != "string" { + if fieldInfo.FieldType != "string" { idx.Method += "Something" } - field.Indexes = append(field.Indexes, idx) + fieldInfo.Indexes = append(fieldInfo.Indexes, idx) } else { filters := strings.Split(ft.Value(), ",") for _, fil := range filters { @@ -198,11 +197,11 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err default: continue } - field.Indexes = append(field.Indexes, idx) + fieldInfo.Indexes = append(fieldInfo.Indexes, idx) } } - gen.FieldInfos = append(gen.FieldInfos, field) + gen.FieldInfos = append(gen.FieldInfos, fieldInfo) continue } From cca83db14427b89ac5fa810ff0cc473a4aaba561 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 19:53:24 +0900 Subject: [PATCH 23/77] fix: minor correction #4 --- testfiles/a/name.go | 5 ++++- testfiles/a/task.go | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/testfiles/a/name.go b/testfiles/a/name.go index d352afd..ad5aff0 100644 --- a/testfiles/a/name.go +++ b/testfiles/a/name.go @@ -7,10 +7,13 @@ import ( //go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/a //go:generate gofmt -w ./ +// Name 拡張インデックスあり type Name struct { ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key Created time.Time `datastore:"created"` - Desc string `datastore:"description"` + Desc string `datastore:"description" filter:"l"` // supported word: m/matching(Default), l/like, p/prefix, TODO s/suffix + Desc2 string `datastore:"description2" filter:"p"` // supported word: m/matching(Default), l/like, p/prefix, TODO s/suffix Done bool `datastore:"done"` Count int `datastore:"count"` + Indexes []string `datastore:"indexes"` } diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 3d58422..783b3a5 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -7,13 +7,13 @@ import ( //go:generate repo_generator Task github.com/go-generalize/repo_generator/testfiles/a //go:generate gofmt -w ./ +// Task 拡張インデックスなし type Task struct { - ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key - Desc string `datastore:"description" filter:"l"` // supported word: m/matching(Default), l/like, p/prefix, TODO s/suffix + ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key + Desc string `datastore:"description"` Created time.Time `datastore:"created"` Done bool `datastore:"done"` Done2 bool `datastore:"done2"` Count int `datastore:"count"` Count64 int64 `datastore:"count64"` - Indexes []string `datastore:"indexes"` // for XIAN } From 03b311a167e0ec6d4f5912200938e3676cb4df8e Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 19:53:53 +0900 Subject: [PATCH 24/77] feat: add test pattern #4 --- testfiles/a/tests/task_test.go | 188 ++++++++++++++++++++++++++++++--- 1 file changed, 173 insertions(+), 15 deletions(-) diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 0d02508..61f7c8d 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -55,10 +55,10 @@ func compareTask(t *testing.T, expected, actual *task.Task) { } } -func TestDatastoreList(t *testing.T) { +func TestDatastoreListTask(t *testing.T) { client := initDatastoreClient(t) - taskRepo := task.NewNameRepository(client) + taskRepo := task.NewTaskRepository(client) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) var ids []int64 @@ -70,11 +70,11 @@ func TestDatastoreList(t *testing.T) { }() now := time.Unix(time.Now().Unix(), 0) - desc := "Hello, World." + desc := "Hello, World!" - tks := make([]*task.Name, 0) + tks := make([]*task.Task, 0) for i := int64(1); i <= 10; i++ { - tk := &task.Name{ + tk := &task.Task{ ID: i, Created: now, Desc: fmt.Sprintf("%s%d", desc, i), @@ -88,20 +88,178 @@ func TestDatastoreList(t *testing.T) { t.Fatalf("%+v", err) } - req := &task.NameListReq{ - Done: configs.BoolCriteriaTrue, // FIXME 1 これがだけ指定したら条件に引っかかるものが抽出できるはずなのに現状できない - //Count: configs.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい - } + t.Run("int(1件)", func(t *testing.T) { + req := &task.TaskListReq{ + Count: configs.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい + } - tasks, err := taskRepo.List(ctx, req, nil) + tasks, err := taskRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 1 { + t.Fatal("not match") + } + }) + + t.Run("bool(10件)", func(t *testing.T) { + req := &task.TaskListReq{ + Done: configs.BoolCriteriaTrue, + } + + tasks, err := taskRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 10 { + t.Fatal("not match") + } + }) + + t.Run("time.Time(10件)", func(t *testing.T) { + req := &task.TaskListReq{ + Created: now, + } + + tasks, err := taskRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 10 { + t.Fatal("not match") + } + }) +} + +func TestDatastoreListNameWithIndexes(t *testing.T) { + client := initDatastoreClient(t) + + nameRepo := task.NewNameRepository(client) + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + var ids []int64 + defer func() { + defer cancel() + if err := nameRepo.DeleteMultiByIDs(ctx, ids); err != nil { + t.Fatal(err) + } + }() + + now := time.Unix(time.Now().Unix(), 0) + desc := "Hello, World!" + desc2 := "Prefix, Test!" + + tks := make([]*task.Name, 0) + for i := int64(1); i <= 10; i++ { + tk := &task.Name{ + ID: i, + Created: now, + Desc: fmt.Sprintf("%s%d", desc, i), + Desc2: fmt.Sprintf("%s%d", desc2, i), + Done: true, + Count: int(i), + } + tks = append(tks, tk) + } + ids, err := nameRepo.InsertMulti(ctx, tks) if err != nil { t.Fatalf("%+v", err) } - // FIXME 1 - _ = tasks - //if len(tasks) != len(ids) { - // t.Fatal("not match") - //} + + t.Run("int(1件)", func(t *testing.T) { + req := &task.NameListReq{ + Count: configs.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい + } + + tasks, err := nameRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 1 { + t.Fatal("not match") + } + }) + + t.Run("bool(10件)", func(t *testing.T) { + req := &task.NameListReq{ + Done: configs.BoolCriteriaTrue, + } + + tasks, err := nameRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 10 { + t.Fatal("not match") + } + }) + + t.Run("like(10件)", func(t *testing.T) { + req := &task.NameListReq{ + Desc: "ll", + } + + tasks, err := nameRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 10 { + t.Fatal("not match") + } + }) + + t.Run("prefix", func(t *testing.T) { + t.Run("Success", func(t *testing.T) { + req := &task.NameListReq{ + Desc2: "Pre", + } + + tasks, err := nameRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 10 { + t.Fatal("not match") + } + }) + + t.Run("Failure", func(t *testing.T) { + req := &task.NameListReq{ + Desc2: "He", + } + + tasks, err := nameRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 0 { + t.Fatal("not match") + } + }) + }) + + t.Run("time.Time(10件)", func(t *testing.T) { + req := &task.NameListReq{ + Created: now, + } + + tasks, err := nameRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 10 { + t.Fatal("not match") + } + }) } func TestDatastore(t *testing.T) { From 0a28ab657b734fccad36913fe184aba558b3ae50 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 19:54:41 +0900 Subject: [PATCH 25/77] update: go.mod --- go.mod | 9 ++++----- go.sum | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 0871d9a..dd6ce37 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/go-generalize/repo_generator go 1.14 require ( + cloud.google.com/go v0.57.0 // indirect cloud.google.com/go/bigquery v1.6.0 // indirect cloud.google.com/go/datastore v1.1.0 github.com/fatih/structtag v1.2.0 @@ -11,12 +12,10 @@ require ( github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 github.com/knightso/xian v0.1.0 github.com/pkg/errors v0.9.1 // indirect - golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 // indirect + golang.org/x/net v0.0.0-20200506145744-7e3656a0809f // indirect golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect - golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8 + golang.org/x/tools v0.0.0-20200507205054-480da3ebd79c golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 google.golang.org/api v0.23.0 // indirect - google.golang.org/appengine v1.6.6 // indirect - google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 // indirect - google.golang.org/grpc v1.29.1 // indirect + google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31 // indirect ) diff --git a/go.sum b/go.sum index 6c1925f..c31a845 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6 cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4= cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0 h1:EpMNVUorLiZIELdMZbCYX/ByTFCdoYopYAGxaGVz9ms= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -92,6 +94,7 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= @@ -184,6 +187,8 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f h1:QBjCr1Fz5kw158VqdE9JfI9cJnl/ymnJWAdMuinqL7Y= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -220,6 +225,7 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -265,8 +271,9 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200409170454-77362c5149f0/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8 h1:BMFHd4OFnFtWX46Xj4DN6vvT1btiBxyq+s0orYBqcQY= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200507205054-480da3ebd79c h1:TDspWmUQsjdWzrHnd5imfaJSfhR4AO/R7kG++T2cONw= +golang.org/x/tools v0.0.0-20200507205054-480da3ebd79c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= @@ -284,6 +291,7 @@ google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/ google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.21.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.23.0 h1:YlvGEOq2NA2my8cZ/9V8BcEO9okD48FlJcdqN0xJL3s= google.golang.org/api v0.23.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -319,6 +327,8 @@ google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200409111301-baae70f3302d/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 h1:pSLkPbrjnPyLDYUO2VM9mDLqo2V6CFBY84lFSZAfoi4= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31 h1:Bz1qTn2YRWV+9OKJtxHJiQKCiXIdf+kwuKXdt9cBxyU= +google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= From f5591e644e5fc7c4e658fbf280a9501a33418286 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 20:12:10 +0900 Subject: [PATCH 26/77] fix: matching -> equal #4 --- main.go | 2 +- testfiles/a/name.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index ce246a9..68e27a4 100644 --- a/main.go +++ b/main.go @@ -188,7 +188,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err idx.Method += "Suffix" idx.ConstName += "Suffix" idx.Comment = fmt.Sprintf("%s %s後方一致", idx.ConstName, name)*/ - case "m", "matching": // 完全一致 (Add) Default + case "e", "equal": // 完全一致 (Add) Default idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) case "l", "like": // 部分一致 idx.Method += "Biunigrams" diff --git a/testfiles/a/name.go b/testfiles/a/name.go index ad5aff0..f6b57fb 100644 --- a/testfiles/a/name.go +++ b/testfiles/a/name.go @@ -11,8 +11,8 @@ import ( type Name struct { ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key Created time.Time `datastore:"created"` - Desc string `datastore:"description" filter:"l"` // supported word: m/matching(Default), l/like, p/prefix, TODO s/suffix - Desc2 string `datastore:"description2" filter:"p"` // supported word: m/matching(Default), l/like, p/prefix, TODO s/suffix + Desc string `datastore:"description" filter:"l"` // supported word: e/equal(Default), l/like, p/prefix, TODO s/suffix + Desc2 string `datastore:"description2" filter:"p"` // supported word: e/equal(Default), l/like, p/prefix, TODO s/suffix Done bool `datastore:"done"` Count int `datastore:"count"` Indexes []string `datastore:"indexes"` From 69116b3821d2e99fdfc8c25962e50ddc5cb4f9f0 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 20:14:58 +0900 Subject: [PATCH 27/77] fix: filter -> indexer #4 --- main.go | 4 ++-- testfiles/a/name.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 68e27a4..5094e45 100644 --- a/main.go +++ b/main.go @@ -159,7 +159,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } else { fieldInfo.DsTag = strings.Split(dsTag.Value(), ",")[0] } - ft, err := tags.Get("filter") + idr, err := tags.Get("indexer") if err != nil || fieldInfo.FieldType != "string" { idx := &IndexesInfo{ ConstName: filedLabel + name, @@ -172,7 +172,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } fieldInfo.Indexes = append(fieldInfo.Indexes, idx) } else { - filters := strings.Split(ft.Value(), ",") + filters := strings.Split(idr.Value(), ",") for _, fil := range filters { idx := &IndexesInfo{ ConstName: filedLabel + name, diff --git a/testfiles/a/name.go b/testfiles/a/name.go index f6b57fb..b6cd3e6 100644 --- a/testfiles/a/name.go +++ b/testfiles/a/name.go @@ -11,8 +11,8 @@ import ( type Name struct { ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key Created time.Time `datastore:"created"` - Desc string `datastore:"description" filter:"l"` // supported word: e/equal(Default), l/like, p/prefix, TODO s/suffix - Desc2 string `datastore:"description2" filter:"p"` // supported word: e/equal(Default), l/like, p/prefix, TODO s/suffix + Desc string `datastore:"description" indexer:"l"` // supported word: e/equal(Default), l/like, p/prefix, TODO s/suffix + Desc2 string `datastore:"description2" indexer:"p"` // supported word: e/equal(Default), l/like, p/prefix, TODO s/suffix Done bool `datastore:"done"` Count int `datastore:"count"` Indexes []string `datastore:"indexes"` From fc55dd1d6629c9b3955b6f3faddc961d8d84ec18 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 20:18:01 +0900 Subject: [PATCH 28/77] fix: fixed the occasional test failure #4 --- testfiles/a/tests/task_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 61f7c8d..b02af16 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -75,7 +75,7 @@ func TestDatastoreListTask(t *testing.T) { tks := make([]*task.Task, 0) for i := int64(1); i <= 10; i++ { tk := &task.Task{ - ID: i, + ID: i * 100, Created: now, Desc: fmt.Sprintf("%s%d", desc, i), Done: true, From 8108c76f6a9f16f709aa61b275e0e6a624332429 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 20:25:59 +0900 Subject: [PATCH 29/77] clean: lint --- generator.go | 4 ++-- main.go | 37 ++++++++++++++++++++++--------------- testfiles/a/name.go | 12 +++++++----- 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/generator.go b/generator.go index 88afee0..75a1ea1 100644 --- a/generator.go +++ b/generator.go @@ -81,8 +81,8 @@ func (g *generator) generate(writer io.Writer) { "Parse": func(field, fieldType string) string { fn := ".Int()" switch fieldType { - case "int": - case "int64": + case typeInt: + case typeInt64: fn = ".Int64()" default: panic("invalid types") diff --git a/main.go b/main.go index 5094e45..51d4909 100644 --- a/main.go +++ b/main.go @@ -102,7 +102,14 @@ func uppercaseExtraction(name string) (lower string) { return } -const queryLabel = "QueryLabel" +const ( + biunigrams = "Biunigrams" + prefix = "Prefix" + queryLabel = "QueryLabel" + typeString = "string" + typeInt = "int" + typeInt64 = "int64" +) func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) error { dupMap := make(map[string]int) @@ -136,8 +143,8 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err continue } - _, err = tags.Get("datastore_key") - if err != nil { + _, er := tags.Get("datastore_key") + if er != nil { f := func() string { u := uppercaseExtraction(name) if _, ok := dupMap[u]; !ok { @@ -153,21 +160,21 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err FieldType: getTypeName(field.Type), Indexes: make([]*IndexesInfo, 0), } - dsTag, err := tags.Get("datastore") - if err != nil { + + if dsTag, err := tags.Get("datastore"); err != nil { fieldInfo.DsTag = fieldInfo.Field } else { fieldInfo.DsTag = strings.Split(dsTag.Value(), ",")[0] } - idr, err := tags.Get("indexer") - if err != nil || fieldInfo.FieldType != "string" { + + if idr, err := tags.Get("indexer"); err != nil || fieldInfo.FieldType != typeString { idx := &IndexesInfo{ ConstName: filedLabel + name, Label: f(), Method: "Add", } idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) - if fieldInfo.FieldType != "string" { + if fieldInfo.FieldType != typeString { idx.Method += "Something" } fieldInfo.Indexes = append(fieldInfo.Indexes, idx) @@ -181,17 +188,17 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } switch fil { case "p", "prefix": // 前方一致 (AddPrefix) - idx.Method += "Prefix" - idx.ConstName += "Prefix" + idx.Method += prefix + idx.ConstName += prefix idx.Comment = fmt.Sprintf("%s %s前方一致", idx.ConstName, name) case "s", "suffix": /* TODO 後方一致 - idx.Method += "Suffix" - idx.ConstName += "Suffix" + idx.Method += Suffix + idx.ConstName += Suffix idx.Comment = fmt.Sprintf("%s %s後方一致", idx.ConstName, name)*/ case "e", "equal": // 完全一致 (Add) Default idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) case "l", "like": // 部分一致 - idx.Method += "Biunigrams" + idx.Method += biunigrams idx.ConstName += "Like" idx.Comment = fmt.Sprintf("%s %s部分一致", idx.ConstName, name) default: @@ -215,8 +222,8 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err gen.KeyFieldName = name gen.KeyFieldType = getTypeName(field.Type) - if gen.KeyFieldType != "int64" && - gen.KeyFieldType != "string" && + if gen.KeyFieldType != typeInt64 && + gen.KeyFieldType != typeString && !strings.HasSuffix(gen.KeyFieldType, ".Key") { return fmt.Errorf("%s: supported key types are int64, string, *datastore.Key", pos) } diff --git a/testfiles/a/name.go b/testfiles/a/name.go index b6cd3e6..e753f83 100644 --- a/testfiles/a/name.go +++ b/testfiles/a/name.go @@ -11,9 +11,11 @@ import ( type Name struct { ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key Created time.Time `datastore:"created"` - Desc string `datastore:"description" indexer:"l"` // supported word: e/equal(Default), l/like, p/prefix, TODO s/suffix - Desc2 string `datastore:"description2" indexer:"p"` // supported word: e/equal(Default), l/like, p/prefix, TODO s/suffix - Done bool `datastore:"done"` - Count int `datastore:"count"` - Indexes []string `datastore:"indexes"` + // supported indexer tags word: e/equal(Default), l/like, p/prefix, + // TODO s/suffix + Desc string `datastore:"description" indexer:"l"` + Desc2 string `datastore:"description2" indexer:"p"` + Done bool `datastore:"done"` + Count int `datastore:"count"` + Indexes []string `datastore:"indexes"` } From 9877119274164f6578133f54e3f62698f237fdc9 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Fri, 8 May 2020 20:42:02 +0900 Subject: [PATCH 30/77] fix: repeat prohibition #4 --- main.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index 51d4909..850b703 100644 --- a/main.go +++ b/main.go @@ -180,30 +180,41 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err fieldInfo.Indexes = append(fieldInfo.Indexes, idx) } else { filters := strings.Split(idr.Value(), ",") + dupIdr := make(map[string]struct{}) for _, fil := range filters { idx := &IndexesInfo{ ConstName: filedLabel + name, Label: f(), Method: "Add", } + var dupFlag string switch fil { case "p", "prefix": // 前方一致 (AddPrefix) idx.Method += prefix idx.ConstName += prefix idx.Comment = fmt.Sprintf("%s %s前方一致", idx.ConstName, name) + dupFlag = "p" case "s", "suffix": /* TODO 後方一致 idx.Method += Suffix idx.ConstName += Suffix - idx.Comment = fmt.Sprintf("%s %s後方一致", idx.ConstName, name)*/ + idx.Comment = fmt.Sprintf("%s %s後方一致", idx.ConstName, name) + dup = "s"*/ case "e", "equal": // 完全一致 (Add) Default idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) + dupIdr["equal"] = struct{}{} + dupFlag = "e" case "l", "like": // 部分一致 idx.Method += biunigrams idx.ConstName += "Like" idx.Comment = fmt.Sprintf("%s %s部分一致", idx.ConstName, name) + dupFlag = "l" default: continue } + if _, ok := dupIdr[dupFlag]; ok { + continue + } + dupIdr[dupFlag] = struct{}{} fieldInfo.Indexes = append(fieldInfo.Indexes, idx) } } From f49fddacb4d7ccd1bc76ae77eb7011d90725a16c Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 00:36:04 +0900 Subject: [PATCH 31/77] fix: remove configs layer #4 --- generator.go | 34 +++++++++++++-------------- testfiles/a/{configs => }/constant.go | 2 +- testfiles/a/tests/task_test.go | 9 ++++--- 3 files changed, 21 insertions(+), 24 deletions(-) rename testfiles/a/{configs => }/constant.go (97%) diff --git a/generator.go b/generator.go index 75a1ea1..d3e9f4d 100644 --- a/generator.go +++ b/generator.go @@ -49,7 +49,6 @@ type generator struct { } func (g *generator) setting() { - g.ImportName = ImportName g.GoGenerate = "go:generate" g.RepositoryInterfaceName = g.StructName + "Repository" g.setRepositoryStructName() @@ -120,7 +119,7 @@ func (g *generator) generateConstant(writer io.Writer) { } const tmplConst = `// THIS FILE IS A GENERATED CODE. DO NOT EDIT -package configs +package {{ .PackageName }} import "strconv" @@ -160,7 +159,7 @@ func (str IntegerCriteria) Int64() int64 { ` const tmplLabel = `// THIS FILE IS A GENERATED CODE. EDIT OK -package configs +package {{ .PackageName }} const ( {{- range $fi := .FieldInfos }} @@ -183,7 +182,6 @@ import ( {{- end }} "cloud.google.com/go/datastore" - "{{ .ImportName }}/configs" {{- if eq .EnableIndexes true }} "github.com/knightso/xian" {{- end }} @@ -256,21 +254,21 @@ func (repo *{{ .RepositoryStructName }}) getKeys(subjects ...*{{ .StructName }}) // saveIndexes 拡張フィルタを保存する func (repo *{{ .RepositoryStructName }}) saveIndexes(subjects ...*{{ .StructName }}) error { for _, subject := range subjects { - idx := xian.NewIndexes({{ .LowerStructName }}IndexesConfig) + idx := xian.NewIndexes({{ .StructName }}IndexesConfig) {{- range $fi := .FieldInfos }} {{- range $idx := $fi.Indexes }} {{- if eq $fi.FieldType "bool" }} - idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}) + idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}) {{- else if eq $fi.FieldType "string" }} {{- if eq $idx.Method "AddPrefix" }} - idx.{{ $idx.Method }}es(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}) + idx.{{ $idx.Method }}es({{ $idx.ConstName }}, subject.{{ $fi.Field }}) {{- else }} - idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}) + idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}) {{- end }} {{- else if eq $fi.FieldType "int" }} - idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}) + idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}) {{- else if eq $fi.FieldType "time.Time" }} - idx.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, subject.{{ $fi.Field }}.Unix()) + idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}.Unix()) {{- end }} {{- end }} {{- end }} @@ -291,13 +289,13 @@ var {{ .LowerStructName }}IndexesConfig = &xian.Config{ {{- end }} // {{ .StructName }}ListReq List取得時に渡すリクエスト -// └─ bool/int(64) は stringで渡す(configs.BoolCriteria | configs.IntegerCriteria) +// └─ bool/int(64) は stringで渡す(BoolCriteria | IntegerCriteria) type {{ .StructName }}ListReq struct { {{- range .FieldInfos }} {{- if eq .FieldType "bool" }} - {{ .Field }} configs.BoolCriteria + {{ .Field }} BoolCriteria {{- else if or (eq .FieldType "int") (eq .FieldType "int64") }} - {{ .Field }} configs.IntegerCriteria + {{ .Field }} IntegerCriteria {{- else }} {{ .Field }} {{ .FieldType }} {{- end }} @@ -321,7 +319,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru if req.{{ $fi.Field }} != "" { {{- if eq $Enable true }} {{- range $idx := $fi.Indexes }} - filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}) + filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ $fi.Field }}) {{- end }} {{- else }} q = q.Filter("{{ $fi.DsTag }} =", req.{{ $fi.Field }}.Bool()) @@ -331,17 +329,17 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru if req.{{ $fi.Field }} != "" { {{- if eq $Enable true }} {{- range $idx := $fi.Indexes }} - filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}) + filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ $fi.Field }}) {{- end }} {{- else }} q = q.Filter("{{ $fi.DsTag }} =", req.{{ $fi.Field }}) {{- end }} } {{- else if or (eq $fi.FieldType "int") (eq $fi.FieldType "int64") }} - if req.{{ $fi.Field }} != configs.IntegerCriteriaEmpty { + if req.{{ $fi.Field }} != IntegerCriteriaEmpty { {{- if eq $Enable true }} {{- range $idx := $fi.Indexes }} - filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ Parse $fi.Field $fi.FieldType }}) + filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ Parse $fi.Field $fi.FieldType }}) {{- end }} {{- else }} q = q.Filter("{{ $fi.DsTag }} =", req.{{ Parse $fi.Field $fi.FieldType }}) @@ -351,7 +349,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru if !req.{{ $fi.Field }}.IsZero() { {{- if eq $Enable true }} {{- range $idx := $fi.Indexes }} - filters.{{ $idx.Method }}(configs.{{ $idx.ConstName }}, req.{{ $fi.Field }}.Unix()) + filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ $fi.Field }}.Unix()) {{- end }} {{- else }} q = q.Filter("{{ $fi.DsTag }} =", req.{{ $fi.Field }}) diff --git a/testfiles/a/configs/constant.go b/testfiles/a/constant.go similarity index 97% rename from testfiles/a/configs/constant.go rename to testfiles/a/constant.go index 8bc439b..743be8c 100644 --- a/testfiles/a/configs/constant.go +++ b/testfiles/a/constant.go @@ -1,5 +1,5 @@ // THIS FILE IS A GENERATED CODE. DO NOT EDIT -package configs +package task import "strconv" diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index b02af16..4ae1e98 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -11,7 +11,6 @@ import ( "cloud.google.com/go/datastore" task "github.com/go-generalize/repo_generator/testfiles/a" - "github.com/go-generalize/repo_generator/testfiles/a/configs" ) func initDatastoreClient(t *testing.T) *datastore.Client { @@ -90,7 +89,7 @@ func TestDatastoreListTask(t *testing.T) { t.Run("int(1件)", func(t *testing.T) { req := &task.TaskListReq{ - Count: configs.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい + Count: task.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい } tasks, err := taskRepo.List(ctx, req, nil) @@ -105,7 +104,7 @@ func TestDatastoreListTask(t *testing.T) { t.Run("bool(10件)", func(t *testing.T) { req := &task.TaskListReq{ - Done: configs.BoolCriteriaTrue, + Done: task.BoolCriteriaTrue, } tasks, err := taskRepo.List(ctx, req, nil) @@ -171,7 +170,7 @@ func TestDatastoreListNameWithIndexes(t *testing.T) { t.Run("int(1件)", func(t *testing.T) { req := &task.NameListReq{ - Count: configs.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい + Count: task.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい } tasks, err := nameRepo.List(ctx, req, nil) @@ -186,7 +185,7 @@ func TestDatastoreListNameWithIndexes(t *testing.T) { t.Run("bool(10件)", func(t *testing.T) { req := &task.NameListReq{ - Done: configs.BoolCriteriaTrue, + Done: task.BoolCriteriaTrue, } tasks, err := nameRepo.List(ctx, req, nil) From c4567e637a0920d3e78fe98ec7755d3f35f1b15e Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 00:38:54 +0900 Subject: [PATCH 32/77] change: quit lower camel case #4 --- generator.go | 3 +-- main.go | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/generator.go b/generator.go index d3e9f4d..80e6d1d 100644 --- a/generator.go +++ b/generator.go @@ -31,7 +31,6 @@ type generator struct { GeneratedFileName string FileName string StructName string - LowerStructName string GoGenerate string RepositoryStructName string @@ -312,7 +311,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru } {{ $Enable := .EnableIndexes }} {{- if eq $Enable true }} - filters := xian.NewFilters({{ .LowerStructName }}IndexesConfig) + filters := xian.NewFilters({{ .StructName }}IndexesConfig) {{- end }} {{- range $fi := .FieldInfos }} {{- if eq $fi.FieldType "bool" }} diff --git a/main.go b/main.go index 850b703..7d295fa 100644 --- a/main.go +++ b/main.go @@ -83,7 +83,6 @@ func traverse(pkg *ast.Package, fs *token.FileSet, structName string) error { continue } gen.StructName = name - gen.LowerStructName = strcase.ToLowerCamel(name) return generate(gen, fs, structType) } From e0029b5cc71b02838ab1b69c1fa4cb653f1e43f6 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 00:41:24 +0900 Subject: [PATCH 33/77] clean: fix by deleting unnecessary things #4 --- main.go | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/main.go b/main.go index 7d295fa..0545049 100644 --- a/main.go +++ b/main.go @@ -15,17 +15,13 @@ import ( "golang.org/x/xerrors" ) -var ImportName string - func main() { l := len(os.Args) - if l < 3 { + if l < 2 { fmt.Println("You have to specify the struct name of target") os.Exit(1) } - ImportName = os.Args[2] - if err := run(os.Args[1]); err != nil { log.Fatal(err.Error()) } @@ -252,12 +248,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } { - if !exists("configs") { - if err := os.Mkdir("configs", 0777); err != nil { - return err - } - } - path := "configs/" + strcase.ToLowerCamel(gen.StructName) + "_label.go" + path := gen.FileName + "_label.go" fp, err := os.Create(path) if err != nil { panic(err) @@ -267,7 +258,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } { - fp, err := os.Create("configs/constant.go") + fp, err := os.Create("constant.go") if err != nil { panic(err) } @@ -277,8 +268,3 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err return nil } - -func exists(filename string) bool { - _, err := os.Stat(filename) - return err == nil -} From 6c8b91671595b4083e6b7133ebd13351b3e94896 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 00:41:55 +0900 Subject: [PATCH 34/77] feat: add godoc #4 --- generator.go | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/generator.go b/generator.go index 80e6d1d..6db9281 100644 --- a/generator.go +++ b/generator.go @@ -213,6 +213,7 @@ type {{ .RepositoryStructName }} struct { datastoreClient *datastore.Client } +// New{{ .RepositoryInterfaceName }} constructor func New{{ .RepositoryInterfaceName }}(datastoreClient *datastore.Client) {{ .RepositoryInterfaceName }} { return &{{ .RepositoryStructName }}{ kind: "{{ .StructName }}", @@ -220,6 +221,7 @@ func New{{ .RepositoryInterfaceName }}(datastoreClient *datastore.Client) {{ .Re } } +// GetKindName KindName getter func (repo *{{ .RepositoryStructName }}) GetKindName() string { return repo.kind } @@ -281,9 +283,15 @@ func (repo *{{ .RepositoryStructName }}) saveIndexes(subjects ...*{{ .StructName return nil } -var {{ .LowerStructName }}IndexesConfig = &xian.Config{ - IgnoreCase: true, // Case insensitive - SaveNoFiltersIndex: true, // https://qiita.com/hogedigo/items/02dcce80f6197faae1fb#savenofiltersindex +// {{ .StructName }}IndexesConfig {{ .StructName }}用のIndexesConfigを設定する +var {{ .StructName }}IndexesConfig = &xian.Config{ + // IgnoreCase Case insensitive + // └──大文字小文字を区別しない + IgnoreCase: true, + // SaveNoFiltersIndex 検索時にフィルタを設定しない場合、この拡張フィルタなし検索用インデックスのEquality Filterが自動で適用される + // ├── falseで、拡張フィルタのあり・なしの両パターンの検索がある場合、カスタムインデックスを両パターン分用意しておく必要がある + // └── trueにしておくことでカスタムインデックスを半分に節約することができる + SaveNoFiltersIndex: true, } {{- end }} @@ -302,8 +310,8 @@ type {{ .StructName }}ListReq struct { } // List datastore.Queryを使用し条件抽出をする -// └─ 第3引数はNOT/OR/IN/RANGEなど、より複雑な条件を適用したいときにつける -// └─ 基本的にnilを渡せば良い +// └─ 第3引数はNOT/OR/IN/RANGEなど、より複雑な条件を適用したいときにつける +// └─ 基本的にnilを渡せば良い // BUG(54mch4n) 潜在的なバグがあるかもしれない func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .StructName }}ListReq, q *datastore.Query) ([]*{{ .StructName }}, error) { if q == nil { @@ -381,6 +389,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru return subjects, nil } +// Get 処理中の {{ .StructName }} の取得処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) Get(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) (*{{ .StructName }}, error) { {{- if eq .KeyFieldType "int64" }} key := datastore.IDKey(repo.kind, {{ .KeyValueName }}, nil) @@ -404,6 +413,7 @@ func (repo *{{ .RepositoryStructName }}) Get(ctx context.Context, {{ .KeyValueNa return subject, nil } +// Insert 処理中の {{ .StructName }} の登録処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) Insert(ctx context.Context, subject *{{ .StructName }}) ({{ .KeyFieldType }}, error) { {{- if eq .KeyFieldType "int64" }} zero := int64(0) @@ -434,6 +444,7 @@ func (repo *{{ .RepositoryStructName }}) Insert(ctx context.Context, subject *{{ {{- end }} } +// Update 処理中の {{ .StructName }} の更新処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) Update(ctx context.Context, subject *{{ .StructName }}) error { if _, err := repo.Get(ctx, subject.{{ .KeyFieldName }}); err == datastore.ErrNoSuchEntity { return err @@ -455,6 +466,7 @@ func (repo *{{ .RepositoryStructName }}) Update(ctx context.Context, subject *{{ return nil } +// Delete 処理中の {{ .StructName }} の削除処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) Delete(ctx context.Context, subject *{{ .StructName }}) error { keys, err := repo.getKeys(subject) if err != nil { @@ -464,6 +476,7 @@ func (repo *{{ .RepositoryStructName }}) Delete(ctx context.Context, subject *{{ return repo.datastoreClient.Delete(ctx, keys[0]) } +// DeleteBy{{ .KeyFieldName }} 処理中の {{ .StructName }} の{{ .KeyFieldName }}から削除処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) DeleteBy{{ .KeyFieldName }}(ctx context.Context, {{ .KeyValueName }} {{ .KeyFieldType }}) error { {{- if eq .KeyFieldType "int64" }} key := datastore.IDKey(repo.kind, {{ .KeyValueName }}, nil) @@ -475,6 +488,7 @@ func (repo *{{ .RepositoryStructName }}) DeleteBy{{ .KeyFieldName }}(ctx context return repo.datastoreClient.Delete(ctx, key) } +// GetMulti 処理中の {{ .StructName }} の一括取得処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) GetMulti(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) ([]*{{ .StructName }}, error) { {{- if eq .KeyFieldType "int64" }} keys := make([]*datastore.Key, 0, len({{ .KeyValueName }}s)) @@ -509,6 +523,7 @@ func (repo *{{ .RepositoryStructName }}) GetMulti(ctx context.Context, {{ .KeyVa return vessels, err } +// InsertMulti 処理中の {{ .StructName }} の一括挿入処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) InsertMulti(ctx context.Context, subjects []*{{ .StructName }}) ([]{{ .KeyFieldType }}, error) { keys, err := repo.getKeys(subjects...) if err != nil { @@ -555,6 +570,7 @@ func (repo *{{ .RepositoryStructName }}) InsertMulti(ctx context.Context, subjec return vessels, err } +// UpdateMulti 処理中の {{ .StructName }} の一括更新処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) UpdateMulti(ctx context.Context, subjects []*{{ .StructName }}) error { keys, err := repo.getKeys(subjects...) if err != nil { @@ -579,6 +595,7 @@ func (repo *{{ .RepositoryStructName }}) UpdateMulti(ctx context.Context, subjec return nil } +// DeleteMulti 処理中の {{ .StructName }} の一括削除処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) DeleteMulti(ctx context.Context, subjects []*{{ .StructName }}) error { keys, err := repo.getKeys(subjects...) if err != nil { @@ -588,6 +605,7 @@ func (repo *{{ .RepositoryStructName }}) DeleteMulti(ctx context.Context, subjec return repo.datastoreClient.DeleteMulti(ctx, keys) } +// DeleteMultiBy{{ .KeyFieldName }}s 処理中の {{ .StructName }} の{{ .KeyFieldName }}群を元に一括削除処理一切の責任を持ち、これを行う func (repo *{{ .RepositoryStructName }}) DeleteMultiBy{{ .KeyFieldName }}s(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) error { {{- if eq .KeyFieldType "int64" }} keys := make([]*datastore.Key, 0, len({{ .KeyValueName }}s)) From 7089645b34476d5ae72147853ccd8671123d9c2b Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 00:42:23 +0900 Subject: [PATCH 35/77] hotfix: improve fatal problems #4 --- generator.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/generator.go b/generator.go index 6db9281..c185462 100644 --- a/generator.go +++ b/generator.go @@ -382,7 +382,13 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru for i, k := range keys { if k != nil { +{{- if eq .KeyFieldType "int64" }} subjects[i].ID = k.ID +{{ else if eq .KeyFieldType "string" }} + subjects[i].ID = k.Name +{{ else }} + subjects[i].ID = k +{{ end }} } } From 948a6d26e1d7b3b162ed5df24be5d9ab5cf5036a Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 00:43:22 +0900 Subject: [PATCH 36/77] add: constant.go --- testfiles/b/constant.go | 38 ++++++++++++++++++++++++++++++++++++++ testfiles/c/constant.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 testfiles/b/constant.go create mode 100644 testfiles/c/constant.go diff --git a/testfiles/b/constant.go b/testfiles/b/constant.go new file mode 100644 index 0000000..743be8c --- /dev/null +++ b/testfiles/b/constant.go @@ -0,0 +1,38 @@ +// THIS FILE IS A GENERATED CODE. DO NOT EDIT +package task + +import "strconv" + +type BoolCriteria string + +const ( + BoolCriteriaEmpty BoolCriteria = "" + BoolCriteriaTrue BoolCriteria = "true" + BoolCriteriaFalse BoolCriteria = "false" +) + +func (src BoolCriteria) Bool() bool { + return src == BoolCriteriaTrue +} + +type IntegerCriteria string + +const ( + IntegerCriteriaEmpty IntegerCriteria = "" +) + +func (str IntegerCriteria) Int() int { + i32, err := strconv.Atoi(string(str)) + if err != nil { + return -1 + } + return i32 +} + +func (str IntegerCriteria) Int64() int64 { + i64, err := strconv.ParseInt(string(str), 10, 64) + if err != nil { + return -1 + } + return i64 +} diff --git a/testfiles/c/constant.go b/testfiles/c/constant.go new file mode 100644 index 0000000..743be8c --- /dev/null +++ b/testfiles/c/constant.go @@ -0,0 +1,38 @@ +// THIS FILE IS A GENERATED CODE. DO NOT EDIT +package task + +import "strconv" + +type BoolCriteria string + +const ( + BoolCriteriaEmpty BoolCriteria = "" + BoolCriteriaTrue BoolCriteria = "true" + BoolCriteriaFalse BoolCriteria = "false" +) + +func (src BoolCriteria) Bool() bool { + return src == BoolCriteriaTrue +} + +type IntegerCriteria string + +const ( + IntegerCriteriaEmpty IntegerCriteria = "" +) + +func (str IntegerCriteria) Int() int { + i32, err := strconv.Atoi(string(str)) + if err != nil { + return -1 + } + return i32 +} + +func (str IntegerCriteria) Int64() int64 { + i64, err := strconv.ParseInt(string(str), 10, 64) + if err != nil { + return -1 + } + return i64 +} From 49efff247eb00571d89f851adbb33d1f9c8c3514 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 01:01:28 +0900 Subject: [PATCH 37/77] hotfix: resolve fatal error #4 --- emulator_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/emulator_test.go b/emulator_test.go index 3d0927d..9c111c6 100644 --- a/emulator_test.go +++ b/emulator_test.go @@ -35,6 +35,10 @@ func TestGenerator(t *testing.T) { t.Fatalf("failed to generate for testfiles/a: %+v", err) } + if err := run("Name"); err != nil { + t.Fatalf("failed to generate for testfiles/a: %+v", err) + } + execTest(t) }) From ff49487ec2589b1547b93ffc9f3401c4f61b9654 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 01:02:51 +0900 Subject: [PATCH 38/77] fix: mistake #4 --- emulator_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/emulator_test.go b/emulator_test.go index 9c111c6..0305b02 100644 --- a/emulator_test.go +++ b/emulator_test.go @@ -48,7 +48,7 @@ func TestGenerator(t *testing.T) { } if err := run("Task"); err != nil { - t.Fatalf("failed to generate for testfiles/a: %+v", err) + t.Fatalf("failed to generate for testfiles/b: %+v", err) } execTest(t) @@ -60,7 +60,7 @@ func TestGenerator(t *testing.T) { } if err := run("Task"); err != nil { - t.Fatalf("failed to generate for testfiles/a: %+v", err) + t.Fatalf("failed to generate for testfiles/c: %+v", err) } execTest(t) From 018924d8445abee954fc2de75c68d34f9e6218fd Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 01:13:49 +0900 Subject: [PATCH 39/77] update: fmt.Errorf -> xerrors.Errorf --- main.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/main.go b/main.go index 0545049..956662a 100644 --- a/main.go +++ b/main.go @@ -85,7 +85,7 @@ func traverse(pkg *ast.Package, fs *token.FileSet, structName string) error { } } - return fmt.Errorf("no such struct: %s", structName) + return xerrors.Errorf("no such struct: %s", structName) } func uppercaseExtraction(name string) (lower string) { @@ -106,7 +106,7 @@ const ( typeInt64 = "int64" ) -func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) error { +func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) (err error) { dupMap := make(map[string]int) filedLabel := gen.StructName + queryLabel for _, field := range structType.Fields.List { @@ -138,8 +138,8 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err continue } - _, er := tags.Get("datastore_key") - if er != nil { + _, err = tags.Get("datastore_key") + if err != nil { f := func() string { u := uppercaseExtraction(name) if _, ok := dupMap[u]; !ok { @@ -222,7 +222,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err // datastore タグが存在しないか-になっていない if err != nil || strings.Split(dsTag.Value(), ",")[0] != "-" { - return fmt.Errorf("%s: key field for datastore should have datastore:\"-\" tag", pos) + return xerrors.Errorf("%s: key field for datastore should have datastore:\"-\" tag", pos) } gen.KeyFieldName = name @@ -231,7 +231,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err if gen.KeyFieldType != typeInt64 && gen.KeyFieldType != typeString && !strings.HasSuffix(gen.KeyFieldType, ".Key") { - return fmt.Errorf("%s: supported key types are int64, string, *datastore.Key", pos) + return xerrors.Errorf("%s: supported key types are int64, string, *datastore.Key", pos) } gen.KeyValueName = strcase.ToLowerCamel(name) From 41f7d40b8b01fe2fdb46bbc799de67ae32863be4 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 01:45:44 +0900 Subject: [PATCH 40/77] clean: lint --- main.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index 956662a..3f7b59f 100644 --- a/main.go +++ b/main.go @@ -106,7 +106,11 @@ const ( typeInt64 = "int64" ) -func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) (err error) { +func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) error { + var ( + tags *structtag.Tags + err error + ) dupMap := make(map[string]int) filedLabel := gen.StructName + queryLabel for _, field := range structType.Fields.List { @@ -122,14 +126,13 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) (er pos := fs.Position(field.Pos()).String() - tags, err := structtag.Parse(strings.Trim(field.Tag.Value, "`")) + tags, err = structtag.Parse(strings.Trim(field.Tag.Value, "`")) if err != nil { log.Printf( "%s: tag for %s in struct %s in %s", pos, name, gen.StructName, gen.GeneratedFileName+".go", ) - continue } @@ -138,8 +141,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) (er continue } - _, err = tags.Get("datastore_key") - if err != nil { + if _, err := tags.Get("datastore_key"); err != nil { f := func() string { u := uppercaseExtraction(name) if _, ok := dupMap[u]; !ok { @@ -163,6 +165,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) (er } if idr, err := tags.Get("indexer"); err != nil || fieldInfo.FieldType != typeString { + _ = err idx := &IndexesInfo{ ConstName: filedLabel + name, Label: f(), From ddfa1e9f78794ca3e6900d259bcbc4ec7357cbf8 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 13:42:20 +0900 Subject: [PATCH 41/77] remove: constant.go --- testfiles/a/constant.go | 38 -------------------------------------- testfiles/b/constant.go | 38 -------------------------------------- testfiles/c/constant.go | 38 -------------------------------------- 3 files changed, 114 deletions(-) delete mode 100644 testfiles/a/constant.go delete mode 100644 testfiles/b/constant.go delete mode 100644 testfiles/c/constant.go diff --git a/testfiles/a/constant.go b/testfiles/a/constant.go deleted file mode 100644 index 743be8c..0000000 --- a/testfiles/a/constant.go +++ /dev/null @@ -1,38 +0,0 @@ -// THIS FILE IS A GENERATED CODE. DO NOT EDIT -package task - -import "strconv" - -type BoolCriteria string - -const ( - BoolCriteriaEmpty BoolCriteria = "" - BoolCriteriaTrue BoolCriteria = "true" - BoolCriteriaFalse BoolCriteria = "false" -) - -func (src BoolCriteria) Bool() bool { - return src == BoolCriteriaTrue -} - -type IntegerCriteria string - -const ( - IntegerCriteriaEmpty IntegerCriteria = "" -) - -func (str IntegerCriteria) Int() int { - i32, err := strconv.Atoi(string(str)) - if err != nil { - return -1 - } - return i32 -} - -func (str IntegerCriteria) Int64() int64 { - i64, err := strconv.ParseInt(string(str), 10, 64) - if err != nil { - return -1 - } - return i64 -} diff --git a/testfiles/b/constant.go b/testfiles/b/constant.go deleted file mode 100644 index 743be8c..0000000 --- a/testfiles/b/constant.go +++ /dev/null @@ -1,38 +0,0 @@ -// THIS FILE IS A GENERATED CODE. DO NOT EDIT -package task - -import "strconv" - -type BoolCriteria string - -const ( - BoolCriteriaEmpty BoolCriteria = "" - BoolCriteriaTrue BoolCriteria = "true" - BoolCriteriaFalse BoolCriteria = "false" -) - -func (src BoolCriteria) Bool() bool { - return src == BoolCriteriaTrue -} - -type IntegerCriteria string - -const ( - IntegerCriteriaEmpty IntegerCriteria = "" -) - -func (str IntegerCriteria) Int() int { - i32, err := strconv.Atoi(string(str)) - if err != nil { - return -1 - } - return i32 -} - -func (str IntegerCriteria) Int64() int64 { - i64, err := strconv.ParseInt(string(str), 10, 64) - if err != nil { - return -1 - } - return i64 -} diff --git a/testfiles/c/constant.go b/testfiles/c/constant.go deleted file mode 100644 index 743be8c..0000000 --- a/testfiles/c/constant.go +++ /dev/null @@ -1,38 +0,0 @@ -// THIS FILE IS A GENERATED CODE. DO NOT EDIT -package task - -import "strconv" - -type BoolCriteria string - -const ( - BoolCriteriaEmpty BoolCriteria = "" - BoolCriteriaTrue BoolCriteria = "true" - BoolCriteriaFalse BoolCriteria = "false" -) - -func (src BoolCriteria) Bool() bool { - return src == BoolCriteriaTrue -} - -type IntegerCriteria string - -const ( - IntegerCriteriaEmpty IntegerCriteria = "" -) - -func (str IntegerCriteria) Int() int { - i32, err := strconv.Atoi(string(str)) - if err != nil { - return -1 - } - return i32 -} - -func (str IntegerCriteria) Int64() int64 { - i64, err := strconv.ParseInt(string(str), 10, 64) - if err != nil { - return -1 - } - return i64 -} From da5ba0a08f1b1a5787a4f2f2636962c99e18b3ae Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 13:42:35 +0900 Subject: [PATCH 42/77] add: constant.go --- testfiles/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testfiles/.gitignore b/testfiles/.gitignore index 9856778..96a9eeb 100644 --- a/testfiles/.gitignore +++ b/testfiles/.gitignore @@ -1,3 +1,4 @@ mock_*/ *_gen.go -*_label.go \ No newline at end of file +*_label.go +constant.go \ No newline at end of file From b6a19db8992dc01af5873941f8e2d6c8c64549a8 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 17:44:50 +0900 Subject: [PATCH 43/77] feat: tag check #4 --- main.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/main.go b/main.go index 3f7b59f..207c342 100644 --- a/main.go +++ b/main.go @@ -106,6 +106,8 @@ const ( typeInt64 = "int64" ) +var valueCheck = regexp.MustCompile("^[0-9a-zA-Z_]+$") + func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) error { var ( tags *structtag.Tags @@ -271,3 +273,17 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err return nil } + +func tagCheck(pos string, tags *structtag.Tags) (string, error) { + if dsTag, err := tags.Get("datastore"); err == nil { + tag := strings.Split(dsTag.Value(), ",")[0] + if !valueCheck.MatchString(tag) { // 空白と記号チェック + return "", xerrors.Errorf("%s: key field for datastore should have other than blanks and symbols tag", pos) + } + if strings.Contains("0123456789", string(tag[0])) { + return "", xerrors.Errorf("%s: key field for datastore should have prefix other than numbers required", pos) + } + return tag, nil + } + return "", nil +} From e88523284d8e447371c93cc6a1461bdcbbe6d818 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 17:46:24 +0900 Subject: [PATCH 44/77] update: changed handling of indexes tag and refactoring #4 --- generator.go | 8 +-- main.go | 190 +++++++++++++++++++++++++++------------------------ 2 files changed, 103 insertions(+), 95 deletions(-) diff --git a/generator.go b/generator.go index c185462..8d6a130 100644 --- a/generator.go +++ b/generator.go @@ -38,13 +38,13 @@ type generator struct { KeyFieldName string KeyFieldType string - KeyValueName string // lower camel case FieldInfos []*FieldInfo - EnableIndexes bool - BoolCriteriaCnt int + EnableIndexes bool + FieldInfoForIndexes *FieldInfo + BoolCriteriaCnt int } func (g *generator) setting() { @@ -371,7 +371,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru } for _, f := range built { - q = q.Filter("indexes =", f) + q = q.Filter("{{ .FieldInfoForIndexes.DsTag }} =", f) } {{- end }} subjects := make([]*{{ .StructName }}, 0) diff --git a/main.go b/main.go index 207c342..f174fb6 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,7 @@ import ( "log" "os" "path/filepath" + "regexp" "strings" "github.com/fatih/structtag" @@ -109,10 +110,6 @@ const ( var valueCheck = regexp.MustCompile("^[0-9a-zA-Z_]+$") func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) error { - var ( - tags *structtag.Tags - err error - ) dupMap := make(map[string]int) filedLabel := gen.StructName + queryLabel for _, field := range structType.Fields.List { @@ -128,118 +125,129 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err pos := fs.Position(field.Pos()).String() - tags, err = structtag.Parse(strings.Trim(field.Tag.Value, "`")) - - if err != nil { + if tags, err := structtag.Parse(strings.Trim(field.Tag.Value, "`")); err != nil { log.Printf( "%s: tag for %s in struct %s in %s", pos, name, gen.StructName, gen.GeneratedFileName+".go", ) continue - } - - if name == "Indexes" { - gen.EnableIndexes = true - continue - } - - if _, err := tags.Get("datastore_key"); err != nil { - f := func() string { - u := uppercaseExtraction(name) - if _, ok := dupMap[u]; !ok { - dupMap[u] = 1 - } else { - dupMap[u]++ - u = fmt.Sprintf("%s%d", u, dupMap[u]) + } else { + if name == "Indexes" { + gen.EnableIndexes = true + fieldInfo := &FieldInfo{ + DsTag: name, + Field: name, + FieldType: getTypeName(field.Type), } - return u - } - fieldInfo := &FieldInfo{ - Field: name, - FieldType: getTypeName(field.Type), - Indexes: make([]*IndexesInfo, 0), - } - - if dsTag, err := tags.Get("datastore"); err != nil { - fieldInfo.DsTag = fieldInfo.Field - } else { - fieldInfo.DsTag = strings.Split(dsTag.Value(), ",")[0] + if tag, err := tagCheck(pos, tags); err != nil { + return xerrors.Errorf("error in tagCheck method: %w", err) + } else if tag != "" { + fieldInfo.DsTag = tag + } + gen.FieldInfoForIndexes = fieldInfo + continue } - if idr, err := tags.Get("indexer"); err != nil || fieldInfo.FieldType != typeString { - _ = err - idx := &IndexesInfo{ - ConstName: filedLabel + name, - Label: f(), - Method: "Add", + if _, err := tags.Get("datastore_key"); err != nil { + f := func() string { + u := uppercaseExtraction(name) + if _, ok := dupMap[u]; !ok { + dupMap[u] = 1 + } else { + dupMap[u]++ + u = fmt.Sprintf("%s%d", u, dupMap[u]) + } + return u } - idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) - if fieldInfo.FieldType != typeString { - idx.Method += "Something" + fieldInfo := &FieldInfo{ + DsTag: name, + Field: name, + FieldType: getTypeName(field.Type), + Indexes: make([]*IndexesInfo, 0), } - fieldInfo.Indexes = append(fieldInfo.Indexes, idx) - } else { - filters := strings.Split(idr.Value(), ",") - dupIdr := make(map[string]struct{}) - for _, fil := range filters { + + if tag, err := tagCheck(pos, tags); err != nil { + return xerrors.Errorf("error in tagCheck method: %w", err) + } else if tag != "" { + fieldInfo.DsTag = tag + } + + if idr, err := tags.Get("indexer"); err != nil || fieldInfo.FieldType != typeString { + _ = err idx := &IndexesInfo{ ConstName: filedLabel + name, Label: f(), Method: "Add", } - var dupFlag string - switch fil { - case "p", "prefix": // 前方一致 (AddPrefix) - idx.Method += prefix - idx.ConstName += prefix - idx.Comment = fmt.Sprintf("%s %s前方一致", idx.ConstName, name) - dupFlag = "p" - case "s", "suffix": /* TODO 後方一致 - idx.Method += Suffix - idx.ConstName += Suffix - idx.Comment = fmt.Sprintf("%s %s後方一致", idx.ConstName, name) - dup = "s"*/ - case "e", "equal": // 完全一致 (Add) Default - idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) - dupIdr["equal"] = struct{}{} - dupFlag = "e" - case "l", "like": // 部分一致 - idx.Method += biunigrams - idx.ConstName += "Like" - idx.Comment = fmt.Sprintf("%s %s部分一致", idx.ConstName, name) - dupFlag = "l" - default: - continue + idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) + if fieldInfo.FieldType != typeString { + idx.Method += "Something" } - if _, ok := dupIdr[dupFlag]; ok { - continue - } - dupIdr[dupFlag] = struct{}{} fieldInfo.Indexes = append(fieldInfo.Indexes, idx) + } else { + filters := strings.Split(idr.Value(), ",") + dupIdr := make(map[string]struct{}) + for _, fil := range filters { + idx := &IndexesInfo{ + ConstName: filedLabel + name, + Label: f(), + Method: "Add", + } + var dupFlag string + switch fil { + case "p", "prefix": // 前方一致 (AddPrefix) + idx.Method += prefix + idx.ConstName += prefix + idx.Comment = fmt.Sprintf("%s %s前方一致", idx.ConstName, name) + dupFlag = "p" + case "s", "suffix": /* TODO 後方一致 + idx.Method += Suffix + idx.ConstName += Suffix + idx.Comment = fmt.Sprintf("%s %s後方一致", idx.ConstName, name) + dup = "s"*/ + case "e", "equal": // 完全一致 (Add) Default + idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) + dupIdr["equal"] = struct{}{} + dupFlag = "e" + case "l", "like": // 部分一致 + idx.Method += biunigrams + idx.ConstName += "Like" + idx.Comment = fmt.Sprintf("%s %s部分一致", idx.ConstName, name) + dupFlag = "l" + default: + continue + } + if _, ok := dupIdr[dupFlag]; ok { + continue + } + dupIdr[dupFlag] = struct{}{} + fieldInfo.Indexes = append(fieldInfo.Indexes, idx) + } } + + gen.FieldInfos = append(gen.FieldInfos, fieldInfo) + continue } - gen.FieldInfos = append(gen.FieldInfos, fieldInfo) - continue - } + dsTag, err := tags.Get("datastore") - dsTag, err := tags.Get("datastore") + // datastore タグが存在しないか-になっていない + if err != nil || strings.Split(dsTag.Value(), ",")[0] != "-" { + return xerrors.Errorf("%s: key field for datastore should have datastore:\"-\" tag", pos) + } - // datastore タグが存在しないか-になっていない - if err != nil || strings.Split(dsTag.Value(), ",")[0] != "-" { - return xerrors.Errorf("%s: key field for datastore should have datastore:\"-\" tag", pos) - } + gen.KeyFieldName = name + gen.KeyFieldType = getTypeName(field.Type) - gen.KeyFieldName = name - gen.KeyFieldType = getTypeName(field.Type) + if gen.KeyFieldType != typeInt64 && + gen.KeyFieldType != typeString && + !strings.HasSuffix(gen.KeyFieldType, ".Key") { + return xerrors.Errorf("%s: supported key types are int64, string, *datastore.Key", pos) + } - if gen.KeyFieldType != typeInt64 && - gen.KeyFieldType != typeString && - !strings.HasSuffix(gen.KeyFieldType, ".Key") { - return xerrors.Errorf("%s: supported key types are int64, string, *datastore.Key", pos) - } + gen.KeyValueName = strcase.ToLowerCamel(name) - gen.KeyValueName = strcase.ToLowerCamel(name) + } } { From a1188b6ebccbaa2b3cb5391a4e5a26d6adc42570 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 17:58:28 +0900 Subject: [PATCH 45/77] hotfix: fix mistake ( Name -> Task ) #4 --- testfiles/b/task.go | 2 +- testfiles/c/task.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testfiles/b/task.go b/testfiles/b/task.go index c93a1b8..7a8809a 100644 --- a/testfiles/b/task.go +++ b/testfiles/b/task.go @@ -4,7 +4,7 @@ import ( "time" ) -//go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/b +//go:generate repo_generator Task github.com/go-generalize/repo_generator/testfiles/b //go:generate gofmt -w ./ type Task struct { diff --git a/testfiles/c/task.go b/testfiles/c/task.go index 97da911..53d3910 100644 --- a/testfiles/c/task.go +++ b/testfiles/c/task.go @@ -6,7 +6,7 @@ import ( "cloud.google.com/go/datastore" ) -//go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/c +//go:generate repo_generator Task github.com/go-generalize/repo_generator/testfiles/c //go:generate gofmt -w ./ type Task struct { From 791d09efb240126c5b3c863341a906375ea1de60 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 18:00:34 +0900 Subject: [PATCH 46/77] clean: removed unnecessary trailing newline --- main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main.go b/main.go index f174fb6..6b04cd2 100644 --- a/main.go +++ b/main.go @@ -246,7 +246,6 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } gen.KeyValueName = strcase.ToLowerCamel(name) - } } From f464fa8a505547c83603a2058d933f21deeab685 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sat, 9 May 2020 20:45:27 +0900 Subject: [PATCH 47/77] clean: delete unnecessary things --- generator.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/generator.go b/generator.go index 8d6a130..0f7aaa0 100644 --- a/generator.go +++ b/generator.go @@ -32,7 +32,6 @@ type generator struct { FileName string StructName string - GoGenerate string RepositoryStructName string RepositoryInterfaceName string @@ -48,7 +47,6 @@ type generator struct { } func (g *generator) setting() { - g.GoGenerate = "go:generate" g.RepositoryInterfaceName = g.StructName + "Repository" g.setRepositoryStructName() g.buildConditions() @@ -187,7 +185,8 @@ import ( "golang.org/x/xerrors" ) -//{{ .GoGenerate }} mockgen -source {{ .GeneratedFileName }}.go -destination mock_{{ .GeneratedFileName }}/mock_{{ .GeneratedFileName }}.go +{{ $generate := "go:generate" }} +//{{ $generate }} mockgen -source {{ .GeneratedFileName }}.go -destination mock_{{ .GeneratedFileName }}/mock_{{ .GeneratedFileName }}.go type {{ .RepositoryInterfaceName }} interface { // Single From 5107afc617b011b629390fb0e27c29f416c7ecf8 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sun, 10 May 2020 01:56:43 +0900 Subject: [PATCH 48/77] fix: fix potential bugs #4 --- main.go | 64 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/main.go b/main.go index 6b04cd2..f7739c2 100644 --- a/main.go +++ b/main.go @@ -111,7 +111,29 @@ var valueCheck = regexp.MustCompile("^[0-9a-zA-Z_]+$") func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) error { dupMap := make(map[string]int) - filedLabel := gen.StructName + queryLabel + f := func(name string) string { + u := uppercaseExtraction(name) + if _, ok := dupMap[u]; !ok { + dupMap[u] = 1 + } else { + dupMap[u]++ + u = fmt.Sprintf("%s%d", u, dupMap[u]) + } + return u + } + fieldLabel := gen.StructName + queryLabel + appendIndexesInfo := func(fieldInfo *FieldInfo) { + idx := &IndexesInfo{ + ConstName: fieldLabel + fieldInfo.Field, + Label: f(fieldInfo.Field), + Method: "Add", + } + idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, fieldInfo.Field) + if fieldInfo.FieldType != typeString { + idx.Method += "Something" + } + fieldInfo.Indexes = append(fieldInfo.Indexes, idx) + } for _, field := range structType.Fields.List { // structの各fieldを調査 if len(field.Names) != 1 { @@ -120,6 +142,14 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err name := field.Names[0].Name if field.Tag == nil { + fieldInfo := &FieldInfo{ + DsTag: name, + Field: name, + FieldType: getTypeName(field.Type), + Indexes: make([]*IndexesInfo, 0), + } + appendIndexesInfo(fieldInfo) + gen.FieldInfos = append(gen.FieldInfos, fieldInfo) continue } @@ -147,25 +177,13 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err gen.FieldInfoForIndexes = fieldInfo continue } - if _, err := tags.Get("datastore_key"); err != nil { - f := func() string { - u := uppercaseExtraction(name) - if _, ok := dupMap[u]; !ok { - dupMap[u] = 1 - } else { - dupMap[u]++ - u = fmt.Sprintf("%s%d", u, dupMap[u]) - } - return u - } fieldInfo := &FieldInfo{ DsTag: name, Field: name, FieldType: getTypeName(field.Type), Indexes: make([]*IndexesInfo, 0), } - if tag, err := tagCheck(pos, tags); err != nil { return xerrors.Errorf("error in tagCheck method: %w", err) } else if tag != "" { @@ -173,24 +191,14 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } if idr, err := tags.Get("indexer"); err != nil || fieldInfo.FieldType != typeString { - _ = err - idx := &IndexesInfo{ - ConstName: filedLabel + name, - Label: f(), - Method: "Add", - } - idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) - if fieldInfo.FieldType != typeString { - idx.Method += "Something" - } - fieldInfo.Indexes = append(fieldInfo.Indexes, idx) + appendIndexesInfo(fieldInfo) } else { filters := strings.Split(idr.Value(), ",") dupIdr := make(map[string]struct{}) for _, fil := range filters { idx := &IndexesInfo{ - ConstName: filedLabel + name, - Label: f(), + ConstName: fieldLabel + name, + Label: f(name), Method: "Add", } var dupFlag string @@ -259,7 +267,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err gen.generate(fp) } - { + if gen.EnableIndexes { path := gen.FileName + "_label.go" fp, err := os.Create(path) if err != nil { @@ -284,7 +292,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err func tagCheck(pos string, tags *structtag.Tags) (string, error) { if dsTag, err := tags.Get("datastore"); err == nil { tag := strings.Split(dsTag.Value(), ",")[0] - if !valueCheck.MatchString(tag) { // 空白と記号チェック + if !valueCheck.MatchString(tag) { return "", xerrors.Errorf("%s: key field for datastore should have other than blanks and symbols tag", pos) } if strings.Contains("0123456789", string(tag[0])) { From c77aae15d08e3dfdbe846c3d714686f4284685e9 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sun, 10 May 2020 02:33:51 +0900 Subject: [PATCH 49/77] feat: support float64 #4 --- generator.go | 18 +++++++++++++----- main.go | 13 +++++++------ testfiles/a/task.go | 15 ++++++++------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/generator.go b/generator.go index 0f7aaa0..6105663 100644 --- a/generator.go +++ b/generator.go @@ -80,6 +80,8 @@ func (g *generator) generate(writer io.Writer) { case typeInt: case typeInt64: fn = ".Int64()" + case typeFloat64: + fn = ".Float64()" default: panic("invalid types") } @@ -153,6 +155,14 @@ func (str IntegerCriteria) Int64() int64 { } return i64 } + +func (str IntegerCriteria) Float64() float64 { + f64, err := strconv.ParseFloat(string(str), 64) + if err != nil { + return -1 + } + return f64 +} ` const tmplLabel = `// THIS FILE IS A GENERATED CODE. EDIT OK @@ -257,7 +267,7 @@ func (repo *{{ .RepositoryStructName }}) saveIndexes(subjects ...*{{ .StructName idx := xian.NewIndexes({{ .StructName }}IndexesConfig) {{- range $fi := .FieldInfos }} {{- range $idx := $fi.Indexes }} -{{- if eq $fi.FieldType "bool" }} +{{- if or (eq $fi.FieldType "bool") (eq $fi.FieldType "int" ) (eq $fi.FieldType "int64" ) (eq $fi.FieldType "float64" ) }} idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}) {{- else if eq $fi.FieldType "string" }} {{- if eq $idx.Method "AddPrefix" }} @@ -265,8 +275,6 @@ func (repo *{{ .RepositoryStructName }}) saveIndexes(subjects ...*{{ .StructName {{- else }} idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}) {{- end }} -{{- else if eq $fi.FieldType "int" }} - idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}) {{- else if eq $fi.FieldType "time.Time" }} idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}.Unix()) {{- end }} @@ -300,7 +308,7 @@ type {{ .StructName }}ListReq struct { {{- range .FieldInfos }} {{- if eq .FieldType "bool" }} {{ .Field }} BoolCriteria -{{- else if or (eq .FieldType "int") (eq .FieldType "int64") }} +{{- else if or (eq .FieldType "int") (eq .FieldType "int64") (eq .FieldType "float64" ) }} {{ .Field }} IntegerCriteria {{- else }} {{ .Field }} {{ .FieldType }} @@ -341,7 +349,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru q = q.Filter("{{ $fi.DsTag }} =", req.{{ $fi.Field }}) {{- end }} } -{{- else if or (eq $fi.FieldType "int") (eq $fi.FieldType "int64") }} +{{- else if or (eq $fi.FieldType "int") (eq $fi.FieldType "int64") (eq $fi.FieldType "float64" ) }} if req.{{ $fi.Field }} != IntegerCriteriaEmpty { {{- if eq $Enable true }} {{- range $idx := $fi.Indexes }} diff --git a/main.go b/main.go index f7739c2..77ec114 100644 --- a/main.go +++ b/main.go @@ -99,12 +99,13 @@ func uppercaseExtraction(name string) (lower string) { } const ( - biunigrams = "Biunigrams" - prefix = "Prefix" - queryLabel = "QueryLabel" - typeString = "string" - typeInt = "int" - typeInt64 = "int64" + biunigrams = "Biunigrams" + prefix = "Prefix" + queryLabel = "QueryLabel" + typeString = "string" + typeInt = "int" + typeInt64 = "int64" + typeFloat64 = "float64" ) var valueCheck = regexp.MustCompile("^[0-9a-zA-Z_]+$") diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 783b3a5..96e9f62 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -9,11 +9,12 @@ import ( // Task 拡張インデックスなし type Task struct { - ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key - Desc string `datastore:"description"` - Created time.Time `datastore:"created"` - Done bool `datastore:"done"` - Done2 bool `datastore:"done2"` - Count int `datastore:"count"` - Count64 int64 `datastore:"count64"` + ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key + Desc string `datastore:"description"` + Created time.Time `datastore:"created"` + Done bool `datastore:"done"` + Done2 bool `datastore:"done2"` + Count int `datastore:"count"` + Count64 int64 `datastore:"count64"` + Proportion float64 `datastore:"proportion"` } From a4908a5500706e34276f2badb4909aa950fcf9c5 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sun, 10 May 2020 02:50:32 +0900 Subject: [PATCH 50/77] clean: delete unnecessary things #4 --- testfiles/a/name.go | 2 +- testfiles/a/task.go | 2 +- testfiles/b/task.go | 2 +- testfiles/c/task.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testfiles/a/name.go b/testfiles/a/name.go index e753f83..c7ffc20 100644 --- a/testfiles/a/name.go +++ b/testfiles/a/name.go @@ -4,7 +4,7 @@ import ( "time" ) -//go:generate repo_generator Name github.com/go-generalize/repo_generator/testfiles/a +//go:generate repo_generator Name //go:generate gofmt -w ./ // Name 拡張インデックスあり diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 96e9f62..6c4df8c 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -4,7 +4,7 @@ import ( "time" ) -//go:generate repo_generator Task github.com/go-generalize/repo_generator/testfiles/a +//go:generate repo_generator Task //go:generate gofmt -w ./ // Task 拡張インデックスなし diff --git a/testfiles/b/task.go b/testfiles/b/task.go index 7a8809a..0fcdb3e 100644 --- a/testfiles/b/task.go +++ b/testfiles/b/task.go @@ -4,7 +4,7 @@ import ( "time" ) -//go:generate repo_generator Task github.com/go-generalize/repo_generator/testfiles/b +//go:generate repo_generator Task //go:generate gofmt -w ./ type Task struct { diff --git a/testfiles/c/task.go b/testfiles/c/task.go index 53d3910..fd152e0 100644 --- a/testfiles/c/task.go +++ b/testfiles/c/task.go @@ -6,7 +6,7 @@ import ( "cloud.google.com/go/datastore" ) -//go:generate repo_generator Task github.com/go-generalize/repo_generator/testfiles/c +//go:generate repo_generator Task //go:generate gofmt -w ./ type Task struct { From a23e248adb4ca411e314da546b903806f9316d48 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sun, 10 May 2020 13:46:38 +0900 Subject: [PATCH 51/77] clean: summarized #4 --- main.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 77ec114..335d6d0 100644 --- a/main.go +++ b/main.go @@ -142,11 +142,13 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } name := field.Names[0].Name + typeName := getTypeName(field.Type) + if field.Tag == nil { fieldInfo := &FieldInfo{ DsTag: name, Field: name, - FieldType: getTypeName(field.Type), + FieldType: typeName, Indexes: make([]*IndexesInfo, 0), } appendIndexesInfo(fieldInfo) @@ -168,7 +170,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err fieldInfo := &FieldInfo{ DsTag: name, Field: name, - FieldType: getTypeName(field.Type), + FieldType: typeName, } if tag, err := tagCheck(pos, tags); err != nil { return xerrors.Errorf("error in tagCheck method: %w", err) @@ -182,7 +184,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err fieldInfo := &FieldInfo{ DsTag: name, Field: name, - FieldType: getTypeName(field.Type), + FieldType: typeName, Indexes: make([]*IndexesInfo, 0), } if tag, err := tagCheck(pos, tags); err != nil { @@ -246,7 +248,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } gen.KeyFieldName = name - gen.KeyFieldType = getTypeName(field.Type) + gen.KeyFieldType = typeName if gen.KeyFieldType != typeInt64 && gen.KeyFieldType != typeString && From 36e53dae46970b4d1d5154e543afa856613a7825 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Sun, 10 May 2020 13:49:31 +0900 Subject: [PATCH 52/77] fix: comparison method #4 --- testfiles/a/tests/task_test.go | 8 ++++---- testfiles/b/tests/task_test.go | 4 ++-- testfiles/c/tests/task_test.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 4ae1e98..360c5b3 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -41,7 +41,7 @@ func compareTask(t *testing.T, expected, actual *task.Task) { t.Fatalf("unexpected id: %d(expected: %d)", actual.ID, expected.ID) } - if actual.Created != expected.Created { + if !actual.Created.Equal(expected.Created) { t.Fatalf("unexpected time: %s(expected: %s)", actual.Created, expected.Created) } @@ -68,7 +68,7 @@ func TestDatastoreListTask(t *testing.T) { } }() - now := time.Unix(time.Now().Unix(), 0) + now := time.Now() desc := "Hello, World!" tks := make([]*task.Task, 0) @@ -147,7 +147,7 @@ func TestDatastoreListNameWithIndexes(t *testing.T) { } }() - now := time.Unix(time.Now().Unix(), 0) + now := time.Now() desc := "Hello, World!" desc2 := "Prefix, Test!" @@ -269,7 +269,7 @@ func TestDatastore(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - now := time.Unix(time.Now().Unix(), 0) + now := time.Now() desc := "hello" id, err := taskRepo.Insert(ctx, &task.Task{ diff --git a/testfiles/b/tests/task_test.go b/testfiles/b/tests/task_test.go index df5dc23..acd049b 100644 --- a/testfiles/b/tests/task_test.go +++ b/testfiles/b/tests/task_test.go @@ -40,7 +40,7 @@ func compareTask(t *testing.T, expected, actual *task.Task) { t.Fatalf("unexpected id: %s(expected: %s)", actual.ID, expected.ID) } - if actual.Created != expected.Created { + if !actual.Created.Equal(expected.Created) { t.Fatalf("unexpected time: %s(expected: %s)", actual.Created, expected.Created) } @@ -61,7 +61,7 @@ func TestDatastore(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - now := time.Unix(time.Now().Unix(), 0) + now := time.Now() desc := "hello" id, err := taskRepo.Insert(ctx, &task.Task{ diff --git a/testfiles/c/tests/task_test.go b/testfiles/c/tests/task_test.go index 6b3c904..4e86c9d 100644 --- a/testfiles/c/tests/task_test.go +++ b/testfiles/c/tests/task_test.go @@ -40,7 +40,7 @@ func compareTask(t *testing.T, expected, actual *task.Task) { t.Fatalf("unexpected id: %s(expected: %s)", actual.ID, expected.ID) } - if actual.Created != expected.Created { + if !actual.Created.Equal(expected.Created) { t.Fatalf("unexpected time: %s(expected: %s)", actual.Created, expected.Created) } @@ -61,7 +61,7 @@ func TestDatastore(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - now := time.Unix(time.Now().Unix(), 0) + now := time.Now() desc := "hello" incmplKey := datastore.IncompleteKey("Task", nil) From 6705bfb42a7ff021e0686d542468006ab4b956ea Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 01:22:58 +0900 Subject: [PATCH 53/77] fix: godoc #4 --- generator.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator.go b/generator.go index 6105663..6181507 100644 --- a/generator.go +++ b/generator.go @@ -303,7 +303,7 @@ var {{ .StructName }}IndexesConfig = &xian.Config{ {{- end }} // {{ .StructName }}ListReq List取得時に渡すリクエスト -// └─ bool/int(64) は stringで渡す(BoolCriteria | IntegerCriteria) +// └─ bool/int(64)|float64 は stringで渡す(BoolCriteria | IntegerCriteria) type {{ .StructName }}ListReq struct { {{- range .FieldInfos }} {{- if eq .FieldType "bool" }} From 7f750650988bd79a572303756219449d467e9775 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 01:26:33 +0900 Subject: [PATCH 54/77] fix: Check compatible type / support unique type #4 --- main.go | 146 +++++++++++++++++++++++++++----------------- misc.go | 51 +++++++++++++++- testfiles/a/task.go | 17 +++--- 3 files changed, 150 insertions(+), 64 deletions(-) diff --git a/main.go b/main.go index 335d6d0..04074b2 100644 --- a/main.go +++ b/main.go @@ -8,10 +8,10 @@ import ( "log" "os" "path/filepath" - "regexp" "strings" "github.com/fatih/structtag" + "github.com/go-utils/cont" "github.com/iancoleman/strcase" "golang.org/x/xerrors" ) @@ -89,52 +89,9 @@ func traverse(pkg *ast.Package, fs *token.FileSet, structName string) error { return xerrors.Errorf("no such struct: %s", structName) } -func uppercaseExtraction(name string) (lower string) { - for _, x := range name { - if 65 <= x && x <= 90 { - lower += string(x + 32) - } - } - return -} - -const ( - biunigrams = "Biunigrams" - prefix = "Prefix" - queryLabel = "QueryLabel" - typeString = "string" - typeInt = "int" - typeInt64 = "int64" - typeFloat64 = "float64" -) - -var valueCheck = regexp.MustCompile("^[0-9a-zA-Z_]+$") - func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) error { dupMap := make(map[string]int) - f := func(name string) string { - u := uppercaseExtraction(name) - if _, ok := dupMap[u]; !ok { - dupMap[u] = 1 - } else { - dupMap[u]++ - u = fmt.Sprintf("%s%d", u, dupMap[u]) - } - return u - } - fieldLabel := gen.StructName + queryLabel - appendIndexesInfo := func(fieldInfo *FieldInfo) { - idx := &IndexesInfo{ - ConstName: fieldLabel + fieldInfo.Field, - Label: f(fieldInfo.Field), - Method: "Add", - } - idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, fieldInfo.Field) - if fieldInfo.FieldType != typeString { - idx.Method += "Something" - } - fieldInfo.Indexes = append(fieldInfo.Indexes, idx) - } + fieldLabel = gen.StructName + queryLabel for _, field := range structType.Fields.List { // structの各fieldを調査 if len(field.Names) != 1 { @@ -142,7 +99,19 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err } name := field.Names[0].Name - typeName := getTypeName(field.Type) + pos := fs.Position(field.Pos()).String() + + typeError := func(typeName string) { + log.Printf( + "%s: the type of `%s` is an invalid type in struct `%s` [%s]", + pos, name, gen.StructName, typeName, + ) + } + + typeName, continued := getTypeNameAndCheck(field, typeError) + if continued { + continue + } if field.Tag == nil { fieldInfo := &FieldInfo{ @@ -151,13 +120,11 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err FieldType: typeName, Indexes: make([]*IndexesInfo, 0), } - appendIndexesInfo(fieldInfo) + appendIndexesInfo(fieldInfo, dupMap) gen.FieldInfos = append(gen.FieldInfos, fieldInfo) continue } - pos := fs.Position(field.Pos()).String() - if tags, err := structtag.Parse(strings.Trim(field.Tag.Value, "`")); err != nil { log.Printf( "%s: tag for %s in struct %s in %s", @@ -172,7 +139,7 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err Field: name, FieldType: typeName, } - if tag, err := tagCheck(pos, tags); err != nil { + if tag, err := dataStoreTagCheck(pos, tags); err != nil { return xerrors.Errorf("error in tagCheck method: %w", err) } else if tag != "" { fieldInfo.DsTag = tag @@ -187,21 +154,20 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err FieldType: typeName, Indexes: make([]*IndexesInfo, 0), } - if tag, err := tagCheck(pos, tags); err != nil { + if tag, err := dataStoreTagCheck(pos, tags); err != nil { return xerrors.Errorf("error in tagCheck method: %w", err) } else if tag != "" { fieldInfo.DsTag = tag } - if idr, err := tags.Get("indexer"); err != nil || fieldInfo.FieldType != typeString { - appendIndexesInfo(fieldInfo) + appendIndexesInfo(fieldInfo, dupMap) } else { filters := strings.Split(idr.Value(), ",") dupIdr := make(map[string]struct{}) for _, fil := range filters { idx := &IndexesInfo{ ConstName: fieldLabel + name, - Label: f(name), + Label: uppercaseExtraction(fieldInfo.Field, dupMap), Method: "Add", } var dupFlag string @@ -292,7 +258,77 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err return nil } -func tagCheck(pos string, tags *structtag.Tags) (string, error) { +func uppercaseExtraction(name string, dupMap map[string]int) (lower string) { + for _, x := range name { + if 65 <= x && x <= 90 { + lower += string(x + 32) + } + } + if _, ok := dupMap[lower]; !ok { + dupMap[lower] = 1 + } else { + dupMap[lower]++ + lower = fmt.Sprintf("%s%d", lower, dupMap[lower]) + } + return +} + +func appendIndexesInfo(fieldInfo *FieldInfo, dupMap map[string]int) { + idx := &IndexesInfo{ + ConstName: fieldLabel + fieldInfo.Field, + Label: uppercaseExtraction(fieldInfo.Field, dupMap), + Method: "Add", + } + idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, fieldInfo.Field) + if fieldInfo.FieldType != typeString { + idx.Method += "Something" + } + fieldInfo.Indexes = append(fieldInfo.Indexes, idx) +} + +func getTypeNameAndCheck(field *ast.Field, f func(string)) (string, bool) { + typeName := getTypeName(field.Type) + if typeName == "*datastore.Key" { + return typeName, false + } + if !cont.Contains(supportType, typeName) { + s := typeName + var p string + if strings.HasPrefix(typeName, "[]") { + p = "[]" + s = typeName[2:] + } + if cont.Contains(supportType, s) { + typeName = p + s + } else { + if cont.Contains(builtInType, s) || field.Tag == nil { + f(typeName) + return "", true + } else { + tags, err := structtag.Parse(strings.Trim(field.Tag.Value, "`")) + if err != nil { + f(typeName) + return "", true + } + tag, err := tags.Get("type") + if err != nil { + f(typeName) + return "", true + } + val := tag.Value() + if cont.Contains(supportType, val) { + typeName = p + val + } else { + f(typeName) + return "", true + } + } + } + } + return typeName, false +} + +func dataStoreTagCheck(pos string, tags *structtag.Tags) (string, error) { if dsTag, err := tags.Get("datastore"); err == nil { tag := strings.Split(dsTag.Value(), ",")[0] if !valueCheck.MatchString(tag) { diff --git a/misc.go b/misc.go index 755650a..c0cebc9 100644 --- a/misc.go +++ b/misc.go @@ -2,6 +2,7 @@ package main import ( "go/ast" + "regexp" ) func getTypeName(typ ast.Expr) string { @@ -10,13 +11,61 @@ func getTypeName(typ ast.Expr) string { return getTypeName(v.X) + "." + v.Sel.Name case *ast.Ident: - return v.Name case *ast.StarExpr: return "*" + getTypeName(v.X) + case *ast.ArrayType: + return "[]" + getTypeName(v.Elt) + default: return "" } } + +const ( + biunigrams = "Biunigrams" + prefix = "Prefix" + queryLabel = "QueryLabel" + typeString = "string" + typeInt = "int" + typeInt64 = "int64" + typeFloat64 = "float64" + typeBool = "bool" + typeTime = "time.Time" +) + +var ( + fieldLabel string + valueCheck = regexp.MustCompile("^[0-9a-zA-Z_]+$") + builtInType = []string{ + "uint8", + "uint16", + "uint32", + "uint64", + "int8", + "int16", + "int32", + "float32", + "complex64", + "complex128", + "uint", + "uintptr", + "byte", + "rune", + typeBool, + typeString, + typeInt, + typeInt64, + typeFloat64, + } + supportType = []string{ + typeBool, + typeString, + typeInt, + typeInt64, + typeFloat64, + typeTime, + } +) diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 6c4df8c..127ef07 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -9,12 +9,13 @@ import ( // Task 拡張インデックスなし type Task struct { - ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key - Desc string `datastore:"description"` - Created time.Time `datastore:"created"` - Done bool `datastore:"done"` - Done2 bool `datastore:"done2"` - Count int `datastore:"count"` - Count64 int64 `datastore:"count64"` - Proportion float64 `datastore:"proportion"` + ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key + Desc string `datastore:"description"` + Created time.Time `datastore:"created"` + Done bool `datastore:"done"` + Done2 bool `datastore:"done2"` + Count int `datastore:"count"` + Count64 int64 `datastore:"count64"` + Proportion float64 `datastore:"proportion"` + Flag BoolCriteria `datastore:"flag" type:"string"` // If you want to use your unique type, set the original type to `type` } From dac03405ec36bfd7fa6cf94b73062cd7230e2fa1 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 01:28:38 +0900 Subject: [PATCH 55/77] feat: supports Slices #4 --- generator.go | 17 +++++++++++++++++ testfiles/a/name.go | 11 ++++++----- testfiles/a/task.go | 1 + 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/generator.go b/generator.go index 6181507..6a20150 100644 --- a/generator.go +++ b/generator.go @@ -3,6 +3,7 @@ package main import ( "io" "log" + "strings" "text/template" ) @@ -87,6 +88,9 @@ func (g *generator) generate(writer io.Writer) { } return field + fn }, + "HasPrefixSlice": func(types string) bool { + return strings.HasPrefix(types, "[]") + }, } t := template.Must(template.New("tmpl").Funcs(funcMap).Parse(tmpl)) @@ -329,6 +333,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters := xian.NewFilters({{ .StructName }}IndexesConfig) {{- end }} {{- range $fi := .FieldInfos }} +{{ $PrefixIsSlice := HasPrefixSlice $fi.FieldType}} {{- if eq $fi.FieldType "bool" }} if req.{{ $fi.Field }} != "" { {{- if eq $Enable true }} @@ -369,6 +374,18 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru q = q.Filter("{{ $fi.DsTag }} =", req.{{ $fi.Field }}) {{- end }} } +{{- else if eq $PrefixIsSlice true }} + if len(req.{{ $fi.Field }}) > 0 { +{{- if eq $Enable true }} +{{- range $idx := $fi.Indexes }} + filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ $fi.Field }}) +{{- end }} +{{- else }} + for _, x := range req.{{ $fi.Field }} { + q = q.Filter("{{ $fi.DsTag }} =", x) + } +{{- end }} + } {{- end }} {{- end }} {{ if eq $Enable true }} diff --git a/testfiles/a/name.go b/testfiles/a/name.go index c7ffc20..7326fd4 100644 --- a/testfiles/a/name.go +++ b/testfiles/a/name.go @@ -13,9 +13,10 @@ type Name struct { Created time.Time `datastore:"created"` // supported indexer tags word: e/equal(Default), l/like, p/prefix, // TODO s/suffix - Desc string `datastore:"description" indexer:"l"` - Desc2 string `datastore:"description2" indexer:"p"` - Done bool `datastore:"done"` - Count int `datastore:"count"` - Indexes []string `datastore:"indexes"` + Desc string `datastore:"description" indexer:"l"` + Desc2 string `datastore:"description2" indexer:"p"` + Done bool `datastore:"done"` + Count int `datastore:"count"` + PriceList []int `datastore:"priceList"` + Indexes []string `datastore:"indexes"` } diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 127ef07..2caa26e 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -18,4 +18,5 @@ type Task struct { Count64 int64 `datastore:"count64"` Proportion float64 `datastore:"proportion"` Flag BoolCriteria `datastore:"flag" type:"string"` // If you want to use your unique type, set the original type to `type` + NameList []string `datastore:"nameList"` } From e9e2903b60e02237ac5815bdb9277d981341903e Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 01:28:53 +0900 Subject: [PATCH 56/77] update: go.mod --- go.mod | 3 ++- go.sum | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index dd6ce37..667660e 100644 --- a/go.mod +++ b/go.mod @@ -7,13 +7,14 @@ require ( cloud.google.com/go/bigquery v1.6.0 // indirect cloud.google.com/go/datastore v1.1.0 github.com/fatih/structtag v1.2.0 + github.com/go-utils/cont v0.1.0 github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.4.1 // indirect github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 github.com/knightso/xian v0.1.0 github.com/pkg/errors v0.9.1 // indirect golang.org/x/net v0.0.0-20200506145744-7e3656a0809f // indirect - golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 // indirect + golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f // indirect golang.org/x/tools v0.0.0-20200507205054-480da3ebd79c golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 google.golang.org/api v0.23.0 // indirect diff --git a/go.sum b/go.sum index c31a845..1803da9 100644 --- a/go.sum +++ b/go.sum @@ -52,6 +52,8 @@ github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4 github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-utils/cont v0.1.0 h1:Zz3oiCzLdbfujHNUQKjjOKbO0+/9CCgjXO3cKuaECjI= +github.com/go-utils/cont v0.1.0/go.mod h1:DvdqFD+3nl8bUcFVUyR6t4ScyJZ6ls8IX9vdiwVWqDk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -226,8 +228,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w= -golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI= +golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= From 4dd4fc63328ac11a87ae46c7186a8f50d6a4b52f Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 13:36:23 +0900 Subject: [PATCH 57/77] feat: deduplication of slices #4 --- .gitignore | 2 + generator.go | 11 ++ go.sum | 369 -------------------------------------------- main.go | 4 + testfiles/a/task.go | 21 +-- 5 files changed, 28 insertions(+), 379 deletions(-) delete mode 100644 go.sum diff --git a/.gitignore b/.gitignore index a070a73..889b526 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ .idea/ .DS_Store + +go.sum diff --git a/generator.go b/generator.go index 6a20150..8acb936 100644 --- a/generator.go +++ b/generator.go @@ -45,6 +45,7 @@ type generator struct { EnableIndexes bool FieldInfoForIndexes *FieldInfo BoolCriteriaCnt int + SliceExist bool } func (g *generator) setting() { @@ -83,6 +84,10 @@ func (g *generator) generate(writer io.Writer) { fn = ".Int64()" case typeFloat64: fn = ".Float64()" + case typeString: + fn = ".String()" + case typeBool: + fn = ".Bool()" default: panic("invalid types") } @@ -195,6 +200,9 @@ import ( "cloud.google.com/go/datastore" {{- if eq .EnableIndexes true }} "github.com/knightso/xian" +{{- end }} +{{- if eq .SliceExist true }} + "github.com/go-utils/dedupe" {{- end }} "golang.org/x/xerrors" ) @@ -376,6 +384,9 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru } {{- else if eq $PrefixIsSlice true }} if len(req.{{ $fi.Field }}) > 0 { + if err := dedupe.Do(&req.{{ $fi.Field }}); err != nil { + return nil, xerrors.Errorf("error in dedupe.Do method: %w", err) + } {{- if eq $Enable true }} {{- range $idx := $fi.Indexes }} filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ $fi.Field }}) diff --git a/go.sum b/go.sum deleted file mode 100644 index 1803da9..0000000 --- a/go.sum +++ /dev/null @@ -1,369 +0,0 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0 h1:GGslhk/BU052LPlnI1vpp3fcbUs+hQ3E+Doti/3/vF8= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0 h1:WRz29PgAsVEyPSDHyk+0fpEkwEFyfhHn+JbksT6gIL4= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0 h1:EpMNVUorLiZIELdMZbCYX/ByTFCdoYopYAGxaGVz9ms= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.6.0 h1:ajp/DjpiCHO71SyIhwb83YsUGAyWuzVvMko+9xCsJLw= -cloud.google.com/go/bigquery v1.6.0/go.mod h1:hyFDG0qSGdHNz8Q6nDN8rYIkld0q/+5uBZaelxiDLfE= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0 h1:UDpwYIwla4jHGzZJaEJYx1tOejbgSoNqsAfHAUYe2r8= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= -github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-utils/cont v0.1.0 h1:Zz3oiCzLdbfujHNUQKjjOKbO0+/9CCgjXO3cKuaECjI= -github.com/go-utils/cont v0.1.0/go.mod h1:DvdqFD+3nl8bUcFVUyR6t4ScyJZ6ls8IX9vdiwVWqDk= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFEB7inlalqfNqw65aNkM1lGX2yt3NmbS8= -github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/knightso/xian v0.1.0 h1:tbSxtKEB0jMK9M4U6ftbh33LwLDASQqknR0pTodRNBQ= -github.com/knightso/xian v0.1.0/go.mod h1:awKIZpjAL+4BI/y7lanh65Qf2uz2lwQGK8mK+gW+QUo= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd h1:zkO/Lhoka23X63N9OSzpSeROEUQ5ODw47tM3YWjygbs= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367 h1:0IiAsCRByjO2QjX7ZPkw5oU9x+n1YqRL802rjC0c3Aw= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b h1:0mm1VjtFUOIlE1SbDlwjYaDxZVDP2S5ou6y0gSgXHu8= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f h1:QBjCr1Fz5kw158VqdE9JfI9cJnl/ymnJWAdMuinqL7Y= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 h1:sfkvUWPNGwSV+8/fNqctR5lS2AqCSqYwXdrjCxp/dXo= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI= -golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56 h1:DFtSed2q3HtNuVazwVDZ4nSRS/JrZEig0gz2BY4VNrg= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200409170454-77362c5149f0/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200507205054-480da3ebd79c h1:TDspWmUQsjdWzrHnd5imfaJSfhR4AO/R7kG++T2cONw= -golang.org/x/tools v0.0.0-20200507205054-480da3ebd79c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0 h1:0q95w+VuFtv4PAx4PZVQdBMmYbaCHbnfKaEiDIcVyag= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.21.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.23.0 h1:YlvGEOq2NA2my8cZ/9V8BcEO9okD48FlJcdqN0xJL3s= -google.golang.org/api v0.23.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce h1:1mbrb1tUU+Zmt5C94IGKADBTJZjZXAd+BubWi7r9EiI= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200409111301-baae70f3302d/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 h1:pSLkPbrjnPyLDYUO2VM9mDLqo2V6CFBY84lFSZAfoi4= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31 h1:Bz1qTn2YRWV+9OKJtxHJiQKCiXIdf+kwuKXdt9cBxyU= -google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1 h1:zvIju4sqAGvwKspUQOhwnpcqSbzi7/H6QomNNjTL4sk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/main.go b/main.go index 04074b2..d58c4dc 100644 --- a/main.go +++ b/main.go @@ -113,6 +113,10 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err continue } + if strings.HasPrefix(typeName, "[]") { + gen.SliceExist = true + } + if field.Tag == nil { fieldInfo := &FieldInfo{ DsTag: name, diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 2caa26e..1cbf9fb 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -9,14 +9,15 @@ import ( // Task 拡張インデックスなし type Task struct { - ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key - Desc string `datastore:"description"` - Created time.Time `datastore:"created"` - Done bool `datastore:"done"` - Done2 bool `datastore:"done2"` - Count int `datastore:"count"` - Count64 int64 `datastore:"count64"` - Proportion float64 `datastore:"proportion"` - Flag BoolCriteria `datastore:"flag" type:"string"` // If you want to use your unique type, set the original type to `type` - NameList []string `datastore:"nameList"` + ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key + Desc string `datastore:"description"` + Created time.Time `datastore:"created"` + Done bool `datastore:"done"` + Done2 bool `datastore:"done2"` + Count int `datastore:"count"` + Count64 int64 `datastore:"count64"` + Proportion float64 `datastore:"proportion"` + Flag BoolCriteria `datastore:"flag" type:"string"` // If you want to use your unique type, set the original type to `type` + NameList []string `datastore:"nameList"` + FlagList []BoolCriteria `datastore:"flagList" type:"bool"` // If you want to use your unique type, set the original type to `type` } From dddf54765bbb5acd732bae32bcf172b8d362531d Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 13:36:44 +0900 Subject: [PATCH 58/77] update: go.mod --- go.mod | 1 + 1 file changed, 1 insertion(+) diff --git a/go.mod b/go.mod index 667660e..ddb6288 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( cloud.google.com/go/datastore v1.1.0 github.com/fatih/structtag v1.2.0 github.com/go-utils/cont v0.1.0 + github.com/go-utils/dedupe v1.0.0 github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.4.1 // indirect github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 From e73a108f77d81f5eb1c0c3d42aea5a25b9c5a472 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 15:52:38 +0900 Subject: [PATCH 59/77] update: change treatment --- generator.go | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/generator.go b/generator.go index 8acb936..8862fe6 100644 --- a/generator.go +++ b/generator.go @@ -76,22 +76,25 @@ func (g *generator) setRepositoryStructName() { func (g *generator) generate(writer io.Writer) { g.setting() funcMap := template.FuncMap{ - "Parse": func(field, fieldType string) string { - fn := ".Int()" + "Parse": func(fieldType string) string { + if strings.HasPrefix(fieldType, "[]") { + fieldType = fieldType[2:] + } + fn := "Int" switch fieldType { case typeInt: case typeInt64: - fn = ".Int64()" + fn = "Int64" case typeFloat64: - fn = ".Float64()" + fn = "Float64" case typeString: - fn = ".String()" + fn = "String" case typeBool: - fn = ".Bool()" + fn = "Bool" default: panic("invalid types") } - return field + fn + return fn }, "HasPrefixSlice": func(types string) bool { return strings.HasPrefix(types, "[]") @@ -201,7 +204,7 @@ import ( {{- if eq .EnableIndexes true }} "github.com/knightso/xian" {{- end }} -{{- if eq .SliceExist true }} +{{- if and (eq .SliceExist true) (eq .EnableIndexes false) }} "github.com/go-utils/dedupe" {{- end }} "golang.org/x/xerrors" @@ -278,6 +281,7 @@ func (repo *{{ .RepositoryStructName }}) saveIndexes(subjects ...*{{ .StructName for _, subject := range subjects { idx := xian.NewIndexes({{ .StructName }}IndexesConfig) {{- range $fi := .FieldInfos }} +{{- $PrefixIsSlice := HasPrefixSlice $fi.FieldType}} {{- range $idx := $fi.Indexes }} {{- if or (eq $fi.FieldType "bool") (eq $fi.FieldType "int" ) (eq $fi.FieldType "int64" ) (eq $fi.FieldType "float64" ) }} idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}) @@ -289,6 +293,8 @@ func (repo *{{ .RepositoryStructName }}) saveIndexes(subjects ...*{{ .StructName {{- end }} {{- else if eq $fi.FieldType "time.Time" }} idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}.Unix()) +{{- else if eq $PrefixIsSlice true }} + idx.{{ $idx.Method }}({{ $idx.ConstName }}, subject.{{ $fi.Field }}) {{- end }} {{- end }} {{- end }} @@ -366,10 +372,10 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru if req.{{ $fi.Field }} != IntegerCriteriaEmpty { {{- if eq $Enable true }} {{- range $idx := $fi.Indexes }} - filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ Parse $fi.Field $fi.FieldType }}) + filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ $fi.Field }}.{{ Parse $fi.FieldType }}()) {{- end }} {{- else }} - q = q.Filter("{{ $fi.DsTag }} =", req.{{ Parse $fi.Field $fi.FieldType }}) + q = q.Filter("{{ $fi.DsTag }} =", req.{{ $fi.Field }}.{{ Parse $fi.FieldType }}()) {{- end }} } {{- else if eq $fi.FieldType "time.Time" }} @@ -384,14 +390,12 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru } {{- else if eq $PrefixIsSlice true }} if len(req.{{ $fi.Field }}) > 0 { - if err := dedupe.Do(&req.{{ $fi.Field }}); err != nil { - return nil, xerrors.Errorf("error in dedupe.Do method: %w", err) - } {{- if eq $Enable true }} {{- range $idx := $fi.Indexes }} filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ $fi.Field }}) {{- end }} {{- else }} + dedupe.Do(&req.{{ $fi.Field }}) for _, x := range req.{{ $fi.Field }} { q = q.Filter("{{ $fi.DsTag }} =", x) } From add5960e4cff01db25e5321a7005a5962d087fa2 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 15:53:22 +0900 Subject: [PATCH 60/77] update: add test pattern --- testfiles/a/tests/task_test.go | 90 +++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 11 deletions(-) diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 360c5b3..3df1fd3 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -74,11 +74,17 @@ func TestDatastoreListTask(t *testing.T) { tks := make([]*task.Task, 0) for i := int64(1); i <= 10; i++ { tk := &task.Task{ - ID: i * 100, - Created: now, - Desc: fmt.Sprintf("%s%d", desc, i), - Done: true, - Count: int(i), + ID: i * 100, + Desc: fmt.Sprintf("%s%d", desc, i), + Created: now, + Done: true, + Done2: false, + Count: int(i), + Count64: 0, + Proportion: 0.12345 + float64(i), + Flag: task.BoolCriteriaTrue, + NameList: []string{"a", "b", "c"}, + //FlagList: []task.BoolCriteria{task.BoolCriteriaTrue, task.BoolCriteriaFalse, task.BoolCriteriaFalse}, // TODO 独自型の対応 } tks = append(tks, tk) } @@ -102,6 +108,21 @@ func TestDatastoreListTask(t *testing.T) { } }) + t.Run("float(1件)", func(t *testing.T) { + req := &task.TaskListReq{ + Proportion: task.IntegerCriteria("1.12345"), // FIXME 2 この実装をどうにかしたい + } + + tasks, err := taskRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 1 { + t.Fatal("not match") + } + }) + t.Run("bool(10件)", func(t *testing.T) { req := &task.TaskListReq{ Done: task.BoolCriteriaTrue, @@ -131,6 +152,37 @@ func TestDatastoreListTask(t *testing.T) { t.Fatal("not match") } }) + + t.Run("[]string(10件)", func(t *testing.T) { + req := &task.TaskListReq{ + NameList: []string{"a", "b"}, + } + + tasks, err := taskRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 10 { + t.Fatal("not match") + } + }) + + // TODO 現状、独自型のスライスを許容できない + /* t.Run("[]task.BoolCriteria(10件)", func(t *testing.T) { + req := &task.TaskListReq{ + FlagList: []task.BoolCriteria{task.BoolCriteriaTrue}, + } + + tasks, err := taskRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 10 { + t.Fatal("not match") + } + }) */ } func TestDatastoreListNameWithIndexes(t *testing.T) { @@ -154,12 +206,13 @@ func TestDatastoreListNameWithIndexes(t *testing.T) { tks := make([]*task.Name, 0) for i := int64(1); i <= 10; i++ { tk := &task.Name{ - ID: i, - Created: now, - Desc: fmt.Sprintf("%s%d", desc, i), - Desc2: fmt.Sprintf("%s%d", desc2, i), - Done: true, - Count: int(i), + ID: i, + Created: now, + Desc: fmt.Sprintf("%s%d", desc, i), + Desc2: fmt.Sprintf("%s%d", desc2, i), + Done: true, + Count: int(i), + PriceList: []int{1, 2, 3, 4, 5}, } tks = append(tks, tk) } @@ -259,6 +312,21 @@ func TestDatastoreListNameWithIndexes(t *testing.T) { t.Fatal("not match") } }) + + t.Run("[]int(10件)", func(t *testing.T) { + req := &task.NameListReq{ + PriceList: []int{1, 2, 3}, + } + + tasks, err := nameRepo.List(ctx, req, nil) + if err != nil { + t.Fatalf("%+v", err) + } + + if len(tasks) != 10 { + t.Fatal("not match") + } + }) } func TestDatastore(t *testing.T) { From 519c5c17db981a5ca650b70066918ec67738ee97 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 15:54:57 +0900 Subject: [PATCH 61/77] remove: unique type slices cannot be supported... --- testfiles/a/task.go | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 1cbf9fb..19d094f 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -9,15 +9,15 @@ import ( // Task 拡張インデックスなし type Task struct { - ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key - Desc string `datastore:"description"` - Created time.Time `datastore:"created"` - Done bool `datastore:"done"` - Done2 bool `datastore:"done2"` - Count int `datastore:"count"` - Count64 int64 `datastore:"count64"` - Proportion float64 `datastore:"proportion"` - Flag BoolCriteria `datastore:"flag" type:"string"` // If you want to use your unique type, set the original type to `type` - NameList []string `datastore:"nameList"` - FlagList []BoolCriteria `datastore:"flagList" type:"bool"` // If you want to use your unique type, set the original type to `type` + ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key + Desc string `datastore:"description"` + Created time.Time `datastore:"created"` + Done bool `datastore:"done"` + Done2 bool `datastore:"done2"` + Count int `datastore:"count"` + Count64 int64 `datastore:"count64"` + Proportion float64 `datastore:"proportion"` + Flag BoolCriteria `datastore:"flag" type:"string"` // If you want to use your unique type, set the original type to `type` + NameList []string `datastore:"nameList"` + // FlagList []BoolCriteria `datastore:"flagList" type:"bool"` // TODO no support } From 3191ace8526e1a8f15af8674a18ec95851f3a050 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 15:55:36 +0900 Subject: [PATCH 62/77] update: go.mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index ddb6288..e6d10bf 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( cloud.google.com/go/datastore v1.1.0 github.com/fatih/structtag v1.2.0 github.com/go-utils/cont v0.1.0 - github.com/go-utils/dedupe v1.0.0 + github.com/go-utils/dedupe v0.1.1 github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.4.1 // indirect github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 From a3984086293a90665cf43545877fcdd84fd50d91 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 16:01:06 +0900 Subject: [PATCH 63/77] chore: lint --- main.go | 33 ++++++++++++++++----------------- testfiles/a/task.go | 21 +++++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/main.go b/main.go index d58c4dc..cea2cd5 100644 --- a/main.go +++ b/main.go @@ -308,24 +308,23 @@ func getTypeNameAndCheck(field *ast.Field, f func(string)) (string, bool) { if cont.Contains(builtInType, s) || field.Tag == nil { f(typeName) return "", true + } + tags, err := structtag.Parse(strings.Trim(field.Tag.Value, "`")) + if err != nil { + f(typeName) + return "", true + } + tag, err := tags.Get("type") + if err != nil { + f(typeName) + return "", true + } + val := tag.Value() + if cont.Contains(supportType, val) { + typeName = p + val } else { - tags, err := structtag.Parse(strings.Trim(field.Tag.Value, "`")) - if err != nil { - f(typeName) - return "", true - } - tag, err := tags.Get("type") - if err != nil { - f(typeName) - return "", true - } - val := tag.Value() - if cont.Contains(supportType, val) { - typeName = p + val - } else { - f(typeName) - return "", true - } + f(typeName) + return "", true } } } diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 19d094f..93d8d82 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -9,15 +9,16 @@ import ( // Task 拡張インデックスなし type Task struct { - ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key - Desc string `datastore:"description"` - Created time.Time `datastore:"created"` - Done bool `datastore:"done"` - Done2 bool `datastore:"done2"` - Count int `datastore:"count"` - Count64 int64 `datastore:"count64"` - Proportion float64 `datastore:"proportion"` - Flag BoolCriteria `datastore:"flag" type:"string"` // If you want to use your unique type, set the original type to `type` - NameList []string `datastore:"nameList"` + ID int64 `datastore:"-" datastore_key:""` // supported type: string, int64, *datastore.Key + Desc string `datastore:"description"` + Created time.Time `datastore:"created"` + Done bool `datastore:"done"` + Done2 bool `datastore:"done2"` + Count int `datastore:"count"` + Count64 int64 `datastore:"count64"` + NameList []string `datastore:"nameList"` + Proportion float64 `datastore:"proportion"` + // If you want to use your unique type, set the original type to `type` + Flag BoolCriteria `datastore:"flag" type:"string"` // FlagList []BoolCriteria `datastore:"flagList" type:"bool"` // TODO no support } From 9826594e713b0633cb4a331b88b187b32cb7d783 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 16:14:46 +0900 Subject: [PATCH 64/77] fix: change handling of time --- testfiles/a/tests/task_test.go | 6 +++--- testfiles/b/tests/task_test.go | 2 +- testfiles/c/tests/task_test.go | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 3df1fd3..7c7eb7b 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -68,7 +68,7 @@ func TestDatastoreListTask(t *testing.T) { } }() - now := time.Now() + now := time.Unix(0, time.Now().UnixNano()) desc := "Hello, World!" tks := make([]*task.Task, 0) @@ -199,7 +199,7 @@ func TestDatastoreListNameWithIndexes(t *testing.T) { } }() - now := time.Now() + now := time.Unix(0, time.Now().UnixNano()) desc := "Hello, World!" desc2 := "Prefix, Test!" @@ -337,7 +337,7 @@ func TestDatastore(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - now := time.Now() + now := time.Unix(time.Now().Unix(), 0) desc := "hello" id, err := taskRepo.Insert(ctx, &task.Task{ diff --git a/testfiles/b/tests/task_test.go b/testfiles/b/tests/task_test.go index acd049b..24cd547 100644 --- a/testfiles/b/tests/task_test.go +++ b/testfiles/b/tests/task_test.go @@ -61,7 +61,7 @@ func TestDatastore(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - now := time.Now() + now := time.Unix(time.Now().Unix(), 0) desc := "hello" id, err := taskRepo.Insert(ctx, &task.Task{ diff --git a/testfiles/c/tests/task_test.go b/testfiles/c/tests/task_test.go index 4e86c9d..b29b8e6 100644 --- a/testfiles/c/tests/task_test.go +++ b/testfiles/c/tests/task_test.go @@ -61,7 +61,7 @@ func TestDatastore(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() - now := time.Now() + now := time.Unix(time.Now().Unix(), 0) desc := "hello" incmplKey := datastore.IncompleteKey("Task", nil) From 622febe2c85976b1c7214e69215c3b6ff7831fe7 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Mon, 11 May 2020 17:30:02 +0900 Subject: [PATCH 65/77] fix: minor fix --- testfiles/a/task.go | 4 +++- testfiles/a/tests/task_test.go | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/testfiles/a/task.go b/testfiles/a/task.go index 93d8d82..d037e0e 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -19,6 +19,8 @@ type Task struct { NameList []string `datastore:"nameList"` Proportion float64 `datastore:"proportion"` // If you want to use your unique type, set the original type to `type` - Flag BoolCriteria `datastore:"flag" type:"string"` + Flag Flag `datastore:"flag" type:"bool"` // FlagList []BoolCriteria `datastore:"flagList" type:"bool"` // TODO no support } + +type Flag bool diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 7c7eb7b..4de0b58 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -82,7 +82,7 @@ func TestDatastoreListTask(t *testing.T) { Count: int(i), Count64: 0, Proportion: 0.12345 + float64(i), - Flag: task.BoolCriteriaTrue, + Flag: task.Flag(true), NameList: []string{"a", "b", "c"}, //FlagList: []task.BoolCriteria{task.BoolCriteriaTrue, task.BoolCriteriaFalse, task.BoolCriteriaFalse}, // TODO 独自型の対応 } From cfd306c1651866dae4106cc8057da31115655e22 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Tue, 12 May 2020 13:38:26 +0900 Subject: [PATCH 66/77] chore: final adjustment --- emulator_test.go | 2 + generator.go | 69 ++++++++++++++++++-------------- main.go | 56 +++++--------------------- misc.go | 73 +++++++++++++--------------------- testfiles/a/task.go | 4 +- testfiles/a/tests/task_test.go | 22 ++-------- 6 files changed, 82 insertions(+), 144 deletions(-) diff --git a/emulator_test.go b/emulator_test.go index 0305b02..0595397 100644 --- a/emulator_test.go +++ b/emulator_test.go @@ -3,6 +3,7 @@ package main import ( + "fmt" "os" "os/exec" "path/filepath" @@ -31,6 +32,7 @@ func TestGenerator(t *testing.T) { t.Fatalf("chdir failed: %+v", err) } + fmt.Print("Failure pattern -> ") if err := run("Task"); err != nil { t.Fatalf("failed to generate for testfiles/a: %+v", err) } diff --git a/generator.go b/generator.go index 8862fe6..7599805 100644 --- a/generator.go +++ b/generator.go @@ -5,6 +5,8 @@ import ( "log" "strings" "text/template" + + "github.com/iancoleman/strcase" ) type IndexesInfo struct { @@ -50,7 +52,7 @@ type generator struct { func (g *generator) setting() { g.RepositoryInterfaceName = g.StructName + "Repository" - g.setRepositoryStructName() + g.RepositoryStructName = strcase.ToLowerCamel(g.RepositoryInterfaceName) g.buildConditions() } @@ -63,16 +65,6 @@ func (g *generator) buildConditions() { } } -func (g *generator) setRepositoryStructName() { - name := g.RepositoryInterfaceName - prefix := name[:1] - r := []rune(prefix)[0] - if 65 <= r && r <= 90 { - prefix = string(r + 32) - } - g.RepositoryStructName = prefix + name[1:] -} - func (g *generator) generate(writer io.Writer) { g.setting() funcMap := template.FuncMap{ @@ -132,7 +124,10 @@ func (g *generator) generateConstant(writer io.Writer) { const tmplConst = `// THIS FILE IS A GENERATED CODE. DO NOT EDIT package {{ .PackageName }} -import "strconv" +import ( + "log" + "strconv" +) type BoolCriteria string @@ -146,13 +141,28 @@ func (src BoolCriteria) Bool() bool { return src == BoolCriteriaTrue } -type IntegerCriteria string +type NumericCriteria string const ( - IntegerCriteriaEmpty IntegerCriteria = "" + NumericCriteriaEmpty NumericCriteria = "" + NumericCriteriaBase NumericCriteria = "0" ) -func (str IntegerCriteria) Int() int { +func (str NumericCriteria) Parse(i interface{}) NumericCriteria { + switch x := i.(type) { + case int: + return NumericCriteria(strconv.Itoa(x)) + case int64: + return NumericCriteria(strconv.FormatInt(x, 10)) + case float64: + return NumericCriteria(strconv.FormatFloat(x, 'f', -1, 64)) + default: + log.Println("invalid NumericCriteria value") + } + return NumericCriteriaEmpty +} + +func (str NumericCriteria) Int() int { i32, err := strconv.Atoi(string(str)) if err != nil { return -1 @@ -160,7 +170,7 @@ func (str IntegerCriteria) Int() int { return i32 } -func (str IntegerCriteria) Int64() int64 { +func (str NumericCriteria) Int64() int64 { i64, err := strconv.ParseInt(string(str), 10, 64) if err != nil { return -1 @@ -168,7 +178,7 @@ func (str IntegerCriteria) Int64() int64 { return i64 } -func (str IntegerCriteria) Float64() float64 { +func (str NumericCriteria) Float64() float64 { f64, err := strconv.ParseFloat(string(str), 64) if err != nil { return -1 @@ -275,7 +285,8 @@ func (repo *{{ .RepositoryStructName }}) getKeys(subjects ...*{{ .StructName }}) return keys, nil } -{{ if eq .EnableIndexes true }} + +{{- if eq .EnableIndexes true }} // saveIndexes 拡張フィルタを保存する func (repo *{{ .RepositoryStructName }}) saveIndexes(subjects ...*{{ .StructName }}) error { for _, subject := range subjects { @@ -321,13 +332,13 @@ var {{ .StructName }}IndexesConfig = &xian.Config{ {{- end }} // {{ .StructName }}ListReq List取得時に渡すリクエスト -// └─ bool/int(64)|float64 は stringで渡す(BoolCriteria | IntegerCriteria) +// └─ bool/int(64)|float64 は stringの独自型で渡す(BoolCriteria | NumericCriteria) type {{ .StructName }}ListReq struct { {{- range .FieldInfos }} {{- if eq .FieldType "bool" }} {{ .Field }} BoolCriteria {{- else if or (eq .FieldType "int") (eq .FieldType "int64") (eq .FieldType "float64" ) }} - {{ .Field }} IntegerCriteria + {{ .Field }} NumericCriteria {{- else }} {{ .Field }} {{ .FieldType }} {{- end }} @@ -347,7 +358,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru filters := xian.NewFilters({{ .StructName }}IndexesConfig) {{- end }} {{- range $fi := .FieldInfos }} -{{ $PrefixIsSlice := HasPrefixSlice $fi.FieldType}} +{{- $PrefixIsSlice := HasPrefixSlice $fi.FieldType}} {{- if eq $fi.FieldType "bool" }} if req.{{ $fi.Field }} != "" { {{- if eq $Enable true }} @@ -369,7 +380,7 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru {{- end }} } {{- else if or (eq $fi.FieldType "int") (eq $fi.FieldType "int64") (eq $fi.FieldType "float64" ) }} - if req.{{ $fi.Field }} != IntegerCriteriaEmpty { + if req.{{ $fi.Field }} != NumericCriteriaEmpty { {{- if eq $Enable true }} {{- range $idx := $fi.Indexes }} filters.{{ $idx.Method }}({{ $idx.ConstName }}, req.{{ $fi.Field }}.{{ Parse $fi.FieldType }}()) @@ -423,11 +434,11 @@ func (repo *{{ .RepositoryStructName }}) List(ctx context.Context, req *{{ .Stru if k != nil { {{- if eq .KeyFieldType "int64" }} subjects[i].ID = k.ID -{{ else if eq .KeyFieldType "string" }} +{{- else if eq .KeyFieldType "string" }} subjects[i].ID = k.Name -{{ else }} +{{- else }} subjects[i].ID = k -{{ end }} +{{- end }} } } @@ -448,7 +459,7 @@ func (repo *{{ .RepositoryStructName }}) Get(ctx context.Context, {{ .KeyValueNa if err != nil { return nil, err } -{{if eq .KeyFieldType "int64" }} +{{ if eq .KeyFieldType "int64" }} subject.{{ .KeyFieldName }} = key.ID {{ else if eq .KeyFieldType "string" }} subject.{{ .KeyFieldName }} = key.Name @@ -480,11 +491,11 @@ func (repo *{{ .RepositoryStructName }}) Insert(ctx context.Context, subject *{{ if err != nil { return zero, err } -{{if eq .KeyFieldType "int64" }} +{{ if eq .KeyFieldType "int64" }} return key.ID, nil -{{ else if eq .KeyFieldType "string" }} +{{- else if eq .KeyFieldType "string" }} return key.Name, nil -{{ else }} +{{- else }} return key, nil {{- end }} } diff --git a/main.go b/main.go index cea2cd5..80baaae 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,12 @@ import ( "golang.org/x/xerrors" ) +func init() { + for _, x := range supportType { + supportType = append(supportType, "[]"+x) + } +} + func main() { l := len(os.Args) if l < 2 { @@ -101,15 +107,12 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err pos := fs.Position(field.Pos()).String() - typeError := func(typeName string) { + typeName := getTypeName(field.Type) + if !cont.Contains(supportType, typeName) { log.Printf( - "%s: the type of `%s` is an invalid type in struct `%s` [%s]", + "%s: the type of `%s` is an invalid type in struct `%s` [%s]\n", pos, name, gen.StructName, typeName, ) - } - - typeName, continued := getTypeNameAndCheck(field, typeError) - if continued { continue } @@ -290,47 +293,6 @@ func appendIndexesInfo(fieldInfo *FieldInfo, dupMap map[string]int) { fieldInfo.Indexes = append(fieldInfo.Indexes, idx) } -func getTypeNameAndCheck(field *ast.Field, f func(string)) (string, bool) { - typeName := getTypeName(field.Type) - if typeName == "*datastore.Key" { - return typeName, false - } - if !cont.Contains(supportType, typeName) { - s := typeName - var p string - if strings.HasPrefix(typeName, "[]") { - p = "[]" - s = typeName[2:] - } - if cont.Contains(supportType, s) { - typeName = p + s - } else { - if cont.Contains(builtInType, s) || field.Tag == nil { - f(typeName) - return "", true - } - tags, err := structtag.Parse(strings.Trim(field.Tag.Value, "`")) - if err != nil { - f(typeName) - return "", true - } - tag, err := tags.Get("type") - if err != nil { - f(typeName) - return "", true - } - val := tag.Value() - if cont.Contains(supportType, val) { - typeName = p + val - } else { - f(typeName) - return "", true - } - } - } - return typeName, false -} - func dataStoreTagCheck(pos string, tags *structtag.Tags) (string, error) { if dsTag, err := tags.Get("datastore"); err == nil { tag := strings.Split(dsTag.Value(), ",")[0] diff --git a/misc.go b/misc.go index c0cebc9..3a927cf 100644 --- a/misc.go +++ b/misc.go @@ -5,6 +5,33 @@ import ( "regexp" ) +const ( + biunigrams = "Biunigrams" + prefix = "Prefix" + queryLabel = "QueryLabel" + typeString = "string" + typeInt = "int" + typeInt64 = "int64" + typeFloat64 = "float64" + typeBool = "bool" + typeTime = "time.Time" + datastoreKey = "*datastore.Key" +) + +var ( + fieldLabel string + valueCheck = regexp.MustCompile("^[0-9a-zA-Z_]+$") + supportType = []string{ + typeBool, + typeString, + typeInt, + typeInt64, + typeFloat64, + typeTime, + datastoreKey, + } +) + func getTypeName(typ ast.Expr) string { switch v := typ.(type) { case *ast.SelectorExpr: @@ -23,49 +50,3 @@ func getTypeName(typ ast.Expr) string { return "" } } - -const ( - biunigrams = "Biunigrams" - prefix = "Prefix" - queryLabel = "QueryLabel" - typeString = "string" - typeInt = "int" - typeInt64 = "int64" - typeFloat64 = "float64" - typeBool = "bool" - typeTime = "time.Time" -) - -var ( - fieldLabel string - valueCheck = regexp.MustCompile("^[0-9a-zA-Z_]+$") - builtInType = []string{ - "uint8", - "uint16", - "uint32", - "uint64", - "int8", - "int16", - "int32", - "float32", - "complex64", - "complex128", - "uint", - "uintptr", - "byte", - "rune", - typeBool, - typeString, - typeInt, - typeInt64, - typeFloat64, - } - supportType = []string{ - typeBool, - typeString, - typeInt, - typeInt64, - typeFloat64, - typeTime, - } -) diff --git a/testfiles/a/task.go b/testfiles/a/task.go index d037e0e..ad77c33 100644 --- a/testfiles/a/task.go +++ b/testfiles/a/task.go @@ -18,9 +18,7 @@ type Task struct { Count64 int64 `datastore:"count64"` NameList []string `datastore:"nameList"` Proportion float64 `datastore:"proportion"` - // If you want to use your unique type, set the original type to `type` - Flag Flag `datastore:"flag" type:"bool"` - // FlagList []BoolCriteria `datastore:"flagList" type:"bool"` // TODO no support + Flag Flag `datastore:"flag"` // NG } type Flag bool diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 4de0b58..41c73fe 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -95,7 +95,7 @@ func TestDatastoreListTask(t *testing.T) { t.Run("int(1件)", func(t *testing.T) { req := &task.TaskListReq{ - Count: task.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい + Count: task.NumericCriteriaBase.Parse(1), } tasks, err := taskRepo.List(ctx, req, nil) @@ -110,7 +110,7 @@ func TestDatastoreListTask(t *testing.T) { t.Run("float(1件)", func(t *testing.T) { req := &task.TaskListReq{ - Proportion: task.IntegerCriteria("1.12345"), // FIXME 2 この実装をどうにかしたい + Proportion: task.NumericCriteriaBase.Parse(1.12345), } tasks, err := taskRepo.List(ctx, req, nil) @@ -167,22 +167,6 @@ func TestDatastoreListTask(t *testing.T) { t.Fatal("not match") } }) - - // TODO 現状、独自型のスライスを許容できない - /* t.Run("[]task.BoolCriteria(10件)", func(t *testing.T) { - req := &task.TaskListReq{ - FlagList: []task.BoolCriteria{task.BoolCriteriaTrue}, - } - - tasks, err := taskRepo.List(ctx, req, nil) - if err != nil { - t.Fatalf("%+v", err) - } - - if len(tasks) != 10 { - t.Fatal("not match") - } - }) */ } func TestDatastoreListNameWithIndexes(t *testing.T) { @@ -223,7 +207,7 @@ func TestDatastoreListNameWithIndexes(t *testing.T) { t.Run("int(1件)", func(t *testing.T) { req := &task.NameListReq{ - Count: task.IntegerCriteria("1"), // FIXME 2 この実装をどうにかしたい + Count: task.NumericCriteriaBase.Parse(1), } tasks, err := nameRepo.List(ctx, req, nil) From f61e3cf51d27d63359bf8447cfd31a2616d64dfa Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Tue, 12 May 2020 19:16:50 +0900 Subject: [PATCH 67/77] chore: divided processing --- main.go | 140 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 76 insertions(+), 64 deletions(-) diff --git a/main.go b/main.go index 80baaae..49d5049 100644 --- a/main.go +++ b/main.go @@ -161,75 +161,15 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err FieldType: typeName, Indexes: make([]*IndexesInfo, 0), } - if tag, err := dataStoreTagCheck(pos, tags); err != nil { - return xerrors.Errorf("error in tagCheck method: %w", err) - } else if tag != "" { - fieldInfo.DsTag = tag + if fieldInfo, err = appendIndexer(pos, tags, fieldInfo, dupMap); err != nil { + return xerrors.Errorf("error in appendIndexer: %w", err) } - if idr, err := tags.Get("indexer"); err != nil || fieldInfo.FieldType != typeString { - appendIndexesInfo(fieldInfo, dupMap) - } else { - filters := strings.Split(idr.Value(), ",") - dupIdr := make(map[string]struct{}) - for _, fil := range filters { - idx := &IndexesInfo{ - ConstName: fieldLabel + name, - Label: uppercaseExtraction(fieldInfo.Field, dupMap), - Method: "Add", - } - var dupFlag string - switch fil { - case "p", "prefix": // 前方一致 (AddPrefix) - idx.Method += prefix - idx.ConstName += prefix - idx.Comment = fmt.Sprintf("%s %s前方一致", idx.ConstName, name) - dupFlag = "p" - case "s", "suffix": /* TODO 後方一致 - idx.Method += Suffix - idx.ConstName += Suffix - idx.Comment = fmt.Sprintf("%s %s後方一致", idx.ConstName, name) - dup = "s"*/ - case "e", "equal": // 完全一致 (Add) Default - idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, name) - dupIdr["equal"] = struct{}{} - dupFlag = "e" - case "l", "like": // 部分一致 - idx.Method += biunigrams - idx.ConstName += "Like" - idx.Comment = fmt.Sprintf("%s %s部分一致", idx.ConstName, name) - dupFlag = "l" - default: - continue - } - if _, ok := dupIdr[dupFlag]; ok { - continue - } - dupIdr[dupFlag] = struct{}{} - fieldInfo.Indexes = append(fieldInfo.Indexes, idx) - } - } - gen.FieldInfos = append(gen.FieldInfos, fieldInfo) continue } - - dsTag, err := tags.Get("datastore") - - // datastore タグが存在しないか-になっていない - if err != nil || strings.Split(dsTag.Value(), ",")[0] != "-" { - return xerrors.Errorf("%s: key field for datastore should have datastore:\"-\" tag", pos) - } - - gen.KeyFieldName = name - gen.KeyFieldType = typeName - - if gen.KeyFieldType != typeInt64 && - gen.KeyFieldType != typeString && - !strings.HasSuffix(gen.KeyFieldType, ".Key") { - return xerrors.Errorf("%s: supported key types are int64, string, *datastore.Key", pos) + if err := keyFieldHandler(gen, tags, name, typeName, pos); err != nil { + return xerrors.Errorf("error in keyFieldHandler: %w", err) } - - gen.KeyValueName = strcase.ToLowerCamel(name) } } @@ -265,6 +205,78 @@ func generate(gen *generator, fs *token.FileSet, structType *ast.StructType) err return nil } +func keyFieldHandler(gen *generator, tags *structtag.Tags, name, typeName, pos string) error { + dsTag, err := tags.Get("datastore") + + // datastore タグが存在しないか-になっていない + if err != nil || strings.Split(dsTag.Value(), ",")[0] != "-" { + return xerrors.Errorf("%s: key field for datastore should have datastore:\"-\" tag", pos) + } + + gen.KeyFieldName = name + gen.KeyFieldType = typeName + + if gen.KeyFieldType != typeInt64 && + gen.KeyFieldType != typeString && + !strings.HasSuffix(gen.KeyFieldType, ".Key") { + return xerrors.Errorf("%s: supported key types are int64, string, *datastore.Key", pos) + } + + gen.KeyValueName = strcase.ToLowerCamel(name) + return nil +} + +func appendIndexer(pos string, tags *structtag.Tags, fieldInfo *FieldInfo, dupMap map[string]int) (*FieldInfo, error) { + if tag, err := dataStoreTagCheck(pos, tags); err != nil { + return nil, xerrors.Errorf("error in tagCheck method: %w", err) + } else if tag != "" { + fieldInfo.DsTag = tag + } + if idr, err := tags.Get("indexer"); err != nil || fieldInfo.FieldType != typeString { + appendIndexesInfo(fieldInfo, dupMap) + } else { + filters := strings.Split(idr.Value(), ",") + dupIdr := make(map[string]struct{}) + for _, fil := range filters { + idx := &IndexesInfo{ + ConstName: fieldLabel + fieldInfo.Field, + Label: uppercaseExtraction(fieldInfo.Field, dupMap), + Method: "Add", + } + var dupFlag string + switch fil { + case "p", "prefix": // 前方一致 (AddPrefix) + idx.Method += prefix + idx.ConstName += prefix + idx.Comment = fmt.Sprintf("%s %s前方一致", idx.ConstName, fieldInfo.Field) + dupFlag = "p" + case "s", "suffix": /* TODO 後方一致 + idx.Method += Suffix + idx.ConstName += Suffix + idx.Comment = fmt.Sprintf("%s %s後方一致", idx.ConstName, name) + dup = "s"*/ + case "e", "equal": // 完全一致 (Add) Default + idx.Comment = fmt.Sprintf("%s %s", idx.ConstName, fieldInfo.Field) + dupIdr["equal"] = struct{}{} + dupFlag = "e" + case "l", "like": // 部分一致 + idx.Method += biunigrams + idx.ConstName += "Like" + idx.Comment = fmt.Sprintf("%s %s部分一致", idx.ConstName, fieldInfo.Field) + dupFlag = "l" + default: + continue + } + if _, ok := dupIdr[dupFlag]; ok { + continue + } + dupIdr[dupFlag] = struct{}{} + fieldInfo.Indexes = append(fieldInfo.Indexes, idx) + } + } + return fieldInfo, nil +} + func uppercaseExtraction(name string, dupMap map[string]int) (lower string) { for _, x := range name { if 65 <= x && x <= 90 { From d01f8870e4c5f18b3044e969f1575da9017b77b7 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Tue, 12 May 2020 19:23:25 +0900 Subject: [PATCH 68/77] chore: fixed the pointed out --- emulator_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/emulator_test.go b/emulator_test.go index 0595397..c07306e 100644 --- a/emulator_test.go +++ b/emulator_test.go @@ -32,6 +32,8 @@ func TestGenerator(t *testing.T) { t.Fatalf("chdir failed: %+v", err) } + // t.Logだと通常テスト時に出力されない & verboseモードでもt.Logだと改行されてしまう + // 以上により `fmt.Print` を採用 fmt.Print("Failure pattern -> ") if err := run("Task"); err != nil { t.Fatalf("failed to generate for testfiles/a: %+v", err) From 206a2a1bd07bc349bb07cfa69bd952322ceb6101 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Wed, 13 May 2020 13:39:10 +0900 Subject: [PATCH 69/77] clean: delete unnecessary comments --- testfiles/a/tests/task_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index 41c73fe..d23d3bd 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -84,7 +84,6 @@ func TestDatastoreListTask(t *testing.T) { Proportion: 0.12345 + float64(i), Flag: task.Flag(true), NameList: []string{"a", "b", "c"}, - //FlagList: []task.BoolCriteria{task.BoolCriteriaTrue, task.BoolCriteriaFalse, task.BoolCriteriaFalse}, // TODO 独自型の対応 } tks = append(tks, tk) } From 209a7ce6996f4de6b2d9b7f6618cfde536e2d380 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Wed, 13 May 2020 19:23:15 +0900 Subject: [PATCH 70/77] clean: change name (t -> tr) --- emulator_test.go | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/emulator_test.go b/emulator_test.go index c07306e..c98906c 100644 --- a/emulator_test.go +++ b/emulator_test.go @@ -27,47 +27,47 @@ func TestGenerator(t *testing.T) { t.Fatalf("failed to getwd: %+v", err) } - t.Run("int64", func(t *testing.T) { + t.Run("int64", func(tr *testing.T) { if err := os.Chdir(filepath.Join(root, "testfiles/a")); err != nil { - t.Fatalf("chdir failed: %+v", err) + tr.Fatalf("chdir failed: %+v", err) } // t.Logだと通常テスト時に出力されない & verboseモードでもt.Logだと改行されてしまう // 以上により `fmt.Print` を採用 fmt.Print("Failure pattern -> ") if err := run("Task"); err != nil { - t.Fatalf("failed to generate for testfiles/a: %+v", err) + tr.Fatalf("failed to generate for testfiles/a: %+v", err) } if err := run("Name"); err != nil { - t.Fatalf("failed to generate for testfiles/a: %+v", err) + tr.Fatalf("failed to generate for testfiles/a: %+v", err) } - execTest(t) + execTest(tr) }) - t.Run("string", func(t *testing.T) { + t.Run("string", func(tr *testing.T) { if err := os.Chdir(filepath.Join(root, "testfiles/b")); err != nil { - t.Fatalf("chdir failed: %+v", err) + tr.Fatalf("chdir failed: %+v", err) } if err := run("Task"); err != nil { - t.Fatalf("failed to generate for testfiles/b: %+v", err) + tr.Fatalf("failed to generate for testfiles/b: %+v", err) } - execTest(t) + execTest(tr) }) - t.Run("datastore.Key", func(t *testing.T) { + t.Run("datastore.Key", func(tr *testing.T) { if err := os.Chdir(filepath.Join(root, "testfiles/c")); err != nil { - t.Fatalf("chdir failed: %+v", err) + tr.Fatalf("chdir failed: %+v", err) } if err := run("Task"); err != nil { - t.Fatalf("failed to generate for testfiles/c: %+v", err) + tr.Fatalf("failed to generate for testfiles/c: %+v", err) } - execTest(t) + execTest(tr) }) } From b63a5032fe9bcdeccb6369eac4810fa618422ea3 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Wed, 13 May 2020 19:23:53 +0900 Subject: [PATCH 71/77] feat: supports parallelization --- emulator_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/emulator_test.go b/emulator_test.go index c98906c..d988051 100644 --- a/emulator_test.go +++ b/emulator_test.go @@ -47,6 +47,7 @@ func TestGenerator(t *testing.T) { }) t.Run("string", func(tr *testing.T) { + tr.Parallel() if err := os.Chdir(filepath.Join(root, "testfiles/b")); err != nil { tr.Fatalf("chdir failed: %+v", err) } @@ -59,6 +60,7 @@ func TestGenerator(t *testing.T) { }) t.Run("datastore.Key", func(tr *testing.T) { + tr.Parallel() if err := os.Chdir(filepath.Join(root, "testfiles/c")); err != nil { tr.Fatalf("chdir failed: %+v", err) } From 08695be14ef006e3d1fdcf322b91dc351a5e59fb Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Wed, 13 May 2020 19:27:41 +0900 Subject: [PATCH 72/77] fix: abolished incomplete key --- generator.go | 11 +++++++---- go.mod | 1 + testfiles/c/tests/task_test.go | 5 ++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/generator.go b/generator.go index 7599805..7980648 100644 --- a/generator.go +++ b/generator.go @@ -211,11 +211,14 @@ import ( {{- end }} "cloud.google.com/go/datastore" -{{- if eq .EnableIndexes true }} - "github.com/knightso/xian" -{{- end }} {{- if and (eq .SliceExist true) (eq .EnableIndexes false) }} "github.com/go-utils/dedupe" +{{- end }} +{{- if eq .KeyFieldType "*datastore.Key" }} + "github.com/google/uuid" +{{- end }} +{{- if eq .EnableIndexes true }} + "github.com/knightso/xian" {{- end }} "golang.org/x/xerrors" ) @@ -277,7 +280,7 @@ func (repo *{{ .RepositoryStructName }}) getKeys(subjects ...*{{ .StructName }}) keys = append(keys, datastore.NameKey(repo.kind, key, nil)) {{- else }} if key == nil { - key = datastore.IncompleteKey(repo.kind, nil) + key = datastore.NameKey(repo.kind, uuid.New().String(), nil) } keys = append(keys, key) {{- end }} diff --git a/go.mod b/go.mod index e6d10bf..0bc412a 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( github.com/go-utils/dedupe v0.1.1 github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.4.1 // indirect + github.com/google/uuid v1.1.1 github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 github.com/knightso/xian v0.1.0 github.com/pkg/errors v0.9.1 // indirect diff --git a/testfiles/c/tests/task_test.go b/testfiles/c/tests/task_test.go index b29b8e6..46d82db 100644 --- a/testfiles/c/tests/task_test.go +++ b/testfiles/c/tests/task_test.go @@ -10,6 +10,7 @@ import ( "cloud.google.com/go/datastore" task "github.com/go-generalize/repo_generator/testfiles/c" + "github.com/google/uuid" ) func initDatastoreClient(t *testing.T) *datastore.Client { @@ -64,10 +65,8 @@ func TestDatastore(t *testing.T) { now := time.Unix(time.Now().Unix(), 0) desc := "hello" - incmplKey := datastore.IncompleteKey("Task", nil) - id, err := taskRepo.Insert(ctx, &task.Task{ - ID: incmplKey, + ID: datastore.NameKey("Task", uuid.New().String(), nil), Desc: desc, Created: now, Done: true, From 27b8135455face67d6026f7c5287f9245917eb15 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Wed, 13 May 2020 19:29:37 +0900 Subject: [PATCH 73/77] clean: rename return value (vessels -> subjects) --- generator.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/generator.go b/generator.go index 7980648..c484f77 100644 --- a/generator.go +++ b/generator.go @@ -548,7 +548,7 @@ func (repo *{{ .RepositoryStructName }}) DeleteBy{{ .KeyFieldName }}(ctx context } // GetMulti 処理中の {{ .StructName }} の一括取得処理一切の責任を持ち、これを行う -func (repo *{{ .RepositoryStructName }}) GetMulti(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) ([]*{{ .StructName }}, error) { +func (repo *{{ .RepositoryStructName }}) GetMulti(ctx context.Context, {{ .KeyValueName }}s []{{ .KeyFieldType }}) (subjects []*{{ .StructName }}, err error) { {{- if eq .KeyFieldType "int64" }} keys := make([]*datastore.Key, 0, len({{ .KeyValueName }}s)) @@ -564,22 +564,22 @@ func (repo *{{ .RepositoryStructName }}) GetMulti(ctx context.Context, {{ .KeyVa {{ else }} keys := {{ .KeyValueName }}s {{ end }} - vessels := make([]*{{ .StructName }}, len({{ .KeyValueName }}s)) - err := repo.datastoreClient.GetMulti(ctx, keys, vessels) + subjects = make([]*{{ .StructName }}, len({{ .KeyValueName }}s)) + err = repo.datastoreClient.GetMulti(ctx, keys, subjects) - for i := range vessels { - if vessels[i] != nil { + for i := range subjects { + if subjects[i] != nil { {{- if eq .KeyFieldType "int64" }} - vessels[i].{{ .KeyFieldName }} = keys[i].ID + subjects[i].{{ .KeyFieldName }} = keys[i].ID {{- else if eq .KeyFieldType "string" }} - vessels[i].{{ .KeyFieldName }} = keys[i].Name + subjects[i].{{ .KeyFieldName }} = keys[i].Name {{- else }} - vessels[i].{{ .KeyFieldName }} = keys[i] + subjects[i].{{ .KeyFieldName }} = keys[i] {{- end }} } } - return vessels, err + return } // InsertMulti 処理中の {{ .StructName }} の一括挿入処理一切の責任を持ち、これを行う From c781134971ea9d86c5af76b41ad72607279655e4 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Wed, 13 May 2020 19:31:13 +0900 Subject: [PATCH 74/77] feat: supports transactions #11 --- generator.go | 159 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 61 deletions(-) diff --git a/generator.go b/generator.go index c484f77..a799a60 100644 --- a/generator.go +++ b/generator.go @@ -485,44 +485,66 @@ func (repo *{{ .RepositoryStructName }}) Insert(ctx context.Context, subject *{{ if err != nil { return zero, xerrors.Errorf("error in getKeys method: %w", err) } -{{ if eq .EnableIndexes true }} - if err := repo.saveIndexes(subject); err != nil { - return zero, xerrors.Errorf("error in saveIndexes method: %w", err) - } -{{ end }} - key, err := repo.datastoreClient.Put(ctx, keys[0], subject) + + _, err = repo.datastoreClient.RunInTransaction(ctx, func(tx *datastore.Transaction) error { + if err := tx.Get(keys[0], nil); err != datastore.ErrNoSuchEntity { + return xerrors.Errorf("error in datastore.Transaction.Get method: %w", err) + } + +{{- if eq .EnableIndexes true }} + if err := repo.saveIndexes(subject); err != nil { + return xerrors.Errorf("error in saveIndexes method: %w", err) + } +{{- end }} + + _, err := tx.Put(keys[0], subject) + if err != nil { + return err + } + + return nil + }) if err != nil { - return zero, err + return zero, xerrors.Errorf("error in datastore.Client.RunInTransaction method: %w", err) } {{ if eq .KeyFieldType "int64" }} - return key.ID, nil + return keys[0].ID, nil {{- else if eq .KeyFieldType "string" }} - return key.Name, nil + return keys[0].Name, nil {{- else }} - return key, nil + return keys[0], nil {{- end }} } // Update 処理中の {{ .StructName }} の更新処理一切の責任を持ち、これを行う -func (repo *{{ .RepositoryStructName }}) Update(ctx context.Context, subject *{{ .StructName }}) error { - if _, err := repo.Get(ctx, subject.{{ .KeyFieldName }}); err == datastore.ErrNoSuchEntity { - return err - } +func (repo *{{ .RepositoryStructName }}) Update(ctx context.Context, subject *{{ .StructName }}) (err error) { + _, err = repo.datastoreClient.RunInTransaction(ctx, func(tx *datastore.Transaction) error { + keys, err := repo.getKeys(subject) + if err != nil { + return xerrors.Errorf("error in getKeys method: %w", err) + } - keys, err := repo.getKeys(subject) + if err := tx.Get(keys[0], nil); err == datastore.ErrNoSuchEntity { + return xerrors.Errorf("error in datastore.Transaction.Get method: %w", err) + } + +{{- if eq .EnableIndexes true }} + if err := repo.saveIndexes(subject); err != nil { + return xerrors.Errorf("error in saveIndexes method: %w", err) + } +{{- end }} + + if _, err := tx.Put(keys[0], subject); err != nil { + return err + } + + return nil + }) if err != nil { - return xerrors.Errorf("error in getKeys method: %w", err) - } -{{ if eq .EnableIndexes true }} - if err := repo.saveIndexes(subject); err != nil { - return xerrors.Errorf("error in saveIndexes method: %w", err) - } -{{ end }} - if _, err := repo.datastoreClient.Put(ctx, keys[0], subject); err != nil { - return err + err = xerrors.Errorf("error in datastore.Client.RunInTransaction method: %w", err) } - return nil + return } // Delete 処理中の {{ .StructName }} の削除処理一切の責任を持ち、これを行う @@ -583,50 +605,58 @@ func (repo *{{ .RepositoryStructName }}) GetMulti(ctx context.Context, {{ .KeyVa } // InsertMulti 処理中の {{ .StructName }} の一括挿入処理一切の責任を持ち、これを行う -func (repo *{{ .RepositoryStructName }}) InsertMulti(ctx context.Context, subjects []*{{ .StructName }}) ([]{{ .KeyFieldType }}, error) { +func (repo *{{ .RepositoryStructName }}) InsertMulti(ctx context.Context, subjects []*{{ .StructName }}) ({{ .KeyValueName }}s []{{ .KeyFieldType }}, err error) { keys, err := repo.getKeys(subjects...) if err != nil { return nil, xerrors.Errorf("error in getKeys method: %w", err) } - var cnt int - if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{ .StructName }}, len(subjects))); err != nil { - if errs, ok := err.(datastore.MultiError); ok { - for _, err := range errs { - if err == datastore.ErrNoSuchEntity { - cnt++ + _, err = repo.datastoreClient.RunInTransaction(ctx, func(tx *datastore.Transaction) error { + var cnt int + if err := tx.GetMulti(keys, make([]*{{ .StructName }}, len(subjects))); err != nil { + if errs, ok := err.(datastore.MultiError); ok { + for _, err := range errs { + if err == datastore.ErrNoSuchEntity { + cnt++ + } else { + return xerrors.Errorf("error in datastore.Client.GetMulti method: %w", err) + } } } } - } - - if len(subjects) != cnt { - return nil, xerrors.Errorf("already exist. (%d)", len(subjects)-cnt) - } + if len(subjects) != cnt { + return xerrors.Errorf("already exist. (%d)", len(subjects)-cnt) + } {{ if eq .EnableIndexes true }} - if err := repo.saveIndexes(subjects...); err != nil { - return nil, xerrors.Errorf("error in saveIndexes method: %w", err) - } -{{ end }} - resKeys, err := repo.datastoreClient.PutMulti(ctx, keys, subjects) - if err != nil { - return nil, err - } + if err := repo.saveIndexes(subjects...); err != nil { + return xerrors.Errorf("error in saveIndexes method: %w", err) + } +{{- end }} + _, err := tx.PutMulti(keys, subjects) + if err != nil { + return err + } - vessels := make([]{{ .KeyFieldType }}, len(resKeys)) - for i := range resKeys { - if keys[i] != nil { + {{ .KeyValueName }}s = make([]{{ .KeyFieldType }}, len(keys)) + for i := range keys { + if keys[i] != nil { {{- if eq .KeyFieldType "int64" }} - vessels[i] = resKeys[i].ID + {{ .KeyValueName }}s[i] = keys[i].ID {{- else if eq .KeyFieldType "string" }} - vessels[i] = resKeys[i].Name + {{ .KeyValueName }}s[i] = keys[i].Name {{- else }} - vessels[i] = resKeys[i] + {{ .KeyValueName }}s[i] = keys[i] {{- end }} + } } + + return nil + }) + if err != nil { + return nil, xerrors.Errorf("error in datastore.Client.RunInTransaction method: %w", err) } - return vessels, err + return } // UpdateMulti 処理中の {{ .StructName }} の一括更新処理一切の責任を持ち、これを行う @@ -636,19 +666,26 @@ func (repo *{{ .RepositoryStructName }}) UpdateMulti(ctx context.Context, subjec return xerrors.Errorf("error in getKeys method: %w", err) } - if err := repo.datastoreClient.GetMulti(ctx, keys, make([]*{{ .StructName }}, len(subjects))); err != nil { - if _, ok := err.(datastore.MultiError); ok { - return err + _, err = repo.datastoreClient.RunInTransaction(ctx, func(tx *datastore.Transaction) error { + if err := tx.GetMulti(keys, make([]*{{ .StructName }}, len(subjects))); err != nil { + if _, ok := err.(datastore.MultiError); ok { + return err + } } - } {{ if eq .EnableIndexes true }} - if err := repo.saveIndexes(subjects...); err != nil { - return xerrors.Errorf("error in saveIndexes method: %w", err) - } + if err := repo.saveIndexes(subjects...); err != nil { + return xerrors.Errorf("error in saveIndexes method: %w", err) + } {{ end }} - _, err = repo.datastoreClient.PutMulti(ctx, keys, subjects) + _, err = tx.PutMulti(keys, subjects) + if err != nil { + return err + } + + return nil + }) if err != nil { - return err + return xerrors.Errorf("error in datastore.Client.RunInTransaction method: %w", err) } return nil From 28314e12c4036e551124158823beeebb28a29286 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Wed, 13 May 2020 19:32:08 +0900 Subject: [PATCH 75/77] feat: added test for transaction support #11 --- testfiles/a/tests/task_test.go | 99 ++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/testfiles/a/tests/task_test.go b/testfiles/a/tests/task_test.go index d23d3bd..c8cce82 100644 --- a/testfiles/a/tests/task_test.go +++ b/testfiles/a/tests/task_test.go @@ -54,6 +54,105 @@ func compareTask(t *testing.T, expected, actual *task.Task) { } } +func TestDatastoreTransactionTask(t *testing.T) { + client := initDatastoreClient(t) + + taskRepo := task.NewTaskRepository(client) + + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + var ids []int64 + defer func() { + defer cancel() + if err := taskRepo.DeleteMultiByIDs(ctx, ids); err != nil { + t.Fatal(err) + } + }() + + now := time.Unix(0, time.Now().UnixNano()) + desc := "Hello, World!" + + t.Run("Multi", func(tr *testing.T) { + tks := make([]*task.Task, 0) + for i := int64(1); i <= 10; i++ { + tk := &task.Task{ + ID: i * 100, + Desc: fmt.Sprintf("%s%d", desc, i), + Created: now, + Done: true, + Done2: false, + Count: int(i), + Count64: 0, + Proportion: 0.12345 + float64(i), + Flag: task.Flag(true), + NameList: []string{"a", "b", "c"}, + } + tks = append(tks, tk) + } + idList, err := taskRepo.InsertMulti(ctx, tks) + if err != nil { + tr.Fatalf("%+v", err) + } + ids = append(ids, idList...) + + tks2 := make([]*task.Task, 0) + for i := int64(1); i <= 10; i++ { + tk := &task.Task{ + ID: i * 100, + Desc: fmt.Sprintf("%s%d", desc, i), + Created: now, + Done: true, + Done2: false, + Count: int(i), + Count64: i, + Proportion: 0.12345 + float64(i), + Flag: task.Flag(true), + NameList: []string{"a", "b", "c"}, + } + tks2 = append(tks2, tk) + } + if err := taskRepo.UpdateMulti(ctx, tks2); err != nil { + tr.Fatalf("%+v", err) + } + + if tks[0].ID != tks2[0].ID { + tr.Fatalf("unexpected id: %d (expected: %d)", tks[0].ID, tks2[0].ID) + } + }) + + t.Run("Single", func(tr *testing.T) { + tk := &task.Task{ + ID: 1001, + Desc: fmt.Sprintf("%s%d", desc, 1001), + Created: now, + Done: true, + Done2: false, + Count: 11, + Count64: 11, + Proportion: 0.12345 + 11, + NameList: []string{"a", "b", "c"}, + } + id, err := taskRepo.Insert(ctx, tk) + if err != nil { + tr.Fatalf("%+v", err) + } + ids = append(ids, id) + + tk.Count = 12 + if err := taskRepo.Update(ctx, tk); err != nil { + tr.Fatalf("%+v", err) + } + + tsk, err := taskRepo.Get(ctx, tk.ID) + if err != nil { + tr.Fatalf("%+v", err) + } + + if tsk.Count != 12 { + tr.Fatalf("unexpected Count: %d (expected: %d)", tsk.Count, 12) + } + }) +} + func TestDatastoreListTask(t *testing.T) { client := initDatastoreClient(t) From e9f7931bda6024c293f0ff1a3eab6bc10bf4a008 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Wed, 13 May 2020 19:32:24 +0900 Subject: [PATCH 76/77] update: go.mod --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0bc412a..2c479f2 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( cloud.google.com/go/bigquery v1.6.0 // indirect cloud.google.com/go/datastore v1.1.0 github.com/fatih/structtag v1.2.0 - github.com/go-utils/cont v0.1.0 + github.com/go-utils/cont v0.1.1 github.com/go-utils/dedupe v0.1.1 github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.4.1 // indirect From 9a98767c392d17f50aad5e3f94e51d37885cb4c4 Mon Sep 17 00:00:00 2001 From: 54mch4n <54mch4n.1111@gmail.com> Date: Thu, 14 May 2020 12:38:12 +0900 Subject: [PATCH 77/77] fix: added go.sum --- .gitignore | 2 - go.mod | 14 +-- go.sum | 361 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 368 insertions(+), 9 deletions(-) create mode 100644 go.sum diff --git a/.gitignore b/.gitignore index 889b526..a070a73 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ .idea/ .DS_Store - -go.sum diff --git a/go.mod b/go.mod index 2c479f2..626f579 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/go-generalize/repo_generator -go 1.14 +go 1.12 require ( cloud.google.com/go v0.57.0 // indirect @@ -8,17 +8,17 @@ require ( cloud.google.com/go/datastore v1.1.0 github.com/fatih/structtag v1.2.0 github.com/go-utils/cont v0.1.1 - github.com/go-utils/dedupe v0.1.1 + github.com/go-utils/dedupe v0.1.3 github.com/golang/mock v1.4.3 github.com/golang/protobuf v1.4.1 // indirect github.com/google/uuid v1.1.1 github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 github.com/knightso/xian v0.1.0 github.com/pkg/errors v0.9.1 // indirect - golang.org/x/net v0.0.0-20200506145744-7e3656a0809f // indirect - golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f // indirect - golang.org/x/tools v0.0.0-20200507205054-480da3ebd79c + golang.org/x/net v0.0.0-20200513185701-a91f0712d120 // indirect + golang.org/x/sys v0.0.0-20200513112337-417ce2331b5c // indirect + golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 - google.golang.org/api v0.23.0 // indirect - google.golang.org/genproto v0.0.0-20200507105951-43844f6eee31 // indirect + google.golang.org/api v0.24.0 // indirect + google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 // indirect ) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..b24bf3f --- /dev/null +++ b/go.sum @@ -0,0 +1,361 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0 h1:EpMNVUorLiZIELdMZbCYX/ByTFCdoYopYAGxaGVz9ms= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.6.0 h1:ajp/DjpiCHO71SyIhwb83YsUGAyWuzVvMko+9xCsJLw= +cloud.google.com/go/bigquery v1.6.0/go.mod h1:hyFDG0qSGdHNz8Q6nDN8rYIkld0q/+5uBZaelxiDLfE= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1 h1:ukjixP1wl0LpnZ6LWtZJ0mX5tBmjp1f8Sqer8Z2OMUU= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0 h1:UDpwYIwla4jHGzZJaEJYx1tOejbgSoNqsAfHAUYe2r8= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4= +github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-utils/cont v0.1.1 h1:my04uGn+7M3e7yx6TtABznKSA/zGoAy2J2pTUxqA9hg= +github.com/go-utils/cont v0.1.1/go.mod h1:zXQ9kh3mb8Bydc0Ce+12tHwn/cb/+zL8twUeOs4E+eA= +github.com/go-utils/dedupe v0.1.3 h1:VMB9L7Xws6jk3Srxadix6EVKY292HBKE7cV8GqtX36k= +github.com/go-utils/dedupe v0.1.3/go.mod h1:djuV2+bSo4GJof/CgXcV54k5NwDkSqnevZ5ySgPp/hM= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334 h1:VHgatEHNcBFEB7inlalqfNqw65aNkM1lGX2yt3NmbS8= +github.com/iancoleman/strcase v0.0.0-20191112232945-16388991a334/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/knightso/xian v0.1.0 h1:tbSxtKEB0jMK9M4U6ftbh33LwLDASQqknR0pTodRNBQ= +github.com/knightso/xian v0.1.0/go.mod h1:awKIZpjAL+4BI/y7lanh65Qf2uz2lwQGK8mK+gW+QUo= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120 h1:EZ3cVSzKOlJxAd8e8YAJ7no8nNypTxexh/YE/xW3ZEY= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200409092240-59c9f1ba88fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200513112337-417ce2331b5c h1:kISX68E8gSkNYAFRFiDU8rl5RIn1sJYKYb/r2vMLDrU= +golang.org/x/sys v0.0.0-20200513112337-417ce2331b5c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200409170454-77362c5149f0/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97 h1:DAuln/hGp+aJiHpID1Y1hYzMEPP5WLwtZHPb50mN0OE= +golang.org/x/tools v0.0.0-20200513201620-d5fe73897c97/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.21.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0 h1:cG03eaksBzhfSIk7JRGctfp3lanklcOM/mTGvow7BbQ= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200409111301-baae70f3302d/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 h1:fiNLklpBwWK1mth30Hlwk+fcdBmIALlgF5iy77O37Ig= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=