mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-07 15:10:01 +08:00
feat: add cmdline argument to control whether generate package name from proto filename (#5387)
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
module github.com/zeromicro/go-zero/tools/goctl
|
module github.com/zeromicro/go-zero/tools/goctl
|
||||||
|
|
||||||
go 1.21
|
go 1.23
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||||
github.com/emicklei/proto v1.14.2
|
github.com/emicklei/proto v1.14.2
|
||||||
github.com/fatih/structtag v1.2.0
|
github.com/fatih/structtag v1.2.0
|
||||||
github.com/go-openapi/spec v0.21.1-0.20250328170532-a3928469592e
|
github.com/go-openapi/spec v0.21.1-0.20250328170532-a3928469592e
|
||||||
github.com/go-sql-driver/mysql v1.9.0
|
github.com/go-sql-driver/mysql v1.9.3
|
||||||
github.com/gookit/color v1.6.0
|
github.com/gookit/color v1.6.0
|
||||||
github.com/iancoleman/strcase v0.3.0
|
github.com/iancoleman/strcase v0.3.0
|
||||||
github.com/spf13/cobra v1.10.2
|
github.com/spf13/cobra v1.10.2
|
||||||
@@ -19,7 +19,7 @@ require (
|
|||||||
github.com/zeromicro/go-zero v1.9.4
|
github.com/zeromicro/go-zero v1.9.4
|
||||||
golang.org/x/text v0.22.0
|
golang.org/x/text v0.22.0
|
||||||
google.golang.org/grpc v1.65.0
|
google.golang.org/grpc v1.65.0
|
||||||
google.golang.org/protobuf v1.36.5
|
google.golang.org/protobuf v1.36.11
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ require (
|
|||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/google/gnostic-models v0.6.8 // indirect
|
github.com/google/gnostic-models v0.6.8 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.7.0 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/grafana/pyroscope-go v1.2.7 // indirect
|
github.com/grafana/pyroscope-go v1.2.7 // indirect
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ github.com/go-openapi/spec v0.21.1-0.20250328170532-a3928469592e h1:auobAirzhPsL
|
|||||||
github.com/go-openapi/spec v0.21.1-0.20250328170532-a3928469592e/go.mod h1:NAKTe9SplQBxIUlHlsuId1jk1I7bWTVV/2q/GtdRi6g=
|
github.com/go-openapi/spec v0.21.1-0.20250328170532-a3928469592e/go.mod h1:NAKTe9SplQBxIUlHlsuId1jk1I7bWTVV/2q/GtdRi6g=
|
||||||
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
|
||||||
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
|
||||||
github.com/go-sql-driver/mysql v1.9.0 h1:Y0zIbQXhQKmQgTp44Y1dp3wTXcn804QoTptLZT1vtvo=
|
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
|
||||||
github.com/go-sql-driver/mysql v1.9.0/go.mod h1:pDetrLJeA3oMujJuvXc8RJoasr589B6A9fwzD3QMrqw=
|
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
@@ -62,8 +62,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
|
|||||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
@@ -281,8 +281,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:
|
|||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
|
||||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||||
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
|
||||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ Goctl Rpc是`goctl`脚手架下的一个rpc服务代码生成模块,支持prot
|
|||||||
```Bash
|
```Bash
|
||||||
$ goctl rpc template -o=user.proto
|
$ goctl rpc template -o=user.proto
|
||||||
```
|
```
|
||||||
|
|
||||||
```proto
|
```proto
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ service User {
|
|||||||
rpc Ping(Request) returns(Response);
|
rpc Ping(Request) returns(Response);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
* 生成rpc服务代码
|
* 生成rpc服务代码
|
||||||
|
|
||||||
@@ -96,15 +96,16 @@ Examples:
|
|||||||
goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
|
goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
--branch string The branch of the remote repo, it does work with --remote
|
--branch string The branch of the remote repo, it does work with --remote
|
||||||
-h, --help help for protoc
|
-h, --help help for protoc
|
||||||
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
|
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
|
||||||
-m, --multiple Generated in multiple rpc service mode
|
-m, --multiple Generated in multiple rpc service mode
|
||||||
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
|
--name-from-filename Use proto filename instead of package name for service naming (legacy behavior)
|
||||||
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
|
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
|
||||||
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md] (default "gozero")
|
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
|
||||||
-v, --verbose Enable log output
|
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md] (default "gozero")
|
||||||
--zrpc_out string The zrpc output directory
|
-v, --verbose Enable log output
|
||||||
|
--zrpc_out string The zrpc output directory
|
||||||
```
|
```
|
||||||
|
|
||||||
### 参数说明
|
### 参数说明
|
||||||
@@ -112,19 +113,43 @@ Flags:
|
|||||||
* --branch 指定远程仓库模板分支
|
* --branch 指定远程仓库模板分支
|
||||||
* --home 指定goctl模板根目录
|
* --home 指定goctl模板根目录
|
||||||
* -m, --multiple 指定生成多个rpc服务模式, 默认为 false, 如果为 false, 则只支持生成一个rpc service, 如果为 true, 则支持生成多个 rpc service,且多个 rpc service 会分组。
|
* -m, --multiple 指定生成多个rpc服务模式, 默认为 false, 如果为 false, 则只支持生成一个rpc service, 如果为 true, 则支持生成多个 rpc service,且多个 rpc service 会分组。
|
||||||
|
* --name-from-filename 使用proto文件名而非package名称来命名服务(旧版行为)。默认使用package名称,这样可以支持多个proto文件共享同一个package。
|
||||||
* --style 指定文件输出格式
|
* --style 指定文件输出格式
|
||||||
* -v, --verbose 显示日志
|
* -v, --verbose 显示日志
|
||||||
* --zrpc_out 指定zrpc输出目录
|
* --zrpc_out 指定zrpc输出目录
|
||||||
|
|
||||||
> ## --multiple
|
> ## --multiple
|
||||||
> 是否开启多个 rpc service 生成,如果开启,则满足一下新特性
|
> 是否开启多个 rpc service 生成,如果开启,则满足一下新特性
|
||||||
> 1. 支持 1 到多个 rpc service
|
> 1. 支持 1 到多个 rpc service
|
||||||
> 2. 生成 rpc 服务会按照服务名称分组(尽管只有一个 rpc service)
|
> 2. 生成 rpc 服务会按照服务名称分组(尽管只有一个 rpc service)
|
||||||
> 3. rpc client 的文件目录变更为固定名称 `client`
|
> 3. rpc client 的文件目录变更为固定名称 `client`
|
||||||
>
|
>
|
||||||
> 如果不开启,则和旧版本 rpc 生成逻辑一样(兼容)
|
> 如果不开启,则和旧版本 rpc 生成逻辑一样(兼容)
|
||||||
> 1. 有且只能有一个 rpc service
|
> 1. 有且只能有一个 rpc service
|
||||||
|
|
||||||
|
> ## Service Naming (Multi-Proto File Support)
|
||||||
|
>
|
||||||
|
> By default, the service name is derived from the **proto package name** (e.g., `package user;` → service name `user`).
|
||||||
|
> This enables splitting a large proto file into multiple smaller files that share the same package name,
|
||||||
|
> which is particularly useful for AI-assisted development where smaller files are easier to process.
|
||||||
|
>
|
||||||
|
> **Example: Multiple proto files with same package**
|
||||||
|
> ```
|
||||||
|
> protos/
|
||||||
|
> ├── user_base.proto # package user;
|
||||||
|
> ├── user_auth.proto # package user;
|
||||||
|
> └── user_profile.proto # package user;
|
||||||
|
> ```
|
||||||
|
> All three files will generate into a single `user` service.
|
||||||
|
>
|
||||||
|
> **Legacy behavior (--name-from-filename)**
|
||||||
|
>
|
||||||
|
> If you need the old behavior where service name is derived from the proto filename,
|
||||||
|
> use the `--name-from-filename` flag:
|
||||||
|
> ```bash
|
||||||
|
> goctl rpc protoc user.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=. --name-from-filename
|
||||||
|
> ```
|
||||||
|
|
||||||
|
|
||||||
## rpc 服务生成 example
|
## rpc 服务生成 example
|
||||||
详情见 [example/rpc](https://github.com/zeromicro/go-zero/tree/master/tools/goctl/example)
|
详情见 [example/rpc](https://github.com/zeromicro/go-zero/tree/master/tools/goctl/example)
|
||||||
|
|||||||
@@ -48,6 +48,9 @@ var (
|
|||||||
VarBoolClient bool
|
VarBoolClient bool
|
||||||
// VarStringModule describes the module name for go.mod.
|
// VarStringModule describes the module name for go.mod.
|
||||||
VarStringModule string
|
VarStringModule string
|
||||||
|
// VarBoolNameFromFilename describes whether to derive service name from proto filename
|
||||||
|
// instead of the proto package name. Default is false (uses package name).
|
||||||
|
VarBoolNameFromFilename bool
|
||||||
)
|
)
|
||||||
|
|
||||||
// RPCNew is to generate rpc greet service, this greet service can speed
|
// RPCNew is to generate rpc greet service, this greet service can speed
|
||||||
@@ -94,6 +97,7 @@ func RPCNew(_ *cobra.Command, args []string) error {
|
|||||||
ctx.ProtocCmd = fmt.Sprintf("protoc -I=%s %s --go_out=%s --go-grpc_out=%s", filepath.Dir(src), filepath.Base(src), filepath.Dir(src), filepath.Dir(src))
|
ctx.ProtocCmd = fmt.Sprintf("protoc -I=%s %s --go_out=%s --go-grpc_out=%s", filepath.Dir(src), filepath.Base(src), filepath.Dir(src), filepath.Dir(src))
|
||||||
ctx.IsGenClient = VarBoolClient
|
ctx.IsGenClient = VarBoolClient
|
||||||
ctx.Module = VarStringModule
|
ctx.Module = VarStringModule
|
||||||
|
ctx.NameFromFilename = VarBoolNameFromFilename
|
||||||
|
|
||||||
grpcOptList := VarStringSliceGoGRPCOpt
|
grpcOptList := VarStringSliceGoGRPCOpt
|
||||||
if len(grpcOptList) > 0 {
|
if len(grpcOptList) > 0 {
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ func ZRPC(_ *cobra.Command, args []string) error {
|
|||||||
ctx.ProtocCmd = strings.Join(protocArgs, " ")
|
ctx.ProtocCmd = strings.Join(protocArgs, " ")
|
||||||
ctx.IsGenClient = VarBoolClient
|
ctx.IsGenClient = VarBoolClient
|
||||||
ctx.Module = VarStringModule
|
ctx.Module = VarStringModule
|
||||||
|
ctx.NameFromFilename = VarBoolNameFromFilename
|
||||||
g := generator.NewGenerator(style, verbose)
|
g := generator.NewGenerator(style, verbose)
|
||||||
return g.Generate(&ctx)
|
return g.Generate(&ctx)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ func init() {
|
|||||||
newCmdFlags.StringVar(&cli.VarStringBranch, "branch")
|
newCmdFlags.StringVar(&cli.VarStringBranch, "branch")
|
||||||
newCmdFlags.StringVar(&cli.VarStringModule, "module")
|
newCmdFlags.StringVar(&cli.VarStringModule, "module")
|
||||||
newCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
|
newCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
|
||||||
|
newCmdFlags.BoolVar(&cli.VarBoolNameFromFilename, "name-from-filename")
|
||||||
newCmdFlags.MarkHidden("go_opt")
|
newCmdFlags.MarkHidden("go_opt")
|
||||||
newCmdFlags.MarkHidden("go-grpc_opt")
|
newCmdFlags.MarkHidden("go-grpc_opt")
|
||||||
newCmdFlags.BoolVarPWithDefaultValue(&cli.VarBoolClient, "client", "c", true)
|
newCmdFlags.BoolVarPWithDefaultValue(&cli.VarBoolClient, "client", "c", true)
|
||||||
@@ -60,6 +61,7 @@ func init() {
|
|||||||
protocCmdFlags.StringVar(&cli.VarStringBranch, "branch")
|
protocCmdFlags.StringVar(&cli.VarStringBranch, "branch")
|
||||||
protocCmdFlags.StringVar(&cli.VarStringModule, "module")
|
protocCmdFlags.StringVar(&cli.VarStringModule, "module")
|
||||||
protocCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
|
protocCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
|
||||||
|
protocCmdFlags.BoolVar(&cli.VarBoolNameFromFilename, "name-from-filename")
|
||||||
protocCmdFlags.MarkHidden("go_out")
|
protocCmdFlags.MarkHidden("go_out")
|
||||||
protocCmdFlags.MarkHidden("go-grpc_out")
|
protocCmdFlags.MarkHidden("go-grpc_out")
|
||||||
protocCmdFlags.MarkHidden("go_opt")
|
protocCmdFlags.MarkHidden("go_opt")
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ type ZRpcContext struct {
|
|||||||
IsGenClient bool
|
IsGenClient bool
|
||||||
// Module is the custom module name for go.mod
|
// Module is the custom module name for go.mod
|
||||||
Module string
|
Module string
|
||||||
|
// NameFromFilename uses proto filename instead of package name for service naming.
|
||||||
|
// Default is false (uses package name, which supports multi-proto files).
|
||||||
|
NameFromFilename bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate generates a rpc service, through the proto file,
|
// Generate generates a rpc service, through the proto file,
|
||||||
|
|||||||
@@ -199,7 +199,9 @@ func mkdir(ctx *ctx.ProjectContext, proto parser.Proto, conf *conf.Config, c *ZR
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serviceName := proto.Package.Name
|
|
||||||
|
serviceName := determineServiceName(proto, c)
|
||||||
|
|
||||||
return &defaultDirContext{
|
return &defaultDirContext{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
inner: inner,
|
inner: inner,
|
||||||
@@ -270,3 +272,16 @@ func (d *defaultDirContext) GetServiceName() stringx.String {
|
|||||||
func (d *Dir) Valid() bool {
|
func (d *Dir) Valid() bool {
|
||||||
return len(d.Filename) > 0 && len(d.Package) > 0
|
return len(d.Filename) > 0 && len(d.Package) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// determineServiceName returns the service name based on the proto file and context.
|
||||||
|
// By default, it uses the proto package name (supports multi-proto files).
|
||||||
|
// Falls back to filename if --name-from-filename flag is set or package name is empty.
|
||||||
|
func determineServiceName(proto parser.Proto, c *ZRpcContext) string {
|
||||||
|
if c != nil && c.NameFromFilename {
|
||||||
|
return strings.TrimSuffix(proto.Name, filepath.Ext(proto.Name))
|
||||||
|
}
|
||||||
|
if proto.Package.Package != nil && len(proto.Package.Name) > 0 {
|
||||||
|
return proto.Package.Name
|
||||||
|
}
|
||||||
|
return strings.TrimSuffix(proto.Name, filepath.Ext(proto.Name))
|
||||||
|
}
|
||||||
|
|||||||
147
tools/goctl/rpc/generator/mkdir_test.go
Normal file
147
tools/goctl/rpc/generator/mkdir_test.go
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/emicklei/proto"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/zeromicro/go-zero/tools/goctl/rpc/parser"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestServiceNameDetermination(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
protoName string
|
||||||
|
packageName string
|
||||||
|
hasPackage bool
|
||||||
|
nameFromFilename bool
|
||||||
|
expectedName string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "default uses package name when available",
|
||||||
|
protoName: "user.proto",
|
||||||
|
packageName: "userservice",
|
||||||
|
hasPackage: true,
|
||||||
|
nameFromFilename: false,
|
||||||
|
expectedName: "userservice",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "flag enabled uses filename instead of package",
|
||||||
|
protoName: "user.proto",
|
||||||
|
packageName: "userservice",
|
||||||
|
hasPackage: true,
|
||||||
|
nameFromFilename: true,
|
||||||
|
expectedName: "user",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fallback to filename when package is empty",
|
||||||
|
protoName: "order.proto",
|
||||||
|
packageName: "",
|
||||||
|
hasPackage: true,
|
||||||
|
nameFromFilename: false,
|
||||||
|
expectedName: "order",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "fallback to filename when package is nil",
|
||||||
|
protoName: "product.proto",
|
||||||
|
packageName: "",
|
||||||
|
hasPackage: false,
|
||||||
|
nameFromFilename: false,
|
||||||
|
expectedName: "product",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "flag enabled with nil package uses filename",
|
||||||
|
protoName: "catalog.proto",
|
||||||
|
packageName: "",
|
||||||
|
hasPackage: false,
|
||||||
|
nameFromFilename: true,
|
||||||
|
expectedName: "catalog",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "handles proto file with complex name",
|
||||||
|
protoName: "user-service.proto",
|
||||||
|
packageName: "user",
|
||||||
|
hasPackage: true,
|
||||||
|
nameFromFilename: false,
|
||||||
|
expectedName: "user",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "handles proto file with complex name and flag",
|
||||||
|
protoName: "user-service.proto",
|
||||||
|
packageName: "user",
|
||||||
|
hasPackage: true,
|
||||||
|
nameFromFilename: true,
|
||||||
|
expectedName: "user-service",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil context uses package name",
|
||||||
|
protoName: "account.proto",
|
||||||
|
packageName: "accountpb",
|
||||||
|
hasPackage: true,
|
||||||
|
nameFromFilename: false,
|
||||||
|
expectedName: "accountpb",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
// Build the proto struct
|
||||||
|
p := parser.Proto{
|
||||||
|
Name: tt.protoName,
|
||||||
|
}
|
||||||
|
if tt.hasPackage {
|
||||||
|
p.Package = parser.Package{
|
||||||
|
Package: &proto.Package{
|
||||||
|
Name: tt.packageName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the context
|
||||||
|
var ctx *ZRpcContext
|
||||||
|
if tt.name != "nil context uses package name" {
|
||||||
|
ctx = &ZRpcContext{
|
||||||
|
NameFromFilename: tt.nameFromFilename,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the helper function to determine service name
|
||||||
|
serviceName := determineServiceName(p, ctx)
|
||||||
|
assert.Equal(t, tt.expectedName, serviceName)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServiceNameWithNilContext(t *testing.T) {
|
||||||
|
p := parser.Proto{
|
||||||
|
Name: "test.proto",
|
||||||
|
Package: parser.Package{
|
||||||
|
Package: &proto.Package{
|
||||||
|
Name: "testpkg",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// nil context should use package name
|
||||||
|
serviceName := determineServiceName(p, nil)
|
||||||
|
assert.Equal(t, "testpkg", serviceName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServiceNameFallbackWithEmptyPackage(t *testing.T) {
|
||||||
|
p := parser.Proto{
|
||||||
|
Name: "myservice.proto",
|
||||||
|
Package: parser.Package{
|
||||||
|
Package: &proto.Package{
|
||||||
|
Name: "", // empty package name
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := &ZRpcContext{
|
||||||
|
NameFromFilename: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should fall back to filename when package name is empty
|
||||||
|
serviceName := determineServiceName(p, ctx)
|
||||||
|
assert.Equal(t, "myservice", serviceName)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user