mirror of
https://github.com/go-kratos/kratos.git
synced 2025-01-10 00:29:01 +02:00
add protoc gen ecode (#274)
* add protoc gen ecode * add protobuf example
This commit is contained in:
parent
c1f9b5ca81
commit
1481e14c12
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,4 +28,5 @@ tool/kratos-gen-bts/kratos-gen-bts
|
|||||||
tool/kratos-gen-mc/kratos-gen-mc
|
tool/kratos-gen-mc/kratos-gen-mc
|
||||||
tool/kratos/kratos-protoc/kratos-protoc
|
tool/kratos/kratos-protoc/kratos-protoc
|
||||||
tool/kratos/protobuf/protoc-gen-bm/protoc-gen-bm
|
tool/kratos/protobuf/protoc-gen-bm/protoc-gen-bm
|
||||||
|
tool/kratos/protobuf/protoc-gen-ecode/protoc-gen-ecode
|
||||||
tool/kratos/protobuf/protoc-gen-bswagger/protoc-gen-bswagger
|
tool/kratos/protobuf/protoc-gen-bswagger/protoc-gen-bswagger
|
||||||
|
@ -1,38 +1,31 @@
|
|||||||
### kratos tool protoc
|
### kratos tool protoc
|
||||||
|
|
||||||
```
|
```shell
|
||||||
// generate all
|
# generate all
|
||||||
kratos tool protoc api.proto
|
kratos tool protoc api.proto
|
||||||
// generate gRPC
|
# generate gRPC
|
||||||
kratos tool protoc --grpc api.proto
|
kratos tool protoc --grpc api.proto
|
||||||
// generate BM HTTP
|
# generate BM HTTP
|
||||||
kratos tool protoc --bm api.proto
|
kratos tool protoc --bm api.proto
|
||||||
// generate swagger
|
# generate ecode
|
||||||
|
kratos tool protoc --ecode api.proto
|
||||||
|
# generate swagger
|
||||||
kratos tool protoc --swagger api.proto
|
kratos tool protoc --swagger api.proto
|
||||||
```
|
```
|
||||||
执行对应生成 `api.pb.go/api.bm.go/api.swagger.json` 源文档。
|
|
||||||
|
|
||||||
> 该工具在Windows/Linux下运行,需提前安装好 protobuf 工具
|
执行生成如 `api.pb.go/api.bm.go/api.swagger.json/api.ecode.go` 的对应文件,需要注意的是:`ecode`生成有固定规则,需要首先是`enum`类型,且`enum`名字要以`ErrCode`结尾,如`enum UserErrCode`。详情可见:[example](https://github.com/bilibili/kratos/tree/master/example/protobuf)
|
||||||
|
|
||||||
该工具实际是一段`shell`脚本,其中自动将`protoc`命令进行了拼接,识别了需要的`*.proto`文件和当前目录下的`proto`文件,最终会拼接为如下命令进行执行:
|
> 该工具在Windows/Linux下运行,需提前安装好 [protobuf](https://github.com/google/protobuf) 工具
|
||||||
|
|
||||||
|
`kratos tool protoc`本质上是拼接好了`protoc`命令然后进行执行,在执行时会打印出对应执行的`protoc`命令,如下可见:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
export $KRATOS_HOME = kratos路径
|
protoc --proto_path=$GOPATH --proto_path=$GOPATH/github.com/bilibili/kratos/third_party --proto_path=. --bm_out=:. api.proto
|
||||||
export $KRATOS_DEMO = 项目路径
|
protoc --proto_path=$GOPATH --proto_path=$GOPATH/github.com/bilibili/kratos/third_party --proto_path=. --gofast_out=plugins=grpc:. api.proto
|
||||||
|
protoc --proto_path=$GOPATH --proto_path=$GOPATH/github.com/bilibili/kratos/third_party --proto_path=. --bswagger_out=:. api.proto
|
||||||
// 生成:api.pb.go
|
protoc --proto_path=$GOPATH --proto_path=$GOPATH/github.com/bilibili/kratos/third_party --proto_path=. --ecode_out=:. api.proto
|
||||||
protoc -I$GOPATH/src:$KRATOS_HOME/third_party:$KRATOS_DEMO/api --gofast_out=plugins=grpc:$KRATOS_DEMO/api $KRATOS_DEMO/api/api.proto
|
|
||||||
|
|
||||||
// 生成:api.bm.go
|
|
||||||
protoc -I$GOPATH/src:$KRATOS_HOME/third_party:$KRATOS_DEMO/api --bm_out=$KRATOS_DEMO/api $KRATOS_DEMO/api/api.proto
|
|
||||||
|
|
||||||
// 生成:api.swagger.json
|
|
||||||
protoc -I$GOPATH/src:$KRATOS_HOME/third_party:$KRATOS_DEMO/api --bswagger_out=$KRATOS_DEMO/api $KRATOS_DEMO/api/api.proto
|
|
||||||
```
|
```
|
||||||
|
|
||||||
大家也可以参考该命令进行`proto`生成,也可以参考 [protobuf](https://github.com/google/protobuf) 官方参数。
|
|
||||||
|
|
||||||
|
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
[文档目录树](summary.md)
|
[文档目录树](summary.md)
|
||||||
|
40
example/protobuf/api.bm.go
Normal file
40
example/protobuf/api.bm.go
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// Code generated by protoc-gen-bm v0.1, DO NOT EDIT.
|
||||||
|
// source: api.proto
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
bm "github.com/bilibili/kratos/pkg/net/http/blademaster"
|
||||||
|
"github.com/bilibili/kratos/pkg/net/http/blademaster/binding"
|
||||||
|
)
|
||||||
|
|
||||||
|
// to suppressed 'imported but not used warning'
|
||||||
|
var _ *bm.Context
|
||||||
|
var _ context.Context
|
||||||
|
var _ binding.StructValidator
|
||||||
|
|
||||||
|
var PathUserInfo = "/user.api.User/Info"
|
||||||
|
|
||||||
|
// UserBMServer is the server API for User service.
|
||||||
|
type UserBMServer interface {
|
||||||
|
Info(ctx context.Context, req *UserReq) (resp *InfoReply, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var UserSvc UserBMServer
|
||||||
|
|
||||||
|
func userInfo(c *bm.Context) {
|
||||||
|
p := new(UserReq)
|
||||||
|
if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp, err := UserSvc.Info(c, p)
|
||||||
|
c.JSON(resp, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterUserBMServer Register the blademaster route
|
||||||
|
func RegisterUserBMServer(e *bm.Engine, server UserBMServer) {
|
||||||
|
UserSvc = server
|
||||||
|
e.GET("/user.api.User/Info", userInfo)
|
||||||
|
}
|
17
example/protobuf/api.ecode.go
Normal file
17
example/protobuf/api.ecode.go
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Code generated by protoc-gen-ecode v0.1, DO NOT EDIT.
|
||||||
|
// source: api.proto
|
||||||
|
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/bilibili/kratos/pkg/ecode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// to suppressed 'imported but not used warning'
|
||||||
|
var _ ecode.Codes
|
||||||
|
|
||||||
|
// UserErrCode ecode
|
||||||
|
var (
|
||||||
|
UserNotExist = ecode.New(-404)
|
||||||
|
UserUpdateNameFailed = ecode.New(10000)
|
||||||
|
)
|
1000
example/protobuf/api.pb.go
Normal file
1000
example/protobuf/api.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
33
example/protobuf/api.proto
Normal file
33
example/protobuf/api.proto
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package user.api;
|
||||||
|
|
||||||
|
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
||||||
|
|
||||||
|
option go_package = "api";
|
||||||
|
|
||||||
|
enum UserErrCode {
|
||||||
|
OK = 0;
|
||||||
|
UserNotExist = -404;
|
||||||
|
UserUpdateNameFailed = 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Info {
|
||||||
|
int64 mid = 1 [(gogoproto.jsontag) = "mid"];
|
||||||
|
string name = 2 [(gogoproto.jsontag) = "name"];
|
||||||
|
string sex = 3 [(gogoproto.jsontag) = "sex"];
|
||||||
|
string face = 4 [(gogoproto.jsontag) = "face"];
|
||||||
|
string sign = 5 [(gogoproto.jsontag) = "sign"];
|
||||||
|
}
|
||||||
|
|
||||||
|
message UserReq {
|
||||||
|
int64 mid = 1 [(gogoproto.moretags) = "validate:\"gt=0,required\""];
|
||||||
|
}
|
||||||
|
|
||||||
|
message InfoReply {
|
||||||
|
Info info = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
service User {
|
||||||
|
rpc Info(UserReq) returns (InfoReply);
|
||||||
|
}
|
96
example/protobuf/api.swagger.json
Normal file
96
example/protobuf/api.swagger.json
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
{
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"title": "api.proto",
|
||||||
|
"version": ""
|
||||||
|
},
|
||||||
|
"schemes": [
|
||||||
|
"http",
|
||||||
|
"https"
|
||||||
|
],
|
||||||
|
"consumes": [
|
||||||
|
"application/json",
|
||||||
|
"multipart/form-data"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"/user.api.User/Info": {
|
||||||
|
"get": {
|
||||||
|
"summary": "/user.api.User/Info",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "A successful response.",
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"code": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"data": {
|
||||||
|
"$ref": "#/definitions/.user.api.InfoReply"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "mid",
|
||||||
|
"in": "query",
|
||||||
|
"required": true,
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"user.api.User"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
".user.api.Info": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"mid": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sex": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"face": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sign": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
".user.api.InfoReply": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"info": {
|
||||||
|
"$ref": "#/definitions/.user.api.Info"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
".user.api.UserReq": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"mid": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"mid"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
example/protobuf/gen.sh
Normal file
3
example/protobuf/gen.sh
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
kratos tool protoc api.proto
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
_getBMGen = "go get -u github.com/bilibili/kratos/tool/protobuf/protoc-gen-bm"
|
_getBMGen = "go get -u github.com/bilibili/kratos/tool/protobuf/protoc-gen-bm"
|
||||||
_bmProtoc = "protoc --proto_path=%s --proto_path=%s --proto_path=%s --bm_out=explicit_http=true:."
|
_bmProtoc = "protoc --proto_path=%s --proto_path=%s --proto_path=%s --bm_out=:."
|
||||||
)
|
)
|
||||||
|
|
||||||
func installBMGen() error {
|
func installBMGen() error {
|
||||||
|
25
tool/kratos-protoc/ecode.go
Normal file
25
tool/kratos-protoc/ecode.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_getEcodeGen = "go get -u github.com/bilibili/kratos/tool/protobuf/protoc-gen-ecode"
|
||||||
|
_ecodeProtoc = "protoc --proto_path=%s --proto_path=%s --proto_path=%s --ecode_out=:."
|
||||||
|
)
|
||||||
|
|
||||||
|
func installEcodeGen() error {
|
||||||
|
if _, err := exec.LookPath("protoc-gen-ecode"); err != nil {
|
||||||
|
if err := goget(_getEcodeGen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func genEcode(ctx *cli.Context) error {
|
||||||
|
return generate(ctx, _ecodeProtoc)
|
||||||
|
}
|
@ -27,6 +27,11 @@ func main() {
|
|||||||
Usage: "whether to use swagger for generation",
|
Usage: "whether to use swagger for generation",
|
||||||
Destination: &withSwagger,
|
Destination: &withSwagger,
|
||||||
},
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "ecode",
|
||||||
|
Usage: "whether to use ecode for generation",
|
||||||
|
Destination: &withEcode,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
app.Action = func(c *cli.Context) error {
|
app.Action = func(c *cli.Context) error {
|
||||||
return protocAction(c)
|
return protocAction(c)
|
||||||
|
@ -20,16 +20,18 @@ var (
|
|||||||
withBM bool
|
withBM bool
|
||||||
withGRPC bool
|
withGRPC bool
|
||||||
withSwagger bool
|
withSwagger bool
|
||||||
|
withEcode bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func protocAction(ctx *cli.Context) (err error) {
|
func protocAction(ctx *cli.Context) (err error) {
|
||||||
if err = checkProtoc(); err != nil {
|
if err = checkProtoc(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !withGRPC && !withBM && !withSwagger {
|
if !withGRPC && !withBM && !withSwagger && !withEcode {
|
||||||
withBM = true
|
withBM = true
|
||||||
withGRPC = true
|
withGRPC = true
|
||||||
withSwagger = true
|
withSwagger = true
|
||||||
|
withEcode = true
|
||||||
}
|
}
|
||||||
if withBM {
|
if withBM {
|
||||||
if err = installBMGen(); err != nil {
|
if err = installBMGen(); err != nil {
|
||||||
@ -55,6 +57,14 @@ func protocAction(ctx *cli.Context) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if withEcode {
|
||||||
|
if err = installEcodeGen(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = genEcode(ctx); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
log.Printf("generate %v success.\n", ctx.Args())
|
log.Printf("generate %v success.\n", ctx.Args())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
_getSwaggerGen = "go get -u github.com/bilibili/kratos/tool/protobuf/protoc-gen-bswagger"
|
_getSwaggerGen = "go get -u github.com/bilibili/kratos/tool/protobuf/protoc-gen-bswagger"
|
||||||
_swaggerProtoc = "protoc --proto_path=%s --proto_path=%s --proto_path=%s --bswagger_out=explicit_http=true:."
|
_swaggerProtoc = "protoc --proto_path=%s --proto_path=%s --proto_path=%s --bswagger_out=:."
|
||||||
)
|
)
|
||||||
|
|
||||||
func installSwaggerGen() error {
|
func installSwaggerGen() error {
|
||||||
|
@ -2,6 +2,7 @@ package naming
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -25,6 +26,16 @@ func GetVersionPrefix(pkg string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GenFileName returns the output name for the generated Go file.
|
||||||
|
func GenFileName(f *descriptor.FileDescriptorProto, suffix string) string {
|
||||||
|
name := *f.Name
|
||||||
|
if ext := path.Ext(name); ext == ".pb" || ext == ".proto" || ext == ".protodevel" {
|
||||||
|
name = name[:len(name)-len(ext)]
|
||||||
|
}
|
||||||
|
name += suffix
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
func ServiceName(service *descriptor.ServiceDescriptorProto) string {
|
func ServiceName(service *descriptor.ServiceDescriptorProto) string {
|
||||||
return utils.CamelCase(service.GetName())
|
return utils.CamelCase(service.GetName())
|
||||||
}
|
}
|
||||||
|
@ -44,9 +44,6 @@ func (t *bm) Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResp
|
|||||||
|
|
||||||
func (t *bm) generateForFile(file *descriptor.FileDescriptorProto) *plugin.CodeGeneratorResponse_File {
|
func (t *bm) generateForFile(file *descriptor.FileDescriptorProto) *plugin.CodeGeneratorResponse_File {
|
||||||
resp := new(plugin.CodeGeneratorResponse_File)
|
resp := new(plugin.CodeGeneratorResponse_File)
|
||||||
//if len(file.Service) == 0 {
|
|
||||||
// return nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
t.generateFileHeader(file, t.GenPkgName)
|
t.generateFileHeader(file, t.GenPkgName)
|
||||||
t.generateImports(file)
|
t.generateImports(file)
|
||||||
@ -56,11 +53,8 @@ func (t *bm) generateForFile(file *descriptor.FileDescriptorProto) *plugin.CodeG
|
|||||||
count += t.generateBMInterface(file, service)
|
count += t.generateBMInterface(file, service)
|
||||||
t.generateBMRoute(file, service, i)
|
t.generateBMRoute(file, service, i)
|
||||||
}
|
}
|
||||||
//if count == 0 {
|
|
||||||
// return nil
|
|
||||||
//}
|
|
||||||
|
|
||||||
resp.Name = proto.String(naming.GoFileName(file, ".bm.go"))
|
resp.Name = proto.String(naming.GenFileName(file, ".bm.go"))
|
||||||
resp.Content = proto.String(t.FormattedOutput())
|
resp.Content = proto.String(t.FormattedOutput())
|
||||||
t.Output.Reset()
|
t.Output.Reset()
|
||||||
|
|
||||||
@ -88,13 +82,13 @@ func (t *bm) generateFileHeader(file *descriptor.FileDescriptorProto, pkgName st
|
|||||||
t.P("// source: ", file.GetName())
|
t.P("// source: ", file.GetName())
|
||||||
t.P()
|
t.P()
|
||||||
if t.filesHandled == 0 {
|
if t.filesHandled == 0 {
|
||||||
// doc for the first file
|
|
||||||
t.P("/*")
|
|
||||||
t.P("Package ", t.GenPkgName, " is a generated blademaster stub package.")
|
|
||||||
t.P("This code was generated with kratos/tool/protobuf/protoc-gen-bm ", generator.Version, ".")
|
|
||||||
t.P()
|
|
||||||
comment, err := t.Reg.FileComments(file)
|
comment, err := t.Reg.FileComments(file)
|
||||||
if err == nil && comment.Leading != "" {
|
if err == nil && comment.Leading != "" {
|
||||||
|
// doc for the first file
|
||||||
|
t.P("/*")
|
||||||
|
t.P("Package ", t.GenPkgName, " is a generated blademaster stub package.")
|
||||||
|
t.P("This code was generated with kratos/tool/protobuf/protoc-gen-bm ", generator.Version, ".")
|
||||||
|
t.P()
|
||||||
for _, line := range strings.Split(comment.Leading, "\n") {
|
for _, line := range strings.Split(comment.Leading, "\n") {
|
||||||
line = strings.TrimPrefix(line, " ")
|
line = strings.TrimPrefix(line, " ")
|
||||||
// ensure we don't escape from the block comment
|
// ensure we don't escape from the block comment
|
||||||
@ -102,12 +96,12 @@ func (t *bm) generateFileHeader(file *descriptor.FileDescriptorProto, pkgName st
|
|||||||
t.P(line)
|
t.P(line)
|
||||||
}
|
}
|
||||||
t.P()
|
t.P()
|
||||||
|
t.P("It is generated from these files:")
|
||||||
|
for _, f := range t.GenFiles {
|
||||||
|
t.P("\t", f.GetName())
|
||||||
|
}
|
||||||
|
t.P("*/")
|
||||||
}
|
}
|
||||||
t.P("It is generated from these files:")
|
|
||||||
for _, f := range t.GenFiles {
|
|
||||||
t.P("\t", f.GetName())
|
|
||||||
}
|
|
||||||
t.P("*/")
|
|
||||||
}
|
}
|
||||||
t.P(`package `, pkgName)
|
t.P(`package `, pkgName)
|
||||||
t.P()
|
t.P()
|
||||||
|
@ -66,7 +66,7 @@ func (t *swaggerGen) generateSwagger(file *descriptor.FileDescriptorProto) *plug
|
|||||||
t.defsMap = map[string]*typemap.MessageDefinition{}
|
t.defsMap = map[string]*typemap.MessageDefinition{}
|
||||||
|
|
||||||
out := &plugin.CodeGeneratorResponse_File{}
|
out := &plugin.CodeGeneratorResponse_File{}
|
||||||
name := naming.GoFileName(file, ".swagger.json")
|
name := naming.GenFileName(file, ".swagger.json")
|
||||||
for _, svc := range file.Service {
|
for _, svc := range file.Service {
|
||||||
for _, meth := range svc.Method {
|
for _, meth := range svc.Method {
|
||||||
if !t.ShouldGenForMethod(file, svc, meth) {
|
if !t.ShouldGenForMethod(file, svc, meth) {
|
||||||
|
117
tool/protobuf/protoc-gen-ecode/generator/generator.go
Normal file
117
tool/protobuf/protoc-gen-ecode/generator/generator.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/generator"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/naming"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ecode struct {
|
||||||
|
generator.Base
|
||||||
|
filesHandled int
|
||||||
|
}
|
||||||
|
|
||||||
|
// EcodeGenerator ecode generator.
|
||||||
|
func EcodeGenerator() *ecode {
|
||||||
|
t := &ecode{}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate ...
|
||||||
|
func (t *ecode) Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse {
|
||||||
|
t.Setup(in)
|
||||||
|
|
||||||
|
// Showtime! Generate the response.
|
||||||
|
resp := new(plugin.CodeGeneratorResponse)
|
||||||
|
for _, f := range t.GenFiles {
|
||||||
|
respFile := t.generateForFile(f)
|
||||||
|
if respFile != nil {
|
||||||
|
resp.File = append(resp.File, respFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ecode) generateForFile(file *descriptor.FileDescriptorProto) *plugin.CodeGeneratorResponse_File {
|
||||||
|
var enums []*descriptor.EnumDescriptorProto
|
||||||
|
for _, enum := range file.EnumType {
|
||||||
|
if strings.HasSuffix(*enum.Name, "ErrCode") {
|
||||||
|
enums = append(enums, enum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(enums) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
resp := new(plugin.CodeGeneratorResponse_File)
|
||||||
|
t.generateFileHeader(file, t.GenPkgName)
|
||||||
|
t.generateImports(file)
|
||||||
|
for _, enum := range enums {
|
||||||
|
t.generateEcode(file, enum)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.Name = proto.String(naming.GenFileName(file, ".ecode.go"))
|
||||||
|
resp.Content = proto.String(t.FormattedOutput())
|
||||||
|
t.Output.Reset()
|
||||||
|
|
||||||
|
t.filesHandled++
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ecode) generateFileHeader(file *descriptor.FileDescriptorProto, pkgName string) {
|
||||||
|
t.P("// Code generated by protoc-gen-ecode ", generator.Version, ", DO NOT EDIT.")
|
||||||
|
t.P("// source: ", file.GetName())
|
||||||
|
t.P()
|
||||||
|
if t.filesHandled == 0 {
|
||||||
|
comment, err := t.Reg.FileComments(file)
|
||||||
|
if err == nil && comment.Leading != "" {
|
||||||
|
// doc for the first file
|
||||||
|
t.P("/*")
|
||||||
|
t.P("Package ", t.GenPkgName, " is a generated ecode package.")
|
||||||
|
t.P("This code was generated with kratos/tool/protobuf/protoc-gen-ecode ", generator.Version, ".")
|
||||||
|
t.P()
|
||||||
|
for _, line := range strings.Split(comment.Leading, "\n") {
|
||||||
|
line = strings.TrimPrefix(line, " ")
|
||||||
|
// ensure we don't escape from the block comment
|
||||||
|
line = strings.Replace(line, "*/", "* /", -1)
|
||||||
|
t.P(line)
|
||||||
|
}
|
||||||
|
t.P()
|
||||||
|
t.P("It is generated from these files:")
|
||||||
|
for _, f := range t.GenFiles {
|
||||||
|
t.P("\t", f.GetName())
|
||||||
|
}
|
||||||
|
t.P("*/")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.P(`package `, pkgName)
|
||||||
|
t.P()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ecode) generateImports(file *descriptor.FileDescriptorProto) {
|
||||||
|
t.P(`import (`)
|
||||||
|
t.P(` "github.com/bilibili/kratos/pkg/ecode"`)
|
||||||
|
t.P(`)`)
|
||||||
|
t.P()
|
||||||
|
t.P(`// to suppressed 'imported but not used warning'`)
|
||||||
|
t.P(`var _ ecode.Codes`)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ecode) generateEcode(file *descriptor.FileDescriptorProto, enum *descriptor.EnumDescriptorProto) {
|
||||||
|
t.P("// ", *enum.Name, " ecode")
|
||||||
|
t.P("var (")
|
||||||
|
|
||||||
|
for _, item := range enum.Value {
|
||||||
|
if *item.Number == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// NOTE: eg: t.P("UserNotExist = New(-404) ")
|
||||||
|
t.P(*item.Name, " = ", "ecode.New(", strconv.Itoa(int(*item.Number)), ")")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.P(")")
|
||||||
|
}
|
27
tool/protobuf/protoc-gen-ecode/generator/generator_test.go
Normal file
27
tool/protobuf/protoc-gen-ecode/generator/generator_test.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGenerateParseCommandLineParamsError(t *testing.T) {
|
||||||
|
if os.Getenv("BE_CRASHER") == "1" {
|
||||||
|
g := &ecode{}
|
||||||
|
g.Generate(&plugin.CodeGeneratorRequest{
|
||||||
|
Parameter: proto.String("invalid"),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cmd := exec.Command(os.Args[0], "-test.run=TestGenerateParseCommandLineParamsError")
|
||||||
|
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
|
||||||
|
err := cmd.Run()
|
||||||
|
if e, ok := err.(*exec.ExitError); ok && !e.Success() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Fatalf("process ran with err %v, want exit status 1", err)
|
||||||
|
}
|
23
tool/protobuf/protoc-gen-ecode/main.go
Normal file
23
tool/protobuf/protoc-gen-ecode/main.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/gen"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/generator"
|
||||||
|
ecodegen "github.com/bilibili/kratos/tool/protobuf/protoc-gen-ecode/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
versionFlag := flag.Bool("version", false, "print version and exit")
|
||||||
|
flag.Parse()
|
||||||
|
if *versionFlag {
|
||||||
|
fmt.Println(generator.Version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
g := ecodegen.EcodeGenerator()
|
||||||
|
gen.Main(g)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user