不支持多个相同类型的参数
package utility
import (
"fmt"
"html/template"
"io/ioutil"
"os"
"regexp"
"sort"
"strings"
"testing"
)
type Repository struct {
Name string
}
type Service struct {
Name string
Args []ServiceArg
}
func (s Service) NewFuncString() string {
sb := new(strings.Builder)
for _, arg := range s.Args {
if strings.HasPrefix(arg.TypeName, "repository.") {
sb.WriteString("repositoryContainer.")
sb.WriteString(arg.TypeName[len("repository."):])
sb.WriteString(",\n")
} else {
dotIndex := strings.LastIndex(arg.TypeName, ".")
if dotIndex > -1 {
str := arg.TypeName[strings.LastIndex(arg.TypeName, ".")+1:]
sb.WriteString(strings.ToLower(str[0:1]))
sb.WriteString(str[1:])
sb.WriteString(",\n")
} else {
sb.WriteString(strings.ToLower(arg.TypeName[0:1]))
sb.WriteString(arg.TypeName[1:])
sb.WriteString(",\n")
}
}
}
return sb.String()
}
type ServiceArg struct {
Name string
TypeName string
}
type RepositoryContext struct {
Repositories []Repository
}
type ServiceContext struct {
Services []Service
}
func (c *ServiceContext) NewFuncString() string {
typeNames := make([]string, 0)
typeNameMap := make(map[string]string)
for _, s := range c.Services {
for _, arg := range s.Args {
typeName := arg.TypeName
if strings.HasPrefix(typeName, "repository.") {
typeName = "repository.RepositoryContainer"
}
if _, ok := typeNameMap[typeName]; !ok {
typeNameMap[typeName] = typeName
typeNames = append(typeNames, typeName)
}
}
}
sort.Strings(typeNames)
sb := new(strings.Builder)
for _, typeName := range typeNames {
if strings.HasPrefix(typeName, "repository.") {
sb.WriteString("repositoryContainer ")
sb.WriteString(typeName)
sb.WriteString(",\n")
} else {
dotIndex := strings.LastIndex(typeName, ".")
if dotIndex > -1 {
str := typeName[strings.LastIndex(typeName, ".")+1:]
sb.WriteString(strings.ToLower(str[0:1]))
sb.WriteString(str[1:])
sb.WriteString(" ")
sb.WriteString(typeName)
sb.WriteString(",\n")
} else {
sb.WriteString(strings.ToLower(typeName[0:1]))
sb.WriteString(typeName[1:])
sb.WriteString(" ")
sb.WriteString(typeName)
sb.WriteString(",\n")
}
}
}
return sb.String()
}
func Test_GenerateRepositoryContainer(t *testing.T) {
files, err1 := os.ReadDir("../repository")
if err1 != nil {
fmt.Println("parse file err:", err1)
return
}
repositories := make([]Repository, 0)
for _, file := range files {
name := file.Name()
if strings.HasSuffix(name, "_repository.go") {
repositories = append(repositories, Repository{Name: UpperCamelCase(name[:len(name)-3])})
}
}
if f, err := os.Stat("../repository/repository_container.go"); f != nil && err == nil {
if err := os.Remove("../repository/repository_container.go"); err != nil {
fmt.Println("remove file err:", err)
return
}
}
f, err2 := os.OpenFile("../repository/repository_container.go", os.O_CREATE|os.O_WRONLY, 0666)
defer f.Close()
if err2 != nil {
fmt.Println("can not create output file,err:", err2)
return
}
tpl, err3 := template.New("repository-container.tpl").ParseFiles("./repository-container.tpl")
if err3 != nil {
fmt.Println("parse file err:", err3)
return
}
if err := tpl.Execute(f, &RepositoryContext{Repositories: repositories}); err != nil {
fmt.Println("There was an error:", err.Error())
return
}
}
func Test_GenerateServiceContainer(t *testing.T) {
files, err1 := os.ReadDir("../service")
if err1 != nil {
fmt.Println("parse file err:", err1)
return
}
services := make([]Service, 0)
for _, file := range files {
filename := file.Name()
if strings.HasSuffix(filename, "_service.go") {
serviceName := UpperCamelCase(filename[:len(filename)-3])
args, err2 := ServiceArgs(fmt.Sprintf("../service/%s", filename), serviceName)
if err2 != nil {
fmt.Println(err2)
return
}
services = append(services, Service{Name: serviceName, Args: args})
}
}
if f, err := os.Stat("../service/service_container.go"); f != nil && err == nil {
if err := os.Remove("../service/service_container.go"); err != nil {
fmt.Println("remove file err:", err)
return
}
}
f, err2 := os.OpenFile("../service/service_container.go", os.O_CREATE|os.O_WRONLY, 0666)
defer f.Close()
if err2 != nil {
fmt.Println("can not create output file,err:", err2)
return
}
tpl, err3 := template.New("service-container.tpl").ParseFiles("./service-container.tpl")
if err3 != nil {
fmt.Println("parse file err:", err3)
return
}
if err := tpl.Execute(f, &ServiceContext{Services: services}); err != nil {
fmt.Println("There was an error:", err.Error())
}
}
func UpperCamelCase(txt string) string {
sb := new(strings.Builder)
strs := strings.Split(txt, "_")
for _, str := range strs {
sb.WriteString(strings.ToUpper(string(str[0])))
sb.WriteString(str[1:])
}
return sb.String()
}
func ServiceArgs(filename, serviceName string) ([]ServiceArg, error) {
content, err1 := ReadGoFile(filename)
if err1 != nil {
return nil, err1
}
args := make([]ServiceArg, 0)
startTxt := fmt.Sprintf("New%s(", serviceName)
firstIndex := strings.Index(content, startTxt) + len(startTxt)
lastIndex := firstIndex + strings.Index(content[firstIndex:], ")")
reg := regexp.MustCompile(`\s+`)
strs := strings.Split(reg.ReplaceAllString(content[firstIndex:lastIndex], " "), ",")
for _, str := range strs {
txt := strings.TrimSpace(str)
if len(txt) > 0 {
args = append(args, Arg(txt))
}
}
return args, nil
}
func Arg(str string) ServiceArg {
strs := strings.Split(str, " ")
return ServiceArg{Name: strings.TrimSpace(strs[0]), TypeName: strings.TrimSpace(strs[1])}
}
func ReadGoFile(fileName string) (string, error) {
f, err := os.OpenFile(fileName, os.O_RDONLY, 0600)
defer f.Close()
if err != nil {
return "", err
} else {
if bytes, err := ioutil.ReadAll(f); err != nil {
return "", err
} else {
return string(bytes), nil
}
}
}
repository container template
package repository
import (
"github.com/kataras/golog"
"xorm.io/xorm"
)
type RepositoryContainer struct{
{{range $repository := .Repositories -}}
{{.Name}} {{.Name}}
{{end -}}
}
func NewRepositoryContainer(engine *xorm.Engine, logger *golog.Logger) *RepositoryContainer{
return &RepositoryContainer{
{{range $repository := .Repositories -}}
{{.Name}}: New{{.Name}}(engine, logger),
{{end -}}
}
}
service container template
package service
import (
"github.com/kataras/golog"
"xorm.io/xorm"
)
type ServiceContainer struct{
{{range $service := .Services -}}
{{.Name}} {{.Name}}
{{end -}}
}
func NewServiceContainer({{.NewFuncString}}) *ServiceContainer{
return &ServiceContainer{
{{range $service := .Services -}}
{{.Name}}: New{{.Name}}({{.NewFuncString}}),
{{end -}}
}
}
网友评论