Пример #1
0
func (g *Generator) createMainFile(mainFile string, funcs template.FuncMap) error {
	g.genfiles = append(g.genfiles, mainFile)
	file, err := codegen.SourceFileFor(mainFile)
	if err != nil {
		return err
	}
	funcs["getPort"] = func(hostport string) string {
		_, port, err := net.SplitHostPort(hostport)
		if err != nil {
			return "8080"
		}
		return port
	}
	outPkg, err := codegen.PackagePath(g.OutDir)
	if err != nil {
		return err
	}
	appPkg := path.Join(outPkg, "app")
	imports := []*codegen.ImportSpec{
		codegen.SimpleImport("time"),
		codegen.SimpleImport("github.com/goadesign/goa"),
		codegen.SimpleImport("github.com/goadesign/goa/middleware"),
		codegen.SimpleImport(appPkg),
	}
	file.Write([]byte("//go:generate goagen bootstrap -d " + g.DesignPkg + "\n\n"))
	file.WriteHeader("", "main", imports)
	data := map[string]interface{}{
		"Name": g.API.Name,
		"API":  g.API,
	}
	if err = file.ExecuteTemplate("main", mainT, funcs, data); err != nil {
		return err
	}
	return file.FormatCode()
}
Пример #2
0
// Generate is the generator entry point called by the meta generator.
func Generate() (files []string, err error) {
	var outDir, target, appPkg, ver string

	set := flag.NewFlagSet("gorma", flag.PanicOnError)
	set.String("design", "", "")
	set.StringVar(&outDir, "out", "", "")
	set.StringVar(&ver, "version", "", "")
	set.StringVar(&target, "pkg", "models", "")
	set.StringVar(&appPkg, "app", "app", "")
	set.Parse(os.Args[2:])

	// First check compatibility
	if err := codegen.CheckVersion(ver); err != nil {
		return nil, err
	}

	// Now proceed
	appPkgPath, err := codegen.PackagePath(filepath.Join(outDir, appPkg))
	if err != nil {
		return nil, fmt.Errorf("invalid app package: %s", err)
	}
	outDir = filepath.Join(outDir, target)

	g := &Generator{outDir: outDir, target: target, appPkg: appPkg, appPkgPath: appPkgPath}

	return g.Generate(design.Design)
}
Пример #3
0
// Generate produces the skeleton main.
func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) {
	go utils.Catch(nil, func() { g.Cleanup() })

	defer func() {
		if err != nil {
			g.Cleanup()
		}
	}()

	// Make tool directory
	toolDir, err := makeToolDir(g, api.Name)
	if err != nil {
		return
	}

	funcs := template.FuncMap{
		"goify":        codegen.Goify,
		"gotypedef":    codegen.GoTypeDef,
		"gotyperefext": goTypeRefExt,
		"nativeType":   codegen.GoNativeType,
		"joinNames":    joinNames,
		"join":         join,
		"toString":     toString,
		"tempvar":      codegen.Tempvar,
		"title":        strings.Title,
		"flagType":     flagType,
		"defaultPath":  defaultPath,
		"toGo":         toGo,
	}
	clientPkg, err := codegen.PackagePath(codegen.OutputDir)
	if err != nil {
		return
	}
	arrayToStringTmpl = template.Must(template.New("client").Funcs(funcs).Parse(arrayToStringT))

	// Generate client/client-cli/main.go
	if err = g.generateMain(filepath.Join(toolDir, "main.go"), clientPkg, funcs, api); err != nil {
		return
	}

	// Generate client/client-cli/commands.go
	if err = g.generateCommands(filepath.Join(toolDir, "commands.go"), clientPkg, funcs, api); err != nil {
		return
	}

	// Generate client/client.go
	if err = g.generateClient(filepath.Join(codegen.OutputDir, "client.go"), clientPkg, funcs, api); err != nil {
		return
	}

	// Generate client/$res.go
	if err = g.generateClientResources(clientPkg, funcs, api); err != nil {
		return
	}

	return g.genfiles, nil
}
Пример #4
0
// Generate produces the skeleton main.
func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) {
	go utils.Catch(nil, func() { g.Cleanup() })

	defer func() {
		if err != nil {
			g.Cleanup()
		}
	}()

	// Make tool directory
	var toolDir string
	toolDir, err = makeToolDir(g, api.Name)
	if err != nil {
		return
	}

	funcs := template.FuncMap{
		"add":             func(a, b int) int { return a + b },
		"cmdFieldType":    cmdFieldType,
		"defaultPath":     defaultPath,
		"escapeBackticks": escapeBackticks,
		"flagType":        flagType,
		"goify":           codegen.Goify,
		"gotypedef":       codegen.GoTypeDef,
		"gotypedesc":      codegen.GoTypeDesc,
		"gotyperef":       codegen.GoTypeRef,
		"gotypename":      codegen.GoTypeName,
		"gotyperefext":    goTypeRefExt,
		"join":            join,
		"multiComment":    multiComment,
		"pathParams":      pathParams,
		"pathParamNames":  pathParamNames,
		"pathTemplate":    pathTemplate,
		"tempvar":         codegen.Tempvar,
		"title":           strings.Title,
		"toString":        toString,
		"typeName":        typeName,
		"signerType":      signerType,
	}
	clientPkg, err := codegen.PackagePath(codegen.OutputDir)
	if err != nil {
		return
	}
	arrayToStringTmpl = template.Must(template.New("client").Funcs(funcs).Parse(arrayToStringT))

	// Generate client/client-cli/main.go
	if err = g.generateMain(filepath.Join(toolDir, "main.go"), clientPkg, funcs, api); err != nil {
		return
	}

	// Generate client/client-cli/commands.go
	if err = g.generateCommands(filepath.Join(toolDir, "commands.go"), clientPkg, funcs, api); err != nil {
		return
	}

	// Generate client/client.go
	if err = g.generateClient(filepath.Join(codegen.OutputDir, "client.go"), clientPkg, funcs, api); err != nil {
		return
	}

	// Generate client/$res.go and types.go
	if err = g.generateClientResources(clientPkg, funcs, api); err != nil {
		return
	}

	return g.genfiles, nil
}
Пример #5
0
// Generate produces the skeleton main.
func (g *Generator) Generate(api *design.APIDefinition) (_ []string, err error) {
	go utils.Catch(nil, func() { g.Cleanup() })

	defer func() {
		if err != nil {
			g.Cleanup()
		}
	}()

	mainFile := filepath.Join(codegen.OutputDir, "main.go")
	if Force {
		os.Remove(mainFile)
	}
	g.genfiles = append(g.genfiles, mainFile)
	_, err = os.Stat(mainFile)
	funcs := template.FuncMap{
		"tempvar":              tempvar,
		"generateSwagger":      generateSwagger,
		"okResp":               okResp,
		"newControllerVersion": newControllerVersion,
		"targetPkg":            func() string { return TargetPackage },
	}
	if err != nil {
		file, err := codegen.SourceFileFor(mainFile)
		if err != nil {
			return nil, err
		}
		var outPkg string
		outPkg, err = codegen.PackagePath(codegen.OutputDir)
		if err != nil {
			return nil, err
		}
		outPkg = strings.TrimPrefix(filepath.ToSlash(outPkg), "src/")
		appPkg := path.Join(outPkg, "app")
		swaggerPkg := path.Join(outPkg, "swagger")
		imports := []*codegen.ImportSpec{
			codegen.SimpleImport("github.com/goadesign/goa"),
			codegen.SimpleImport("github.com/goadesign/middleware"),
			codegen.SimpleImport(appPkg),
			codegen.SimpleImport(swaggerPkg),
		}
		if generateSwagger() {
			jsonSchemaPkg := path.Join(outPkg, "schema")
			imports = append(imports, codegen.SimpleImport(jsonSchemaPkg))
		}
		file.WriteHeader("", "main", imports)
		data := map[string]interface{}{
			"Name": AppName,
			"API":  api,
		}
		if err = file.ExecuteTemplate("main", mainT, funcs, data); err != nil {
			return nil, err
		}
		if err = file.FormatCode(); err != nil {
			return nil, err
		}
	}
	imp, err := codegen.PackagePath(codegen.OutputDir)
	if err != nil {
		return
	}
	imp = path.Join(filepath.ToSlash(imp), "app")
	imports := []*codegen.ImportSpec{
		codegen.SimpleImport("github.com/goadesign/goa"),
		codegen.SimpleImport(imp),
	}
	api.IterateVersions(func(v *design.APIVersionDefinition) error {
		if v.IsDefault() {
			return nil
		}
		imports = append(imports, codegen.SimpleImport(imp+"/"+codegen.VersionPackage(v.Version)))
		return nil
	})
	err = api.IterateResources(func(r *design.ResourceDefinition) error {
		filename := filepath.Join(codegen.OutputDir, snakeCase(r.Name)+".go")
		if Force {
			if err := os.Remove(filename); err != nil {
				return err
			}
		}
		g.genfiles = append(g.genfiles, filename)
		if _, err := os.Stat(filename); err != nil {
			file, err := codegen.SourceFileFor(filename)
			if err != nil {
				return err
			}
			file.WriteHeader("", "main", imports)
			err = file.ExecuteTemplate("controller", ctrlT, funcs, r)
			if err != nil {
				return err
			}
			if err := file.FormatCode(); err != nil {
				return err
			}
		}
		return nil
	})
	if err != nil {
		return
	}

	return g.genfiles, nil
}
Пример #6
0
// Generate produces the skeleton main.
func (g *Generator) Generate() (_ []string, err error) {
	go utils.Catch(nil, func() { g.Cleanup() })

	defer func() {
		if err != nil {
			g.Cleanup()
		}
	}()

	if g.Target == "" {
		g.Target = "app"
	}

	codegen.Reserved[g.Target] = true

	mainFile := filepath.Join(g.OutDir, "main.go")
	if g.Force {
		os.Remove(mainFile)
	}
	funcs := template.FuncMap{
		"tempvar":   tempvar,
		"okResp":    g.okResp,
		"targetPkg": func() string { return g.Target },
	}
	imp, err := codegen.PackagePath(g.OutDir)
	if err != nil {
		return nil, err
	}
	imp = path.Join(filepath.ToSlash(imp), "app")
	_, err = os.Stat(mainFile)
	if err != nil {
		if err = g.createMainFile(mainFile, funcs); err != nil {
			return nil, err
		}
	}
	imports := []*codegen.ImportSpec{
		codegen.SimpleImport("io"),
		codegen.SimpleImport("github.com/goadesign/goa"),
		codegen.SimpleImport(imp),
		codegen.SimpleImport("golang.org/x/net/websocket"),
	}
	err = g.API.IterateResources(func(r *design.ResourceDefinition) error {
		filename := filepath.Join(g.OutDir, codegen.SnakeCase(r.Name)+".go")
		if g.Force {
			os.Remove(filename)
		}
		if _, e := os.Stat(filename); e != nil {
			g.genfiles = append(g.genfiles, filename)
			file, err2 := codegen.SourceFileFor(filename)
			if err2 != nil {
				return err
			}
			file.WriteHeader("", "main", imports)
			if err2 = file.ExecuteTemplate("controller", ctrlT, funcs, r); err2 != nil {
				return err
			}
			err2 = r.IterateActions(func(a *design.ActionDefinition) error {
				if a.WebSocket() {
					return file.ExecuteTemplate("actionWS", actionWST, funcs, a)
				}
				return file.ExecuteTemplate("action", actionT, funcs, a)
			})
			if err2 != nil {
				return err
			}
			if err2 = file.FormatCode(); err2 != nil {
				return err2
			}
		}
		return nil
	})
	if err != nil {
		return
	}

	return g.genfiles, nil
}
Пример #7
0
func (g *Generator) generateResourceTest() error {
	if len(g.API.Resources) == 0 {
		return nil
	}
	funcs := template.FuncMap{"isSlice": isSlice}
	testTmpl := template.Must(template.New("test").Funcs(funcs).Parse(testTmpl))
	outDir, err := makeTestDir(g, g.API.Name)
	if err != nil {
		return err
	}
	appPkg, err := codegen.PackagePath(g.OutDir)
	if err != nil {
		return err
	}
	imports := []*codegen.ImportSpec{
		codegen.SimpleImport("bytes"),
		codegen.SimpleImport("fmt"),
		codegen.SimpleImport("io"),
		codegen.SimpleImport("log"),
		codegen.SimpleImport("net/http"),
		codegen.SimpleImport("net/http/httptest"),
		codegen.SimpleImport("net/url"),
		codegen.SimpleImport("strconv"),
		codegen.SimpleImport("strings"),
		codegen.SimpleImport("time"),
		codegen.SimpleImport(appPkg),
		codegen.SimpleImport("github.com/goadesign/goa"),
		codegen.SimpleImport("github.com/goadesign/goa/goatest"),
		codegen.SimpleImport("golang.org/x/net/context"),
		codegen.NewImport("uuid", "github.com/satori/go.uuid"),
	}

	return g.API.IterateResources(func(res *design.ResourceDefinition) error {
		filename := filepath.Join(outDir, codegen.SnakeCase(res.Name)+"_testing.go")
		file, err := codegen.SourceFileFor(filename)
		if err != nil {
			return err
		}
		title := fmt.Sprintf("%s: %s TestHelpers", g.API.Context(), res.Name)
		if err := file.WriteHeader(title, "test", imports); err != nil {
			return err
		}

		var methods []*TestMethod

		if err := res.IterateActions(func(action *design.ActionDefinition) error {
			if err := action.IterateResponses(func(response *design.ResponseDefinition) error {
				if response.Status == 101 { // SwitchingProtocols, Don't currently handle WebSocket endpoints
					return nil
				}
				for routeIndex, route := range action.Routes {
					mediaType := design.Design.MediaTypeWithIdentifier(response.MediaType)
					if mediaType == nil {
						methods = append(methods, g.createTestMethod(res, action, response, route, routeIndex, nil, nil))
					} else {
						if err := mediaType.IterateViews(func(view *design.ViewDefinition) error {
							methods = append(methods, g.createTestMethod(res, action, response, route, routeIndex, mediaType, view))
							return nil
						}); err != nil {
							return err
						}
					}
				}
				return nil
			}); err != nil {
				return err
			}
			return nil
		}); err != nil {
			return err
		}
		g.genfiles = append(g.genfiles, filename)
		err = testTmpl.Execute(file, methods)
		if err != nil {
			panic(err)
		}
		return file.FormatCode()
	})
}
Пример #8
0
// Generate generats the client package and CLI.
func (g *Generator) Generate() (_ []string, err error) {
	go utils.Catch(nil, func() { g.Cleanup() })

	defer func() {
		if err != nil {
			g.Cleanup()
		}
	}()

	if g.Target == "" {
		g.Target = "client"
	}
	if g.ToolDirName == "" {
		g.ToolDirName = "tool"
	}
	if g.Tool == "" {
		g.Tool = defaultToolName(g.API)
	}

	codegen.Reserved[g.Target] = true

	// Setup output directories as needed
	var pkgDir, toolDir, cliDir string
	{
		if !g.NoTool {
			toolDir = filepath.Join(g.OutDir, g.ToolDirName, g.Tool)
			if _, err = os.Stat(toolDir); err != nil {
				if err = os.MkdirAll(toolDir, 0755); err != nil {
					return
				}
			}

			cliDir = filepath.Join(g.OutDir, g.ToolDirName, "cli")
			if err = os.RemoveAll(cliDir); err != nil {
				return
			}
			if err = os.MkdirAll(cliDir, 0755); err != nil {
				return
			}
		}

		pkgDir = filepath.Join(g.OutDir, g.Target)
		if err = os.RemoveAll(pkgDir); err != nil {
			return
		}
		if err = os.MkdirAll(pkgDir, 0755); err != nil {
			return
		}
	}

	// Setup generation
	var funcs template.FuncMap
	var clientPkg, cliPkg string
	{
		funcs = template.FuncMap{
			"add":                func(a, b int) int { return a + b },
			"cmdFieldType":       cmdFieldType,
			"defaultPath":        defaultPath,
			"escapeBackticks":    escapeBackticks,
			"goify":              codegen.Goify,
			"gotypedef":          codegen.GoTypeDef,
			"gotypedesc":         codegen.GoTypeDesc,
			"gotypename":         codegen.GoTypeName,
			"gotyperef":          codegen.GoTypeRef,
			"gotyperefext":       goTypeRefExt,
			"join":               join,
			"joinStrings":        strings.Join,
			"multiComment":       multiComment,
			"pathParamNames":     pathParamNames,
			"pathParams":         pathParams,
			"pathTemplate":       pathTemplate,
			"signerType":         signerType,
			"tempvar":            codegen.Tempvar,
			"title":              strings.Title,
			"toString":           toString,
			"typeName":           typeName,
			"format":             format,
			"handleSpecialTypes": handleSpecialTypes,
		}
		clientPkg, err = codegen.PackagePath(pkgDir)
		if err != nil {
			return
		}
		cliPkg, err = codegen.PackagePath(cliDir)
		if err != nil {
			return
		}
		arrayToStringTmpl = template.Must(template.New("client").Funcs(funcs).Parse(arrayToStringT))
	}

	if !g.NoTool {
		// Generate tool/main.go (only once)
		mainFile := filepath.Join(toolDir, "main.go")
		if _, err := os.Stat(mainFile); err != nil {
			g.genfiles = append(g.genfiles, toolDir)
			if err = g.generateMain(mainFile, clientPkg, cliPkg, funcs); err != nil {
				return nil, err
			}
		}

		// Generate tool/cli/commands.go
		g.genfiles = append(g.genfiles, cliDir)
		if err = g.generateCommands(filepath.Join(cliDir, "commands.go"), clientPkg, funcs); err != nil {
			return
		}
	}

	// Generate client/client.go
	g.genfiles = append(g.genfiles, pkgDir)
	if err = g.generateClient(filepath.Join(pkgDir, "client.go"), clientPkg, funcs); err != nil {
		return
	}

	// Generate client/$res.go and types.go
	if err = g.generateClientResources(pkgDir, clientPkg, funcs); err != nil {
		return
	}

	return g.genfiles, nil
}