Refactor names and tests in preperation for middleware addition
This commit is contained in:
Родитель
5924b77e11
Коммит
926895c623
|
@ -2,13 +2,10 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/format"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -21,32 +18,26 @@ import (
|
|||
"github.com/TuneLab/go-truss/truss"
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetLevel(log.InfoLevel)
|
||||
log.SetOutput(os.Stderr)
|
||||
log.SetFormatter(&log.TextFormatter{
|
||||
ForceColors: true,
|
||||
})
|
||||
}
|
||||
|
||||
// GenerateGokit returns a gokit service generated from a service definition (svcdef),
|
||||
// the package to the root of the generated service goPackage, the package
|
||||
// to the .pb.go service struct files (goPBPackage) and any prevously generated files.
|
||||
func GenerateGokit(sd *svcdef.Svcdef, conf gengokit.Config) ([]truss.NamedReadWriter, error) {
|
||||
te, err := gengokit.NewTemplateExecutor(sd, conf)
|
||||
executor, err := gengokit.NewExecutor(sd, conf)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot create template executor")
|
||||
}
|
||||
|
||||
fpm := make(map[string]io.Reader, len(conf.PreviousFiles))
|
||||
prevFiles := make(map[string]io.Reader, len(conf.PreviousFiles))
|
||||
for _, f := range conf.PreviousFiles {
|
||||
fpm[f.Name()] = f
|
||||
prevFiles[f.Name()] = f
|
||||
}
|
||||
|
||||
var codeGenFiles []truss.NamedReadWriter
|
||||
|
||||
for _, templFP := range templFiles.AssetNames() {
|
||||
file, err := generateResponseFile(templFP, te, fpm)
|
||||
actualFP := templatePathToActual(templFP, sd.PkgName)
|
||||
prev := prevFiles[actualFP]
|
||||
file, err := generateResponseFile(executor, prev, templFP)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot render template")
|
||||
}
|
||||
|
@ -62,32 +53,28 @@ func GenerateGokit(sd *svcdef.Svcdef, conf gengokit.Config) ([]truss.NamedReadWr
|
|||
|
||||
// generateResponseFile contains logic to choose how to render a template file
|
||||
// based on path and if that file was generated previously. It accepts a
|
||||
// template path to render, a templateExecutor to apply to the template, and a
|
||||
// map of paths to files for the previous generation. It returns a
|
||||
// truss.NamedReadWriter representing the generated file
|
||||
func generateResponseFile(templFP string, te *gengokit.TemplateExecutor, prevGenMap map[string]io.Reader) (truss.NamedReadWriter, error) {
|
||||
// template path to render, a executor to apply to the template,
|
||||
// and . It returns a truss.NamedReadWriter representing the generated file.
|
||||
func generateResponseFile(executor *gengokit.Executor, file io.Reader, templFP string) (truss.NamedReadWriter, error) {
|
||||
var genCode io.Reader
|
||||
var err error
|
||||
|
||||
// Get the actual path to the file rather than the template file path
|
||||
actualFP := templatePathToActual(templFP, te.PackageName)
|
||||
// If we are rendering the server and or the client
|
||||
if templFP == "NAME-service/handlers/server/server_handler.gotemplate" {
|
||||
file := prevGenMap[actualFP]
|
||||
h, err := handler.New(te.Service, file, te.PackageName)
|
||||
actualFP := templatePathToActual(templFP, executor.PackageName)
|
||||
|
||||
switch templFP {
|
||||
case handler.ServerFile:
|
||||
h, err := handler.New(executor.Service, file, executor.PackageName)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot parse previous handler: %q", actualFP)
|
||||
}
|
||||
|
||||
if genCode, err = h.Render(templFP, te); err != nil {
|
||||
return nil, errors.Wrap(err, "cannot render template")
|
||||
if genCode, err = h.Render(templFP, executor); err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot render template: %s", templFP)
|
||||
}
|
||||
}
|
||||
|
||||
// if no code has been generated just apply the template
|
||||
if genCode == nil {
|
||||
if genCode, err = applyTemplateFromPath(templFP, te); err != nil {
|
||||
return nil, errors.Wrap(err, "cannot render template")
|
||||
default:
|
||||
if genCode, err = applyTemplateFromPath(templFP, executor); err != nil {
|
||||
return nil, errors.Wrapf(err, "cannot render template: %s", templFP)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -125,30 +112,13 @@ func templatePathToActual(templFilePath, packageName string) string {
|
|||
}
|
||||
|
||||
// applyTemplateFromPath calls applyTemplate with the template at templFilePath
|
||||
func applyTemplateFromPath(templFilePath string, executor *gengokit.TemplateExecutor) (io.Reader, error) {
|
||||
templBytes, err := templFiles.Asset(templFilePath)
|
||||
func applyTemplateFromPath(templFP string, executor *gengokit.Executor) (io.Reader, error) {
|
||||
templBytes, err := templFiles.Asset(templFP)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to find template file: %v", templFilePath)
|
||||
return nil, errors.Wrapf(err, "unable to find template file: %v", templFP)
|
||||
}
|
||||
|
||||
return applyTemplate(templBytes, templFilePath, executor)
|
||||
}
|
||||
|
||||
func applyTemplate(templBytes []byte, templName string, executor *gengokit.TemplateExecutor) (io.Reader, error) {
|
||||
templateString := string(templBytes)
|
||||
|
||||
codeTemplate, err := template.New(templName).Funcs(executor.FuncMap).Parse(templateString)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot create template")
|
||||
}
|
||||
|
||||
outputBuffer := bytes.NewBuffer(nil)
|
||||
err = codeTemplate.Execute(outputBuffer, executor)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "template error")
|
||||
}
|
||||
|
||||
return outputBuffer, nil
|
||||
return executor.ApplyTemplate(string(templBytes), templFP)
|
||||
}
|
||||
|
||||
// formatCode takes a string representing golang code and attempts to return a
|
||||
|
@ -164,5 +134,4 @@ func formatCode(code []byte) []byte {
|
|||
}
|
||||
|
||||
return formatted
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package generator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/format"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
@ -29,6 +28,7 @@ func init() {
|
|||
|
||||
func init() {
|
||||
log.SetLevel(log.DebugLevel)
|
||||
_ = errors.Wrap
|
||||
}
|
||||
|
||||
func TestTemplatePathToActual(t *testing.T) {
|
||||
|
@ -85,7 +85,7 @@ func TestApplyTemplateFromPath(t *testing.T) {
|
|||
PBPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
|
||||
}
|
||||
|
||||
te, err := gengokit.NewTemplateExecutor(sd, conf)
|
||||
te, err := gengokit.NewExecutor(sd, conf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -100,11 +100,10 @@ func TestApplyTemplateFromPath(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = testFormat(endCode)
|
||||
_, err = testFormat(string(endCode))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func svcMethodsNames(methods []*svcdef.ServiceMethod) []string {
|
||||
|
@ -116,7 +115,7 @@ func svcMethodsNames(methods []*svcdef.ServiceMethod) []string {
|
|||
return mNames
|
||||
}
|
||||
|
||||
func stringToTemplateExector(def, importPath string) (*gengokit.TemplateExecutor, error) {
|
||||
func stringToTemplateExector(def, importPath string) (*gengokit.Executor, error) {
|
||||
sd, err := svcdef.NewFromString(def, gopath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -127,13 +126,12 @@ func stringToTemplateExector(def, importPath string) (*gengokit.TemplateExecutor
|
|||
PBPackage: importPath,
|
||||
}
|
||||
|
||||
te, err := gengokit.NewTemplateExecutor(sd, conf)
|
||||
te, err := gengokit.NewExecutor(sd, conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return te, nil
|
||||
|
||||
}
|
||||
|
||||
func TestAllTemplates(t *testing.T) {
|
||||
|
@ -207,17 +205,7 @@ func TestAllTemplates(t *testing.T) {
|
|||
}
|
||||
`
|
||||
|
||||
sd, err := svcdef.NewFromString(def, gopath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
conf := gengokit.Config{
|
||||
GoPackage: "github.com/TuneLab/go-truss/gengokit",
|
||||
PBPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
|
||||
}
|
||||
|
||||
te, err := gengokit.NewTemplateExecutor(sd, conf)
|
||||
sd1, err := svcdef.NewFromString(def, gopath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -227,54 +215,60 @@ func TestAllTemplates(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
te2, err := gengokit.NewTemplateExecutor(sd2, conf)
|
||||
conf := gengokit.Config{
|
||||
GoPackage: "github.com/TuneLab/go-truss/gengokit",
|
||||
PBPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
|
||||
}
|
||||
|
||||
executor1, err := gengokit.NewExecutor(sd1, conf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
executor2, err := gengokit.NewExecutor(sd2, conf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, templFP := range templateFileAssets.AssetNames() {
|
||||
// skip the partial templates
|
||||
if filepath.Ext(templFP) != ".gotemplate" {
|
||||
continue
|
||||
}
|
||||
prevGenMap := make(map[string]io.Reader)
|
||||
var prev io.Reader
|
||||
|
||||
firstCode, err := testGenerateResponseFile(templFP, te, prevGenMap)
|
||||
firstCode, err := testGenerateResponseFile(executor1, prev, templFP)
|
||||
if err != nil {
|
||||
t.Fatalf("%v failed to format on first generation\n\nERROR:\n\n%v\n\nCODE:\n\n%v", templFP, err.Error(), string(firstCode))
|
||||
t.Fatalf("%s failed to format on first generation\n\nERROR:\n\n%s\n\nCODE:\n\n%s", templFP, err.Error(), firstCode)
|
||||
}
|
||||
|
||||
// store the file to act to pass back to testGenerateResponseFile for second generation
|
||||
prevGenMap[templatePathToActual(templFP, te.PackageName)] = bytes.NewReader(firstCode)
|
||||
// store the file to pass back to testGenerateResponseFile for second generation
|
||||
prev = strings.NewReader(firstCode)
|
||||
|
||||
secondCode, err := testGenerateResponseFile(templFP, te, prevGenMap)
|
||||
secondCode, err := testGenerateResponseFile(executor1, prev, templFP)
|
||||
if err != nil {
|
||||
t.Fatalf("%v failed to format on second identical generation\n\nERROR: %v\nCODE:\n\n%v",
|
||||
templFP, err.Error(), string(secondCode))
|
||||
t.Fatalf("%s failed to format on second identical generation\n\nERROR: %s\nCODE:\n\n%s",
|
||||
templFP, err.Error(), secondCode)
|
||||
}
|
||||
|
||||
if bytes.Compare(firstCode, secondCode) != 0 {
|
||||
t.Fatal("Generated code differs after regeneration with same definition\n" + gentesthelper.DiffStrings(string(firstCode), string(secondCode)))
|
||||
if firstCode != secondCode {
|
||||
t.Fatal("Generated code differs after regeneration with same definition\n" + diff(firstCode, secondCode))
|
||||
}
|
||||
|
||||
// store the file to act to pass back to testGenerateResponseFile for third generation
|
||||
prevGenMap[templatePathToActual(templFP, te.PackageName)] = bytes.NewReader(secondCode)
|
||||
// store the file to pass back to testGenerateResponseFile for third generation
|
||||
prev = strings.NewReader(secondCode)
|
||||
|
||||
// pass in templateExecutor created from def2
|
||||
addRPCCode, err := testGenerateResponseFile(templFP, te2, prevGenMap)
|
||||
// pass in Executor created from def2
|
||||
addRPCCode, err := testGenerateResponseFile(executor2, prev, templFP)
|
||||
if err != nil {
|
||||
t.Fatalf("%v failed to format on third generation with 1 rpc added\n\nERROR: %v\nCODE:\n\n%v",
|
||||
templFP, err.Error(), string(addRPCCode))
|
||||
t.Fatalf("%s failed to format on third generation with 1 rpc added\n\nERROR: %s\nCODE:\n\n%s",
|
||||
templFP, err.Error(), addRPCCode)
|
||||
}
|
||||
|
||||
// store the file to act to pass back to testGenerateResponseFile for forth generation
|
||||
prevGenMap[templatePathToActual(templFP, te.PackageName)] = bytes.NewReader(addRPCCode)
|
||||
// store the file to pass back to testGenerateResponseFile for forth generation
|
||||
prev = strings.NewReader(addRPCCode)
|
||||
|
||||
// pass in templateExecutor create from def1
|
||||
_, err = testGenerateResponseFile(templFP, te, prevGenMap)
|
||||
// pass in Executor create from def1
|
||||
_, err = testGenerateResponseFile(executor1, prev, templFP)
|
||||
if err != nil {
|
||||
t.Fatalf("%v failed to format on forth generation with 1 rpc removed\n\nERROR: %v\nCODE:\n\n%v",
|
||||
templFP, err.Error(), string(addRPCCode))
|
||||
t.Fatalf("%s failed to format on forth generation with 1 rpc removed\n\nERROR: %s\nCODE:\n\n%s",
|
||||
templFP, err.Error(), addRPCCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -346,82 +340,79 @@ func TestUpdateMethods(t *testing.T) {
|
|||
PBPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
|
||||
}
|
||||
|
||||
te, err := gengokit.NewTemplateExecutor(sd, conf)
|
||||
te, err := gengokit.NewExecutor(sd, conf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testHandlerGeneration := func(templPath string) {
|
||||
svc.Methods = []*svcdef.ServiceMethod{allMethods[0]}
|
||||
firstBytes, err := testGenerateResponseFile(templPath, te, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
firstCode := strings.TrimSpace(string(firstBytes))
|
||||
templPath := handler.ServerFile
|
||||
|
||||
secondCode, err := renderService(svc, firstCode, te, templPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
svc.Methods = []*svcdef.ServiceMethod{allMethods[0]}
|
||||
|
||||
if strings.Compare(firstCode, secondCode) != 0 {
|
||||
t.Fatal("Generated code differs after regenerated with same definition\n" +
|
||||
templPath + "\n" +
|
||||
diff(firstCode, secondCode))
|
||||
}
|
||||
|
||||
svc.Methods = append(svc.Methods, allMethods[1])
|
||||
|
||||
thirdCode, err := renderService(svc, secondCode, te, templPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if strings.Compare(secondCode, thirdCode) != -1 {
|
||||
t.Fatal("Generated code not longer after regenerated with additional service method\n" +
|
||||
templPath + "\n" +
|
||||
diff(secondCode, thirdCode))
|
||||
}
|
||||
|
||||
// remove the first one rpc
|
||||
svc.Methods = svc.Methods[1:]
|
||||
|
||||
forthCode, err := renderService(svc, thirdCode, te, templPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if strings.Compare(thirdCode, forthCode) != 1 {
|
||||
t.Fatal("Generated code not shorter after regenerated with fewer service method\n" +
|
||||
templPath + "\n" +
|
||||
diff(secondCode, thirdCode))
|
||||
}
|
||||
|
||||
svc.Methods = allMethods
|
||||
|
||||
fifthCode, err := renderService(svc, forthCode, te, templPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if strings.Compare(forthCode, fifthCode) != -1 {
|
||||
t.Fatal("Generated code not longer after regenerated with additional service method\n" +
|
||||
templPath + "\n" +
|
||||
diff(secondCode, thirdCode))
|
||||
}
|
||||
firstCode, err := renderService(svc, "", te, templPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
secondCode, err := renderService(svc, firstCode, te, templPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if strings.Compare(firstCode, secondCode) != 0 {
|
||||
t.Fatal("Generated code differs after regenerated with same definition\n" +
|
||||
templPath + "\n" +
|
||||
diff(firstCode, secondCode))
|
||||
}
|
||||
|
||||
svc.Methods = append(svc.Methods, allMethods[1])
|
||||
|
||||
thirdCode, err := renderService(svc, secondCode, te, templPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if thirdCode <= secondCode {
|
||||
t.Fatal("Generated code not longer after regenerated with additional service method\n" +
|
||||
templPath + "\n" +
|
||||
diff(secondCode, thirdCode))
|
||||
}
|
||||
|
||||
// remove the first one rpc
|
||||
svc.Methods = svc.Methods[1:]
|
||||
|
||||
forthCode, err := renderService(svc, thirdCode, te, templPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if forthCode >= thirdCode {
|
||||
t.Fatal("Generated code not shorter after regenerated with fewer service method\n" +
|
||||
templPath + "\n" +
|
||||
diff(thirdCode, forthCode))
|
||||
}
|
||||
|
||||
svc.Methods = allMethods
|
||||
|
||||
fifthCode, err := renderService(svc, forthCode, te, templPath)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if fifthCode <= forthCode {
|
||||
t.Fatal("Generated code not longer after regenerated with additional service method\n" +
|
||||
templPath + "\n" +
|
||||
diff(forthCode, fifthCode))
|
||||
}
|
||||
testHandlerGeneration("NAME-service/handlers/server/server_handler.gotemplate")
|
||||
}
|
||||
|
||||
func diff(a, b string) string {
|
||||
return gentesthelper.DiffStrings(
|
||||
a,
|
||||
b,
|
||||
)
|
||||
}
|
||||
func renderService(svc *svcdef.Service, prev string, te *gengokit.Executor, templPath string) (string, error) {
|
||||
var prevFile io.Reader
|
||||
if prev != "" {
|
||||
prevFile = strings.NewReader(prev)
|
||||
}
|
||||
|
||||
func renderService(svc *svcdef.Service, prev string, te *gengokit.TemplateExecutor, templPath string) (string, error) {
|
||||
h, err := handler.New(svc, strings.NewReader(prev), te.PackageName)
|
||||
h, err := handler.New(svc, prevFile, te.PackageName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -436,33 +427,40 @@ func renderService(svc *svcdef.Service, prev string, te *gengokit.TemplateExecut
|
|||
return "", err
|
||||
}
|
||||
|
||||
nextBytes, err = testFormat(nextBytes)
|
||||
nextCode, err := testFormat(string(nextBytes))
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "cannot format")
|
||||
}
|
||||
|
||||
nextCode := strings.TrimSpace(string(nextBytes))
|
||||
nextCode = strings.TrimSpace(nextCode)
|
||||
|
||||
return nextCode, nil
|
||||
}
|
||||
|
||||
func testGenerateResponseFile(templFP string, te *gengokit.TemplateExecutor, prevGenMap map[string]io.Reader) ([]byte, error) {
|
||||
func diff(a, b string) string {
|
||||
return gentesthelper.DiffStrings(
|
||||
a,
|
||||
b,
|
||||
)
|
||||
}
|
||||
|
||||
func testGenerateResponseFile(executor *gengokit.Executor, prev io.Reader, templFP string) (string, error) {
|
||||
// apply server_handler.go template
|
||||
code, err := generateResponseFile(templFP, te, prevGenMap)
|
||||
code, err := generateResponseFile(executor, prev, templFP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
// read the code off the io.Reader
|
||||
codeBytes, err := ioutil.ReadAll(code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return "", err
|
||||
}
|
||||
|
||||
// format the code
|
||||
formatted, err := testFormat(codeBytes)
|
||||
formatted, err := testFormat(string(codeBytes))
|
||||
if err != nil {
|
||||
return codeBytes, err
|
||||
return string(codeBytes), err
|
||||
}
|
||||
|
||||
return formatted, nil
|
||||
|
@ -470,12 +468,12 @@ func testGenerateResponseFile(templFP string, te *gengokit.TemplateExecutor, pre
|
|||
|
||||
// testFormat takes a string representing golang code and attempts to return a
|
||||
// formated copy of that code.
|
||||
func testFormat(code []byte) ([]byte, error) {
|
||||
formatted, err := format.Source(code)
|
||||
func testFormat(code string) (string, error) {
|
||||
formatted, err := format.Source([]byte(code))
|
||||
|
||||
if err != nil {
|
||||
return code, err
|
||||
}
|
||||
|
||||
return formatted, nil
|
||||
return string(formatted), nil
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package gengokit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
generatego "github.com/golang/protobuf/protoc-gen-go/generator"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/TuneLab/go-truss/gengokit/clientarggen"
|
||||
"github.com/TuneLab/go-truss/gengokit/httptransport"
|
||||
|
@ -14,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
type Renderable interface {
|
||||
Render(string, *TemplateExecutor) (io.Reader, error)
|
||||
Render(string, *Executor) (io.Reader, error)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
|
@ -24,9 +26,9 @@ type Config struct {
|
|||
PreviousFiles []truss.NamedReadWriter
|
||||
}
|
||||
|
||||
// templateExecutor is passed to templates as the executing struct; its fields
|
||||
// Executor is passed to templates as the executing struct; its fields
|
||||
// and methods are used to modify the template
|
||||
type TemplateExecutor struct {
|
||||
type Executor struct {
|
||||
// import path for the directory containing the definition .proto files
|
||||
ImportPath string
|
||||
// import path for .pb.go files containing service structs
|
||||
|
@ -41,12 +43,12 @@ type TemplateExecutor struct {
|
|||
FuncMap template.FuncMap
|
||||
}
|
||||
|
||||
func NewTemplateExecutor(sd *svcdef.Svcdef, conf Config) (*TemplateExecutor, error) {
|
||||
func NewExecutor(sd *svcdef.Svcdef, conf Config) (*Executor, error) {
|
||||
funcMap := template.FuncMap{
|
||||
"ToLower": strings.ToLower,
|
||||
"GoName": generatego.CamelCase,
|
||||
}
|
||||
return &TemplateExecutor{
|
||||
return &Executor{
|
||||
ImportPath: conf.GoPackage,
|
||||
PBImportPath: conf.PBPackage,
|
||||
PackageName: sd.PkgName,
|
||||
|
@ -56,3 +58,25 @@ func NewTemplateExecutor(sd *svcdef.Svcdef, conf Config) (*TemplateExecutor, err
|
|||
FuncMap: funcMap,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ApplyTemplate applies the passed template with the Executor
|
||||
func (e *Executor) ApplyTemplate(templ string, templName string) (io.Reader, error) {
|
||||
return ApplyTemplate(templ, templName, e, e.FuncMap)
|
||||
}
|
||||
|
||||
// ApplyTemplate is a helper methods that packages can call to render a
|
||||
// template with any executor and func map
|
||||
func ApplyTemplate(templ string, templName string, executor interface{}, funcMap template.FuncMap) (io.Reader, error) {
|
||||
codeTemplate, err := template.New(templName).Funcs(funcMap).Parse(templ)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot create template")
|
||||
}
|
||||
|
||||
outputBuffer := bytes.NewBuffer(nil)
|
||||
err = codeTemplate.Execute(outputBuffer, executor)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "template error")
|
||||
}
|
||||
|
||||
return outputBuffer, nil
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ func init() {
|
|||
gopath = filepath.SplitList(os.Getenv("GOPATH"))
|
||||
}
|
||||
|
||||
func TestNewTemplateExecutor(t *testing.T) {
|
||||
func TestNewExecutor(t *testing.T) {
|
||||
const def = `
|
||||
syntax = "proto3";
|
||||
|
||||
|
@ -54,7 +54,7 @@ func TestNewTemplateExecutor(t *testing.T) {
|
|||
PBPackage: "github.com/TuneLab/go-truss/gengokit/general-service",
|
||||
}
|
||||
|
||||
te, err := NewTemplateExecutor(sd, conf)
|
||||
te, err := NewExecutor(sd, conf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -23,7 +23,9 @@ import (
|
|||
// NewService is an exported func that creates a new service
|
||||
// it will not be defined in the service definition but is required
|
||||
const ignoredFunc = "NewService"
|
||||
const serverTemplPath = "NAME-service/handlers/server/server_handler.gotemplate"
|
||||
|
||||
// ServerFile is the path to the service handelr file that handler will render
|
||||
const ServerFile = "NAME-service/handlers/server/server_handler.gotemplate"
|
||||
|
||||
// New returns a truss.Renderable capable of updating server handlers.
|
||||
// New should be passed the previous version of the server handler to parse.
|
||||
|
@ -74,23 +76,23 @@ type handlerExecutor struct {
|
|||
|
||||
// Render returns a go code server handler that has functions for all
|
||||
// ServiceMethods in the service definition.
|
||||
func (h *handler) Render(f string, te *gengokit.TemplateExecutor) (io.Reader, error) {
|
||||
if f != serverTemplPath {
|
||||
return nil, errors.Errorf("cannot render unknown file: %q", f)
|
||||
func (h *handler) Render(alias string, executor *gengokit.Executor) (io.Reader, error) {
|
||||
if alias != ServerFile {
|
||||
return nil, errors.Errorf("cannot render unknown file: %q", alias)
|
||||
}
|
||||
if h.ast == nil {
|
||||
return applyServerTempl(te)
|
||||
return applyServerTempl(executor)
|
||||
}
|
||||
|
||||
// Remove exported methods not defined in service definition
|
||||
// and remove methods defined in the previous file from methodMap
|
||||
log.WithField("Service Methods", len(h.mMap)).Debug("Before prune")
|
||||
h.ast.Decls = h.mMap.pruneDecls(h.ast.Decls, te.PackageName)
|
||||
h.ast.Decls = h.mMap.pruneDecls(h.ast.Decls, executor.PackageName)
|
||||
log.WithField("Service Methods", len(h.mMap)).Debug("After prune")
|
||||
|
||||
// create a new executor, and add all methods not defined in the previous file
|
||||
ex := handlerExecutor{
|
||||
PackageName: te.PackageName,
|
||||
PackageName: executor.PackageName,
|
||||
}
|
||||
|
||||
// If there are no methods to template then exit early
|
||||
|
@ -283,30 +285,15 @@ func exprString(e ast.Expr) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func applyServerTempl(exec *gengokit.TemplateExecutor) (io.Reader, error) {
|
||||
func applyServerTempl(exec *gengokit.Executor) (io.Reader, error) {
|
||||
log.Debug("Rendering handler for the first time")
|
||||
return applyTemplate(serverTempl, "ServerTempl", exec)
|
||||
return exec.ApplyTemplate(serverTempl, "ServerTempl")
|
||||
}
|
||||
|
||||
func applyServerMethsTempl(exec handlerExecutor) (io.Reader, error) {
|
||||
return applyTemplate(serverMethsTempl, "ServerMethsTempl", exec)
|
||||
}
|
||||
|
||||
func applyTemplate(templ string, templName string, exec interface{}) (io.Reader, error) {
|
||||
funcMap := template.FuncMap{
|
||||
"ToLower": strings.ToLower,
|
||||
"GoName": generatego.CamelCase,
|
||||
}
|
||||
codeTemplate, err := template.New(templName).Funcs(funcMap).Parse(templ)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot create template")
|
||||
}
|
||||
|
||||
outputBuffer := bytes.NewBuffer(nil)
|
||||
err = codeTemplate.Execute(outputBuffer, exec)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "template error")
|
||||
}
|
||||
|
||||
return outputBuffer, nil
|
||||
return gengokit.ApplyTemplate(serverMethsTempl, "ServerMethsTempl", exec, funcMap)
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ func TestApplyServerTempl(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
te, err := gengokit.NewTemplateExecutor(sd, conf)
|
||||
te, err := gengokit.NewExecutor(sd, conf)
|
||||
|
||||
gen, err := applyServerTempl(te)
|
||||
genBytes, err := ioutil.ReadAll(gen)
|
||||
|
|
Загрузка…
Ссылка в новой задаче