Skip to content

Commit

Permalink
Merge branch 'gogf:master' into fix/cli-genctrl
Browse files Browse the repository at this point in the history
  • Loading branch information
wln32 authored Apr 14, 2024
2 parents b02a0c2 + 91f449d commit 18bf1f0
Show file tree
Hide file tree
Showing 21 changed files with 521 additions and 63 deletions.
4 changes: 1 addition & 3 deletions cmd/gf/internal/cmd/cmd_z_unit_gen_ctrl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ func Test_Gen_Ctrl_Default(t *testing.T) {
defer gfile.Remove(path)

_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
if err != nil {
panic(err)
}
t.AssertNil(err)

// apiInterface file
var (
Expand Down
106 changes: 91 additions & 15 deletions cmd/gf/internal/cmd/cmd_z_unit_gen_pbentity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ package cmd

import (
"fmt"
"os"
"path/filepath"
"testing"

"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genpbentity"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/guid"
"github.com/gogf/gf/v2/util/gutil"
)

func Test_Gen_Pbentity_NameCase(t *testing.T) {
func Test_Gen_Pbentity_Default(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
Expand All @@ -38,31 +38,107 @@ func Test_Gen_Pbentity_NameCase(t *testing.T) {
}
}
defer dropTableWithDb(db, table)
var path = gfile.Temp(guid.S())

var (
path = gfile.Temp(guid.S())
in = genpbentity.CGenPbEntityInput{
Path: path,
Package: "unittest",
Link: link,
Tables: "",
Prefix: "",
RemovePrefix: "",
RemoveFieldPrefix: "",
NameCase: "",
JsonCase: "",
Option: "",
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)

err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)

root, err := gcmd.NewFromObject(GF)
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
t.AssertNil(err)
err = root.AddObject(
Gen,

// files
files, err := gfile.ScanDir(path, "*.proto", false)
t.AssertNil(err)
t.Assert(files, []string{
path + filepath.FromSlash("/table_user.proto"),
})

// contents
testPath := gtest.DataPath("genpbentity", "generated")
expectFiles := []string{
testPath + filepath.FromSlash("/table_user.proto"),
}
for i := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}

func Test_Gen_Pbentity_NameCase_SnakeScreaming(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
table,
)
)
dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)

var (
path = gfile.Temp(guid.S())
in = genpbentity.CGenPbEntityInput{
Path: path,
Package: "unittest",
Link: link,
Tables: "",
Prefix: "",
RemovePrefix: "",
RemoveFieldPrefix: "",
NameCase: "SnakeScreaming",
JsonCase: "",
Option: "",
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
os.Args = []string{"gf", "gen", "pbentity", "-l", link, "-p", path, "-package=unittest", "-nameCase=SnakeScreaming"}

err = root.RunWithError(ctx)
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)

files := []string{
filepath.FromSlash(path + "/table_user.proto"),
}
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
t.AssertNil(err)

// files
files, err := gfile.ScanDir(path, "*.proto", false)
t.AssertNil(err)
t.Assert(files, []string{
path + filepath.FromSlash("/table_user.proto"),
})

testPath := gtest.DataPath("genpbentity", "generated_user")
// contents
testPath := gtest.DataPath("genpbentity", "generated")
expectFiles := []string{
filepath.FromSlash(testPath + "/table_user.proto"),
testPath + filepath.FromSlash("/table_user_snake_screaming.proto"),
}
// check files content
for i := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
Expand Down
4 changes: 1 addition & 3 deletions cmd/gf/internal/cmd/cmd_z_unit_gen_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,7 @@ func Test_Gen_Service_Default(t *testing.T) {
defer gfile.Remove(path)

_, err = genservice.CGenService{}.Service(ctx, in)
if err != nil {
panic(err)
}
t.AssertNil(err)

// logic file
var (
Expand Down
11 changes: 6 additions & 5 deletions cmd/gf/internal/cmd/genctrl/genctrl.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ package genctrl
import (
"context"

"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag"

"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
)

const (
Expand All @@ -38,7 +36,6 @@ gf gen ctrl
)

const (
PatternApiDefinition = `type[\s\(]+(\w+)Req\s+struct\s+{([\s\S]+?)}`
PatternCtrlDefinition = `func\s+\(.+?\)\s+\w+\(.+?\*(\w+)\.(\w+)Req\)\s+\(.+?\*(\w+)\.(\w+)Res,\s+\w+\s+error\)\s+{`
)

Expand Down Expand Up @@ -146,7 +143,11 @@ func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion,
}
// watch file should have api definitions.
if gfile.Exists(watchFile) {
if !gregex.IsMatchString(PatternApiDefinition, gfile.GetContents(watchFile)) {
structsInfo, err := c.getStructsNameInSrc(watchFile)
if err != nil {
return err
}
if len(structsInfo) == 0 {
return nil
}
}
Expand Down
64 changes: 49 additions & 15 deletions cmd/gf/internal/cmd/genctrl/genctrl_calculate.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@
package genctrl

import (
"bytes"
"go/ast"
"go/parser"
"go/printer"
"go/token"

"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
)

func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem, err error) {
var (
fileContent string
importPath string
)
var importPath string
// The second level folders: versions.
apiVersionFolderPaths, err := gfile.ScanDir(apiModuleFolderPath, "*", false)
if err != nil {
Expand All @@ -37,20 +40,13 @@ func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem,
if gfile.IsDir(apiFileFolderPath) {
continue
}
fileContent = gfile.GetContents(apiFileFolderPath)
matches, err := gregex.MatchAllString(PatternApiDefinition, fileContent)
structsInfo, err := c.getStructsNameInSrc(apiFileFolderPath)
if err != nil {
return nil, err
}
for _, match := range matches {
var (
methodName = match[1]
structBody = match[2]
)
// ignore struct name that match a request, but has no g.Meta in its body.
if !gstr.Contains(structBody, `g.Meta`) {
continue
}
for _, methodName := range structsInfo {
// remove end "Req"
methodName = gstr.TrimRightStr(methodName, "Req", 1)
item := apiItem{
Import: gstr.Trim(importPath, `"`),
FileName: gfile.Name(apiFileFolderPath),
Expand Down Expand Up @@ -143,3 +139,41 @@ func (c CGenCtrl) getApiItemsInDst(dstFolder string) (items []apiItem, err error
}
return
}

// getStructsNameInSrc retrieves all struct names
// that end in "Req" and have "g.Meta" in their body.
func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, err error) {
var (
fileContent = gfile.GetContents(filePath)
fileSet = token.NewFileSet()
)

node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
if err != nil {
return
}

ast.Inspect(node, func(n ast.Node) bool {
if typeSpec, ok := n.(*ast.TypeSpec); ok {
methodName := typeSpec.Name.Name
if !gstr.HasSuffix(methodName, "Req") {
// ignore struct name that do not end in "Req"
return true
}
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
var buf bytes.Buffer
if err := printer.Fprint(&buf, fileSet, structType); err != nil {
return false
}
// ignore struct name that match a request, but has no g.Meta in its body.
if !gstr.Contains(buf.String(), `g.Meta`) {
return true
}
structsName = append(structsName, methodName)
}
}
return true
})

return
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================

syntax = "proto3";

package unittest;

option go_package = "unittest";

import "google/protobuf/timestamp.proto";

message TableUser {
uint32 Id = 1; // User ID
string Passport = 2; // User Passport
string Password = 3; // User Password
string Nickname = 4; // User Nickname
string Score = 5; // Total score amount.
google.protobuf.Timestamp CreateAt = 6; // Created Time
google.protobuf.Timestamp UpdateAt = 7; // Updated Time
}
2 changes: 1 addition & 1 deletion contrib/drivers/dm/dm_z_unit_basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func Test_DB_Query(t *testing.T) {
}

func TestModelSave(t *testing.T) {
table := createTable("test")
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
Expand Down
2 changes: 1 addition & 1 deletion contrib/drivers/mssql/mssql_z_unit_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2590,7 +2590,7 @@ func Test_Model_ScanAndCount(t *testing.T) {
}

func Test_Model_Save(t *testing.T) {
table := createTable("test")
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
Expand Down
2 changes: 1 addition & 1 deletion contrib/drivers/oracle/oracle_z_unit_model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1101,7 +1101,7 @@ func Test_Model_WhereOrNotLike(t *testing.T) {
}

func Test_Model_Save(t *testing.T) {
table := createTable("test")
table := createTable()
defer dropTable(table)
gtest.C(t, func(t *gtest.T) {
type User struct {
Expand Down
27 changes: 27 additions & 0 deletions contrib/nosql/redis/redis_group_generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,33 @@ func (r GroupGeneric) Keys(ctx context.Context, pattern string) ([]string, error
return v.Strings(), err
}

// Scan executes a single iteration of the SCAN command, returning a subset of keys matching the pattern along with the next cursor position.
// This method provides more efficient and safer way to iterate over large datasets compared to KEYS command.
//
// Users are responsible for controlling the iteration by managing the cursor.
//
// The `count` optional parameter advises Redis on the number of keys to return. While it's not a strict limit, it guides the operation's granularity.
//
// https://redis.io/commands/scan/
func (r GroupGeneric) Scan(ctx context.Context, cursor uint64, option ...gredis.ScanOption) (uint64, []string, error) {
var usedOption interface{}
if len(option) > 0 {
usedOption = option[0].ToUsedOption()
}

v, err := r.Operation.Do(ctx, "Scan", mustMergeOptionToArgs(
[]interface{}{cursor}, usedOption,
)...)
if err != nil {
return 0, nil, err
}

nextCursor := gconv.Uint64(v.Slice()[0])
keys := gconv.SliceStr(v.Slice()[1])

return nextCursor, keys, nil
}

// FlushDB delete all the keys of the currently selected DB. This command never fails.
//
// https://redis.io/commands/flushdb/
Expand Down
Loading

0 comments on commit 18bf1f0

Please sign in to comment.