From 81f585cd644ae4f3ff6363789d7d7744abda3938 Mon Sep 17 00:00:00 2001 From: alimy Date: Fri, 6 Mar 2020 16:29:59 +0800 Subject: [PATCH] optimize generator and parser init logic --- core/core.go | 43 +++++--------- engine/engine.go | 13 +++-- internal/generator/generator.go | 66 +++++++++++++++++++--- internal/generator/generator_chi.go | 25 -------- internal/generator/generator_gin.go | 22 -------- internal/generator/generator_httprouter.go | 25 -------- internal/generator/generator_mux.go | 25 -------- internal/parser/fields.go | 4 +- internal/parser/parser.go | 37 ++++++------ internal/parser/reflex.go | 8 +-- 10 files changed, 107 insertions(+), 161 deletions(-) delete mode 100644 internal/generator/generator_chi.go delete mode 100644 internal/generator/generator_gin.go delete mode 100644 internal/generator/generator_httprouter.go delete mode 100644 internal/generator/generator_mux.go diff --git a/core/core.go b/core/core.go index eb66600..8dcb4f8 100644 --- a/core/core.go +++ b/core/core.go @@ -4,10 +4,10 @@ package core -import ( - "log" - "os" - "path/filepath" +// options key list +const ( + OptSinkPath = "sinkPath" + OptDefaultTag = "defaultTag" ) var ( @@ -27,44 +27,29 @@ var ( ParserStructTag = "structTag" ) +// Opts use for generator or parser init +type InitOpts = map[string]string + // Options generator options type Options struct { GeneratorName string ParserName string - OutPath string + GeneratorOpts InitOpts + ParserOpts InitOpts } // Parser parse entries type Parser interface { Name() string + Init(opts InitOpts) error Parse(entries []interface{}) (Descriptors, error) } // Generator generate interface code for engine type Generator interface { Name() string - Generate(Descriptors, *Options) error -} - -// SinkPath return output path -func (p *Options) SinkPath() string { - path, err := filepath.EvalSymlinks(p.OutPath) - if err != nil { - if os.IsNotExist(err) { - if !filepath.IsAbs(p.OutPath) { - cwd, err := os.Getwd() - if err != nil { - log.Fatal(err) - } - path = filepath.Join(cwd, p.OutPath) - } else { - path = p.OutPath - } - } else { - log.Fatal(err) - } - } - return path + Init(opts InitOpts) error + Generate(Descriptors) error } // RegisterGenerators register generators @@ -90,7 +75,9 @@ func DefaultOptions() *Options { return &Options{ GeneratorName: GeneratorGin, ParserName: ParserStructTag, - OutPath: "./gen", + GeneratorOpts: InitOpts{ + OptSinkPath: "./gen", + }, } } diff --git a/engine/engine.go b/engine/engine.go index c1ee578..3e91a01 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -15,7 +15,7 @@ import ( ) // Generate generate interface code -func Generate(entries []interface{}, opts *core.Options) error { +func Generate(entries []interface{}, opts *core.Options) (err error) { if opts == nil { return errors.New("options is nil") } @@ -25,15 +25,20 @@ func Generate(entries []interface{}, opts *core.Options) error { if p == nil { return errors.New("parser is nil") } + if err = p.Init(opts.ParserOpts); err != nil { + return + } g := core.GeneratorByName(opts.GeneratorName) if g == nil { return fmt.Errorf("unknow generators that name %s", opts.GeneratorName) } + if err = g.Init(opts.GeneratorOpts); err != nil { + return + } - mirTags, err := p.Parse(entries) - if err != nil { - return g.Generate(mirTags, opts) + if mirTags, err := p.Parse(entries); err == nil { + return g.Generate(mirTags) } return err } diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 4f85da8..df363e3 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -5,6 +5,7 @@ package generator import ( + "errors" "fmt" "os" "path" @@ -16,11 +17,43 @@ import ( "github.com/alimy/mir/v2/core" ) +var ( + errNotExistSinkPath = errors.New("not exist output path") +) + func init() { - core.RegisterGenerators(generatorGin{}, - generatorChi{}, - generatorMux{}, - generatorHttpRouter{}) + core.RegisterGenerators( + mirGenerator{name: core.GeneratorGin}, + mirGenerator{name: core.GeneratorChi}, + mirGenerator{name: core.GeneratorMux}, + mirGenerator{name: core.GeneratorHttpRouter}, + ) +} + +type mirGenerator struct { + sinkPath string + name string +} + +// Name name of generator +func (g mirGenerator) Name() string { + return g.name +} + +// Init init generator +func (g mirGenerator) Init(opts core.InitOpts) (err error) { + if len(opts) != 0 { + if sp, exist := opts[core.OptSinkPath]; exist { + g.sinkPath, err = evalSinkPath(sp) + return + } + } + return errNotExistSinkPath +} + +// Generate generate interface code +func (g mirGenerator) Generate(ds core.Descriptors) error { + return generate(g.name, g.sinkPath, ds) } func notEmptyStr(s string) bool { @@ -48,13 +81,13 @@ func inflateQuery(qs []string) string { return strings.TrimRight(b.String(), ",") } -func generate(ds core.Descriptors, opts *core.Options) error { +func generate(generatorName string, sinkPath string, ds core.Descriptors) error { var ( err error dirPath, filePath string ) - apiPath := filepath.Join(opts.SinkPath(), "api") + apiPath := filepath.Join(sinkPath, "api") tmpl := template.New("mir").Funcs(template.FuncMap{ "notEmptyStr": notEmptyStr, "notHttpAny": notHttpAny, @@ -62,9 +95,9 @@ func generate(ds core.Descriptors, opts *core.Options) error { "valideQuery": valideQuery, "inflateQuery": inflateQuery, }) - assetName, exist := tmplFiles[opts.GeneratorName] + assetName, exist := tmplFiles[generatorName] if !exist { - return fmt.Errorf("not exist templates for genererator:%s", opts.GeneratorName) + return fmt.Errorf("not exist templates for genererator:%s", generatorName) } if tmpl, err = tmpl.Parse(MustAssetString(assetName)); err != nil { return err @@ -94,3 +127,20 @@ FuckErr: return err } + +func evalSinkPath(path string) (string, error) { + sp, err := filepath.EvalSymlinks(path) + if err != nil { + if os.IsNotExist(err) { + if !filepath.IsAbs(path) { + if cwd, err := os.Getwd(); err == nil { + sp = filepath.Join(cwd, path) + } + } else { + sp = path + err = nil + } + } + } + return sp, err +} diff --git a/internal/generator/generator_chi.go b/internal/generator/generator_chi.go deleted file mode 100644 index dad84f5..0000000 --- a/internal/generator/generator_chi.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2019 Michael Li . All rights reserved. -// Use of this source code is governed by Apache License 2.0 that -// can be found in the LICENSE file. -// Copyright 2019 Michael Li . All rights reserved. -// Use of this source code is governed by Apache License 2.0 that -// can be found in the LICENSE file. - -package generator - -import ( - "github.com/alimy/mir/v2/core" -) - -// generatorChi generator for go-chi -type generatorChi struct{} - -// Name name of generator -func (generatorChi) Name() string { - return core.GeneratorChi -} - -// Generate generate interface code -func (generatorChi) Generate(ds core.Descriptors, opts *core.Options) error { - return generate(ds, opts) -} diff --git a/internal/generator/generator_gin.go b/internal/generator/generator_gin.go deleted file mode 100644 index 800d8d3..0000000 --- a/internal/generator/generator_gin.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2019 Michael Li . All rights reserved. -// Use of this source code is governed by Apache License 2.0 that -// can be found in the LICENSE file. - -package generator - -import ( - "github.com/alimy/mir/v2/core" -) - -// generatorGin generator for Gin -type generatorGin struct{} - -// Name name of generator -func (generatorGin) Name() string { - return core.GeneratorGin -} - -// Generate generate interface code -func (generatorGin) Generate(ds core.Descriptors, opts *core.Options) error { - return generate(ds, opts) -} diff --git a/internal/generator/generator_httprouter.go b/internal/generator/generator_httprouter.go deleted file mode 100644 index ea2f0c4..0000000 --- a/internal/generator/generator_httprouter.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2019 Michael Li . All rights reserved. -// Use of this source code is governed by Apache License 2.0 that -// can be found in the LICENSE file. -// Copyright 2019 Michael Li . All rights reserved. -// Use of this source code is governed by Apache License 2.0 that -// can be found in the LICENSE file. - -package generator - -import ( - "github.com/alimy/mir/v2/core" -) - -// generatorHttpRouter generator for HttpRouter -type generatorHttpRouter struct{} - -// Name name of generator -func (generatorHttpRouter) Name() string { - return core.GeneratorHttpRouter -} - -// Generate generate interface code -func (generatorHttpRouter) Generate(ds core.Descriptors, opts *core.Options) error { - return generate(ds, opts) -} diff --git a/internal/generator/generator_mux.go b/internal/generator/generator_mux.go deleted file mode 100644 index 02e9d6d..0000000 --- a/internal/generator/generator_mux.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2019 Michael Li . All rights reserved. -// Use of this source code is governed by Apache License 2.0 that -// can be found in the LICENSE file. -// Copyright 2019 Michael Li . All rights reserved. -// Use of this source code is governed by Apache License 2.0 that -// can be found in the LICENSE file. - -package generator - -import ( - "github.com/alimy/mir/v2/core" -) - -// generatorMux generator for Mux -type generatorMux struct{} - -// Name name of generator -func (generatorMux) Name() string { - return core.GeneratorMux -} - -// Generate generate interface code -func (generatorMux) Generate(ds core.Descriptors, opts *core.Options) error { - return generate(ds, opts) -} diff --git a/internal/parser/fields.go b/internal/parser/fields.go index dd39731..dac248e 100644 --- a/internal/parser/fields.go +++ b/internal/parser/fields.go @@ -49,11 +49,11 @@ type tagInfo struct { } // tagInfoFrom build tagInfo from field -func tagInfoFrom(field reflect.StructField) (*tagInfo, error) { +func (p mirParser) tagInfoFrom(field reflect.StructField) (*tagInfo, error) { info := &tagInfo{} // lookup mir tag info from struct field - tag, exist := field.Tag.Lookup(defaultTag) + tag, exist := field.Tag.Lookup(p.tagName) if !exist { return nil, errNotExist } diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 47aaf0d..39b1528 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -11,33 +11,34 @@ import ( ) func init() { - core.RegisterParsers(parserStructTag{}) + core.RegisterParsers(mirParser{tagName: defaultTag}) } -// parserStructTag parse for struct tag -type parserStructTag struct{} +// mirParser parse for struct tag +type mirParser struct { + tagName string +} // Name name of parser -func (parserStructTag) Name() string { +func (p mirParser) Name() string { return core.ParserStructTag } -// Parse parse interface define object entries -func (parserStructTag) Parse(entries []interface{}) (core.Descriptors, error) { - if len(entries) == 0 { - return nil, errors.New("entries is empty") +// Init init parser +func (p mirParser) Init(opts core.InitOpts) error { + if len(opts) != 0 { + p.tagName = opts[core.OptDefaultTag] } - return reflex(entries) -} - -// SetDefaultTag set default tag name -func SetDefaultTag(tag string) { - if len(tag) > 0 { - defaultTag = tag + if p.tagName == "" { + p.tagName = defaultTag } + return nil } -// DefaultTag return default tag name -func DefaultTag() string { - return defaultTag +// Parse parse interface define object entries +func (p mirParser) Parse(entries []interface{}) (core.Descriptors, error) { + if len(entries) == 0 { + return nil, errors.New("entries is empty") + } + return p.reflex(entries) } diff --git a/internal/parser/reflex.go b/internal/parser/reflex.go index f5c3403..2dc0239 100644 --- a/internal/parser/reflex.go +++ b/internal/parser/reflex.go @@ -12,11 +12,11 @@ import ( // reflex get Descriptors from parse entries // Notice: Descriptors may be an empty if no actual item -func reflex(entries []interface{}) (core.Descriptors, error) { +func (p mirParser) reflex(entries []interface{}) (core.Descriptors, error) { var err error ds := make(core.Descriptors) for _, entry := range entries { - iface, err := ifaceFrom(entry) + iface, err := p.ifaceFrom(entry) if err != nil { break } @@ -31,7 +31,7 @@ func reflex(entries []interface{}) (core.Descriptors, error) { return ds, err } -func ifaceFrom(entry interface{}) (*core.IfaceDescriptor, error) { +func (p mirParser) ifaceFrom(entry interface{}) (*core.IfaceDescriptor, error) { // used to find tagInfo entryType := reflect.TypeOf(entry) isPtr := false @@ -65,7 +65,7 @@ func ifaceFrom(entry interface{}) (*core.IfaceDescriptor, error) { var groupSetuped, chainSetuped bool for i := 0; i < entryType.NumField(); i++ { field := entryType.Field(i) - switch tagInfo, err := tagInfoFrom(field); err { + switch tagInfo, err := p.tagInfoFrom(field); err { case nil: // group field so just parse group info.group info only have one field if tagInfo.isGroup {