123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523 |
- package generator
- import (
- "encoding/json"
- "fmt"
- "strings"
-
- "git.eugeniocarvalho.dev/eugeniucarvalho/utils"
- G "github.com/dave/jennifer/jen"
- )
- const (
- // UTILS = "git.gojus.com.br/eugeniucarvalho/utils"
- // GENERATOR_BASE = "git.gojus.com.br/eugeniucarvalho/gg/generator"
- )
- type Generator struct {
- Language string `json:"language"`
- Keywords []string `json:"keywords"`
- Commands map[string]*Command `json:"commands"`
- BuiltIn map[string]*Command `json:"builtIn"`
- Output string
- }
- type Command struct {
- Name string `json:"name"`
- IgnoreGen bool `json:"ignoreGen"`
- Delimiter string `json:"delimiter"`
- MethodName string `json:"-"`
- Template string `json:"template"`
- ParamList []Param `json:"paramList,omitempty"`
- Description string `json:"description,omitempty"`
- RenderChildrenAs string `json:"readChildrenAs,omitempty"`
- ChildrenRenderMode string `json:"childrenRenderMode,omitempty"`
- }
- type Param struct {
- Name string `json:"name"`
- Type string `json:"type"`
- }
- func New(file string) (*Generator, error) {
- data, err := utils.FileGetContents(file)
- if err == nil {
- g := &Generator{}
- if err = json.Unmarshal([]byte(data), g); err == nil {
- // g.BuiltInRegister()
- return g, nil
- }
- }
- return nil, err
- }
- func (g *Generator) AddCommand(key string, cmd *Command) {
- g.Keywords = append(g.Keywords, key)
- g.Commands[key] = cmd
- }
- func (g *Generator) Gen(folder string) (err error) {
- g.Output = folder
- file := G.NewFile(g.Language)
- // Cria interface com todos os metodos
- if err = g.GenBaseInterface(file); err != nil {
- return err
- }
- // Cria todas as funcoes staticas com os comandos basicos
- // g.GenBuiltIn(file)
- fmt.Printf("Filepath: %s\n", g.FilePath("struct.go"))
- if err = file.Save(g.FilePath(g.Language + ".go")); err != nil {
- panic(err)
- }
- return nil
- }
- func (g *Generator) FilePath(name string) string {
- return fmt.Sprintf("%s/%s/%s", g.Output, g.Language, name)
- }
- func (g *Generator) GenBaseInterface(file *G.File) (err error) {
- // file.Type().Id("File").StructFunc(func(g *G.Group) {
- // g.Add(G.Id("Group"))
- // g.Add(G.Id("Name").Id("string"))
- // }).Line()
- // file.Func().Id("NewFile").Params(G.Id("file").Id("string")).Params(G.Op("*").Id("File")).Block(
- // G.Return(G.Op("&").Id("File").Values(G.Dict{
- // G.Id("Name"): G.Id("file"),
- // })),
- // )
- // file.Func().Params(G.Id("f").Op("*").Id("File")).Id("Save").Params().Params(G.Id("error")).Block(
- // G.Return(G.Qual(UTILS, "FilePutContents").Call(
- // G.Id("f").Dot("Name"),
- // G.Id("f").Dot("GoString").Call(),
- // G.Lit(777),
- // )),
- // )
- // file.Comment("Entidade representa menor unidade de Statement.")
- // file.Type().Id("Stmt").StructFunc(func(g *G.Group) {
- // g.Add(G.Id("Group"))
- // g.Add(G.Id("value").Id("interface{}"))
- // g.Add(G.Id("template").Id("string"))
- // g.Add(G.Id("Separete").Id("string"))
- // // g.Add(G.Id("Childrens").Index().Id("CodeInterface"))
- // }).Line()
- // file.Func().Params(
- // G.Id("s").Op("*").Id("Stmt"),
- // ).Id("Render").Params(
- // G.Id("buffer").Op("*").Qual("bytes", "Buffer"),
- // // G.Id("buffer").Op("*").Id("bytes").Dot("Buffer"),
- // ).Params(
- // G.Id("err").Id("error"),
- // ).Block(
- // G.For(
- // G.List(G.Id("_"), G.Id("s")).Op(":=").Range().Id("s").Dot("Stmts"),
- // ).Block(
- // G.Id("err").Op("=").Id("s").Dot("Render").Call(G.Id("buffer")),
- // ).Line().Return(G.Empty()),
- // )
- // file.Comment("Root node group of Statement.")
- // file.Type().Id("Group").StructFunc(func(g *G.Group) {
- // g.Add(G.Qual(GENERATOR_BASE, "Group"))
- // // g.Add(G.Id("Stmts").Index().Id("CodeInterface"))
- // }).Line()
- // file.Comment("Metodo realiza a renderização de um grupo e todos os seus statements.")
- // file.Func().Params(
- // G.Id("g").Op("*").Id("Group"),
- // ).Id("Render").Params(
- // G.Id("buffer").Op("*").Qual("bytes", "Buffer"),
- // // G.Id("buffer").Op("*").Id("bytes").Dot("Buffer"),
- // ).Params(
- // G.Id("err").Id("error"),
- // ).Block(
- // G.For(
- // G.List(G.Id("_"), G.Id("s")).Op(":=").Range().Id("g").Dot("Stmts"),
- // ).Block(
- // G.Id("err").Op("=").Id("s").Dot("Render").Call(G.Id("buffer")),
- // ).Line().Return(G.Empty()),
- // )
- // file.Comment("Metodo Gera a string do arquivo.")
- // file.Func().Params(
- // G.Id("g").Op("*").Id("Group"),
- // ).Id("GoString").Params().Params(
- // G.Id("string"),
- // ).Block(
- // G.Id("buf").Op(":=").Qual("bytes", "Buffer").Values(),
- // // G.Id("buf").Op(":=").Id("bytes").Dot("Buffer"),
- // G.If(
- // G.Id("err").Op(":=").Id("g").Dot("Render").Call(G.Op("&").Id("buf")),
- // G.Id("err").Op("!=").Nil(),
- // ).Block(
- // G.Id("panic").Call(G.Id("err")),
- // ).Line().Return(G.Id("buf").Dot("String").Call()),
- // ).Line()
- // file.Func().Id("NewGroup").Params().Op("*").Id("Group").Block(
- // G.Return(G.Op("&").Id("Group").Values()),
- // ).Line()
- var (
- cmd *Command
- uppKey string
- found bool
- // interfacesMethods = []*G.Statement{}
- method *G.Statement
- methods = []string{}
- )
- codeInterface := file.Type().Id("CodeInterface")
- interfaces := G.Statement{}
- // Adiciona a importacao da interface do gerador
- // interfaces = append(interfaces, G.Qual(GENERATOR_BASE, "CodeInterface"))
- interfaces = append(interfaces, G.Id("BaseCodeInterface"))
- // interfaces = append(interfaces, G.Id("Render").Params(
- // G.Id("buffer").Op("*").Qual("bytes", "Buffer"),
- // ).Params(G.Id("error")))
- for _, key := range g.Keywords {
- uppKey = strings.Title(key)
- methods = append(methods, uppKey)
- if cmd, found = g.Commands[key]; found {
- cmd.Name = key
- cmd.MethodName = uppKey
- interfaces = genCmd(file, cmd, interfaces)
- } else {
- // Todos os metodos para keywords genericas sem template
- // são tratados aqui.
- interfaces = append(interfaces, G.Id(uppKey).Params().Params(G.Op("*").Id("Group")))
- method = G.Func().Params(
- G.Id("g").Op("*").Id("Group"),
- ).Id(uppKey).Params().Params(G.Op("*").Id("Group"))
- file.Add(method.Clone().Block(
- G.Id("s").Op(":=").Op("&").Id("Stmt").Values(G.Dict{
- G.Id("Value"): G.Lit(key),
- G.Id("Template"): G.Lit(" %s "),
- }),
- G.Id("g").Dot("Stmts").Op("=").Append(
- G.Id("g").Dot("Stmts"),
- G.Id("s"),
- ),
- G.Return(G.Id("g")),
- ).Line())
- ModuleFunction(file, uppKey, G.Statement{}, []string{})
- }
- }
- codeInterface.Interface(interfaces...)
- return
- }
- func genCmd(file *G.File, cmd *Command, interfaces G.Statement) G.Statement {
- var (
- p *G.Statement
- params = G.Statement{}
- paramsKeys = []string{}
- paramsTypes = []string{}
- )
- file.Func().Params(
- G.Id("g").Op("*").Id("Group"),
- ).Id(cmd.MethodName).ParamsFunc(func(g *G.Group) {
- if len(cmd.ParamList) == 0 {
- return
- }
- for _, param := range cmd.ParamList {
- p = G.Id(param.Name).Id(param.Type)
- g.Add(p)
- paramsKeys = append(paramsKeys, param.Name)
- paramsTypes = append(paramsTypes, param.Type)
- params = append(params, p)
- }
- interfaces = append(interfaces, G.Id(cmd.MethodName).Params(params...).Params(G.Op("*").Id("Group")))
- }).Params(
- G.Op("*").Id("Group"),
- ).BlockFunc(func(g *G.Group) {
- // g.Add(G.Id("s").Op(":=").Op("&").Qual(GENERATOR_BASE, "Stmt").ValuesFunc(func(x *G.Group) {
- g.Add(G.Id("s").Op(":=").Op("&").Id("Stmt").ValuesFunc(func(x *G.Group) {
- var (
- value interface{}
- // lit bool
- lit = true
- )
- x.Add(G.Id("Template").Op(":").Lit(fmt.Sprintf(" %s ", cmd.Template)))
- for k, typ := range paramsTypes {
- // fmt.Println("---", k, typ, paramsKeys[k])
- switch {
- case typ == "string" || typ == "interface{}":
- value = paramsKeys[k]
- lit = false
- case typ[0:3] == "...":
- x.Add(
- // G.Id("Group").Op(":").Id("Group").Values(
- // G.Id("Group").Op(":").Qual(GENERATOR_BASE, "Group").Values(G.Dict{
- G.Id("Group").Op(":").Id("Group").Values(G.Dict{
- G.Id("Stmts"): G.Id(paramsKeys[k]),
- }),
- )
- paramsKeys[k] += "..."
- default:
- // x.Add(G.Id("Group").Op(":").Id("Group").Values(
- // G.Qual(GENERATOR_BASE, "Group").Op(":").Qual(GENERATOR_BASE, "Group").Values(G.Dict{
- // G.Id("Stmts"): G.Index().Id("CodeInterface").Values(G.Id(paramsKeys[k])),
- // }),
- // ))
- // x.Add(G.Id("Group").Op(":").Qual(GENERATOR_BASE, "Group").Values(G.Dict{
- // G.Id("Stmts"): G.Index().Qual(GENERATOR_BASE, "CodeInterface").Values(G.Id(paramsKeys[k])),
- // }))
- x.Add(G.Id("Group").Op(":").Id("Group").Values(G.Dict{
- G.Id("Stmts"): G.Index().Id("CodeInterface").Values(G.Id(paramsKeys[k])),
- }))
- }
- break
- }
- if value == nil {
- value = cmd.Name
- }
- if lit {
- x.Add(G.Id("Value").Op(":").Lit(value))
- } else {
- x.Add(G.Id("Value").Op(":").Id(value.(string)))
- }
- if cmd.Delimiter != "" {
- x.Add(G.Id("Delimiter").Op(":").Lit(cmd.Delimiter))
- }
- }))
- g.Add(G.Id("g").Dot("Stmts").Op("=").Append(
- G.Id("g").Dot("Stmts"),
- G.Id("s"),
- ))
- g.Add(G.Return(G.Id("g")))
- }).Line()
- ModuleFunction(file, cmd.MethodName, params, paramsKeys)
- return interfaces
- }
- func ModuleFunction(file *G.File, method string, params G.Statement, paramsKeys []string) {
- file.Func().Id(method).Params(params...).Params(G.Op("*").Id("Group")).Block(
- G.Return(G.Id("NewGroup").Call().Dot(method).CallFunc(func(g *G.Group) {
- for _, key := range paramsKeys {
- g.Add(G.Id(key))
- }
- })),
- ).Line()
- }
- // func (g *Generator) BuiltInRegister() {
- // if g.BuiltIn == nil {
- // g.BuiltIn = map[string]*Command{}
- // }
- // fmt.Println("Add built in")
- // g.AddBuiltIn("params", &Command{
- // Template: "(%s)",
- // ParamList: []Param{
- // Param{
- // Name: "params",
- // Type: "...CodeInterface",
- // },
- // },
- // Description: "Parameter definition in function declaration.",
- // })
- // g.AddBuiltIn("op", &Command{
- // Template: " %s ",
- // ParamList: []Param{
- // Param{
- // Name: "op",
- // Type: "string",
- // },
- // },
- // Description: "Representa um operando {=,!=,>,<,>=,<=,-,+,*,/,%}.",
- // })
- // g.AddBuiltIn("block", &Command{
- // // Template: " {\n%s\n}\n",
- // Template: " {%s}\n",
- // RenderChildrenAs: "lines",
- // ParamList: []Param{
- // Param{
- // Name: "stmts",
- // Type: "...CodeInterface",
- // },
- // },
- // })
- // g.AddBuiltIn("call", &Command{
- // Template: "(%s)",
- // ParamList: []Param{
- // Param{
- // Name: "params",
- // Type: "CodeInterface",
- // },
- // },
- // Description: "Generete a call of function or method. The parameter is um List Stmt.",
- // })
- // g.AddBuiltIn("id", &Command{
- // Template: "%s",
- // ParamList: []Param{
- // Param{
- // Name: "stmt",
- // Type: "string",
- // },
- // },
- // })
- // g.AddBuiltIn("comment", &Command{
- // Template: "\n//%s\n",
- // IgnoreGen: true,
- // ParamList: []Param{
- // Param{
- // Name: "stmt",
- // Type: "string",
- // },
- // },
- // })
- // g.AddBuiltIn("lit", &Command{
- // Template: "%s",
- // IgnoreGen: true,
- // ParamList: []Param{
- // Param{
- // Name: "stmt",
- // Type: "interface{}",
- // },
- // },
- // })
- // g.AddBuiltIn("index", &Command{
- // Template: "[%s]",
- // ParamList: []Param{
- // Param{
- // Name: "index",
- // Type: "CodeInterface",
- // },
- // },
- // Description: "Gen a index access. The parameter is a List",
- // })
- // }
- // func (g *Generator) AddBuiltIn(key string, cmd *Command) {
- // // g.BuiltIn = append(g.BuiltIn, key)
- // g.BuiltIn[key] = cmd
- // }
- // func (g *Generator) GenBuiltIn(file *G.File) {
- // var (
- // params *G.Statement
- // paramsKeys []string
- // name string
- // typ string
- // ret string
- // )
- // for method, cmd := range g.BuiltIn {
- // paramsKeys = []string{}
- // method = strings.Title(method)
- // params = &G.Statement{}
- // for _, param := range cmd.ParamList {
- // name = param.Name
- // typ = param.Type
- // ret = ""
- // if strings.Contains(typ, "...") {
- // ret = "..."
- // name += ret
- // typ = typ[3:]
- // }
- // if strings.Contains(param.Type, "CodeInterface") {
- // params.Add(G.Id(param.Name).Op(ret).Qual(GENERATOR_BASE, typ))
- // } else {
- // params.Add(G.Id(param.Name).Id(typ))
- // }
- // paramsKeys = append(paramsKeys, name)
- // // params = append(params, G.Id(param.Name).Id(param.Type))
- // }
- // file.Func().Params(
- // G.Id("g").Op("*").Id("Group"),
- // ).Id(method).Params(*params...).Params(
- // G.Op("*").Id("Group"),
- // ).Block(
- // // G.Id("g").Dot(method).CallFunc(func(g *G.Group) {
- // // for _, key := range paramsKeys {
- // // g.Add(G.Id(key))
- // // }
- // // }),
- // G.Id("g").Dot("Group").Dot(method).CallFunc(func(g *G.Group) {
- // for _, key := range paramsKeys {
- // g.Add(G.Id(key))
- // }
- // }),
- // G.Return(G.Id("g")),
- // ).Line()
- // file.Func().Id(method).Params(*params...).Params(
- // G.Op("*").Id("Group"),
- // ).Block(
- // G.Return(G.Id("NewGroup").Call().Dot(method).CallFunc(func(g *G.Group) {
- // for _, key := range paramsKeys {
- // g.Add(G.Id(key))
- // }
- // })),
- // ).Line()
- // }
- // }
|