diff --git a/cmd/generate.go b/cmd/generate.go index 501a6cc..658b4c4 100644 --- a/cmd/generate.go +++ b/cmd/generate.go @@ -9,6 +9,7 @@ import ( "github.com/phogolabs/stride/codedom" "github.com/phogolabs/stride/service" "github.com/phogolabs/stride/syntax/golang" + "github.com/phogolabs/stride/syntax/markdown" ) // OpenAPIGenerator provides a subcommands to generate source code from OpenAPI specification @@ -62,9 +63,15 @@ func (m *OpenAPIGenerator) generate(ctx *cli.Context) error { Reporter: reporter(ctx), Cache: codedom.TypeDescriptorMap{}, }, - Generator: &golang.Generator{ - Reporter: reporter(ctx), - Path: dir, + Generator: service.CompositeGenerator{ + &golang.Generator{ + Reporter: reporter(ctx), + Path: dir, + }, + &markdown.Generator{ + Reporter: reporter(ctx), + Path: dir, + }, }, } diff --git a/fake/code_generator.go b/fake/syntax_generator.go similarity index 77% rename from fake/code_generator.go rename to fake/syntax_generator.go index 3308a5c..7a56008 100644 --- a/fake/code_generator.go +++ b/fake/syntax_generator.go @@ -8,7 +8,7 @@ import ( "github.com/phogolabs/stride/service" ) -type CodeGenerator struct { +type SyntaxGenerator struct { GenerateStub func(*codedom.SpecDescriptor) error generateMutex sync.RWMutex generateArgsForCall []struct { @@ -24,7 +24,7 @@ type CodeGenerator struct { invocationsMutex sync.RWMutex } -func (fake *CodeGenerator) Generate(arg1 *codedom.SpecDescriptor) error { +func (fake *SyntaxGenerator) Generate(arg1 *codedom.SpecDescriptor) error { fake.generateMutex.Lock() ret, specificReturn := fake.generateReturnsOnCall[len(fake.generateArgsForCall)] fake.generateArgsForCall = append(fake.generateArgsForCall, struct { @@ -42,26 +42,26 @@ func (fake *CodeGenerator) Generate(arg1 *codedom.SpecDescriptor) error { return fakeReturns.result1 } -func (fake *CodeGenerator) GenerateCallCount() int { +func (fake *SyntaxGenerator) GenerateCallCount() int { fake.generateMutex.RLock() defer fake.generateMutex.RUnlock() return len(fake.generateArgsForCall) } -func (fake *CodeGenerator) GenerateCalls(stub func(*codedom.SpecDescriptor) error) { +func (fake *SyntaxGenerator) GenerateCalls(stub func(*codedom.SpecDescriptor) error) { fake.generateMutex.Lock() defer fake.generateMutex.Unlock() fake.GenerateStub = stub } -func (fake *CodeGenerator) GenerateArgsForCall(i int) *codedom.SpecDescriptor { +func (fake *SyntaxGenerator) GenerateArgsForCall(i int) *codedom.SpecDescriptor { fake.generateMutex.RLock() defer fake.generateMutex.RUnlock() argsForCall := fake.generateArgsForCall[i] return argsForCall.arg1 } -func (fake *CodeGenerator) GenerateReturns(result1 error) { +func (fake *SyntaxGenerator) GenerateReturns(result1 error) { fake.generateMutex.Lock() defer fake.generateMutex.Unlock() fake.GenerateStub = nil @@ -70,7 +70,7 @@ func (fake *CodeGenerator) GenerateReturns(result1 error) { }{result1} } -func (fake *CodeGenerator) GenerateReturnsOnCall(i int, result1 error) { +func (fake *SyntaxGenerator) GenerateReturnsOnCall(i int, result1 error) { fake.generateMutex.Lock() defer fake.generateMutex.Unlock() fake.GenerateStub = nil @@ -84,7 +84,7 @@ func (fake *CodeGenerator) GenerateReturnsOnCall(i int, result1 error) { }{result1} } -func (fake *CodeGenerator) Invocations() map[string][][]interface{} { +func (fake *SyntaxGenerator) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() fake.generateMutex.RLock() @@ -96,7 +96,7 @@ func (fake *CodeGenerator) Invocations() map[string][][]interface{} { return copiedInvocations } -func (fake *CodeGenerator) recordInvocation(key string, args []interface{}) { +func (fake *SyntaxGenerator) recordInvocation(key string, args []interface{}) { fake.invocationsMutex.Lock() defer fake.invocationsMutex.Unlock() if fake.invocations == nil { @@ -108,4 +108,4 @@ func (fake *CodeGenerator) recordInvocation(key string, args []interface{}) { fake.invocations[key] = append(fake.invocations[key], args) } -var _ service.CodeGenerator = new(CodeGenerator) +var _ service.SyntaxGenerator = new(SyntaxGenerator) diff --git a/service/generator.go b/service/generator.go index a0f7f83..ac7233c 100644 --- a/service/generator.go +++ b/service/generator.go @@ -13,18 +13,34 @@ type SpecResolver interface { Resolve(spec *openapi3.Swagger) (*codedom.SpecDescriptor, error) } -//go:generate counterfeiter -fake-name CodeGenerator -o ../fake/code_generator.go . CodeGenerator +//go:generate counterfeiter -fake-name SyntaxGenerator -o ../fake/syntax_generator.go . SyntaxGenerator -// CodeGenerator generates the code -type CodeGenerator interface { +// SyntaxGenerator generates the code +type SyntaxGenerator interface { // Generate generates a source code from spec Generate(spec *codedom.SpecDescriptor) error } +var _ SyntaxGenerator = CompositeGenerator{} + +// CompositeGenerator represents a composite generator +type CompositeGenerator []SyntaxGenerator + +// Generate generates the source code +func (items CompositeGenerator) Generate(spec *codedom.SpecDescriptor) error { + for _, generator := range items { + if err := generator.Generate(spec); err != nil { + return err + } + } + + return nil +} + // Generator generates the code type Generator struct { Path string - Generator CodeGenerator + Generator SyntaxGenerator Resolver SpecResolver } diff --git a/service/generator_test.go b/service/generator_test.go index 98170d3..dde90be 100644 --- a/service/generator_test.go +++ b/service/generator_test.go @@ -15,14 +15,14 @@ var _ = Describe("Generator", func() { var ( generator *service.Generator resolver *fake.SpecResolver - coder *fake.CodeGenerator + coder *fake.SyntaxGenerator ) BeforeEach(func() { resolver = &fake.SpecResolver{} resolver.ResolveReturns(&codedom.SpecDescriptor{}, nil) - coder = &fake.CodeGenerator{} + coder = &fake.SyntaxGenerator{} generator = &service.Generator{ Path: path("../fixture/spec/schemas-array.yaml"), diff --git a/syntax/golang/generator.go b/syntax/golang/generator.go index 4556fdf..1e838e5 100644 --- a/syntax/golang/generator.go +++ b/syntax/golang/generator.go @@ -111,17 +111,6 @@ func (g *Generator) Generate(spec *codedom.SpecDescriptor) error { return err } - markdown := &MarkdownGenerator{ - Path: g.Path, - Reporter: g.Reporter, - Info: spec.Info, - } - - if err := markdown.Generate(); err != nil { - reporter.Error(" Generating spec fail") - return err - } - reporter.Success(" Generating spec complete!") return nil } diff --git a/syntax/golang/generator_controller.go b/syntax/golang/generator_controller.go index 0ee99c7..0723a39 100644 --- a/syntax/golang/generator_controller.go +++ b/syntax/golang/generator_controller.go @@ -10,6 +10,7 @@ import ( "github.com/phogolabs/stride/codedom" "github.com/phogolabs/stride/contract" "github.com/phogolabs/stride/inflect" + "github.com/phogolabs/stride/syntax" ) // ControllerGeneratorMode determines the mode of this generator @@ -314,7 +315,7 @@ func (g *ControllerGenerator) function(root *File, name string, ctx map[string]i ) // mount method - writer := &TemplateWriter{ + writer := &syntax.TemplateWriter{ Path: fmt.Sprintf("syntax/golang/%s.go.tpl", name), Context: ctx, } diff --git a/syntax/golang/generator_main.go b/syntax/golang/generator_main.go index 525f277..c19aa3b 100644 --- a/syntax/golang/generator_main.go +++ b/syntax/golang/generator_main.go @@ -5,6 +5,7 @@ import ( "path/filepath" "github.com/phogolabs/stride/contract" + "github.com/phogolabs/stride/syntax" ) // MainGenerator builds the main @@ -23,7 +24,7 @@ func (g *MainGenerator) Generate() *File { reporter := g.Reporter.With(contract.SeverityHigh) reporter.Notice(" Generating main file: %s...", filename) - writer := &TemplateWriter{ + writer := &syntax.TemplateWriter{ Path: "syntax/golang/main.go.tpl", Context: map[string]interface{}{ "command": command, diff --git a/syntax/golang/generator_markdown.go b/syntax/golang/generator_markdown.go deleted file mode 100644 index a954b52..0000000 --- a/syntax/golang/generator_markdown.go +++ /dev/null @@ -1,62 +0,0 @@ -package golang - -import ( - "go/build" - "os" - "path/filepath" - - "github.com/phogolabs/stride/codedom" - "github.com/phogolabs/stride/contract" -) - -// MarkdownGenerator builds the main -type MarkdownGenerator struct { - Path string - Reporter contract.Reporter - Info *codedom.InfoDescriptor -} - -// Generate generates a file -func (g *MarkdownGenerator) Generate() error { - var ( - command = filepath.Base(g.Path) - filename = filepath.Join(g.Path, "README.md") - ) - - reporter := g.Reporter.With(contract.SeverityHigh) - reporter.Notice(" Generating markdown file: %s...", filename) - - project, err := filepath.Rel(filepath.Join(build.Default.GOPATH, "src"), g.Path) - - if err != nil { - reporter.Error(" Generating markdown file: %s fail: %v", filename, err) - return err - } - - writer := &TemplateWriter{ - Path: "syntax/golang/readme.md.tpl", - Context: map[string]interface{}{ - "command": command, - "project": project, - "title": g.Info.Title, - "description": g.Info.Description, - "version": g.Info.Version, - }, - } - - file, err := os.Create(filename) - if err != nil { - reporter.Error(" Generating markdown file: %s fail: %v", filename, err) - return err - } - - defer file.Close() - - if _, err := writer.WriteTo(file); err != nil { - reporter.Error(" Generating markdown file: %s fail: %v", filename, err) - return err - } - - reporter.Notice(" Generating markdown file: %s successful", filename) - return nil -} diff --git a/syntax/golang/generator_server.go b/syntax/golang/generator_server.go index 7057c5b..c0270f2 100644 --- a/syntax/golang/generator_server.go +++ b/syntax/golang/generator_server.go @@ -6,6 +6,7 @@ import ( "github.com/phogolabs/stride/codedom" "github.com/phogolabs/stride/contract" + "github.com/phogolabs/stride/syntax" ) // ServerGenerator builds a server @@ -22,7 +23,7 @@ func (g *ServerGenerator) Generate() *File { reporter := g.Reporter.With(contract.SeverityHigh) reporter.Notice(" Generating server file: %s...", filename) - writer := &TemplateWriter{ + writer := &syntax.TemplateWriter{ Path: "syntax/golang/server.go.tpl", Context: map[string]interface{}{ "controllers": g.Controllers, diff --git a/syntax/markdown/generator.go b/syntax/markdown/generator.go new file mode 100644 index 0000000..d0b3dd4 --- /dev/null +++ b/syntax/markdown/generator.go @@ -0,0 +1,84 @@ +package markdown + +import ( + "fmt" + "go/build" + "os" + "path/filepath" + "strings" + + "github.com/phogolabs/stride/codedom" + "github.com/phogolabs/stride/contract" + "github.com/phogolabs/stride/inflect" + "github.com/phogolabs/stride/syntax" +) + +// Generator builds the main +type Generator struct { + Path string + Reporter contract.Reporter +} + +// Generate generates the source code +func (g *Generator) Generate(spec *codedom.SpecDescriptor) error { + reporter := g.Reporter.With(contract.SeverityVeryHigh) + + if spec.Info == nil { + return nil + } + + reporter.Notice(" Generating markdown documentation...") + + project, err := filepath.Rel(filepath.Join(build.Default.GOPATH, "src"), g.Path) + + if err != nil { + reporter.Error(" Generating markdown documentation fail: ", err) + return err + } + + ctx := map[string]interface{}{ + "command": filepath.Base(g.Path), + "project": project, + "title": strings.TrimSpace(spec.Info.Title), + "description": strings.TrimSpace(spec.Info.Description), + "version": strings.TrimSpace(spec.Info.Version), + } + + // generate README.md + if err := g.sync(filepath.Join(g.Path, "README.md"), ctx); err != nil { + reporter.Error(" Generating markdown documentation fail: ", err) + return err + } + + reporter.Success(" Generating markdown documentation successful!") + return nil +} + +func (g *Generator) sync(path string, ctx map[string]interface{}) error { + reporter := g.Reporter.With(contract.SeverityHigh) + + var ( + name = inflect.LowerCase(filepath.Base(path)) + writer = &syntax.TemplateWriter{ + Path: fmt.Sprintf("syntax/golang/%s.tpl", name), + Context: ctx, + } + ) + + file, err := os.Create(path) + if err != nil { + reporter.Error(" Generating markdown file: %s fail: %v", path, err) + return err + } + + defer file.Close() + + if _, err := writer.WriteTo(file); err != nil { + reporter.Error(" Generating markdown file: %s fail: %v", path, err) + return err + } + + reporter.Notice(" Generating markdown file: %s successful", path) + return nil + +} diff --git a/syntax/golang/generator_template.go b/syntax/writer.go similarity index 98% rename from syntax/golang/generator_template.go rename to syntax/writer.go index 5d0f483..f271740 100644 --- a/syntax/golang/generator_template.go +++ b/syntax/writer.go @@ -1,4 +1,4 @@ -package golang +package syntax import ( "bytes"