mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-10 16:30:01 +08:00
feat: add cmdline argument to control whether generate package name from proto filename (#5387)
This commit is contained in:
@@ -32,6 +32,9 @@ type ZRpcContext struct {
|
||||
IsGenClient bool
|
||||
// Module is the custom module name for go.mod
|
||||
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,
|
||||
|
||||
@@ -199,7 +199,9 @@ func mkdir(ctx *ctx.ProjectContext, proto parser.Proto, conf *conf.Config, c *ZR
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
serviceName := proto.Package.Name
|
||||
|
||||
serviceName := determineServiceName(proto, c)
|
||||
|
||||
return &defaultDirContext{
|
||||
ctx: ctx,
|
||||
inner: inner,
|
||||
@@ -270,3 +272,16 @@ func (d *defaultDirContext) GetServiceName() stringx.String {
|
||||
func (d *Dir) Valid() bool {
|
||||
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