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