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(&regen, "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  }