diff --git a/core/core.go b/core/core.go index 1767522..d8d792a 100644 --- a/core/core.go +++ b/core/core.go @@ -61,6 +61,8 @@ type InitOpts struct { EngineImportAlias string WatchCtxDone bool UseRequestCtx bool + UseNamedBinding bool + UseNamedRender bool NoneQuery bool Cleanup bool } @@ -73,6 +75,8 @@ type ParserOpts struct { DefaultRenderTag string WatchCtxDone bool UseRequestCtx bool + UseNamedBinding bool + UseNamedRender bool NoneQuery bool } @@ -107,6 +111,8 @@ func (opts *InitOpts) ParserOpts() *ParserOpts { DefaultRenderTag: opts.DefaultRenderTag, WatchCtxDone: opts.WatchCtxDone, UseRequestCtx: opts.UseRequestCtx, + UseNamedBinding: opts.UseNamedBinding, + UseNamedRender: opts.UseNamedRender, NoneQuery: opts.NoneQuery, EngineInfo: &EngineInfo{ PkgName: opts.EnginePkgName, @@ -310,6 +316,24 @@ func UseRequestContext() Option { }) } +// UseNamedBinding use Named Binding. +// will generate BindByName(string, *gin.Context, any) mir.Error method to binding +// object when this option is enable. +func UseNamedBinding() Option { + return optFunc(func(opts *InitOpts) { + opts.UseNamedBinding = true + }) +} + +// UseNamedBinding use Named Binding. +// will generate RenderByName(string, *gin.Context, any, mir.Error) method to render +// object when this option is enable. +func UseNamedRender() Option { + return optFunc(func(opts *InitOpts) { + opts.UseNamedRender = true + }) +} + // Cleanup set generator cleanup out first when re-generate code func Cleanup(enable bool) Option { return optFunc(func(opts *InitOpts) { @@ -434,6 +458,8 @@ func defaultInitOpts() *InitOpts { DefaultRenderTag: "render", WatchCtxDone: true, UseRequestCtx: false, + UseNamedBinding: false, + UseNamedRender: false, Cleanup: true, } } diff --git a/core/descriptor.go b/core/descriptor.go index fbcd5af..315249b 100644 --- a/core/descriptor.go +++ b/core/descriptor.go @@ -10,6 +10,7 @@ import ( "reflect" "sort" "strings" + "unicode" "github.com/alimy/mir/v4/internal/utils" ) @@ -47,6 +48,8 @@ type FieldDescriptor struct { IsRenderOut bool BindingName string RenderName string + UseBindingById bool + UseRenderById bool In reflect.Type Out reflect.Type InOuts []reflect.Type @@ -265,21 +268,94 @@ func (d *IfaceDescriptor) BindingFields() (fields []*FieldDescriptor) { } func (d *IfaceDescriptor) IsUseNamedBinding() bool { + var isNamedBinding, useBindingById bool for _, f := range d.Fields { if f.IsUseNamedBinding() { - return true + isNamedBinding = true + break } } - return false + for _, f := range d.Fields { + if f.UseBindingById { + useBindingById = true + break + } + } + return isNamedBinding && !useBindingById } func (d *IfaceDescriptor) IsUseNamedRender() bool { + var isNamedRender, useRenderById bool for _, f := range d.Fields { if f.IsUseNamedRender() { - return true + isNamedRender = true + break } } - return false + for _, f := range d.Fields { + if f.UseRenderById { + useRenderById = true + break + } + } + return isNamedRender && !useRenderById +} + +func (d *IfaceDescriptor) IsUseBindingById() bool { + var isNamedBinding, useBindingById bool + for _, f := range d.Fields { + if f.IsUseNamedBinding() { + isNamedBinding = true + break + } + } + for _, f := range d.Fields { + if f.UseBindingById { + useBindingById = true + } + } + return isNamedBinding && useBindingById +} + +func (d *IfaceDescriptor) IsUseRenderById() bool { + var isNamedRender, useRenderById bool + for _, f := range d.Fields { + if f.IsUseNamedRender() { + isNamedRender = true + break + } + } + for _, f := range d.Fields { + if f.UseRenderById { + useRenderById = true + break + } + } + return isNamedRender && useRenderById +} + +func (d *IfaceDescriptor) BindingIdSet() []string { + set := utils.NewStrSet() + var id string + for _, f := range d.Fields { + id = f.BindingId() + if len(id) > 0 { + set.Add(f.BindingId()) + } + } + return set.List() +} + +func (d *IfaceDescriptor) RenderIdSet() []string { + set := utils.NewStrSet() + var id string + for _, f := range d.Fields { + id = f.RenderId() + if len(id) > 0 { + set.Add(f.RenderId()) + } + } + return set.List() } // HttpMethod return http method when f.NotHttpAny() is true @@ -352,6 +428,38 @@ func (f *FieldDescriptor) IsUseNamedRender() bool { return f.Out != nil && len(f.RenderName) > 0 } +func (f *FieldDescriptor) BindingId() (res string) { + b := &strings.Builder{} + b.Grow(len(f.BindingName)) + for i, r := range f.BindingName { + if r == ' ' || r == '_' { + continue + } + if i == 0 { + b.WriteRune(unicode.ToUpper(r)) + continue + } + b.WriteRune(r) + } + return b.String() +} + +func (f FieldDescriptor) RenderId() string { + b := &strings.Builder{} + b.Grow(len(f.RenderName)) + for i, r := range f.RenderName { + if r == ' ' || r == '_' { + continue + } + if i == 0 { + b.WriteRune(unicode.ToUpper(r)) + continue + } + b.WriteRune(r) + } + return b.String() +} + func (f *FieldDescriptor) aliasPkgName(pkgPath string) string { if alias := f.Imports[pkgPath]; alias != "" { return alias diff --git a/examples/mirc/auto/api/site.go b/examples/mirc/auto/api/site.go index 0f2cc7e..5f23bf0 100644 --- a/examples/mirc/auto/api/site.go +++ b/examples/mirc/auto/api/site.go @@ -22,9 +22,9 @@ type _render_ interface { type _default_ interface { Bind(*gin.Context, any) mir.Error - BindByName(string, *gin.Context, any) mir.Error + BindJson(*gin.Context, any) mir.Error Render(*gin.Context, any, mir.Error) - RenderByName(string, *gin.Context, any, mir.Error) + RenderJson(*gin.Context, any, mir.Error) } type LoginReq struct { @@ -198,11 +198,11 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { } req := new(TweetsReq) if err := s.Bind(c, req); err != nil { - s.RenderByName("json", c, nil, err) + s.RenderJson(c, nil, err) return } resp, err := s.PrevTweets(c.Request.Context(), req) - s.RenderByName("json", c, resp, err) + s.RenderJson(c, resp, err) } router.Handle("GET", "/tweets/prev/", h) router.Handle("HEAD", "/tweets/prev/", h) @@ -215,7 +215,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } req := new(TweetsReq) - if err := s.BindByName("json", c, req); err != nil { + if err := s.BindJson(c, req); err != nil { s.Render(c, nil, err) return } diff --git a/examples/mirc/auto/api/v2/site.go b/examples/mirc/auto/api/v2/site.go index 8e58c26..82eed27 100644 --- a/examples/mirc/auto/api/v2/site.go +++ b/examples/mirc/auto/api/v2/site.go @@ -22,9 +22,12 @@ type _render_ interface { type _default_ interface { Bind(*gin.Context, any) mir.Error - BindByName(string, *gin.Context, any) mir.Error + BindJson(*gin.Context, any) mir.Error + BindYaml(*gin.Context, any) mir.Error Render(*gin.Context, any, mir.Error) - RenderByName(string, *gin.Context, any, mir.Error) + RenderJson(*gin.Context, any, mir.Error) + RenderXML(*gin.Context, any, mir.Error) + RenderJsonp(*gin.Context, any, mir.Error) } type LoginReq struct { @@ -140,11 +143,11 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { } req := new(LoginReq) if err := s.Bind(c, req); err != nil { - s.Render(c, nil, err) + s.RenderJsonp(c, nil, err) return } resp, err := s.SimpleUpload(c, req) - s.Render(c, resp, err) + s.RenderJsonp(c, resp, err) })...) router.Handle("POST", "/upload/file/:name/", append(cc.ChainFileUpload(), s.FileUpload)...) router.Handle("POST", "/upload/image/:name/", s.ImageUpload) @@ -164,7 +167,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } req := new(LoginReq) - if err := s.Bind(c, req); err != nil { + if err := s.BindJson(c, req); err != nil { s.Render(c, nil, err) return } @@ -179,7 +182,7 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { default: } req := new(TweetsReq) - if err := s.BindByName("yaml", c, req); err != nil { + if err := s.BindYaml(c, req); err != nil { s.Render(c, nil, err) return } @@ -198,11 +201,11 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { } req := new(TweetsReq) if err := s.Bind(c, req); err != nil { - s.RenderByName("json", c, nil, err) + s.RenderJson(c, nil, err) return } resp, err := s.NextTweets(c.Request.Context(), req) - s.RenderByName("json", c, resp, err) + s.RenderJson(c, resp, err) }) router.Handle("GET", "/articles/:category/", func(c *gin.Context) { select { diff --git a/examples/mirc/auto/api/v3/site.go b/examples/mirc/auto/api/v3/site.go index 750422c..31caeb4 100644 --- a/examples/mirc/auto/api/v3/site.go +++ b/examples/mirc/auto/api/v3/site.go @@ -24,7 +24,7 @@ type _render_ interface { type _default_ interface { Bind(*gin.Context, any) mir.Error Render(*gin.Context, any, mir.Error) - RenderByName(string, *gin.Context, any, mir.Error) + RenderJsonp(*gin.Context, any, mir.Error) } type Site interface { @@ -146,11 +146,11 @@ func RegisterSiteServant(e *gin.Engine, s Site, m ...SiteChain) { } req := new(model.TweetsReq) if err := s.Bind(c, req); err != nil { - s.RenderByName("jsonp", c, nil, err) + s.RenderJsonp(c, nil, err) return } resp, err := s.NextTweets(c.Request.Context(), req) - s.RenderByName("jsonp", c, resp, err) + s.RenderJsonp(c, resp, err) }) router.Handle("GET", "/articles/:category/", func(c *gin.Context) { select { diff --git a/examples/mirc/routes/v2/site.go b/examples/mirc/routes/v2/site.go index 06e7cb7..099f004 100644 --- a/examples/mirc/routes/v2/site.go +++ b/examples/mirc/routes/v2/site.go @@ -59,13 +59,13 @@ type Site struct { Articles func(Get) `mir:"/articles/:category/"` NextTweets func(Any, TweetsReq) TweetsResp `mir:"/tweets/next/" render:"json"` PrevTweets func(Post, Get, Head, TweetsReq) TweetsResp `mir:"/tweets/prev/" binding:"yaml"` - Login func(Post, LoginReq) LoginResp `mir:"/user/login/"` + Login func(Post, LoginReq) LoginResp `mir:"/user/login/" binding:"json"` Logout func(Post) `mir:"/user/logout/"` ImageUpload func(Post, Context) `mir:"/upload/image/:name/"` FileUpload func(Post, Chain, Context) `mir:"/upload/file/:name/"` - SimpleUpload func(Post, Chain, Context, LoginReq) LoginResp `mir:"/upload/simple/:name/"` + SimpleUpload func(Post, Chain, Context, LoginReq) LoginResp `mir:"/upload/simple/:name/" render:"Jsonp"` Assets func(Get, Context, LoginReq) `mir:"/assets/:name/"` AnyStaticks func(Any, Context) `mir:"/anystaticks/:name/"` ManyResources func(Get, Head, Options, Context) `mir:"/resources/:name/"` - MultiAttachments func(Get, Head, Options, Chain, Context) `mir:"/attachments/:name/"` + MultiAttachments func(Get, Head, Options, Chain, Context) `mir:"/attachments/:name/" render:"XML"` } diff --git a/examples/servants/core.go b/examples/servants/core.go index c98a37c..222a04b 100644 --- a/examples/servants/core.go +++ b/examples/servants/core.go @@ -20,6 +20,20 @@ func (baseSrv) Bind(c *gin.Context, obj any) (err mir.Error) { return } +func (baseSrv) BindJson(c *gin.Context, obj any) (err mir.Error) { + if xerr := c.BindJSON(obj); xerr != nil { + err = mir.NewError(http.StatusBadRequest, xerr) + } + return +} + +func (baseSrv) BindYaml(c *gin.Context, obj any) (err mir.Error) { + if xerr := c.BindYAML(obj); xerr != nil { + err = mir.NewError(http.StatusBadRequest, xerr) + } + return +} + func (baseSrv) Render(c *gin.Context, data any, err mir.Error) { if err == nil { c.JSON(http.StatusOK, data) @@ -28,37 +42,34 @@ func (baseSrv) Render(c *gin.Context, data any, err mir.Error) { } } -func (baseSrv) BindByName(name string, c *gin.Context, obj any) (err mir.Error) { - var xerr error - switch name { - case "yaml": - xerr = c.BindYAML(obj) - case "json": - xerr = c.BindJSON(obj) - default: - xerr = c.ShouldBind(obj) +func (baseSrv) RenderJson(c *gin.Context, data any, err mir.Error) { + if err == nil { + c.JSON(http.StatusOK, data) + } else { + c.JSON(err.StatusCode(), err.Error()) } - if xerr != nil { - err = mir.NewError(http.StatusBadRequest, xerr) +} + +func (baseSrv) RenderJsonp(c *gin.Context, data any, err mir.Error) { + if err == nil { + c.JSONP(http.StatusOK, data) + } else { + c.JSONP(err.StatusCode(), err.Error()) } - return } -func (baseSrv) RenderByName(name string, c *gin.Context, data any, err mir.Error) { - switch name { - case "jsonp": - if err == nil { - c.JSONP(http.StatusOK, data) - } else { - c.JSONP(err.StatusCode(), err.Error()) - } - case "json": - fallthrough - default: - if err == nil { - c.JSON(http.StatusOK, data) - } else { - c.JSON(err.StatusCode(), err.Error()) - } +func (baseSrv) RenderYaml(c *gin.Context, data any, err mir.Error) { + if err == nil { + c.YAML(http.StatusOK, data) + } else { + c.YAML(err.StatusCode(), err.Error()) + } +} + +func (baseSrv) RenderXML(c *gin.Context, data any, err mir.Error) { + if err == nil { + c.XML(http.StatusOK, data) + } else { + c.XML(err.StatusCode(), err.Error()) } } diff --git a/internal/generator/templates/gin_iface.tmpl b/internal/generator/templates/gin_iface.tmpl index c28848c..a244224 100644 --- a/internal/generator/templates/gin_iface.tmpl +++ b/internal/generator/templates/gin_iface.tmpl @@ -26,10 +26,20 @@ type _default_ interface { {{- if .IsUseNamedBinding }} BindByName(string, *gin.Context, any) mir.Error {{- end }} + {{- if .IsUseBindingById }} + {{- range .BindingIdSet }} + Bind{{ . }}(*gin.Context, any) mir.Error + {{- end }} + {{- end }} Render(*gin.Context, any, mir.Error) {{- if .IsUseNamedRender }} RenderByName(string, *gin.Context, any, mir.Error) {{- end }} + {{- if .IsUseRenderById }} + {{- range .RenderIdSet }} + Render{{ . }}(*gin.Context, any, mir.Error) + {{- end }} + {{- end }} } {{- end }} @@ -86,9 +96,9 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField var bv _binding_ = req if err := bv.Bind(c); err != nil { {{- else -}} - if err := {{if .IsUseNamedBinding }}s.BindByName("{{.BindingName}}", c, req){{else}}s.Bind(c, req){{end}}; err != nil { + if err := {{if .IsUseNamedBinding }}{{if .UseBindingById}}s.Bind{{.BindingId}}({{else}}s.BindByName("{{.BindingName}}",{{end}} c, req){{else}}s.Bind(c, req){{end}}; err != nil { {{- end }} - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, nil, err) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, nil, err) return } {{- end }} @@ -96,16 +106,16 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField resp, err := s.{{ .MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName }}req{{end}}) {{if .IsRenderOut -}} if err != nil { - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, nil, err) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, nil, err) return } var rv _render_ = resp rv.Render(c) {{- else -}} - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, resp, err) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, resp, err) {{- end }} {{- else -}} - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, nil, s.{{.MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, nil, s.{{.MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) {{- end }} }{{end}}{{if .IsFieldChain }})...{{end}}) {{else if .JustHttpAny}} router.Any("{{.Path}}", {{if .IsFieldChain }}append(cc.Chain{{.MethodName}}(), {{end}}{{if .JustUseContext}}s.{{ .MethodName}}{{else}}func(c *gin.Context) { @@ -122,9 +132,9 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField var bv _binding_ = req if err := bv.Bind(c); err != nil { {{- else -}} - if err := {{if .IsUseNamedBinding }}s.BindByName("{{.BindingName}}", c, req){{else}}s.Bind(c, req){{end}}; err != nil { + if err := {{if .IsUseNamedBinding }}{{if .UseBindingById}}s.Bind{{.BindingId}}({{else}}s.BindByName("{{.BindingName}}",{{end}} c, req){{else}}s.Bind(c, req){{end}}; err != nil { {{- end }} - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, nil, err) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, nil, err) return } {{- end }} @@ -132,16 +142,16 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField resp, err := s.{{ .MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}}) {{if .IsRenderOut -}} if err != nil { - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, nil, err) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, nil, err) return } var rv _render_ = resp rv.Render(c) {{- else -}} - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, resp, err) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, resp, err) {{- end }} {{- else -}} - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, nil, s.{{.MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, nil, s.{{.MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) {{- end }} }{{end}}{{if .IsFieldChain }})...{{end}}) {{else}}{{$field := .}} { @@ -159,9 +169,9 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField var bv _binding_ = req if err := bv.Bind(c); err != nil { {{- else -}} - if err := {{if .IsUseNamedBinding }}s.BindByName("{{.BindingName}}", c, req){{else}}s.Bind(c, req){{end}}; err != nil { + if err := {{if .IsUseNamedBinding }}{{if .UseBindingById}}s.Bind{{.BindingId}}({{else}}s.BindByName("{{.BindingName}}",{{end}} c, req){{else}}s.Bind(c, req){{end}}; err != nil { {{- end }} - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, nil, err) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, nil, err) return } {{- end }} @@ -169,16 +179,16 @@ func Register{{.TypeName}}Servant(e *gin.Engine, s {{.TypeName}}{{if .IsUseField resp, err := s.{{ .MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}}) {{if .IsRenderOut -}} if err != nil { - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, nil, err) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, nil, err) return } var rv _render_ = resp rv.Render(c) {{- else -}} - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, resp, err) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, resp, err) {{- end }} {{- else -}} - {{if .IsUseNamedRender }}s.RenderByName("{{.RenderName}}", {{else}}s.Render({{end}}c, nil, s.{{.MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) + {{if .IsUseNamedRender }}{{if .UseRenderById}}s.Render{{.RenderId}}({{else}}s.RenderByName("{{.RenderName}}",{{end}} {{else}}s.Render({{end}}c, nil, s.{{.MethodName}}({{if .IsUseRequestContext }}c.Request.Context(){{if notEmptyStr .InName }}, {{end}}{{end}}{{if .IsUseContext }}c{{if notEmptyStr .InName }}, {{end}}{{end}}{{if notEmptyStr .InName}}req{{end}})) {{- end }} }{{end}}{{if .IsFieldChain }}){{end}} {{range .AnyHttpMethods}} router.Handle("{{.}}", "{{$field.Path}}", h{{if $field.IsFieldChain }}...{{end}}) diff --git a/internal/parser/parser.go b/internal/parser/parser.go index c85dedb..7c851a8 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -30,13 +30,15 @@ func init() { // mirParser parse for struct tag type mirParser struct { - engineInfo *core.EngineInfo - tagName string - bindingTagName string - renderTagName string - watchCtxDone bool - useRequestCtx bool - noneQuery bool + engineInfo *core.EngineInfo + tagName string + bindingTagName string + renderTagName string + watchCtxDone bool + useRequestCtx bool + useNamedBinding bool + useNamedRender bool + noneQuery bool } // Name name of parser @@ -57,6 +59,8 @@ func (p *mirParser) Init(opts *core.ParserOpts) error { p.renderTagName = opts.DefaultRenderTag p.watchCtxDone = opts.WatchCtxDone p.useRequestCtx = opts.UseRequestCtx + p.useNamedBinding = opts.UseNamedBinding + p.useNamedRender = opts.UseNamedRender p.noneQuery = opts.NoneQuery if p.tagName == "" { p.tagName = defaultTag @@ -75,7 +79,9 @@ func (p *mirParser) Parse(entries []any) (core.Descriptors, error) { if len(entries) == 0 { return nil, errors.New("entries is empty") } - r := reflex.NewReflex(p.engineInfo, p.tagName, p.bindingTagName, p.renderTagName, p.watchCtxDone, p.useRequestCtx, p.noneQuery) + r := reflex.NewReflex(p.engineInfo, + p.tagName, p.bindingTagName, p.renderTagName, + p.useNamedBinding, p.useNamedRender, p.watchCtxDone, p.useRequestCtx, p.noneQuery) return r.Parse(entries) } @@ -90,7 +96,9 @@ func (p *mirParser) ParseContext(ctx core.MirCtx, entries []any) { go func(ctx core.MirCtx, wg *sync.WaitGroup, ifaceSink chan<- *core.IfaceDescriptor, entry any) { defer wg.Done() - r := reflex.NewReflex(p.engineInfo, p.tagName, p.bindingTagName, p.renderTagName, p.watchCtxDone, p.useRequestCtx, p.noneQuery) + r := reflex.NewReflex(p.engineInfo, + p.tagName, p.bindingTagName, p.renderTagName, + p.useNamedBinding, p.useNamedRender, p.watchCtxDone, p.useRequestCtx, p.noneQuery) iface, err := r.IfaceFrom(entry) if err != nil { core.Logus("ifaceFrom error: %s", err) diff --git a/internal/reflex/reflex.go b/internal/reflex/reflex.go index 3912fa6..f041fd9 100644 --- a/internal/reflex/reflex.go +++ b/internal/reflex/reflex.go @@ -14,14 +14,16 @@ import ( // reflex real parser type reflex struct { - engineInfo *core.EngineInfo - ns naming.NamingStrategy - tagName string - bindingTagName string - renderTagName string - watchCtxDone bool - useRequestCtx bool - noneQuery bool + engineInfo *core.EngineInfo + ns naming.NamingStrategy + tagName string + bindingTagName string + renderTagName string + watchCtxDone bool + useRequestCtx bool + useNamedBinding bool + useNamedRender bool + noneQuery bool } // Parse get Descriptors from parse entries @@ -145,6 +147,8 @@ func (r *reflex) fieldFrom(t *tagInfo, isUseReuestCtx bool, pkgPath string) *cor IsRenderOut: t.isRenderOut, BindingName: strings.Trim(t.bindingName, " "), RenderName: strings.Trim(t.renderName, " "), + UseBindingById: !r.useNamedBinding, + UseRenderById: !r.useNamedRender, In: t.in, Out: t.out, InOuts: t.inOuts, @@ -155,15 +159,19 @@ func (r *reflex) fieldFrom(t *tagInfo, isUseReuestCtx bool, pkgPath string) *cor } } -func NewReflex(info *core.EngineInfo, tagName string, bindingTagName string, renderTagName string, watchCtxDone bool, useRequestCtx bool, noneQuery bool) *reflex { +func NewReflex(info *core.EngineInfo, + tagName, bindingTagName, renderTagName string, + useNamedBinding, useNamedRender, watchCtxDone, useRequestCtx, noneQuery bool) *reflex { return &reflex{ - engineInfo: info, - ns: naming.NewSnakeNamingStrategy(), - tagName: tagName, - bindingTagName: bindingTagName, - renderTagName: renderTagName, - watchCtxDone: watchCtxDone, - useRequestCtx: useRequestCtx, - noneQuery: noneQuery, + engineInfo: info, + ns: naming.NewSnakeNamingStrategy(), + tagName: tagName, + bindingTagName: bindingTagName, + renderTagName: renderTagName, + watchCtxDone: watchCtxDone, + useRequestCtx: useRequestCtx, + useNamedBinding: useNamedBinding, + useNamedRender: useNamedRender, + noneQuery: noneQuery, } }