From d5bc9cdeaa8e395f8528588d97c7ca1992de133a Mon Sep 17 00:00:00 2001 From: snowmerak Date: Thu, 20 Jul 2023 01:48:16 +0900 Subject: [PATCH] make getter and errface --- internal/executor/check/getter.go | 35 ++++++++++++ internal/executor/generate.go | 21 ++++++++ internal/executor/generate/errface.go | 76 +++++++++++++++++++++++++++ internal/executor/generate/getter.go | 76 +++++++++++++++++++++++++++ 4 files changed, 208 insertions(+) create mode 100644 internal/executor/check/getter.go create mode 100644 internal/executor/generate/errface.go create mode 100644 internal/executor/generate/getter.go diff --git a/internal/executor/check/getter.go b/internal/executor/check/getter.go new file mode 100644 index 0000000..28f4a8d --- /dev/null +++ b/internal/executor/check/getter.go @@ -0,0 +1,35 @@ +package check + +import ( + "github.com/snowmerak/jetti/v2/lib/model" + "strings" +) + +type Getter struct { + PackageName string + Imports []model.Import + StructName string + FieldName string + FieldType string +} + +func HasGetter(pkg *model.Package) ([]Getter, error) { + list := make([]Getter, 0) + + for _, s := range pkg.Structs { + if !strings.Contains(s.Doc, "jetti:getter") { + continue + } + for _, f := range s.Fields { + list = append(list, Getter{ + PackageName: pkg.Name, + Imports: pkg.Imports, + StructName: s.Name, + FieldName: f.Name, + FieldType: f.Type, + }) + } + } + + return list, nil +} diff --git a/internal/executor/generate.go b/internal/executor/generate.go index 3af1986..18bfe85 100644 --- a/internal/executor/generate.go +++ b/internal/executor/generate.go @@ -60,6 +60,8 @@ func Generate(root string) error { return nil } + errFaces := make([]check.Getter, 0) + log.Println("check:", relativePath) switch filepath.Ext(path) { case ".go": @@ -128,6 +130,19 @@ func Generate(root string) error { } log.Printf("generate optional: %s", relativePath) } + + getters, err := check.HasGetter(pkg) + if err != nil { + return err + } + + if len(getters) > 0 { + errFaces = append(errFaces, getters...) + if err := generate.Getter(path, getters); err != nil { + return err + } + log.Printf("generate getter: %s", relativePath) + } case ".json": if err := generate.ConvertJson(path); err != nil { return err @@ -161,6 +176,12 @@ func Generate(root string) error { beanUpdated = false } + if len(errFaces) > 0 { + if err := generate.ErrFace(root, errFaces); err != nil { + return err + } + } + log.Println("update:", relativePath) if err := cc.Set(relativePath, info.ModTime().Unix()); err != nil { return err diff --git a/internal/executor/generate/errface.go b/internal/executor/generate/errface.go new file mode 100644 index 0000000..efb9fe4 --- /dev/null +++ b/internal/executor/generate/errface.go @@ -0,0 +1,76 @@ +package generate + +import ( + "fmt" + "github.com/snowmerak/jetti/v2/internal/executor/check" + "github.com/snowmerak/jetti/v2/lib/generator" + "github.com/snowmerak/jetti/v2/lib/model" + "os" + "path/filepath" + "strings" +) + +func ErrFace(root string, getters []check.Getter) error { + dir := filepath.Join(root, "gen", "errface") + if err := os.MkdirAll(dir, os.ModePerm); err != nil { + return err + } + + f, err := os.Create(filepath.Join(dir, "errface.go")) + if err != nil { + return err + } + + pkg := &model.Package{ + Name: "errface", + } + + importsSet := map[string]struct{}{} + for _, getter := range getters { + for _, imp := range getter.Imports { + if _, ok := importsSet[imp.Path]; ok { + continue + } + importsSet[imp.Path] = struct{}{} + pkg.Imports = append(pkg.Imports, imp) + } + + fieldName := strings.ToUpper(getter.FieldName[:1]) + getter.FieldName[1:] + typeName := strings.TrimPrefix(getter.FieldType, "*") + typeName = strings.TrimPrefix(typeName, "[]") + typeName = strings.TrimPrefix(typeName, "...") + typeName = strings.ToUpper(typeName[:1]) + typeName[1:] + switch { + case strings.HasPrefix(getter.FieldType, "*"): + typeName = typeName + "Pointer" + case strings.HasPrefix(getter.FieldType, "[]"): + typeName = typeName + "Slice" + case strings.HasPrefix(getter.FieldType, "..."): + typeName = typeName + "Slice" + } + pkg.Interfaces = append(pkg.Interfaces, model.Interface{ + Name: fmt.Sprintf("%s%s", fieldName, typeName), + Methods: []model.Method{ + { + Name: fmt.Sprintf("Get%s", fieldName), + Return: []model.Field{ + { + Type: getter.FieldType, + }, + }, + }, + }, + }) + } + + value, err := generator.GenerateFile(pkg) + if err != nil { + return err + } + + if _, err := f.Write(value); err != nil { + return err + } + + return nil +} diff --git a/internal/executor/generate/getter.go b/internal/executor/generate/getter.go new file mode 100644 index 0000000..9664d43 --- /dev/null +++ b/internal/executor/generate/getter.go @@ -0,0 +1,76 @@ +package generate + +import ( + "fmt" + "github.com/snowmerak/jetti/v2/internal/executor/check" + "github.com/snowmerak/jetti/v2/lib/generator" + "github.com/snowmerak/jetti/v2/lib/model" + "os" + "path/filepath" + "strings" +) + +func Getter(path string, getters []check.Getter) error { + dir := filepath.Dir(path) + + makeFilename := func(getter check.Getter) string { + return filepath.Join(dir, fmt.Sprintf("%s.getter.go", getter.StructName)) + } + + fileMap := map[string]*model.Package{} + + for _, getter := range getters { + filename := makeFilename(getter) + + pkg, ok := fileMap[filename] + if !ok { + pkg = &model.Package{ + Name: getter.PackageName, + Imports: getter.Imports, + } + fileMap[filename] = pkg + } + + fieldName := strings.ToUpper(getter.FieldName[:1]) + getter.FieldName[1:] + pkg.Methods = append(pkg.Methods, model.Method{ + Name: fmt.Sprintf("Get%s", fieldName), + Receiver: model.Field{ + Name: getter.StructName[:1], + Type: getter.StructName, + }, + Return: []model.Field{ + { + Type: getter.FieldType, + }, + }, + Code: []string{ + fmt.Sprintf("return $RECEIVER$.%s", getter.FieldName), + }, + }) + } + + for filename, pkg := range fileMap { + if err := func() error { + f, err := os.Create(filename) + if err != nil { + return err + } + defer f.Close() + + value, err := generator.GenerateFile(pkg) + if err != nil { + return err + } + + if _, err := f.Write(value); err != nil { + return err + } + + return nil + }(); err != nil { + return err + } + } + + return nil +}