feature: file namestyle (#223)

* add api filename style

* new feature: config.yaml

* optimize

* optimize logic generation

* check hanlder valid

* optimize

* reactor naming style

* optimize

* optimize test

* optimize gen middleware

* format

Co-authored-by: anqiansong <anqiansong@xiaoheiban.cn>
Co-authored-by: kim <xutao@xiaoheiban.cn>
This commit is contained in:
kingxt
2020-11-24 15:11:18 +08:00
committed by GitHub
parent 702e8d79ce
commit b9ac51b6c3
40 changed files with 896 additions and 296 deletions

View File

@@ -2,7 +2,6 @@ package command
import (
"errors"
"fmt"
"io/ioutil"
"path/filepath"
"strings"
@@ -10,6 +9,7 @@ import (
"github.com/go-sql-driver/mysql"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/stores/sqlx"
"github.com/tal-tech/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/gen"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/util"
@@ -24,9 +24,9 @@ const (
flagDir = "dir"
flagCache = "cache"
flagIdea = "idea"
flagStyle = "style"
flagUrl = "url"
flagTable = "table"
flagStyle = "style"
)
func MysqlDDL(ctx *cli.Context) error {
@@ -34,8 +34,13 @@ func MysqlDDL(ctx *cli.Context) error {
dir := ctx.String(flagDir)
cache := ctx.Bool(flagCache)
idea := ctx.Bool(flagIdea)
namingStyle := strings.TrimSpace(ctx.String(flagStyle))
return fromDDl(src, dir, namingStyle, cache, idea)
style := ctx.String(flagStyle)
cfg, err := config.NewConfig(style)
if err != nil {
return err
}
return fromDDl(src, dir, cfg, cache, idea)
}
func MyDataSource(ctx *cli.Context) error {
@@ -43,26 +48,23 @@ func MyDataSource(ctx *cli.Context) error {
dir := strings.TrimSpace(ctx.String(flagDir))
cache := ctx.Bool(flagCache)
idea := ctx.Bool(flagIdea)
namingStyle := strings.TrimSpace(ctx.String(flagStyle))
style := ctx.String(flagStyle)
pattern := strings.TrimSpace(ctx.String(flagTable))
return fromDataSource(url, pattern, dir, namingStyle, cache, idea)
cfg, err := config.NewConfig(style)
if err != nil {
return err
}
return fromDataSource(url, pattern, dir, cfg, cache, idea)
}
func fromDDl(src, dir, namingStyle string, cache, idea bool) error {
func fromDDl(src, dir string, cfg *config.Config, cache, idea bool) error {
log := console.NewConsole(idea)
src = strings.TrimSpace(src)
if len(src) == 0 {
return errors.New("expected path or path globbing patterns, but nothing found")
}
switch namingStyle {
case gen.NamingLower, gen.NamingCamel, gen.NamingSnake:
case "":
namingStyle = gen.NamingLower
default:
return fmt.Errorf("unexpected naming style: %s", namingStyle)
}
files, err := util.MatchFiles(src)
if err != nil {
return err
@@ -81,7 +83,7 @@ func fromDDl(src, dir, namingStyle string, cache, idea bool) error {
source = append(source, string(data))
}
generator, err := gen.NewDefaultGenerator(dir, namingStyle, gen.WithConsoleOption(log))
generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
if err != nil {
return err
}
@@ -90,7 +92,7 @@ func fromDDl(src, dir, namingStyle string, cache, idea bool) error {
return err
}
func fromDataSource(url, pattern, dir, namingStyle string, cache, idea bool) error {
func fromDataSource(url, pattern, dir string, cfg *config.Config, cache, idea bool) error {
log := console.NewConsole(idea)
if len(url) == 0 {
log.Error("%v", "expected data source of mysql, but nothing found")
@@ -102,25 +104,17 @@ func fromDataSource(url, pattern, dir, namingStyle string, cache, idea bool) err
return nil
}
switch namingStyle {
case gen.NamingLower, gen.NamingCamel, gen.NamingSnake:
case "":
namingStyle = gen.NamingLower
default:
return fmt.Errorf("unexpected naming style: %s", namingStyle)
}
cfg, err := mysql.ParseDSN(url)
dsn, err := mysql.ParseDSN(url)
if err != nil {
return err
}
logx.Disable()
databaseSource := strings.TrimSuffix(url, "/"+cfg.DBName) + "/information_schema"
databaseSource := strings.TrimSuffix(url, "/"+dsn.DBName) + "/information_schema"
db := sqlx.NewMysql(databaseSource)
im := model.NewInformationSchemaModel(db)
tables, err := im.GetAllTables(cfg.DBName)
tables, err := im.GetAllTables(dsn.DBName)
if err != nil {
return err
}
@@ -135,7 +129,7 @@ func fromDataSource(url, pattern, dir, namingStyle string, cache, idea bool) err
if !match {
continue
}
columns, err := im.FindByTableName(cfg.DBName, item)
columns, err := im.FindByTableName(dsn.DBName, item)
if err != nil {
return err
}
@@ -146,11 +140,11 @@ func fromDataSource(url, pattern, dir, namingStyle string, cache, idea bool) err
return errors.New("no tables matched")
}
generator, err := gen.NewDefaultGenerator(dir, namingStyle, gen.WithConsoleOption(log))
generator, err := gen.NewDefaultGenerator(dir, cfg, gen.WithConsoleOption(log))
if err != nil {
return err
}
err = generator.StartFromInformationSchema(cfg.DBName, matchTables, cache)
err = generator.StartFromInformationSchema(dsn.DBName, matchTables, cache)
return err
}

View File

@@ -7,19 +7,22 @@ import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/gen"
"github.com/tal-tech/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util"
)
var sql = "-- 用户表 --\nCREATE TABLE `user` (\n `id` bigint(10) NOT NULL AUTO_INCREMENT,\n `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户名称',\n `password` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '用户密码',\n `mobile` varchar(255) COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '手机号',\n `gender` char(5) COLLATE utf8mb4_general_ci NOT NULL COMMENT '男|女|未公开',\n `nickname` varchar(255) COLLATE utf8mb4_general_ci DEFAULT '' COMMENT '用户昵称',\n `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,\n `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n PRIMARY KEY (`id`),\n UNIQUE KEY `name_index` (`name`),\n UNIQUE KEY `mobile_index` (`mobile`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;\n\n"
var cfg = &config.Config{
NamingFormat: "gozero",
}
func TestFromDDl(t *testing.T) {
err := fromDDl("./user.sql", t.TempDir(), gen.NamingCamel, true, false)
err := fromDDl("./user.sql", t.TempDir(), cfg, true, false)
assert.Equal(t, errNotMatched, err)
// case dir is not exists
unknownDir := filepath.Join(t.TempDir(), "test", "user.sql")
err = fromDDl(unknownDir, t.TempDir(), gen.NamingCamel, true, false)
err = fromDDl(unknownDir, t.TempDir(), cfg, true, false)
assert.True(t, func() bool {
switch err.(type) {
case *os.PathError:
@@ -30,18 +33,11 @@ func TestFromDDl(t *testing.T) {
}())
// case empty src
err = fromDDl("", t.TempDir(), gen.NamingCamel, true, false)
err = fromDDl("", t.TempDir(), cfg, true, false)
if err != nil {
assert.Equal(t, "expected path or path globbing patterns, but nothing found", err.Error())
}
// case unknown naming style
tmp := filepath.Join(t.TempDir(), "user.sql")
err = fromDDl(tmp, t.TempDir(), "lower1", true, false)
if err != nil {
assert.Equal(t, "unexpected naming style: lower1", err.Error())
}
tempDir := filepath.Join(t.TempDir(), "test")
err = util.MkdirIfNotExist(tempDir)
if err != nil {
@@ -67,7 +63,7 @@ func TestFromDDl(t *testing.T) {
_, err = os.Stat(user2Sql)
assert.Nil(t, err)
err = fromDDl(filepath.Join(tempDir, "user*.sql"), tempDir, gen.NamingLower, true, false)
err = fromDDl(filepath.Join(tempDir, "user*.sql"), tempDir, cfg, true, false)
assert.Nil(t, err)
_, err = os.Stat(filepath.Join(tempDir, "usermodel.go"))

View File

@@ -7,11 +7,13 @@ import (
"path/filepath"
"strings"
"github.com/tal-tech/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/model"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/parser"
"github.com/tal-tech/go-zero/tools/goctl/model/sql/template"
"github.com/tal-tech/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/console"
"github.com/tal-tech/go-zero/tools/goctl/util/format"
"github.com/tal-tech/go-zero/tools/goctl/util/stringx"
)
@@ -28,13 +30,13 @@ type (
//source string
dir string
console.Console
pkg string
namingStyle string
pkg string
cfg *config.Config
}
Option func(generator *defaultGenerator)
)
func NewDefaultGenerator(dir, namingStyle string, opt ...Option) (*defaultGenerator, error) {
func NewDefaultGenerator(dir string, cfg *config.Config, opt ...Option) (*defaultGenerator, error) {
if dir == "" {
dir = pwd
}
@@ -50,7 +52,7 @@ func NewDefaultGenerator(dir, namingStyle string, opt ...Option) (*defaultGenera
return nil, err
}
generator := &defaultGenerator{dir: dir, namingStyle: namingStyle, pkg: pkg}
generator := &defaultGenerator{dir: dir, cfg: cfg, pkg: pkg}
var optionList []Option
optionList = append(optionList, newDefaultOption())
optionList = append(optionList, opt...)
@@ -114,13 +116,12 @@ func (g *defaultGenerator) createFile(modelList map[string]string) error {
for tableName, code := range modelList {
tn := stringx.From(tableName)
name := fmt.Sprintf("%smodel.go", strings.ToLower(tn.ToCamel()))
switch g.namingStyle {
case NamingCamel:
name = fmt.Sprintf("%sModel.go", tn.ToCamel())
case NamingSnake:
name = fmt.Sprintf("%s_model.go", tn.ToSnake())
modelFilename, err := format.FileNamingFormat(g.cfg.NamingFormat, fmt.Sprintf("%s_model", tn.Source()))
if err != nil {
return err
}
name := modelFilename + ".go"
filename := filepath.Join(dirAbs, name)
if util.FileExists(filename) {
g.Warning("%s already exists, ignored.", name)
@@ -132,10 +133,12 @@ func (g *defaultGenerator) createFile(modelList map[string]string) error {
}
}
// generate error file
filename := filepath.Join(dirAbs, "vars.go")
if g.namingStyle == NamingCamel {
filename = filepath.Join(dirAbs, "Vars.go")
varFilename, err := format.FileNamingFormat(g.cfg.NamingFormat, "vars")
if err != nil {
return err
}
filename := filepath.Join(dirAbs, varFilename+".go")
text, err := util.LoadTemplate(category, errTemplateFile, template.Error)
if err != nil {
return err

View File

@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/tools/goctl/config"
)
var (
@@ -22,7 +23,9 @@ func TestCacheModel(t *testing.T) {
defer func() {
_ = os.RemoveAll(dir)
}()
g, err := NewDefaultGenerator(cacheDir, NamingCamel)
g, err := NewDefaultGenerator(cacheDir, &config.Config{
NamingFormat: "GoZero",
})
assert.Nil(t, err)
err = g.StartFromDDL(source, true)
@@ -31,7 +34,9 @@ func TestCacheModel(t *testing.T) {
_, err := os.Stat(filepath.Join(cacheDir, "TestUserInfoModel.go"))
return err == nil
}())
g, err = NewDefaultGenerator(noCacheDir, NamingLower)
g, err = NewDefaultGenerator(noCacheDir, &config.Config{
NamingFormat: "gozero",
})
assert.Nil(t, err)
err = g.StartFromDDL(source, false)
@@ -51,7 +56,9 @@ func TestNamingModel(t *testing.T) {
defer func() {
_ = os.RemoveAll(dir)
}()
g, err := NewDefaultGenerator(camelDir, NamingCamel)
g, err := NewDefaultGenerator(camelDir, &config.Config{
NamingFormat: "GoZero",
})
assert.Nil(t, err)
err = g.StartFromDDL(source, true)
@@ -60,7 +67,9 @@ func TestNamingModel(t *testing.T) {
_, err := os.Stat(filepath.Join(camelDir, "TestUserInfoModel.go"))
return err == nil
}())
g, err = NewDefaultGenerator(snakeDir, NamingSnake)
g, err = NewDefaultGenerator(snakeDir, &config.Config{
NamingFormat: "go_zero",
})
assert.Nil(t, err)
err = g.StartFromDDL(source, true)