From dc25f9c61e52ec733ec46831b59166386e9c710f Mon Sep 17 00:00:00 2001 From: Igor Lazarev Date: Sun, 24 Nov 2024 20:26:40 +0300 Subject: [PATCH] appending factories into existing files --- examples/basic/di/container.go | 2 +- examples/basic/di/internal/bitset.go | 2 +- examples/basic/di/internal/container.go | 2 +- .../basic/di/internal/lookup/container.go | 2 +- internal/di/factories_generator.go | 89 ++++++++++++++----- internal/di/file.go | 5 ++ internal/di/generator.go | 16 +++- internal/di/writer.go | 30 ++++++- 8 files changed, 115 insertions(+), 33 deletions(-) diff --git a/examples/basic/di/container.go b/examples/basic/di/container.go index dc36277..c05220e 100644 --- a/examples/basic/di/container.go +++ b/examples/basic/di/container.go @@ -1,5 +1,5 @@ // Code generated by DIGEN; DO NOT EDIT. -// This file was generated by Dependency Injection Container Generator rev-4ca64d5. +// This file was generated by Dependency Injection Container Generator rev-5ccec14-dirty. // See docs at https://github.com/strider2038/digen package di diff --git a/examples/basic/di/internal/bitset.go b/examples/basic/di/internal/bitset.go index fb6eeed..b958e91 100644 --- a/examples/basic/di/internal/bitset.go +++ b/examples/basic/di/internal/bitset.go @@ -1,5 +1,5 @@ // Code generated by DIGEN; DO NOT EDIT. -// This file was generated by Dependency Injection Container Generator rev-4ca64d5. +// This file was generated by Dependency Injection Container Generator rev-5ccec14-dirty. // See docs at https://github.com/strider2038/digen package internal diff --git a/examples/basic/di/internal/container.go b/examples/basic/di/internal/container.go index 5cd4d0f..839ef03 100644 --- a/examples/basic/di/internal/container.go +++ b/examples/basic/di/internal/container.go @@ -1,5 +1,5 @@ // Code generated by DIGEN; DO NOT EDIT. -// This file was generated by Dependency Injection Container Generator rev-4ca64d5. +// This file was generated by Dependency Injection Container Generator rev-5ccec14-dirty. // See docs at https://github.com/strider2038/digen package internal diff --git a/examples/basic/di/internal/lookup/container.go b/examples/basic/di/internal/lookup/container.go index 1cc8230..09d57fc 100644 --- a/examples/basic/di/internal/lookup/container.go +++ b/examples/basic/di/internal/lookup/container.go @@ -1,5 +1,5 @@ // Code generated by DIGEN; DO NOT EDIT. -// This file was generated by Dependency Injection Container Generator rev-4ca64d5. +// This file was generated by Dependency Injection Container Generator rev-5ccec14-dirty. // See docs at https://github.com/strider2038/digen package lookup diff --git a/internal/di/factories_generator.go b/internal/di/factories_generator.go index 0b2c4db..278568a 100644 --- a/internal/di/factories_generator.go +++ b/internal/di/factories_generator.go @@ -1,6 +1,8 @@ package di import ( + "bytes" + "fmt" "os" "strings" @@ -32,39 +34,80 @@ func (g *FactoriesGenerator) Generate() ([]*File, error) { files := make([]*File, 0, len(servicesByFiles)) for filename, services := range servicesByFiles { - if g.isFactoryFileExist(filename) { - continue - } + var file *File + var err error - file := NewFileBuilder(filename, "factories", FactoriesPackage) - file.AddImportAliases(g.container.Imports) - - for _, service := range services { - file.Add( - jen.Line(), - jen.Func().Id("Create"+strings.Title(service.Prefix)+service.Title()). - Params( - jen.Id("ctx").Qual("context", "Context"), - jen.Id("c").Qual(g.params.packageName(LookupPackage), "Container"), - ). - Params( - jen.Do(g.container.Type(service.Type)), - jen.Error(), - ). - Block(jen.Panic(jen.Lit("not implemented"))), - ) + if g.isFactoryFileExist(filename) { + file, err = g.generateAppendFile(filename, services) + } else { + file, err = g.generateNewFile(filename, services) } - - content, err := file.GetFile() if err != nil { return nil, err } - files = append(files, content) + + files = append(files, file) } return files, nil } +func (g *FactoriesGenerator) generateNewFile(filename string, services []*ServiceDefinition) (*File, error) { + file := NewFileBuilder(filename, "factories", FactoriesPackage) + file.AddImportAliases(g.container.Imports) + + for _, service := range services { + file.Add( + jen.Line(), + jen.Func().Id("Create"+strings.Title(service.Prefix)+service.Title()). + Params( + jen.Id("ctx").Qual("context", "Context"), + jen.Id("c").Qual(g.params.packageName(LookupPackage), "Container"), + ). + Params( + jen.Do(g.container.Type(service.Type)), + jen.Error(), + ). + Block(jen.Panic(jen.Lit("not implemented"))), + ) + } + + return file.GetFile() +} + +func (g *FactoriesGenerator) generateAppendFile(filename string, services []*ServiceDefinition) (*File, error) { + var content bytes.Buffer + + for _, service := range services { + factoryName := strings.Title(service.Prefix) + service.Title() + if _, exists := g.container.Factories[factoryName]; exists { + continue + } + + content.WriteString("\n") + content.WriteString(fmt.Sprintf("%#v", + jen.Func().Id("Create"+factoryName). + Params( + jen.Id("ctx").Qual("context", "Context"), + jen.Id("c").Qual(g.params.packageName(LookupPackage), "Container"), + ). + Params( + jen.Do(g.container.Type(service.Type)), + jen.Error(), + ). + Block(jen.Panic(jen.Lit("not implemented"))), + )) + content.WriteString("\n") + } + + return &File{ + Package: FactoriesPackage, + Name: filename, + Content: content.Bytes(), + Append: true, + }, nil +} + func (g *FactoriesGenerator) isFactoryFileExist(filename string) bool { _, err := os.Stat(g.workDir + "/" + packageDirs[FactoriesPackage] + "/" + filename) diff --git a/internal/di/file.go b/internal/di/file.go index 6ab602b..990a2d9 100644 --- a/internal/di/file.go +++ b/internal/di/file.go @@ -32,6 +32,7 @@ type File struct { Package PackageType Name string Content []byte + Append bool } func (f *File) Path() string { @@ -43,6 +44,10 @@ func (f *File) Path() string { return path + f.Name } +func (f *File) IsEmpty() bool { + return len(f.Content) == 0 +} + type FileBuilder struct { file *jen.File fileName string diff --git a/internal/di/generator.go b/internal/di/generator.go index a45a0c1..ccb587f 100644 --- a/internal/di/generator.go +++ b/internal/di/generator.go @@ -146,20 +146,28 @@ func (g *Generator) generateFactoriesFiles(container *RootContainerDefinition) e RootPackage: g.RootPackage(), ErrorHandling: g.ErrorWrapping.Defaults(), } - manager := NewFactoriesGenerator(container, g.BaseDir, params) - files, err := manager.Generate() + generator := NewFactoriesGenerator(container, g.BaseDir, params) + files, err := generator.Generate() if err != nil { return err } for _, file := range files { + if file.IsEmpty() { + continue + } writer := NewWriter(g.BaseDir) + writer.Append = file.Append err = writer.WriteFile(file) if err != nil { return err } - g.Logger.Info("factories file", file.Path(), "generated") + action := "generated" + if writer.Append { + action = "updated" + } + g.Logger.Info("factories file", file.Path(), action) } return nil @@ -183,7 +191,7 @@ func (g *Generator) generateUtils() error { return err } - g.Logger.Info("bitset file", file.Path(), "generated") + g.Logger.Info("file", file.Path(), "generated") return nil } diff --git a/internal/di/writer.go b/internal/di/writer.go index a40f108..ae749ac 100644 --- a/internal/di/writer.go +++ b/internal/di/writer.go @@ -10,6 +10,7 @@ import ( type Writer struct { WorkDir string Overwrite bool + Append bool Heading []byte } @@ -24,10 +25,19 @@ func (w *Writer) WriteFile(file *File) error { } filename += file.Name - if !w.Overwrite && isFileExist(filename) { - return errors.Errorf("cannot write to file %s: %w", filename, ErrFileAlreadyExists) + if isFileExist(filename) { + if w.Append { + return w.append(file, filename) + } + if !w.Overwrite { + return errors.Errorf("cannot write to file %s: %w", filename, ErrFileAlreadyExists) + } } + return w.write(file, filename) +} + +func (w *Writer) write(file *File, filename string) error { dir := filepath.Dir(filename) err := os.MkdirAll(dir, 0775) if err != nil { @@ -42,8 +52,24 @@ func (w *Writer) WriteFile(file *File) error { return nil } +func (w *Writer) append(file *File, filename string) error { + return appendFile(filename, file.Content, 0644) +} + func isFileExist(filename string) bool { _, err := os.Stat(filename) return err == nil } + +func appendFile(name string, data []byte, perm os.FileMode) error { + f, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, perm) + if err != nil { + return err + } + _, err = f.Write(data) + if err1 := f.Close(); err1 != nil && err == nil { + err = err1 + } + return err +}