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