github.com/shogo82148/goa-v1@v1.6.2/goagen/gen_controller/generator.go (about) 1 package gencontroller 2 3 import ( 4 "flag" 5 "fmt" 6 "os" 7 "path/filepath" 8 "strings" 9 "unicode" 10 "unicode/utf8" 11 12 "github.com/shogo82148/goa-v1/design" 13 "github.com/shogo82148/goa-v1/goagen/codegen" 14 genmain "github.com/shogo82148/goa-v1/goagen/gen_main" 15 "github.com/shogo82148/goa-v1/goagen/utils" 16 ) 17 18 //NewGenerator returns an initialized instance of a JavaScript Client Generator 19 func NewGenerator(options ...Option) *Generator { 20 g := &Generator{} 21 22 for _, option := range options { 23 option(g) 24 } 25 26 return g 27 } 28 29 // Generator is the application code generator. 30 type Generator struct { 31 API *design.APIDefinition // The API definition 32 OutDir string // Path to output directory 33 DesignPkg string // Path to design package, only used to mark generated files. 34 AppPkg string // Name of generated "app" package 35 Force bool // Whether to override existing files 36 Regen bool // Whether to regenerate scaffolding in place, retaining controller impls 37 Pkg string // Name of the generated package 38 Resource string // Name of the generated file 39 genfiles []string // Generated files 40 } 41 42 // Generate is the generator entry point called by the meta generator. 43 func Generate() (files []string, err error) { 44 var ( 45 outDir, designPkg, appPkg, ver, res, pkg string 46 force, regen bool 47 ) 48 49 set := flag.NewFlagSet("controller", flag.PanicOnError) 50 set.StringVar(&outDir, "out", "", "") 51 set.StringVar(&designPkg, "design", "", "") 52 set.StringVar(&appPkg, "app-pkg", "app", "") 53 set.StringVar(&pkg, "pkg", "main", "") 54 set.StringVar(&res, "res", "", "") 55 set.StringVar(&ver, "version", "", "") 56 set.BoolVar(&force, "force", false, "") 57 set.BoolVar(®en, "regen", false, "") 58 set.Bool("notest", false, "") 59 set.Parse(os.Args[1:]) 60 61 if err := codegen.CheckVersion(ver); err != nil { 62 return nil, err 63 } 64 65 g := &Generator{OutDir: outDir, DesignPkg: designPkg, AppPkg: appPkg, Force: force, Regen: regen, API: design.Design, Pkg: pkg, Resource: res} 66 67 return g.Generate() 68 } 69 70 // Generate produces the skeleton controller service factory. 71 func (g *Generator) Generate() (_ []string, err error) { 72 if g.API == nil { 73 return nil, fmt.Errorf("missing API definition, make sure design is properly initialized") 74 } 75 76 go utils.Catch(nil, func() { g.Cleanup() }) 77 78 defer func() { 79 if err != nil { 80 g.Cleanup() 81 } 82 }() 83 84 if g.AppPkg == "" { 85 g.AppPkg = "app" 86 } 87 g.smartenPkg() 88 elems := strings.Split(g.AppPkg, "/") 89 pkgName := elems[len(elems)-1] 90 codegen.Reserved[pkgName] = true 91 92 err = g.API.IterateResources(func(r *design.ResourceDefinition) error { 93 var ( 94 filename string 95 err error 96 ) 97 if g.Resource == "" || g.Resource == r.Name { 98 filename, err = genmain.GenerateController(g.Force, g.Regen, g.AppPkg, g.OutDir, g.Pkg, r.Name, r) 99 } 100 101 if err != nil { 102 return err 103 } 104 g.genfiles = append(g.genfiles, filename) 105 106 return nil 107 }) 108 if err != nil { 109 return nil, err 110 } 111 112 return g.genfiles, err 113 } 114 115 func (g *Generator) smartenPkg() { 116 if g.Pkg != "main" { 117 return 118 } 119 pwd, err := os.Getwd() 120 if err != nil { 121 return 122 } 123 if g.OutDir == pwd { 124 return 125 } 126 pkg := filepath.Base(g.OutDir) 127 if pkg == "" { 128 return 129 } 130 r, _ := utf8.DecodeRuneInString(pkg) 131 if !unicode.IsLetter(r) { 132 return 133 } 134 g.Pkg = pkg 135 } 136 137 // Cleanup removes all the files generated by this generator during the last invocation of Generate. 138 func (g *Generator) Cleanup() { 139 for _, f := range g.genfiles { 140 os.Remove(f) 141 } 142 g.genfiles = nil 143 }