mirror of
https://github.com/go-kratos/kratos.git
synced 2025-01-20 03:29:45 +02:00
Kratos protobuf protoc (#71)
* add cross-platform protoc * add protobuf generator
This commit is contained in:
parent
8266a50f3d
commit
e5fe1e4f63
@ -1,7 +1,7 @@
|
|||||||
language: go
|
language: go
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.11.x
|
- 1.12.x
|
||||||
|
|
||||||
# Only clone the most recent commit.
|
# Only clone the most recent commit.
|
||||||
git:
|
git:
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
![kratos](doc/img/kratos3.png)
|
![kratos](doc/img/kratos3.png)
|
||||||
|
|
||||||
[![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/)
|
[![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/)
|
||||||
|
[![Build Status](https://travis-ci.org/bilibili/kratos.svg?branch=master)](https://travis-ci.org/bilibili/kratos)
|
||||||
[![GoDoc](https://godoc.org/github.com/bilibili/kratos?status.svg)](https://godoc.org/github.com/bilibili/kratos)
|
[![GoDoc](https://godoc.org/github.com/bilibili/kratos?status.svg)](https://godoc.org/github.com/bilibili/kratos)
|
||||||
[![Go Report Card](https://goreportcard.com/badge/github.com/bilibili/kratos)](https://goreportcard.com/report/github.com/bilibili/kratos)
|
[![Go Report Card](https://goreportcard.com/badge/github.com/bilibili/kratos)](https://goreportcard.com/report/github.com/bilibili/kratos)
|
||||||
|
|
||||||
@ -66,3 +67,4 @@ Kratos is under the MIT license. See the [LICENSE](./LICENSE) file for details.
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
*Please report bugs, concerns, suggestions by issues, or join QQ-group 716486124 to discuss problems around source code.*
|
*Please report bugs, concerns, suggestions by issues, or join QQ-group 716486124 to discuss problems around source code.*
|
||||||
|
|
||||||
|
@ -55,13 +55,13 @@ kratos new kratos-demo
|
|||||||
kratos new kratos-demo -o YourName -d YourPath
|
kratos new kratos-demo -o YourName -d YourPath
|
||||||
```
|
```
|
||||||
|
|
||||||
注意,`kratos new`默认是不会生成`grpc`示例代码的,如需生成请加`--grpc`,如下:
|
注意,`kratos new`默认是不会生成通过protobuf定义的`grpc`和`bm`示例代码的,如需生成请加`--proto`,如下:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
kratos new kratos-demo -o YourName -d YourPath --grpc
|
kratos new kratos-demo -o YourName -d YourPath --proto
|
||||||
```
|
```
|
||||||
|
|
||||||
特别注意,如果不是macos系统,生成的示例项目`api`目录下的`proto`文件并不会自动生成对应的`.pb.go`文件,需要参考以下说明进行生成。
|
特别注意,如果不是macos系统,生成的示例项目`api`目录下的`proto`文件并不会自动生成对应的`.pb.go`和`.bm.go`文件,需要参考以下说明进行生成。
|
||||||
|
|
||||||
[protoc说明](protoc.md)
|
[protoc说明](protoc.md)
|
||||||
|
|
||||||
@ -74,8 +74,9 @@ kratos new kratos-demo -o YourName -d YourPath --grpc
|
|||||||
`kratos tool`是基于proto生成http&grpc代码,生成缓存回源代码,生成memcache执行代码,生成swagger文档等工具集,先看下`kratos tool`的执行效果:
|
`kratos tool`是基于proto生成http&grpc代码,生成缓存回源代码,生成memcache执行代码,生成swagger文档等工具集,先看下`kratos tool`的执行效果:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
swagger(已安装): swagger api文档 Author(goswagger.io) [2019/05/05]
|
||||||
|
protoc(已安装): 快速方便生成pb.go和bm.go的protoc封装,windows、Linux请先安装protoc工具 Author(kratos) [2019/05/04]
|
||||||
kratos(已安装): Kratos工具集本体 Author(kratos) [2019/04/02]
|
kratos(已安装): Kratos工具集本体 Author(kratos) [2019/04/02]
|
||||||
kprotoc(已安装): 快速方便生成pb.go的protoc封装,不支持Windows,Linux请先安装protoc工具 Author(kratos) [2019/04/02]
|
|
||||||
|
|
||||||
安装工具: kratos tool install demo
|
安装工具: kratos tool install demo
|
||||||
执行工具: kratos tool demo
|
执行工具: kratos tool demo
|
||||||
@ -87,25 +88,49 @@ kprotoc(已安装): 快速方便生成pb.go的protoc封装,不支持Windows,
|
|||||||
***小小说明:如未安装工具,第一次运行也可自动安装,不需要特别执行install***
|
***小小说明:如未安装工具,第一次运行也可自动安装,不需要特别执行install***
|
||||||
|
|
||||||
目前已经集成的工具有:
|
目前已经集成的工具有:
|
||||||
* `kprotoc`用于快速生成`pb.go`文件,但目前不支持windows,Linux也需要先自己安装`protoc`工具。
|
* `protoc`用于快速生成`*.pb.go`和`*.bm.go`文件,但目前不支持windows,Linux也需要先自己安装`protoc`工具。
|
||||||
|
* `swagger`用于显示自动生成的BM API接口文档,通过 `kratos tool swagger serve api/api.swagger.json` 可以访问到文档。
|
||||||
* TODOs...
|
* TODOs...
|
||||||
|
|
||||||
### kratos tool kprotoc
|
### kratos tool protoc
|
||||||
|
|
||||||
该命令运行没其他参数,直接`kratos tool kprotoc`运行即可。但使用前需特别说明:
|
该命令运行没其他参数,直接`kratos tool protoc`运行即可。但使用前需特别说明:
|
||||||
|
|
||||||
* 该工具不支持Windows用户,请安装`protoc`和`gogo protobuf`工具
|
* 该工具在Windows/Linux下运行,需提前安装好`protoc`工具
|
||||||
* 该工具在Linux下运行,需提前安装好`protoc`工具
|
|
||||||
|
|
||||||
该工具实际是一段`shell`脚本,其中自动将`protoc`命令进行了拼接,识别了需要`include`的目录和当前目录下的`proto`文件,最终会拼接为如下命令进行执行:
|
该工具实际是一段`shell`脚本,其中自动将`protoc`命令进行了拼接,识别了需要`*.proto`的目录和当前目录下的`proto`文件,最终会拼接为如下命令进行执行:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
protoc -I/Users/felix/work/go/src:/usr/local/include --gogofast_out=plugins=grpc:/Users/felix/work/go/src /Users/felix/work/go/src/kratos-demo/api/api.proto
|
export $KRATOS_HOME = kratos路径
|
||||||
|
export $KRATOS_DEMO = 项目路径
|
||||||
|
|
||||||
|
// 生成:api.pb.go
|
||||||
|
protoc -I$GOPATH/src:$KRATOS_HOME/tool/protobuf/pkg/extensions:$KRATOS_DEMO/api --gogofast_out=plugins=grpc:$KRATOS_DEMO/api $KRATOS_DEMO/api/api.proto
|
||||||
|
// 生成:api.bm.go
|
||||||
|
protoc -I$GOPATH/src:$KRATOS_HOME/tool/protobuf/pkg/extensions:$KRATOS_DEMO/api --bm_out=$KRATOS_DEMO/api $KRATOS_DEMO/api/api.proto
|
||||||
|
// 生成:api.swagger.json
|
||||||
|
protoc -I$GOPATH/src:$KRATOS_HOME/tool/protobuf/pkg/extensions:$KRATOS_DEMO/api --bswagger_out=$KRATOS_DEMO/api $KRATOS_DEMO/api/api.proto
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows和Linux用户可以参考该命令进行`proto`生成`pb.go`文件,也可以参考[protoc说明](protoc.md)。
|
大家也可以参考该命令进行`proto`生成`*.pb.go`和`*.bm.go`文件,也可以参考[protoc说明](protoc.md)。
|
||||||
|
|
||||||
### TODOs
|
### Tool examples
|
||||||
|
```shell
|
||||||
|
// new a project
|
||||||
|
cd $GOPATH/src
|
||||||
|
kratos new kratos-demo -o Tinker --proto
|
||||||
|
|
||||||
|
// build & run
|
||||||
|
cd kratos-demo
|
||||||
|
kratos run
|
||||||
|
|
||||||
|
// swagger docs
|
||||||
|
kratos tool swagger serve kratos-demo/api/api.swagger.json
|
||||||
|
|
||||||
|
// generate proto
|
||||||
|
cd kratos-demo/api
|
||||||
|
kratos tool protoc api.proto
|
||||||
|
```
|
||||||
|
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
2
go.mod
2
go.mod
@ -22,6 +22,7 @@ require (
|
|||||||
github.com/prometheus/client_golang v0.9.2
|
github.com/prometheus/client_golang v0.9.2
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 // indirect
|
||||||
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec // indirect
|
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec // indirect
|
||||||
|
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726
|
||||||
github.com/sirupsen/logrus v1.4.1 // indirect
|
github.com/sirupsen/logrus v1.4.1 // indirect
|
||||||
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a
|
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a
|
||||||
github.com/stretchr/testify v1.3.0
|
github.com/stretchr/testify v1.3.0
|
||||||
@ -29,6 +30,7 @@ require (
|
|||||||
github.com/urfave/cli v1.20.0
|
github.com/urfave/cli v1.20.0
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
|
||||||
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8
|
||||||
google.golang.org/grpc v1.20.1
|
google.golang.org/grpc v1.20.1
|
||||||
gopkg.in/AlecAivazis/survey.v1 v1.8.2
|
gopkg.in/AlecAivazis/survey.v1 v1.8.2
|
||||||
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
if [[ -z $GOPATH ]]; then
|
|
||||||
GOPATH=${HOME}/go
|
|
||||||
fi
|
|
||||||
BIN_PATH=$( cut -d ':' -f 1 <<< "$GOPATH" )/bin
|
|
||||||
if [[ ! -z $GOBIN ]]; then
|
|
||||||
BIN_PATH=$GOBIN
|
|
||||||
fi
|
|
||||||
if [[ ! -z $INSTALL_PATH ]]; then
|
|
||||||
BIN_PATH=$INSTALL_PATH
|
|
||||||
fi
|
|
||||||
if [[ -f $BIN_PATH/kprotoc ]]; then
|
|
||||||
echo "kprotoc alreay install, remove $BIN_PATH/kprotoc first to reinstall."
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
ln -s $GOPATH/src/github.com/bilibili/kratos/tool/kprotoc/kprotoc.sh $BIN_PATH/kprotoc
|
|
||||||
echo "install kprotoc to $BIN_PATH/kprotoc done!"
|
|
@ -1,118 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
DEFAULT_PROTOC_GEN="gogofast"
|
|
||||||
DEFAULT_PROTOC="protoc"
|
|
||||||
KRATOS_DIR_NAME="github.com/bilibili/kratos"
|
|
||||||
USR_INCLUDE_DIR="/usr/local/include"
|
|
||||||
GOPATH=$GOPATH
|
|
||||||
if [[ -z $GOPATH ]]; then
|
|
||||||
GOPATH=${HOME}/go
|
|
||||||
fi
|
|
||||||
|
|
||||||
function _install_protoc() {
|
|
||||||
osname=$(uname -s)
|
|
||||||
echo "install protoc ..."
|
|
||||||
case $osname in
|
|
||||||
"Darwin" )
|
|
||||||
brew install protobuf
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "unknown operating system, need install protobuf manual see: https://developers.google.com/protocol-buffers"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
function _install_protoc_gen() {
|
|
||||||
local protoc_gen=$1
|
|
||||||
case $protoc_gen in
|
|
||||||
"gofast" )
|
|
||||||
echo "install gofast from github.com/gogo/protobuf/protoc-gen-gofast"
|
|
||||||
go get github.com/gogo/protobuf/protoc-gen-gofast
|
|
||||||
;;
|
|
||||||
"gogofast" )
|
|
||||||
echo "install gogofast from github.com/gogo/protobuf/protoc-gen-gogofast"
|
|
||||||
go get github.com/gogo/protobuf/protoc-gen-gogofast
|
|
||||||
;;
|
|
||||||
"gogo" )
|
|
||||||
echo "install gogo from github.com/gogo/protobuf/protoc-gen-gogo"
|
|
||||||
go get github.com/gogo/protobuf/protoc-gen-gogo
|
|
||||||
;;
|
|
||||||
"go" )
|
|
||||||
echo "install protoc-gen-go from github.com/golang/protobuf"
|
|
||||||
go get github.com/golang/protobuf/{proto,protoc-gen-go}
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "can't install protoc-gen-${protoc_gen} automatic !"
|
|
||||||
exit 1;
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
function _find_kratos_dir() {
|
|
||||||
local kratos_dir_name=$1
|
|
||||||
local current_dir="$GOPATH/src/$kratos_dir_name"
|
|
||||||
if [[ ! -d $current_dir ]]; then
|
|
||||||
go get -u $kratos_dir_name
|
|
||||||
fi
|
|
||||||
echo $current_dir
|
|
||||||
}
|
|
||||||
|
|
||||||
function _esc_string() {
|
|
||||||
echo $(echo "$1" | sed 's_/_\\/_g')
|
|
||||||
}
|
|
||||||
|
|
||||||
function _run_protoc() {
|
|
||||||
local proto_dir=$1
|
|
||||||
local proto_files=$(find $proto_dir -maxdepth 1 -name "*.proto")
|
|
||||||
if [[ -z $proto_files ]]; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
local protoc_cmd="$PROTOC -I$PROTO_PATH --${PROTOC_GEN}_out=plugins=grpc:${GOPATH}/src ${proto_files}"
|
|
||||||
echo $protoc_cmd
|
|
||||||
$protoc_cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ -z $PROTOC ]]; then
|
|
||||||
PROTOC=${DEFAULT_PROTOC}
|
|
||||||
which $PROTOC
|
|
||||||
if [[ "$?" -ne "0" ]]; then
|
|
||||||
_install_protoc
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [[ -z $PROTOC_GEN ]]; then
|
|
||||||
PROTOC_GEN=${DEFAULT_PROTOC_GEN}
|
|
||||||
which protoc-gen-$PROTOC_GEN
|
|
||||||
if [[ "$?" -ne "0" ]]; then
|
|
||||||
_install_protoc_gen $PROTOC_GEN
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
KRATOS_DIR=$(_find_kratos_dir $KRATOS_DIR_NAME)
|
|
||||||
if [[ "$?" != "0" ]]; then
|
|
||||||
echo "can't find kratos directoy"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
KRATOS_PARENT=$(dirname $KRATOS_DIR)
|
|
||||||
|
|
||||||
if [[ -z $PROTO_PATH ]]; then
|
|
||||||
PROTO_PATH=$GOPATH/src:$KRATOS_PARENT:$USR_INCLUDE_DIR
|
|
||||||
else
|
|
||||||
PROTO_PATH=$GOPATH/src:$PROTO_PATH:$KRATOS_PARENT:$USR_INCLUDE_DIR
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -z $1 ]]; then
|
|
||||||
cd $1
|
|
||||||
fi
|
|
||||||
TARGET_DIR=$(pwd)
|
|
||||||
|
|
||||||
# switch to $GOPATH/src
|
|
||||||
cd $GOPATH/src
|
|
||||||
echo "switch workdir to $GOPATH/src"
|
|
||||||
|
|
||||||
DIRS=$(find $TARGET_DIR -type d)
|
|
||||||
|
|
||||||
for dir in $DIRS; do
|
|
||||||
echo "run protoc in $dir"
|
|
||||||
_run_protoc $dir
|
|
||||||
done
|
|
25
tool/kratos-protoc/bm.go
Normal file
25
tool/kratos-protoc/bm.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_getBMGen = "go get 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:."
|
||||||
|
)
|
||||||
|
|
||||||
|
func installBMGen() error {
|
||||||
|
if _, err := exec.LookPath("protoc-gen-bm"); err != nil {
|
||||||
|
if err := goget(_getBMGen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func genBM(ctx *cli.Context) error {
|
||||||
|
return generate(ctx, _bmProtoc)
|
||||||
|
}
|
25
tool/kratos-protoc/grpc.go
Normal file
25
tool/kratos-protoc/grpc.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_getGRPCGen = "go get github.com/gogo/protobuf/protoc-gen-gogofast"
|
||||||
|
_grpcProtoc = "protoc --proto_path=%s --proto_path=%s --proto_path=%s --gogofast_out=plugins=grpc:."
|
||||||
|
)
|
||||||
|
|
||||||
|
func installGRPCGen() error {
|
||||||
|
if _, err := exec.LookPath("protoc-gen-gogofast"); err != nil {
|
||||||
|
if err := goget(_getGRPCGen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func genGRPC(ctx *cli.Context) error {
|
||||||
|
return generate(ctx, _grpcProtoc)
|
||||||
|
}
|
37
tool/kratos-protoc/main.go
Normal file
37
tool/kratos-protoc/main.go
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.Name = "protc"
|
||||||
|
app.Usage = "protobuf生成工具"
|
||||||
|
app.Flags = []cli.Flag{
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "bm",
|
||||||
|
Usage: "whether to use BM for generation",
|
||||||
|
Destination: &withBM,
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "grpc",
|
||||||
|
Usage: "whether to use gRPC for generation",
|
||||||
|
Destination: &withGRPC,
|
||||||
|
},
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "swagger",
|
||||||
|
Usage: "whether to use swagger for generation",
|
||||||
|
Destination: &withSwagger,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
app.Action = func(c *cli.Context) error {
|
||||||
|
return protocAction(c)
|
||||||
|
}
|
||||||
|
if err := app.Run(os.Args); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
160
tool/kratos-protoc/protoc.go
Normal file
160
tool/kratos-protoc/protoc.go
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go/build"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
withBM bool
|
||||||
|
withGRPC bool
|
||||||
|
withSwagger bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func protocAction(ctx *cli.Context) (err error) {
|
||||||
|
if err = checkProtoc(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !withGRPC && !withBM && !withSwagger {
|
||||||
|
withBM = true
|
||||||
|
withGRPC = true
|
||||||
|
withSwagger = true
|
||||||
|
}
|
||||||
|
if withBM {
|
||||||
|
if err = installBMGen(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = genBM(ctx); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if withGRPC {
|
||||||
|
if err = installGRPCGen(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = genGRPC(ctx); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if withSwagger {
|
||||||
|
if err = installSwaggerGen(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err = genSwagger(ctx); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Printf("generate %v success.\n", ctx.Args())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkProtoc() error {
|
||||||
|
if _, err := exec.LookPath("protoc"); err != nil {
|
||||||
|
switch runtime.GOOS {
|
||||||
|
case "darwin":
|
||||||
|
fmt.Println("brew install protobuf")
|
||||||
|
cmd := exec.Command("brew", "install", "protobuf")
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err = cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "linux":
|
||||||
|
fmt.Println("snap install --classic protobuf")
|
||||||
|
cmd := exec.Command("snap", "install", "--classic", "protobuf")
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err = cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return errors.New("您还没安装protobuf,请进行手动安装:https://github.com/protocolbuffers/protobuf/releases")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func generate(ctx *cli.Context, protoc string) error {
|
||||||
|
pwd, _ := os.Getwd()
|
||||||
|
gosrc := path.Join(gopath(), "src")
|
||||||
|
ext, err := latestKratos()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
line := fmt.Sprintf(protoc, gosrc, ext, pwd)
|
||||||
|
log.Println(line, strings.Join(ctx.Args(), " "))
|
||||||
|
args := strings.Split(line, " ")
|
||||||
|
args = append(args, ctx.Args()...)
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Dir = pwd
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func goget(url string) error {
|
||||||
|
args := strings.Split(url, " ")
|
||||||
|
cmd := exec.Command(args[0], args[1:]...)
|
||||||
|
cmd.Env = os.Environ()
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
log.Println(url)
|
||||||
|
return cmd.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func latestKratos() (string, error) {
|
||||||
|
gopath := gopath()
|
||||||
|
ext := path.Join(gopath, "src/github.com/bilibili/kratos/tool/protobuf/pkg/extensions")
|
||||||
|
if _, err := os.Stat(ext); !os.IsNotExist(err) {
|
||||||
|
return ext, nil
|
||||||
|
}
|
||||||
|
ext = path.Join(gopath, "pkg/mod/github.com/bilibili")
|
||||||
|
files, err := ioutil.ReadDir(ext)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(files) == 0 {
|
||||||
|
return "", errors.New("not found kratos package")
|
||||||
|
}
|
||||||
|
return path.Join(ext, files[len(files)-1].Name(), "tool/protobuf/pkg/extensions"), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func gopath() (gp string) {
|
||||||
|
gopaths := strings.Split(os.Getenv("GOPATH"), ":")
|
||||||
|
if len(gopaths) == 1 {
|
||||||
|
return gopaths[0]
|
||||||
|
}
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
abspwd, err := filepath.Abs(pwd)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, gopath := range gopaths {
|
||||||
|
absgp, err := filepath.Abs(gopath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(abspwd, absgp) {
|
||||||
|
return absgp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return build.Default.GOPATH
|
||||||
|
}
|
25
tool/kratos-protoc/swagger.go
Normal file
25
tool/kratos-protoc/swagger.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
_getSwaggerGen = "go get 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:."
|
||||||
|
)
|
||||||
|
|
||||||
|
func installSwaggerGen() error {
|
||||||
|
if _, err := exec.LookPath("protoc-gen-bswagger"); err != nil {
|
||||||
|
if err := goget(_getSwaggerGen); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func genSwagger(ctx *cli.Context) error {
|
||||||
|
return generate(ctx, _swaggerProtoc)
|
||||||
|
}
|
@ -31,8 +31,8 @@ func main() {
|
|||||||
Destination: &p.Path,
|
Destination: &p.Path,
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "grpc",
|
Name: "proto",
|
||||||
Usage: "whether to use grpc for create project",
|
Usage: "whether to use protobuf for create project",
|
||||||
Destination: &p.WithGRPC,
|
Destination: &p.WithGRPC,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -50,12 +50,12 @@ func main() {
|
|||||||
Usage: "kratos run",
|
Usage: "kratos run",
|
||||||
Action: runAction,
|
Action: runAction,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
Name: "tool",
|
Name: "tool",
|
||||||
Aliases: []string{"t"},
|
Aliases: []string{"t"},
|
||||||
Usage: "kratos tool",
|
Usage: "kratos tool",
|
||||||
Action: toolAction,
|
Action: toolAction,
|
||||||
|
SkipFlagParsing: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "version",
|
Name: "version",
|
||||||
|
@ -2,11 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
@ -115,16 +113,14 @@ func create() (err error) {
|
|||||||
if err = genpb(); err != nil {
|
if err = genpb(); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if runtime.GOOS != "darwin" {
|
|
||||||
fmt.Println("您的操作系统不是macos,kprotoc工具无法正常运行,请参看kratos tool文档!")
|
|
||||||
fmt.Println("地址:", toolDoc)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func genpb() error {
|
func genpb() error {
|
||||||
cmd := exec.Command("go", "generate", p.Path+"/api/generate.go")
|
cmd := exec.Command("go", "generate", p.Path+"/api/generate.go")
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
return cmd.Run()
|
return cmd.Run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ func main() {
|
|||||||
switch s {
|
switch s {
|
||||||
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 35*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 35*time.Second)
|
||||||
if err := grpcSrv.Shutdown(ctx); err != nil
|
if err := grpcSrv.Shutdown(ctx); err != nil {
|
||||||
log.Error("grpcSrv.Shutdown error(%v)", err)
|
log.Error("grpcSrv.Shutdown error(%v)", err)
|
||||||
} // grpc
|
} // grpc
|
||||||
if err := httpSrv.Shutdown(ctx); err != nil {
|
if err := httpSrv.Shutdown(ctx); err != nil {
|
||||||
@ -302,6 +302,15 @@ func (s *Service) SayHello(ctx context.Context, req *pb.HelloReq) (reply *empty.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SayHelloURL bm demo func.
|
||||||
|
func (s *Service) SayHelloURL(ctx context.Context, req *pb.HelloReq) (reply *pb.HelloResp, err error) {
|
||||||
|
reply = &pb.HelloResp{
|
||||||
|
Content: "hello " + req.Name,
|
||||||
|
}
|
||||||
|
fmt.Printf("hello url %s", req.Name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Ping ping the resource.
|
// Ping ping the resource.
|
||||||
func (s *Service) Ping(ctx context.Context) (err error) {
|
func (s *Service) Ping(ctx context.Context) (err error) {
|
||||||
return s.dao.Ping(ctx)
|
return s.dao.Ping(ctx)
|
||||||
@ -317,6 +326,7 @@ func (s *Service) Close() {
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
pb "{{.Name}}/api"
|
||||||
"{{.Name}}/internal/model"
|
"{{.Name}}/internal/model"
|
||||||
"{{.Name}}/internal/service"
|
"{{.Name}}/internal/service"
|
||||||
|
|
||||||
@ -343,6 +353,7 @@ func New(s *service.Service) (engine *bm.Engine) {
|
|||||||
}
|
}
|
||||||
svc = s
|
svc = s
|
||||||
engine = bm.DefaultServer(hc.Server)
|
engine = bm.DefaultServer(hc.Server)
|
||||||
|
pb.RegisterDemoBMServer(engine, svc)
|
||||||
initRouter(engine)
|
initRouter(engine)
|
||||||
if err := engine.Start(); err != nil {
|
if err := engine.Start(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -377,21 +388,11 @@ func howToStart(c *bm.Context) {
|
|||||||
_tplAPIProto = `// 定义项目 API 的 proto 文件 可以同时描述 gRPC 和 HTTP API
|
_tplAPIProto = `// 定义项目 API 的 proto 文件 可以同时描述 gRPC 和 HTTP API
|
||||||
// protobuf 文件参考:
|
// protobuf 文件参考:
|
||||||
// - https://developers.google.com/protocol-buffers/
|
// - https://developers.google.com/protocol-buffers/
|
||||||
// - TODO:待补充文档URL
|
|
||||||
// protobuf 生成 HTTP 工具:
|
|
||||||
// - TODO:待补充文档URL
|
|
||||||
// gRPC Golang Model:
|
|
||||||
// - TODO:待补充文档URL
|
|
||||||
// gRPC Golang Warden Gen:
|
|
||||||
// - TODO:待补充文档URL
|
|
||||||
// gRPC http 调试工具(无需pb文件):
|
|
||||||
// - TODO:待补充文档URL
|
|
||||||
// grpc 命令行调试工具(无需pb文件):
|
|
||||||
// - TODO:待补充文档URL
|
|
||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
import "gogoproto/gogo.proto";
|
||||||
import "google/protobuf/empty.proto";
|
import "google/protobuf/empty.proto";
|
||||||
|
import "google/api/annotations.proto";
|
||||||
|
|
||||||
// package 命名使用 {appid}.{version} 的方式, version 形如 v1, v2 ..
|
// package 命名使用 {appid}.{version} 的方式, version 形如 v1, v2 ..
|
||||||
package demo.service.v1;
|
package demo.service.v1;
|
||||||
@ -399,21 +400,29 @@ package demo.service.v1;
|
|||||||
// NOTE: 最后请删除这些无用的注释 (゜-゜)つロ
|
// NOTE: 最后请删除这些无用的注释 (゜-゜)つロ
|
||||||
|
|
||||||
option go_package = "api";
|
option go_package = "api";
|
||||||
// do not generate getXXX() method
|
|
||||||
option (gogoproto.goproto_getters_all) = false;
|
option (gogoproto.goproto_getters_all) = false;
|
||||||
|
|
||||||
service Demo {
|
service Demo {
|
||||||
rpc SayHello (HelloReq) returns (.google.protobuf.Empty);
|
rpc SayHello (HelloReq) returns (.google.protobuf.Empty);
|
||||||
|
rpc SayHelloURL(HelloReq) returns (HelloResp) {
|
||||||
|
option (google.api.http) = {
|
||||||
|
get:"/{{.Name}}/say_hello"
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
message HelloReq {
|
message HelloReq {
|
||||||
string name = 1 [(gogoproto.moretags)='form:"name" validate:"required"'];
|
string name = 1 [(gogoproto.moretags)='form:"name" validate:"required"'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message HelloResp {
|
||||||
|
string Content = 1 [(gogoproto.jsontag) = 'content'];
|
||||||
|
}
|
||||||
`
|
`
|
||||||
_tplAPIGenerate = `package api
|
_tplAPIGenerate = `package api
|
||||||
|
|
||||||
// 生成 gRPC 代码
|
// 生成 gRPC 代码
|
||||||
//go:generate kratos tool kprotoc
|
//go:generate kratos tool protoc api.proto
|
||||||
`
|
`
|
||||||
_tplModel = `package model
|
_tplModel = `package model
|
||||||
|
|
||||||
|
@ -130,6 +130,7 @@ func runTool(name, dir, cmd string, args []string) (err error) {
|
|||||||
// Tool .
|
// Tool .
|
||||||
type Tool struct {
|
type Tool struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
Alias string `json:"alias"`
|
||||||
BuildTime time.Time `json:"build_time"`
|
BuildTime time.Time `json:"build_time"`
|
||||||
Install string `json:"install"`
|
Install string `json:"install"`
|
||||||
Summary string `json:"summary"`
|
Summary string `json:"summary"`
|
||||||
@ -151,6 +152,7 @@ func (t Tool) install() {
|
|||||||
fmt.Fprintf(os.Stderr, color.RedString("%s: 自动安装失败详情请查看文档:%s\n", t.Name, toolDoc))
|
fmt.Fprintf(os.Stderr, color.RedString("%s: 自动安装失败详情请查看文档:%s\n", t.Name, toolDoc))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
fmt.Println(t.Install)
|
||||||
cmds := strings.Split(t.Install, " ")
|
cmds := strings.Split(t.Install, " ")
|
||||||
if len(cmds) > 0 {
|
if len(cmds) > 0 {
|
||||||
if err := runTool(t.Name, path.Dir(t.toolPath()), cmds[0], cmds[1:]); err == nil {
|
if err := runTool(t.Name, path.Dir(t.toolPath()), cmds[0], cmds[1:]); err == nil {
|
||||||
@ -172,7 +174,7 @@ func (t Tool) updated() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) toolPath() string {
|
func (t Tool) toolPath() string {
|
||||||
return filepath.Join(goPath(), "bin", t.Name)
|
return filepath.Join(gopath(), "bin", t.Alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t Tool) installed() bool {
|
func (t Tool) installed() bool {
|
||||||
@ -180,7 +182,7 @@ func (t Tool) installed() bool {
|
|||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func goPath() (gp string) {
|
func gopath() (gp string) {
|
||||||
gopaths := strings.Split(os.Getenv("GOPATH"), ":")
|
gopaths := strings.Split(os.Getenv("GOPATH"), ":")
|
||||||
if len(gopaths) == 1 {
|
if len(gopaths) == 1 {
|
||||||
return gopaths[0]
|
return gopaths[0]
|
||||||
|
@ -5,6 +5,7 @@ import "time"
|
|||||||
var toolIndexs = []*Tool{
|
var toolIndexs = []*Tool{
|
||||||
&Tool{
|
&Tool{
|
||||||
Name: "kratos",
|
Name: "kratos",
|
||||||
|
Alias: "kratos",
|
||||||
BuildTime: time.Date(2019, 4, 2, 0, 0, 0, 0, time.Local),
|
BuildTime: time.Date(2019, 4, 2, 0, 0, 0, 0, time.Local),
|
||||||
Install: "go get -u github.com/bilibili/kratos/tool/kratos",
|
Install: "go get -u github.com/bilibili/kratos/tool/kratos",
|
||||||
Summary: "Kratos工具集本体",
|
Summary: "Kratos工具集本体",
|
||||||
@ -12,11 +13,21 @@ var toolIndexs = []*Tool{
|
|||||||
Author: "kratos",
|
Author: "kratos",
|
||||||
},
|
},
|
||||||
&Tool{
|
&Tool{
|
||||||
Name: "kprotoc",
|
Name: "protoc",
|
||||||
BuildTime: time.Date(2019, 4, 2, 0, 0, 0, 0, time.Local),
|
Alias: "kratos-protoc",
|
||||||
Install: "bash -c ${GOPATH}/src/github.com/bilibili/kratos/tool/kprotoc/install_kprotoc.sh",
|
BuildTime: time.Date(2019, 5, 4, 0, 0, 0, 0, time.Local),
|
||||||
Summary: "快速方便生成pb.go的protoc封装,不支持windows,Linux请先安装protoc工具",
|
Install: "go get -u github.com/bilibili/kratos/tool/krotos-protoc",
|
||||||
Platform: []string{"darwin", "linux"},
|
Summary: "快速方便生成pb.go的protoc封装,windows、Linux请先安装protoc工具",
|
||||||
Author: "https://github.com/tomwei7",
|
Platform: []string{"darwin", "linux", "windows"},
|
||||||
|
Author: "kratos",
|
||||||
|
},
|
||||||
|
&Tool{
|
||||||
|
Name: "swagger",
|
||||||
|
Alias: "swagger",
|
||||||
|
BuildTime: time.Date(2019, 5, 5, 0, 0, 0, 0, time.Local),
|
||||||
|
Install: "go get -u github.com/go-swagger/go-swagger/cmd/swagger",
|
||||||
|
Summary: "swagger api文档",
|
||||||
|
Platform: []string{"darwin", "linux", "windows"},
|
||||||
|
Author: "goswagger.io",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
9
tool/protobuf/pkg/extensions/gogoproto/Makefile
Normal file
9
tool/protobuf/pkg/extensions/gogoproto/Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
regenerate:
|
||||||
|
go install go-common/vendor/github.com/golang/protobuf/protoc-gen-go
|
||||||
|
protoc --go_out=paths=source_relative:. gogo.proto
|
||||||
|
|
||||||
|
restore:
|
||||||
|
cp gogo.pb.golden gogo.pb.go
|
||||||
|
|
||||||
|
preserve:
|
||||||
|
cp gogo.pb.go gogo.pb.golden
|
818
tool/protobuf/pkg/extensions/gogoproto/gogo.pb.go
Normal file
818
tool/protobuf/pkg/extensions/gogoproto/gogo.pb.go
Normal file
@ -0,0 +1,818 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// source: gogo.proto
|
||||||
|
|
||||||
|
package gogoproto // import "github.com/bilibili/kratos/tool/protobuf/pkg/extensions/gogoproto"
|
||||||
|
|
||||||
|
import proto "github.com/golang/protobuf/proto"
|
||||||
|
import fmt "fmt"
|
||||||
|
import math "math"
|
||||||
|
import descriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the proto package it is being compiled against.
|
||||||
|
// A compilation error at this line likely means your copy of the
|
||||||
|
// proto package needs to be updated.
|
||||||
|
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
|
||||||
|
|
||||||
|
var E_GoprotoEnumPrefix = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.EnumOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 62001,
|
||||||
|
Name: "gogoproto.goproto_enum_prefix",
|
||||||
|
Tag: "varint,62001,opt,name=goproto_enum_prefix,json=goprotoEnumPrefix",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoEnumStringer = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.EnumOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 62021,
|
||||||
|
Name: "gogoproto.goproto_enum_stringer",
|
||||||
|
Tag: "varint,62021,opt,name=goproto_enum_stringer,json=goprotoEnumStringer",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_EnumStringer = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.EnumOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 62022,
|
||||||
|
Name: "gogoproto.enum_stringer",
|
||||||
|
Tag: "varint,62022,opt,name=enum_stringer,json=enumStringer",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_EnumCustomname = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.EnumOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 62023,
|
||||||
|
Name: "gogoproto.enum_customname",
|
||||||
|
Tag: "bytes,62023,opt,name=enum_customname,json=enumCustomname",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Enumdecl = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.EnumOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 62024,
|
||||||
|
Name: "gogoproto.enumdecl",
|
||||||
|
Tag: "varint,62024,opt,name=enumdecl",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_EnumvalueCustomname = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.EnumValueOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 66001,
|
||||||
|
Name: "gogoproto.enumvalue_customname",
|
||||||
|
Tag: "bytes,66001,opt,name=enumvalue_customname,json=enumvalueCustomname",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoGettersAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63001,
|
||||||
|
Name: "gogoproto.goproto_getters_all",
|
||||||
|
Tag: "varint,63001,opt,name=goproto_getters_all,json=goprotoGettersAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoEnumPrefixAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63002,
|
||||||
|
Name: "gogoproto.goproto_enum_prefix_all",
|
||||||
|
Tag: "varint,63002,opt,name=goproto_enum_prefix_all,json=goprotoEnumPrefixAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoStringerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63003,
|
||||||
|
Name: "gogoproto.goproto_stringer_all",
|
||||||
|
Tag: "varint,63003,opt,name=goproto_stringer_all,json=goprotoStringerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_VerboseEqualAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63004,
|
||||||
|
Name: "gogoproto.verbose_equal_all",
|
||||||
|
Tag: "varint,63004,opt,name=verbose_equal_all,json=verboseEqualAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_FaceAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63005,
|
||||||
|
Name: "gogoproto.face_all",
|
||||||
|
Tag: "varint,63005,opt,name=face_all,json=faceAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GostringAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63006,
|
||||||
|
Name: "gogoproto.gostring_all",
|
||||||
|
Tag: "varint,63006,opt,name=gostring_all,json=gostringAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_PopulateAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63007,
|
||||||
|
Name: "gogoproto.populate_all",
|
||||||
|
Tag: "varint,63007,opt,name=populate_all,json=populateAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_StringerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63008,
|
||||||
|
Name: "gogoproto.stringer_all",
|
||||||
|
Tag: "varint,63008,opt,name=stringer_all,json=stringerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_OnlyoneAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63009,
|
||||||
|
Name: "gogoproto.onlyone_all",
|
||||||
|
Tag: "varint,63009,opt,name=onlyone_all,json=onlyoneAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_EqualAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63013,
|
||||||
|
Name: "gogoproto.equal_all",
|
||||||
|
Tag: "varint,63013,opt,name=equal_all,json=equalAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_DescriptionAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63014,
|
||||||
|
Name: "gogoproto.description_all",
|
||||||
|
Tag: "varint,63014,opt,name=description_all,json=descriptionAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_TestgenAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63015,
|
||||||
|
Name: "gogoproto.testgen_all",
|
||||||
|
Tag: "varint,63015,opt,name=testgen_all,json=testgenAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_BenchgenAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63016,
|
||||||
|
Name: "gogoproto.benchgen_all",
|
||||||
|
Tag: "varint,63016,opt,name=benchgen_all,json=benchgenAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_MarshalerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63017,
|
||||||
|
Name: "gogoproto.marshaler_all",
|
||||||
|
Tag: "varint,63017,opt,name=marshaler_all,json=marshalerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_UnmarshalerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63018,
|
||||||
|
Name: "gogoproto.unmarshaler_all",
|
||||||
|
Tag: "varint,63018,opt,name=unmarshaler_all,json=unmarshalerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_StableMarshalerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63019,
|
||||||
|
Name: "gogoproto.stable_marshaler_all",
|
||||||
|
Tag: "varint,63019,opt,name=stable_marshaler_all,json=stableMarshalerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_SizerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63020,
|
||||||
|
Name: "gogoproto.sizer_all",
|
||||||
|
Tag: "varint,63020,opt,name=sizer_all,json=sizerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoEnumStringerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63021,
|
||||||
|
Name: "gogoproto.goproto_enum_stringer_all",
|
||||||
|
Tag: "varint,63021,opt,name=goproto_enum_stringer_all,json=goprotoEnumStringerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_EnumStringerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63022,
|
||||||
|
Name: "gogoproto.enum_stringer_all",
|
||||||
|
Tag: "varint,63022,opt,name=enum_stringer_all,json=enumStringerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_UnsafeMarshalerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63023,
|
||||||
|
Name: "gogoproto.unsafe_marshaler_all",
|
||||||
|
Tag: "varint,63023,opt,name=unsafe_marshaler_all,json=unsafeMarshalerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_UnsafeUnmarshalerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63024,
|
||||||
|
Name: "gogoproto.unsafe_unmarshaler_all",
|
||||||
|
Tag: "varint,63024,opt,name=unsafe_unmarshaler_all,json=unsafeUnmarshalerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoExtensionsMapAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63025,
|
||||||
|
Name: "gogoproto.goproto_extensions_map_all",
|
||||||
|
Tag: "varint,63025,opt,name=goproto_extensions_map_all,json=goprotoExtensionsMapAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoUnrecognizedAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63026,
|
||||||
|
Name: "gogoproto.goproto_unrecognized_all",
|
||||||
|
Tag: "varint,63026,opt,name=goproto_unrecognized_all,json=goprotoUnrecognizedAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GogoprotoImport = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63027,
|
||||||
|
Name: "gogoproto.gogoproto_import",
|
||||||
|
Tag: "varint,63027,opt,name=gogoproto_import,json=gogoprotoImport",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_ProtosizerAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63028,
|
||||||
|
Name: "gogoproto.protosizer_all",
|
||||||
|
Tag: "varint,63028,opt,name=protosizer_all,json=protosizerAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_CompareAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63029,
|
||||||
|
Name: "gogoproto.compare_all",
|
||||||
|
Tag: "varint,63029,opt,name=compare_all,json=compareAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_TypedeclAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63030,
|
||||||
|
Name: "gogoproto.typedecl_all",
|
||||||
|
Tag: "varint,63030,opt,name=typedecl_all,json=typedeclAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_EnumdeclAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63031,
|
||||||
|
Name: "gogoproto.enumdecl_all",
|
||||||
|
Tag: "varint,63031,opt,name=enumdecl_all,json=enumdeclAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoRegistration = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63032,
|
||||||
|
Name: "gogoproto.goproto_registration",
|
||||||
|
Tag: "varint,63032,opt,name=goproto_registration,json=goprotoRegistration",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_MessagenameAll = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FileOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 63033,
|
||||||
|
Name: "gogoproto.messagename_all",
|
||||||
|
Tag: "varint,63033,opt,name=messagename_all,json=messagenameAll",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoGetters = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64001,
|
||||||
|
Name: "gogoproto.goproto_getters",
|
||||||
|
Tag: "varint,64001,opt,name=goproto_getters,json=goprotoGetters",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoStringer = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64003,
|
||||||
|
Name: "gogoproto.goproto_stringer",
|
||||||
|
Tag: "varint,64003,opt,name=goproto_stringer,json=goprotoStringer",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_VerboseEqual = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64004,
|
||||||
|
Name: "gogoproto.verbose_equal",
|
||||||
|
Tag: "varint,64004,opt,name=verbose_equal,json=verboseEqual",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Face = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64005,
|
||||||
|
Name: "gogoproto.face",
|
||||||
|
Tag: "varint,64005,opt,name=face",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Gostring = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64006,
|
||||||
|
Name: "gogoproto.gostring",
|
||||||
|
Tag: "varint,64006,opt,name=gostring",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Populate = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64007,
|
||||||
|
Name: "gogoproto.populate",
|
||||||
|
Tag: "varint,64007,opt,name=populate",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Stringer = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 67008,
|
||||||
|
Name: "gogoproto.stringer",
|
||||||
|
Tag: "varint,67008,opt,name=stringer",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Onlyone = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64009,
|
||||||
|
Name: "gogoproto.onlyone",
|
||||||
|
Tag: "varint,64009,opt,name=onlyone",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Equal = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64013,
|
||||||
|
Name: "gogoproto.equal",
|
||||||
|
Tag: "varint,64013,opt,name=equal",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Description = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64014,
|
||||||
|
Name: "gogoproto.description",
|
||||||
|
Tag: "varint,64014,opt,name=description",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Testgen = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64015,
|
||||||
|
Name: "gogoproto.testgen",
|
||||||
|
Tag: "varint,64015,opt,name=testgen",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Benchgen = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64016,
|
||||||
|
Name: "gogoproto.benchgen",
|
||||||
|
Tag: "varint,64016,opt,name=benchgen",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Marshaler = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64017,
|
||||||
|
Name: "gogoproto.marshaler",
|
||||||
|
Tag: "varint,64017,opt,name=marshaler",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Unmarshaler = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64018,
|
||||||
|
Name: "gogoproto.unmarshaler",
|
||||||
|
Tag: "varint,64018,opt,name=unmarshaler",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_StableMarshaler = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64019,
|
||||||
|
Name: "gogoproto.stable_marshaler",
|
||||||
|
Tag: "varint,64019,opt,name=stable_marshaler,json=stableMarshaler",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Sizer = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64020,
|
||||||
|
Name: "gogoproto.sizer",
|
||||||
|
Tag: "varint,64020,opt,name=sizer",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_UnsafeMarshaler = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64023,
|
||||||
|
Name: "gogoproto.unsafe_marshaler",
|
||||||
|
Tag: "varint,64023,opt,name=unsafe_marshaler,json=unsafeMarshaler",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_UnsafeUnmarshaler = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64024,
|
||||||
|
Name: "gogoproto.unsafe_unmarshaler",
|
||||||
|
Tag: "varint,64024,opt,name=unsafe_unmarshaler,json=unsafeUnmarshaler",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoExtensionsMap = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64025,
|
||||||
|
Name: "gogoproto.goproto_extensions_map",
|
||||||
|
Tag: "varint,64025,opt,name=goproto_extensions_map,json=goprotoExtensionsMap",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_GoprotoUnrecognized = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64026,
|
||||||
|
Name: "gogoproto.goproto_unrecognized",
|
||||||
|
Tag: "varint,64026,opt,name=goproto_unrecognized,json=goprotoUnrecognized",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Protosizer = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64028,
|
||||||
|
Name: "gogoproto.protosizer",
|
||||||
|
Tag: "varint,64028,opt,name=protosizer",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Compare = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64029,
|
||||||
|
Name: "gogoproto.compare",
|
||||||
|
Tag: "varint,64029,opt,name=compare",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Typedecl = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64030,
|
||||||
|
Name: "gogoproto.typedecl",
|
||||||
|
Tag: "varint,64030,opt,name=typedecl",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Messagename = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.MessageOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 64033,
|
||||||
|
Name: "gogoproto.messagename",
|
||||||
|
Tag: "varint,64033,opt,name=messagename",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Nullable = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 65001,
|
||||||
|
Name: "gogoproto.nullable",
|
||||||
|
Tag: "varint,65001,opt,name=nullable",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Embed = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 65002,
|
||||||
|
Name: "gogoproto.embed",
|
||||||
|
Tag: "varint,65002,opt,name=embed",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Customtype = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 65003,
|
||||||
|
Name: "gogoproto.customtype",
|
||||||
|
Tag: "bytes,65003,opt,name=customtype",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Customname = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 65004,
|
||||||
|
Name: "gogoproto.customname",
|
||||||
|
Tag: "bytes,65004,opt,name=customname",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Jsontag = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 65005,
|
||||||
|
Name: "gogoproto.jsontag",
|
||||||
|
Tag: "bytes,65005,opt,name=jsontag",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Moretags = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 65006,
|
||||||
|
Name: "gogoproto.moretags",
|
||||||
|
Tag: "bytes,65006,opt,name=moretags",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Casttype = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 65007,
|
||||||
|
Name: "gogoproto.casttype",
|
||||||
|
Tag: "bytes,65007,opt,name=casttype",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Castkey = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 65008,
|
||||||
|
Name: "gogoproto.castkey",
|
||||||
|
Tag: "bytes,65008,opt,name=castkey",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Castvalue = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 65009,
|
||||||
|
Name: "gogoproto.castvalue",
|
||||||
|
Tag: "bytes,65009,opt,name=castvalue",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Stdtime = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 65010,
|
||||||
|
Name: "gogoproto.stdtime",
|
||||||
|
Tag: "varint,65010,opt,name=stdtime",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Stdduration = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*descriptor.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 65011,
|
||||||
|
Name: "gogoproto.stdduration",
|
||||||
|
Tag: "varint,65011,opt,name=stdduration",
|
||||||
|
Filename: "gogo.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterExtension(E_GoprotoEnumPrefix)
|
||||||
|
proto.RegisterExtension(E_GoprotoEnumStringer)
|
||||||
|
proto.RegisterExtension(E_EnumStringer)
|
||||||
|
proto.RegisterExtension(E_EnumCustomname)
|
||||||
|
proto.RegisterExtension(E_Enumdecl)
|
||||||
|
proto.RegisterExtension(E_EnumvalueCustomname)
|
||||||
|
proto.RegisterExtension(E_GoprotoGettersAll)
|
||||||
|
proto.RegisterExtension(E_GoprotoEnumPrefixAll)
|
||||||
|
proto.RegisterExtension(E_GoprotoStringerAll)
|
||||||
|
proto.RegisterExtension(E_VerboseEqualAll)
|
||||||
|
proto.RegisterExtension(E_FaceAll)
|
||||||
|
proto.RegisterExtension(E_GostringAll)
|
||||||
|
proto.RegisterExtension(E_PopulateAll)
|
||||||
|
proto.RegisterExtension(E_StringerAll)
|
||||||
|
proto.RegisterExtension(E_OnlyoneAll)
|
||||||
|
proto.RegisterExtension(E_EqualAll)
|
||||||
|
proto.RegisterExtension(E_DescriptionAll)
|
||||||
|
proto.RegisterExtension(E_TestgenAll)
|
||||||
|
proto.RegisterExtension(E_BenchgenAll)
|
||||||
|
proto.RegisterExtension(E_MarshalerAll)
|
||||||
|
proto.RegisterExtension(E_UnmarshalerAll)
|
||||||
|
proto.RegisterExtension(E_StableMarshalerAll)
|
||||||
|
proto.RegisterExtension(E_SizerAll)
|
||||||
|
proto.RegisterExtension(E_GoprotoEnumStringerAll)
|
||||||
|
proto.RegisterExtension(E_EnumStringerAll)
|
||||||
|
proto.RegisterExtension(E_UnsafeMarshalerAll)
|
||||||
|
proto.RegisterExtension(E_UnsafeUnmarshalerAll)
|
||||||
|
proto.RegisterExtension(E_GoprotoExtensionsMapAll)
|
||||||
|
proto.RegisterExtension(E_GoprotoUnrecognizedAll)
|
||||||
|
proto.RegisterExtension(E_GogoprotoImport)
|
||||||
|
proto.RegisterExtension(E_ProtosizerAll)
|
||||||
|
proto.RegisterExtension(E_CompareAll)
|
||||||
|
proto.RegisterExtension(E_TypedeclAll)
|
||||||
|
proto.RegisterExtension(E_EnumdeclAll)
|
||||||
|
proto.RegisterExtension(E_GoprotoRegistration)
|
||||||
|
proto.RegisterExtension(E_MessagenameAll)
|
||||||
|
proto.RegisterExtension(E_GoprotoGetters)
|
||||||
|
proto.RegisterExtension(E_GoprotoStringer)
|
||||||
|
proto.RegisterExtension(E_VerboseEqual)
|
||||||
|
proto.RegisterExtension(E_Face)
|
||||||
|
proto.RegisterExtension(E_Gostring)
|
||||||
|
proto.RegisterExtension(E_Populate)
|
||||||
|
proto.RegisterExtension(E_Stringer)
|
||||||
|
proto.RegisterExtension(E_Onlyone)
|
||||||
|
proto.RegisterExtension(E_Equal)
|
||||||
|
proto.RegisterExtension(E_Description)
|
||||||
|
proto.RegisterExtension(E_Testgen)
|
||||||
|
proto.RegisterExtension(E_Benchgen)
|
||||||
|
proto.RegisterExtension(E_Marshaler)
|
||||||
|
proto.RegisterExtension(E_Unmarshaler)
|
||||||
|
proto.RegisterExtension(E_StableMarshaler)
|
||||||
|
proto.RegisterExtension(E_Sizer)
|
||||||
|
proto.RegisterExtension(E_UnsafeMarshaler)
|
||||||
|
proto.RegisterExtension(E_UnsafeUnmarshaler)
|
||||||
|
proto.RegisterExtension(E_GoprotoExtensionsMap)
|
||||||
|
proto.RegisterExtension(E_GoprotoUnrecognized)
|
||||||
|
proto.RegisterExtension(E_Protosizer)
|
||||||
|
proto.RegisterExtension(E_Compare)
|
||||||
|
proto.RegisterExtension(E_Typedecl)
|
||||||
|
proto.RegisterExtension(E_Messagename)
|
||||||
|
proto.RegisterExtension(E_Nullable)
|
||||||
|
proto.RegisterExtension(E_Embed)
|
||||||
|
proto.RegisterExtension(E_Customtype)
|
||||||
|
proto.RegisterExtension(E_Customname)
|
||||||
|
proto.RegisterExtension(E_Jsontag)
|
||||||
|
proto.RegisterExtension(E_Moretags)
|
||||||
|
proto.RegisterExtension(E_Casttype)
|
||||||
|
proto.RegisterExtension(E_Castkey)
|
||||||
|
proto.RegisterExtension(E_Castvalue)
|
||||||
|
proto.RegisterExtension(E_Stdtime)
|
||||||
|
proto.RegisterExtension(E_Stdduration)
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { proto.RegisterFile("gogo.proto", fileDescriptor_gogo_e935c22a8aa82c87) }
|
||||||
|
|
||||||
|
var fileDescriptor_gogo_e935c22a8aa82c87 = []byte{
|
||||||
|
// 1260 bytes of a gzipped FileDescriptorProto
|
||||||
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x98, 0xc9, 0x6f, 0x1c, 0x45,
|
||||||
|
0x17, 0xc0, 0xf5, 0xe9, 0x4b, 0x14, 0xcf, 0xf3, 0x86, 0xc7, 0xc6, 0x84, 0x08, 0x44, 0xb8, 0x71,
|
||||||
|
0xc1, 0x73, 0x40, 0x11, 0x4a, 0x59, 0x91, 0xe5, 0x58, 0x8e, 0x15, 0x84, 0xc1, 0x98, 0xd8, 0x6c,
|
||||||
|
0x87, 0x51, 0xcf, 0x4c, 0xb9, 0x33, 0xa4, 0xbb, 0xab, 0xe9, 0xae, 0x8e, 0xe2, 0xdc, 0x50, 0x58,
|
||||||
|
0x84, 0x10, 0x3b, 0x12, 0x24, 0x24, 0x81, 0x1c, 0xd8, 0xd7, 0xb0, 0x73, 0xe3, 0xc2, 0x72, 0xe5,
|
||||||
|
0x7f, 0xe0, 0x02, 0x98, 0xdd, 0x37, 0x5f, 0xd0, 0xeb, 0x7e, 0xaf, 0xa7, 0x66, 0x3c, 0x52, 0xd5,
|
||||||
|
0xdc, 0xda, 0x76, 0xfd, 0x7e, 0xae, 0x7e, 0xaf, 0xea, 0xbd, 0x37, 0x03, 0xe0, 0x2b, 0x5f, 0xcd,
|
||||||
|
0xc4, 0x89, 0xd2, 0xaa, 0x5a, 0xc1, 0xe7, 0xfc, 0xf1, 0xc0, 0x41, 0x5f, 0x29, 0x3f, 0x90, 0xb5,
|
||||||
|
0xfc, 0xa7, 0x46, 0xb6, 0x51, 0x6b, 0xc9, 0xb4, 0x99, 0xb4, 0x63, 0xad, 0x92, 0x62, 0xb1, 0xb8,
|
||||||
|
0x0b, 0x26, 0x69, 0x71, 0x5d, 0x46, 0x59, 0x58, 0x8f, 0x13, 0xb9, 0xd1, 0x3e, 0x53, 0xbd, 0x61,
|
||||||
|
0xa6, 0x20, 0x67, 0x98, 0x9c, 0x59, 0x8c, 0xb2, 0xf0, 0xee, 0x58, 0xb7, 0x55, 0x94, 0xee, 0xbf,
|
||||||
|
0xfa, 0xf3, 0xff, 0x0f, 0xfe, 0xef, 0x96, 0xa1, 0xd5, 0x09, 0x42, 0xf1, 0x6f, 0x2b, 0x39, 0x28,
|
||||||
|
0x56, 0xe1, 0xda, 0x2e, 0x5f, 0xaa, 0x93, 0x76, 0xe4, 0xcb, 0xc4, 0x62, 0xfc, 0x8e, 0x8c, 0x93,
|
||||||
|
0x86, 0xf1, 0x5e, 0x42, 0xc5, 0x02, 0x8c, 0x0e, 0xe2, 0xfa, 0x9e, 0x5c, 0x23, 0xd2, 0x94, 0x2c,
|
||||||
|
0xc1, 0x78, 0x2e, 0x69, 0x66, 0xa9, 0x56, 0x61, 0xe4, 0x85, 0xd2, 0xa2, 0xf9, 0x21, 0xd7, 0x54,
|
||||||
|
0x56, 0xc7, 0x10, 0x5b, 0x28, 0x29, 0x21, 0x60, 0x08, 0x7f, 0xd3, 0x92, 0xcd, 0xc0, 0x62, 0xf8,
|
||||||
|
0x91, 0x36, 0x52, 0xae, 0x17, 0xeb, 0x30, 0x85, 0xcf, 0xa7, 0xbd, 0x20, 0x93, 0xe6, 0x4e, 0x6e,
|
||||||
|
0xee, 0xeb, 0x59, 0xc7, 0x65, 0x2c, 0xfb, 0xe9, 0xdc, 0x9e, 0x7c, 0x3b, 0x93, 0xa5, 0xc0, 0xd8,
|
||||||
|
0x93, 0x91, 0x45, 0x5f, 0x6a, 0x2d, 0x93, 0xb4, 0xee, 0x05, 0xfd, 0xb6, 0x77, 0xac, 0x1d, 0x94,
|
||||||
|
0xc6, 0xf3, 0x5b, 0xdd, 0x59, 0x5c, 0x2a, 0xc8, 0xf9, 0x20, 0x10, 0x6b, 0x70, 0x5d, 0x9f, 0x53,
|
||||||
|
0xe1, 0xe0, 0xbc, 0x40, 0xce, 0xa9, 0x5d, 0x27, 0x03, 0xb5, 0x2b, 0xc0, 0xbf, 0x2f, 0x73, 0xe9,
|
||||||
|
0xe0, 0x7c, 0x8d, 0x9c, 0x55, 0x62, 0x39, 0xa5, 0x68, 0xbc, 0x03, 0x26, 0x4e, 0xcb, 0xa4, 0xa1,
|
||||||
|
0x52, 0x59, 0x97, 0x8f, 0x64, 0x5e, 0xe0, 0xa0, 0xbb, 0x48, 0xba, 0x71, 0x02, 0x17, 0x91, 0x43,
|
||||||
|
0xd7, 0x61, 0x18, 0xda, 0xf0, 0x9a, 0xd2, 0x41, 0x71, 0x89, 0x14, 0xfb, 0x70, 0x3d, 0xa2, 0xf3,
|
||||||
|
0x30, 0xe2, 0xab, 0xe2, 0x95, 0x1c, 0xf0, 0xcb, 0x84, 0x0f, 0x33, 0x43, 0x8a, 0x58, 0xc5, 0x59,
|
||||||
|
0xe0, 0x69, 0x97, 0x1d, 0xbc, 0xce, 0x0a, 0x66, 0x48, 0x31, 0x40, 0x58, 0xdf, 0x60, 0x45, 0x6a,
|
||||||
|
0xc4, 0x73, 0x0e, 0x86, 0x55, 0x14, 0x6c, 0xaa, 0xc8, 0x65, 0x13, 0x57, 0xc8, 0x00, 0x84, 0xa0,
|
||||||
|
0x60, 0x16, 0x2a, 0xae, 0x89, 0x78, 0x73, 0x8b, 0xaf, 0x07, 0x67, 0x60, 0x09, 0xc6, 0xb9, 0x40,
|
||||||
|
0xb5, 0x55, 0xe4, 0xa0, 0x78, 0x8b, 0x14, 0x63, 0x06, 0x46, 0xaf, 0xa1, 0x65, 0xaa, 0x7d, 0xe9,
|
||||||
|
0x22, 0x79, 0x9b, 0x5f, 0x83, 0x10, 0x0a, 0x65, 0x43, 0x46, 0xcd, 0x93, 0x6e, 0x86, 0x77, 0x38,
|
||||||
|
0x94, 0xcc, 0xa0, 0x62, 0x01, 0x46, 0x43, 0x2f, 0x49, 0x4f, 0x7a, 0x81, 0x53, 0x3a, 0xde, 0x25,
|
||||||
|
0xc7, 0x48, 0x09, 0x51, 0x44, 0xb2, 0x68, 0x10, 0xcd, 0x7b, 0x1c, 0x11, 0x03, 0xa3, 0xab, 0x97,
|
||||||
|
0x6a, 0xaf, 0x11, 0xc8, 0xfa, 0x20, 0xb6, 0xf7, 0xf9, 0xea, 0x15, 0xec, 0xb2, 0x69, 0x9c, 0x85,
|
||||||
|
0x4a, 0xda, 0x3e, 0xeb, 0xa4, 0xf9, 0x80, 0x33, 0x9d, 0x03, 0x08, 0x3f, 0x00, 0xd7, 0xf7, 0x6d,
|
||||||
|
0x13, 0x0e, 0xb2, 0x0f, 0x49, 0x36, 0xdd, 0xa7, 0x55, 0x50, 0x49, 0x18, 0x54, 0xf9, 0x11, 0x97,
|
||||||
|
0x04, 0xd9, 0xe3, 0x5a, 0x81, 0xa9, 0x2c, 0x4a, 0xbd, 0x8d, 0xc1, 0xa2, 0xf6, 0x31, 0x47, 0xad,
|
||||||
|
0x60, 0xbb, 0xa2, 0x76, 0x02, 0xa6, 0xc9, 0x38, 0x58, 0x5e, 0x3f, 0xe1, 0xc2, 0x5a, 0xd0, 0x6b,
|
||||||
|
0xdd, 0xd9, 0x7d, 0x08, 0x0e, 0x94, 0xe1, 0x3c, 0xa3, 0x65, 0x94, 0x22, 0x53, 0x0f, 0xbd, 0xd8,
|
||||||
|
0xc1, 0x7c, 0x95, 0xcc, 0x5c, 0xf1, 0x17, 0x4b, 0xc1, 0xb2, 0x17, 0xa3, 0xfc, 0x7e, 0xd8, 0xcf,
|
||||||
|
0xf2, 0x2c, 0x4a, 0x64, 0x53, 0xf9, 0x51, 0xfb, 0xac, 0x6c, 0x39, 0xa8, 0x3f, 0xed, 0x49, 0xd5,
|
||||||
|
0x9a, 0x81, 0xa3, 0xf9, 0x38, 0x5c, 0x53, 0xce, 0x2a, 0xf5, 0x76, 0x18, 0xab, 0x44, 0x5b, 0x8c,
|
||||||
|
0x9f, 0x71, 0xa6, 0x4a, 0xee, 0x78, 0x8e, 0x89, 0x45, 0x18, 0xcb, 0x7f, 0x74, 0x3d, 0x92, 0x9f,
|
||||||
|
0x93, 0x68, 0xb4, 0x43, 0x51, 0xe1, 0x68, 0xaa, 0x30, 0xf6, 0x12, 0x97, 0xfa, 0xf7, 0x05, 0x17,
|
||||||
|
0x0e, 0x42, 0xa8, 0x70, 0xe8, 0xcd, 0x58, 0x62, 0xb7, 0x77, 0x30, 0x7c, 0xc9, 0x85, 0x83, 0x19,
|
||||||
|
0x52, 0xf0, 0xc0, 0xe0, 0xa0, 0xf8, 0x8a, 0x15, 0xcc, 0xa0, 0xe2, 0x9e, 0x4e, 0xa3, 0x4d, 0xa4,
|
||||||
|
0xdf, 0x4e, 0x75, 0xe2, 0xe1, 0x6a, 0x8b, 0xea, 0xeb, 0xad, 0xee, 0x21, 0x6c, 0xd5, 0x40, 0xb1,
|
||||||
|
0x12, 0x85, 0x32, 0x4d, 0x3d, 0x5f, 0xe2, 0xc4, 0xe1, 0xb0, 0xb1, 0x6f, 0xb8, 0x12, 0x19, 0x58,
|
||||||
|
0x71, 0x3f, 0xc7, 0x7b, 0x66, 0x95, 0xea, 0x4d, 0xbb, 0x44, 0xcb, 0x05, 0xc3, 0xae, 0x47, 0xb7,
|
||||||
|
0xc9, 0xd5, 0x3d, 0xaa, 0x88, 0x3b, 0xf1, 0x00, 0x75, 0x0f, 0x14, 0x76, 0xd9, 0xb9, 0xed, 0xf2,
|
||||||
|
0x0c, 0x75, 0xcd, 0x13, 0xe2, 0x18, 0x8c, 0x76, 0x0d, 0x13, 0x76, 0xd5, 0x63, 0xa4, 0x1a, 0x31,
|
||||||
|
0x67, 0x09, 0x71, 0x08, 0xf6, 0xe0, 0x60, 0x60, 0xc7, 0x1f, 0x27, 0x3c, 0x5f, 0x2e, 0x8e, 0xc0,
|
||||||
|
0x10, 0x0f, 0x04, 0x76, 0xf4, 0x09, 0x42, 0x4b, 0x04, 0x71, 0x1e, 0x06, 0xec, 0xf8, 0x93, 0x8c,
|
||||||
|
0x33, 0x82, 0xb8, 0x7b, 0x08, 0xbf, 0x7d, 0x7a, 0x0f, 0x15, 0x74, 0x8e, 0xdd, 0x2c, 0xec, 0xa3,
|
||||||
|
0x29, 0xc0, 0x4e, 0x3f, 0x45, 0xff, 0x9c, 0x09, 0x71, 0x3b, 0xec, 0x75, 0x0c, 0xf8, 0x33, 0x84,
|
||||||
|
0x16, 0xeb, 0xc5, 0x02, 0x0c, 0x1b, 0x9d, 0xdf, 0x8e, 0x3f, 0x4b, 0xb8, 0x49, 0xe1, 0xd6, 0xa9,
|
||||||
|
0xf3, 0xdb, 0x05, 0xcf, 0xf1, 0xd6, 0x89, 0xc0, 0xb0, 0x71, 0xd3, 0xb7, 0xd3, 0xcf, 0x73, 0xd4,
|
||||||
|
0x19, 0x11, 0x73, 0x50, 0x29, 0x0b, 0xb9, 0x9d, 0x7f, 0x81, 0xf8, 0x0e, 0x83, 0x11, 0x30, 0x1a,
|
||||||
|
0x89, 0x5d, 0xf1, 0x22, 0x47, 0xc0, 0xa0, 0xf0, 0x1a, 0xf5, 0x0e, 0x07, 0x76, 0xd3, 0x4b, 0x7c,
|
||||||
|
0x8d, 0x7a, 0x66, 0x03, 0xcc, 0x66, 0x5e, 0x4f, 0xed, 0x8a, 0x97, 0x39, 0x9b, 0xf9, 0x7a, 0xdc,
|
||||||
|
0x46, 0x6f, 0xb7, 0xb5, 0x3b, 0x5e, 0xe1, 0x6d, 0xf4, 0x34, 0x5b, 0xb1, 0x02, 0xd5, 0xdd, 0x9d,
|
||||||
|
0xd6, 0xee, 0x7b, 0x95, 0x7c, 0x13, 0xbb, 0x1a, 0xad, 0xb8, 0x0f, 0xa6, 0xfb, 0x77, 0x59, 0xbb,
|
||||||
|
0xf5, 0xfc, 0x76, 0xcf, 0xe7, 0x22, 0xb3, 0xc9, 0x8a, 0x13, 0x9d, 0x72, 0x6d, 0x76, 0x58, 0xbb,
|
||||||
|
0xf6, 0xc2, 0x76, 0x77, 0xc5, 0x36, 0x1b, 0xac, 0x98, 0x07, 0xe8, 0x34, 0x37, 0xbb, 0xeb, 0x22,
|
||||||
|
0xb9, 0x0c, 0x08, 0xaf, 0x06, 0xf5, 0x36, 0x3b, 0x7f, 0x89, 0xaf, 0x06, 0x11, 0x78, 0x35, 0xb8,
|
||||||
|
0xad, 0xd9, 0xe9, 0xcb, 0x7c, 0x35, 0x18, 0xc1, 0x93, 0x6d, 0x74, 0x0e, 0xbb, 0xe1, 0x0a, 0x9f,
|
||||||
|
0x6c, 0x83, 0x12, 0xb3, 0x30, 0x14, 0x65, 0x41, 0x80, 0x07, 0xb4, 0x7a, 0x63, 0x9f, 0x76, 0x25,
|
||||||
|
0x83, 0x16, 0xf3, 0xbf, 0xec, 0xd0, 0x0e, 0x18, 0x10, 0x87, 0x60, 0xaf, 0x0c, 0x1b, 0xb2, 0x65,
|
||||||
|
0x23, 0x7f, 0xdd, 0xe1, 0xa2, 0x84, 0xab, 0xc5, 0x1c, 0x40, 0xf1, 0xd1, 0x1e, 0x5f, 0xc5, 0xc6,
|
||||||
|
0xfe, 0xb6, 0x53, 0x7c, 0xcb, 0x60, 0x20, 0x1d, 0x41, 0xfe, 0xe2, 0x16, 0xc1, 0x56, 0xb7, 0x20,
|
||||||
|
0x7f, 0xeb, 0xc3, 0xb0, 0xef, 0xe1, 0x54, 0x45, 0xda, 0xf3, 0x6d, 0xf4, 0xef, 0x44, 0xf3, 0x7a,
|
||||||
|
0x0c, 0x58, 0xa8, 0x12, 0xa9, 0x3d, 0x3f, 0xb5, 0xb1, 0x7f, 0x10, 0x5b, 0x02, 0x08, 0x37, 0xbd,
|
||||||
|
0x54, 0xbb, 0xbc, 0xf7, 0x9f, 0x0c, 0x33, 0x80, 0x9b, 0xc6, 0xe7, 0x53, 0x72, 0xd3, 0xc6, 0xfe,
|
||||||
|
0xc5, 0x9b, 0xa6, 0xf5, 0xe2, 0x08, 0x54, 0xf0, 0x31, 0xff, 0x56, 0xc4, 0x06, 0xff, 0x4d, 0x70,
|
||||||
|
0x87, 0xc0, 0xff, 0x9c, 0xea, 0x96, 0x6e, 0xdb, 0x83, 0xfd, 0x0f, 0x65, 0x9a, 0xd7, 0x8b, 0x79,
|
||||||
|
0x18, 0x4e, 0x75, 0xab, 0x95, 0xd1, 0x7c, 0x65, 0xc1, 0xff, 0xdd, 0x29, 0x3f, 0x72, 0x97, 0xcc,
|
||||||
|
0xd1, 0x75, 0x98, 0x6c, 0xaa, 0xb0, 0x17, 0x3c, 0x0a, 0x4b, 0x6a, 0x49, 0xad, 0xe4, 0x57, 0xf1,
|
||||||
|
0xc1, 0xdb, 0x7c, 0x75, 0x6b, 0x53, 0x85, 0xa1, 0x8a, 0x6a, 0x5e, 0x1c, 0xd7, 0xb4, 0x52, 0x41,
|
||||||
|
0xad, 0x11, 0xe6, 0x4b, 0x6b, 0xf1, 0x29, 0xbf, 0xd6, 0xa9, 0x46, 0xb5, 0x72, 0x2e, 0xfe, 0x2f,
|
||||||
|
0x00, 0x00, 0xff, 0xff, 0x97, 0xb1, 0x98, 0x88, 0x13, 0x14, 0x00, 0x00,
|
||||||
|
}
|
45
tool/protobuf/pkg/extensions/gogoproto/gogo.pb.golden
Normal file
45
tool/protobuf/pkg/extensions/gogoproto/gogo.pb.golden
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Code generated by protoc-gen-go.
|
||||||
|
// source: gogo.proto
|
||||||
|
// DO NOT EDIT!
|
||||||
|
|
||||||
|
package gogoproto
|
||||||
|
|
||||||
|
import proto "github.com/gogo/protobuf/proto"
|
||||||
|
import json "encoding/json"
|
||||||
|
import math "math"
|
||||||
|
import google_protobuf "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
|
||||||
|
|
||||||
|
// Reference proto, json, and math imports to suppress error if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = &json.SyntaxError{}
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
var E_Nullable = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*google_protobuf.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 51235,
|
||||||
|
Name: "gogoproto.nullable",
|
||||||
|
Tag: "varint,51235,opt,name=nullable",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Embed = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*google_protobuf.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*bool)(nil),
|
||||||
|
Field: 51236,
|
||||||
|
Name: "gogoproto.embed",
|
||||||
|
Tag: "varint,51236,opt,name=embed",
|
||||||
|
}
|
||||||
|
|
||||||
|
var E_Customtype = &proto.ExtensionDesc{
|
||||||
|
ExtendedType: (*google_protobuf.FieldOptions)(nil),
|
||||||
|
ExtensionType: (*string)(nil),
|
||||||
|
Field: 51237,
|
||||||
|
Name: "gogoproto.customtype",
|
||||||
|
Tag: "bytes,51237,opt,name=customtype",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterExtension(E_Nullable)
|
||||||
|
proto.RegisterExtension(E_Embed)
|
||||||
|
proto.RegisterExtension(E_Customtype)
|
||||||
|
}
|
136
tool/protobuf/pkg/extensions/gogoproto/gogo.proto
Normal file
136
tool/protobuf/pkg/extensions/gogoproto/gogo.proto
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
// Protocol Buffers for Go with Gadgets
|
||||||
|
//
|
||||||
|
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
|
||||||
|
// http://github.com/gogo/protobuf
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
syntax = "proto2";
|
||||||
|
package gogoproto;
|
||||||
|
|
||||||
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
|
option java_package = "com.google.protobuf";
|
||||||
|
option java_outer_classname = "GoGoProtos";
|
||||||
|
option go_package = "github.com/bilibili/kratos/tool/protobuf/pkg/extensions/gogoproto";
|
||||||
|
|
||||||
|
extend google.protobuf.EnumOptions {
|
||||||
|
optional bool goproto_enum_prefix = 62001;
|
||||||
|
optional bool goproto_enum_stringer = 62021;
|
||||||
|
optional bool enum_stringer = 62022;
|
||||||
|
optional string enum_customname = 62023;
|
||||||
|
optional bool enumdecl = 62024;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend google.protobuf.EnumValueOptions {
|
||||||
|
optional string enumvalue_customname = 66001;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend google.protobuf.FileOptions {
|
||||||
|
optional bool goproto_getters_all = 63001;
|
||||||
|
optional bool goproto_enum_prefix_all = 63002;
|
||||||
|
optional bool goproto_stringer_all = 63003;
|
||||||
|
optional bool verbose_equal_all = 63004;
|
||||||
|
optional bool face_all = 63005;
|
||||||
|
optional bool gostring_all = 63006;
|
||||||
|
optional bool populate_all = 63007;
|
||||||
|
optional bool stringer_all = 63008;
|
||||||
|
optional bool onlyone_all = 63009;
|
||||||
|
|
||||||
|
optional bool equal_all = 63013;
|
||||||
|
optional bool description_all = 63014;
|
||||||
|
optional bool testgen_all = 63015;
|
||||||
|
optional bool benchgen_all = 63016;
|
||||||
|
optional bool marshaler_all = 63017;
|
||||||
|
optional bool unmarshaler_all = 63018;
|
||||||
|
optional bool stable_marshaler_all = 63019;
|
||||||
|
|
||||||
|
optional bool sizer_all = 63020;
|
||||||
|
|
||||||
|
optional bool goproto_enum_stringer_all = 63021;
|
||||||
|
optional bool enum_stringer_all = 63022;
|
||||||
|
|
||||||
|
optional bool unsafe_marshaler_all = 63023;
|
||||||
|
optional bool unsafe_unmarshaler_all = 63024;
|
||||||
|
|
||||||
|
optional bool goproto_extensions_map_all = 63025;
|
||||||
|
optional bool goproto_unrecognized_all = 63026;
|
||||||
|
optional bool gogoproto_import = 63027;
|
||||||
|
optional bool protosizer_all = 63028;
|
||||||
|
optional bool compare_all = 63029;
|
||||||
|
optional bool typedecl_all = 63030;
|
||||||
|
optional bool enumdecl_all = 63031;
|
||||||
|
|
||||||
|
optional bool goproto_registration = 63032;
|
||||||
|
optional bool messagename_all = 63033;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend google.protobuf.MessageOptions {
|
||||||
|
optional bool goproto_getters = 64001;
|
||||||
|
optional bool goproto_stringer = 64003;
|
||||||
|
optional bool verbose_equal = 64004;
|
||||||
|
optional bool face = 64005;
|
||||||
|
optional bool gostring = 64006;
|
||||||
|
optional bool populate = 64007;
|
||||||
|
optional bool stringer = 67008;
|
||||||
|
optional bool onlyone = 64009;
|
||||||
|
|
||||||
|
optional bool equal = 64013;
|
||||||
|
optional bool description = 64014;
|
||||||
|
optional bool testgen = 64015;
|
||||||
|
optional bool benchgen = 64016;
|
||||||
|
optional bool marshaler = 64017;
|
||||||
|
optional bool unmarshaler = 64018;
|
||||||
|
optional bool stable_marshaler = 64019;
|
||||||
|
|
||||||
|
optional bool sizer = 64020;
|
||||||
|
|
||||||
|
optional bool unsafe_marshaler = 64023;
|
||||||
|
optional bool unsafe_unmarshaler = 64024;
|
||||||
|
|
||||||
|
optional bool goproto_extensions_map = 64025;
|
||||||
|
optional bool goproto_unrecognized = 64026;
|
||||||
|
|
||||||
|
optional bool protosizer = 64028;
|
||||||
|
optional bool compare = 64029;
|
||||||
|
|
||||||
|
optional bool typedecl = 64030;
|
||||||
|
|
||||||
|
optional bool messagename = 64033;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend google.protobuf.FieldOptions {
|
||||||
|
optional bool nullable = 65001;
|
||||||
|
optional bool embed = 65002;
|
||||||
|
optional string customtype = 65003;
|
||||||
|
optional string customname = 65004;
|
||||||
|
optional string jsontag = 65005;
|
||||||
|
optional string moretags = 65006;
|
||||||
|
optional string casttype = 65007;
|
||||||
|
optional string castkey = 65008;
|
||||||
|
optional string castvalue = 65009;
|
||||||
|
|
||||||
|
optional bool stdtime = 65010;
|
||||||
|
optional bool stdduration = 65011;
|
||||||
|
}
|
31
tool/protobuf/pkg/extensions/google/api/annotations.proto
Normal file
31
tool/protobuf/pkg/extensions/google/api/annotations.proto
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright (c) 2015, Google Inc.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package google.api;
|
||||||
|
|
||||||
|
import "google/api/http.proto";
|
||||||
|
import "google/protobuf/descriptor.proto";
|
||||||
|
|
||||||
|
option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_outer_classname = "AnnotationsProto";
|
||||||
|
option java_package = "com.google.api";
|
||||||
|
option objc_class_prefix = "GAPI";
|
||||||
|
|
||||||
|
extend google.protobuf.MethodOptions {
|
||||||
|
// See `HttpRule`.
|
||||||
|
HttpRule http = 72295728;
|
||||||
|
}
|
318
tool/protobuf/pkg/extensions/google/api/http.proto
Normal file
318
tool/protobuf/pkg/extensions/google/api/http.proto
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
// Copyright 2018 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package google.api;
|
||||||
|
|
||||||
|
option cc_enable_arenas = true;
|
||||||
|
option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_outer_classname = "HttpProto";
|
||||||
|
option java_package = "com.google.api";
|
||||||
|
option objc_class_prefix = "GAPI";
|
||||||
|
|
||||||
|
|
||||||
|
// Defines the HTTP configuration for an API service. It contains a list of
|
||||||
|
// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
|
||||||
|
// to one or more HTTP REST API methods.
|
||||||
|
message Http {
|
||||||
|
// A list of HTTP configuration rules that apply to individual API methods.
|
||||||
|
//
|
||||||
|
// **NOTE:** All service configuration rules follow "last one wins" order.
|
||||||
|
repeated HttpRule rules = 1;
|
||||||
|
|
||||||
|
// When set to true, URL path parmeters will be fully URI-decoded except in
|
||||||
|
// cases of single segment matches in reserved expansion, where "%2F" will be
|
||||||
|
// left encoded.
|
||||||
|
//
|
||||||
|
// The default behavior is to not decode RFC 6570 reserved characters in multi
|
||||||
|
// segment matches.
|
||||||
|
bool fully_decode_reserved_expansion = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// `HttpRule` defines the mapping of an RPC method to one or more HTTP
|
||||||
|
// REST API methods. The mapping specifies how different portions of the RPC
|
||||||
|
// request message are mapped to URL path, URL query parameters, and
|
||||||
|
// HTTP request body. The mapping is typically specified as an
|
||||||
|
// `google.api.http` annotation on the RPC method,
|
||||||
|
// see "google/api/annotations.proto" for details.
|
||||||
|
//
|
||||||
|
// The mapping consists of a field specifying the path template and
|
||||||
|
// method kind. The path template can refer to fields in the request
|
||||||
|
// message, as in the example below which describes a REST GET
|
||||||
|
// operation on a resource collection of messages:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// service Messaging {
|
||||||
|
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||||
|
// option (google.api.http).get = "/v1/messages/{message_id}/{sub.subfield}";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// message GetMessageRequest {
|
||||||
|
// message SubMessage {
|
||||||
|
// string subfield = 1;
|
||||||
|
// }
|
||||||
|
// string message_id = 1; // mapped to the URL
|
||||||
|
// SubMessage sub = 2; // `sub.subfield` is url-mapped
|
||||||
|
// }
|
||||||
|
// message Message {
|
||||||
|
// string text = 1; // content of the resource
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// The same http annotation can alternatively be expressed inside the
|
||||||
|
// `GRPC API Configuration` YAML file.
|
||||||
|
//
|
||||||
|
// http:
|
||||||
|
// rules:
|
||||||
|
// - selector: <proto_package_name>.Messaging.GetMessage
|
||||||
|
// get: /v1/messages/{message_id}/{sub.subfield}
|
||||||
|
//
|
||||||
|
// This definition enables an automatic, bidrectional mapping of HTTP
|
||||||
|
// JSON to RPC. Example:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `GET /v1/messages/123456/foo` | `GetMessage(message_id: "123456" sub: SubMessage(subfield: "foo"))`
|
||||||
|
//
|
||||||
|
// In general, not only fields but also field paths can be referenced
|
||||||
|
// from a path pattern. Fields mapped to the path pattern cannot be
|
||||||
|
// repeated and must have a primitive (non-message) type.
|
||||||
|
//
|
||||||
|
// Any fields in the request message which are not bound by the path
|
||||||
|
// pattern automatically become (optional) HTTP query
|
||||||
|
// parameters. Assume the following definition of the request message:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// service Messaging {
|
||||||
|
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||||
|
// option (google.api.http).get = "/v1/messages/{message_id}";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// message GetMessageRequest {
|
||||||
|
// message SubMessage {
|
||||||
|
// string subfield = 1;
|
||||||
|
// }
|
||||||
|
// string message_id = 1; // mapped to the URL
|
||||||
|
// int64 revision = 2; // becomes a parameter
|
||||||
|
// SubMessage sub = 3; // `sub.subfield` becomes a parameter
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// This enables a HTTP JSON to RPC mapping as below:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `GET /v1/messages/123456?revision=2&sub.subfield=foo` | `GetMessage(message_id: "123456" revision: 2 sub: SubMessage(subfield: "foo"))`
|
||||||
|
//
|
||||||
|
// Note that fields which are mapped to HTTP parameters must have a
|
||||||
|
// primitive type or a repeated primitive type. Message types are not
|
||||||
|
// allowed. In the case of a repeated type, the parameter can be
|
||||||
|
// repeated in the URL, as in `...?param=A¶m=B`.
|
||||||
|
//
|
||||||
|
// For HTTP method kinds which allow a request body, the `body` field
|
||||||
|
// specifies the mapping. Consider a REST update method on the
|
||||||
|
// message resource collection:
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// service Messaging {
|
||||||
|
// rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
|
||||||
|
// option (google.api.http) = {
|
||||||
|
// put: "/v1/messages/{message_id}"
|
||||||
|
// body: "message"
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// message UpdateMessageRequest {
|
||||||
|
// string message_id = 1; // mapped to the URL
|
||||||
|
// Message message = 2; // mapped to the body
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// The following HTTP JSON to RPC mapping is enabled, where the
|
||||||
|
// representation of the JSON in the request body is determined by
|
||||||
|
// protos JSON encoding:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" message { text: "Hi!" })`
|
||||||
|
//
|
||||||
|
// The special name `*` can be used in the body mapping to define that
|
||||||
|
// every field not bound by the path template should be mapped to the
|
||||||
|
// request body. This enables the following alternative definition of
|
||||||
|
// the update method:
|
||||||
|
//
|
||||||
|
// service Messaging {
|
||||||
|
// rpc UpdateMessage(Message) returns (Message) {
|
||||||
|
// option (google.api.http) = {
|
||||||
|
// put: "/v1/messages/{message_id}"
|
||||||
|
// body: "*"
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// message Message {
|
||||||
|
// string message_id = 1;
|
||||||
|
// string text = 2;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// The following HTTP JSON to RPC mapping is enabled:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `PUT /v1/messages/123456 { "text": "Hi!" }` | `UpdateMessage(message_id: "123456" text: "Hi!")`
|
||||||
|
//
|
||||||
|
// Note that when using `*` in the body mapping, it is not possible to
|
||||||
|
// have HTTP parameters, as all fields not bound by the path end in
|
||||||
|
// the body. This makes this option more rarely used in practice of
|
||||||
|
// defining REST APIs. The common usage of `*` is in custom methods
|
||||||
|
// which don't use the URL at all for transferring data.
|
||||||
|
//
|
||||||
|
// It is possible to define multiple HTTP methods for one RPC by using
|
||||||
|
// the `additional_bindings` option. Example:
|
||||||
|
//
|
||||||
|
// service Messaging {
|
||||||
|
// rpc GetMessage(GetMessageRequest) returns (Message) {
|
||||||
|
// option (google.api.http) = {
|
||||||
|
// get: "/v1/messages/{message_id}"
|
||||||
|
// additional_bindings {
|
||||||
|
// get: "/v1/users/{user_id}/messages/{message_id}"
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// message GetMessageRequest {
|
||||||
|
// string message_id = 1;
|
||||||
|
// string user_id = 2;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// This enables the following two alternative HTTP JSON to RPC
|
||||||
|
// mappings:
|
||||||
|
//
|
||||||
|
// HTTP | RPC
|
||||||
|
// -----|-----
|
||||||
|
// `GET /v1/messages/123456` | `GetMessage(message_id: "123456")`
|
||||||
|
// `GET /v1/users/me/messages/123456` | `GetMessage(user_id: "me" message_id: "123456")`
|
||||||
|
//
|
||||||
|
// # Rules for HTTP mapping
|
||||||
|
//
|
||||||
|
// The rules for mapping HTTP path, query parameters, and body fields
|
||||||
|
// to the request message are as follows:
|
||||||
|
//
|
||||||
|
// 1. The `body` field specifies either `*` or a field path, or is
|
||||||
|
// omitted. If omitted, it indicates there is no HTTP request body.
|
||||||
|
// 2. Leaf fields (recursive expansion of nested messages in the
|
||||||
|
// request) can be classified into three types:
|
||||||
|
// (a) Matched in the URL template.
|
||||||
|
// (b) Covered by body (if body is `*`, everything except (a) fields;
|
||||||
|
// else everything under the body field)
|
||||||
|
// (c) All other fields.
|
||||||
|
// 3. URL query parameters found in the HTTP request are mapped to (c) fields.
|
||||||
|
// 4. Any body sent with an HTTP request can contain only (b) fields.
|
||||||
|
//
|
||||||
|
// The syntax of the path template is as follows:
|
||||||
|
//
|
||||||
|
// Template = "/" Segments [ Verb ] ;
|
||||||
|
// Segments = Segment { "/" Segment } ;
|
||||||
|
// Segment = "*" | "**" | LITERAL | Variable ;
|
||||||
|
// Variable = "{" FieldPath [ "=" Segments ] "}" ;
|
||||||
|
// FieldPath = IDENT { "." IDENT } ;
|
||||||
|
// Verb = ":" LITERAL ;
|
||||||
|
//
|
||||||
|
// The syntax `*` matches a single path segment. The syntax `**` matches zero
|
||||||
|
// or more path segments, which must be the last part of the path except the
|
||||||
|
// `Verb`. The syntax `LITERAL` matches literal text in the path.
|
||||||
|
//
|
||||||
|
// The syntax `Variable` matches part of the URL path as specified by its
|
||||||
|
// template. A variable template must not contain other variables. If a variable
|
||||||
|
// matches a single path segment, its template may be omitted, e.g. `{var}`
|
||||||
|
// is equivalent to `{var=*}`.
|
||||||
|
//
|
||||||
|
// If a variable contains exactly one path segment, such as `"{var}"` or
|
||||||
|
// `"{var=*}"`, when such a variable is expanded into a URL path, all characters
|
||||||
|
// except `[-_.~0-9a-zA-Z]` are percent-encoded. Such variables show up in the
|
||||||
|
// Discovery Document as `{var}`.
|
||||||
|
//
|
||||||
|
// If a variable contains one or more path segments, such as `"{var=foo/*}"`
|
||||||
|
// or `"{var=**}"`, when such a variable is expanded into a URL path, all
|
||||||
|
// characters except `[-_.~/0-9a-zA-Z]` are percent-encoded. Such variables
|
||||||
|
// show up in the Discovery Document as `{+var}`.
|
||||||
|
//
|
||||||
|
// NOTE: While the single segment variable matches the semantics of
|
||||||
|
// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2
|
||||||
|
// Simple String Expansion, the multi segment variable **does not** match
|
||||||
|
// RFC 6570 Reserved Expansion. The reason is that the Reserved Expansion
|
||||||
|
// does not expand special characters like `?` and `#`, which would lead
|
||||||
|
// to invalid URLs.
|
||||||
|
//
|
||||||
|
// NOTE: the field paths in variables and in the `body` must not refer to
|
||||||
|
// repeated fields or map fields.
|
||||||
|
message HttpRule {
|
||||||
|
// Selects methods to which this rule applies.
|
||||||
|
//
|
||||||
|
// Refer to [selector][google.api.DocumentationRule.selector] for syntax details.
|
||||||
|
string selector = 1;
|
||||||
|
|
||||||
|
// Determines the URL pattern is matched by this rules. This pattern can be
|
||||||
|
// used with any of the {get|put|post|delete|patch} methods. A custom method
|
||||||
|
// can be defined using the 'custom' field.
|
||||||
|
oneof pattern {
|
||||||
|
// Used for listing and getting information about resources.
|
||||||
|
string get = 2;
|
||||||
|
|
||||||
|
// Used for updating a resource.
|
||||||
|
string put = 3;
|
||||||
|
|
||||||
|
// Used for creating a resource.
|
||||||
|
string post = 4;
|
||||||
|
|
||||||
|
// Used for deleting a resource.
|
||||||
|
string delete = 5;
|
||||||
|
|
||||||
|
// Used for updating a resource.
|
||||||
|
string patch = 6;
|
||||||
|
|
||||||
|
// The custom pattern is used for specifying an HTTP method that is not
|
||||||
|
// included in the `pattern` field, such as HEAD, or "*" to leave the
|
||||||
|
// HTTP method unspecified for this rule. The wild-card rule is useful
|
||||||
|
// for services that provide content to Web (HTML) clients.
|
||||||
|
CustomHttpPattern custom = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The name of the request field whose value is mapped to the HTTP body, or
|
||||||
|
// `*` for mapping all fields not captured by the path pattern to the HTTP
|
||||||
|
// body. NOTE: the referred field must not be a repeated field and must be
|
||||||
|
// present at the top-level of request message type.
|
||||||
|
string body = 7;
|
||||||
|
|
||||||
|
// Optional. The name of the response field whose value is mapped to the HTTP
|
||||||
|
// body of response. Other response fields are ignored. When
|
||||||
|
// not set, the response message will be used as HTTP body of response.
|
||||||
|
string response_body = 12;
|
||||||
|
|
||||||
|
// Additional HTTP bindings for the selector. Nested bindings must
|
||||||
|
// not contain an `additional_bindings` field themselves (that is,
|
||||||
|
// the nesting may only be one level deep).
|
||||||
|
repeated HttpRule additional_bindings = 11;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A custom pattern is used for defining custom HTTP verb.
|
||||||
|
message CustomHttpPattern {
|
||||||
|
// The name of this custom HTTP verb.
|
||||||
|
string kind = 1;
|
||||||
|
|
||||||
|
// The path matched by this custom verb.
|
||||||
|
string path = 2;
|
||||||
|
}
|
94
tool/protobuf/pkg/gen/main.go
Normal file
94
tool/protobuf/pkg/gen/main.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package gen
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Generator ...
|
||||||
|
type Generator interface {
|
||||||
|
Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main ...
|
||||||
|
func Main(g Generator) {
|
||||||
|
req := readGenRequest()
|
||||||
|
resp := g.Generate(req)
|
||||||
|
writeResponse(os.Stdout, resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FilesToGenerate ...
|
||||||
|
func FilesToGenerate(req *plugin.CodeGeneratorRequest) []*descriptor.FileDescriptorProto {
|
||||||
|
genFiles := make([]*descriptor.FileDescriptorProto, 0)
|
||||||
|
Outer:
|
||||||
|
for _, name := range req.FileToGenerate {
|
||||||
|
for _, f := range req.ProtoFile {
|
||||||
|
if f.GetName() == name {
|
||||||
|
genFiles = append(genFiles, f)
|
||||||
|
continue Outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fail("could not find file named", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return genFiles
|
||||||
|
}
|
||||||
|
|
||||||
|
func readGenRequest() *plugin.CodeGeneratorRequest {
|
||||||
|
data, err := ioutil.ReadAll(os.Stdin)
|
||||||
|
if err != nil {
|
||||||
|
Error(err, "reading input")
|
||||||
|
}
|
||||||
|
|
||||||
|
req := new(plugin.CodeGeneratorRequest)
|
||||||
|
if err = proto.Unmarshal(data, req); err != nil {
|
||||||
|
Error(err, "parsing input proto")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(req.FileToGenerate) == 0 {
|
||||||
|
Fail("no files to generate")
|
||||||
|
}
|
||||||
|
|
||||||
|
return req
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeResponse(w io.Writer, resp *plugin.CodeGeneratorResponse) {
|
||||||
|
data, err := proto.Marshal(resp)
|
||||||
|
if err != nil {
|
||||||
|
Error(err, "marshaling response")
|
||||||
|
}
|
||||||
|
_, err = w.Write(data)
|
||||||
|
if err != nil {
|
||||||
|
Error(err, "writing response")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fail log and exit
|
||||||
|
func Fail(msgs ...string) {
|
||||||
|
s := strings.Join(msgs, " ")
|
||||||
|
log.Print("error:", s)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fail log and exit
|
||||||
|
func Info(msgs ...string) {
|
||||||
|
s := strings.Join(msgs, " ")
|
||||||
|
log.Print("info:", s)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Error log and exit
|
||||||
|
func Error(err error, msgs ...string) {
|
||||||
|
s := strings.Join(msgs, " ") + ":" + err.Error()
|
||||||
|
log.Print("error:", s)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
71
tool/protobuf/pkg/generator/command_line.go
Normal file
71
tool/protobuf/pkg/generator/command_line.go
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ParamsBase struct {
|
||||||
|
ImportPrefix string // String to prefix to imported package file names.
|
||||||
|
ImportMap map[string]string // Mapping from .proto file name to import path.
|
||||||
|
//Tpl bool // generate service implementation template
|
||||||
|
ExplicitHTTP bool // Only generate for method that add http option
|
||||||
|
}
|
||||||
|
|
||||||
|
type GeneratorParamsInterface interface {
|
||||||
|
GetBase() *ParamsBase
|
||||||
|
SetParam(key string, value string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type BasicParam struct{ ParamsBase }
|
||||||
|
|
||||||
|
func (b *BasicParam) GetBase() *ParamsBase {
|
||||||
|
return &b.ParamsBase
|
||||||
|
}
|
||||||
|
func (b *BasicParam) SetParam(key string, value string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseGeneratorParams(parameter string, result GeneratorParamsInterface) error {
|
||||||
|
ps := make(map[string]string)
|
||||||
|
for _, p := range strings.Split(parameter, ",") {
|
||||||
|
if p == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
i := strings.Index(p, "=")
|
||||||
|
if i < 0 {
|
||||||
|
return fmt.Errorf("invalid parameter %q: expected format of parameter to be k=v", p)
|
||||||
|
}
|
||||||
|
k := p[0:i]
|
||||||
|
v := p[i+1:]
|
||||||
|
if v == "" {
|
||||||
|
return fmt.Errorf("invalid parameter %q: expected format of parameter to be k=v", k)
|
||||||
|
}
|
||||||
|
ps[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
if result.GetBase().ImportMap == nil {
|
||||||
|
result.GetBase().ImportMap = map[string]string{}
|
||||||
|
}
|
||||||
|
for k, v := range ps {
|
||||||
|
switch {
|
||||||
|
case k == "explicit_http":
|
||||||
|
if v == "true" || v == "1" {
|
||||||
|
result.GetBase().ExplicitHTTP = true
|
||||||
|
}
|
||||||
|
case k == "import_prefix":
|
||||||
|
result.GetBase().ImportPrefix = v
|
||||||
|
// Support import map 'M' prefix per https://github.com/golang/protobuf/blob/6fb5325/protoc-gen-go/generator/generator.go#L497.
|
||||||
|
case len(k) > 0 && k[0] == 'M':
|
||||||
|
result.GetBase().ImportMap[k[1:]] = v // 1 is the length of 'M'.
|
||||||
|
case len(k) > 0 && strings.HasPrefix(k, "go_import_mapping@"):
|
||||||
|
result.GetBase().ImportMap[k[18:]] = v // 18 is the length of 'go_import_mapping@'.
|
||||||
|
default:
|
||||||
|
e := result.SetParam(k, v)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
310
tool/protobuf/pkg/generator/generator.go
Normal file
310
tool/protobuf/pkg/generator/generator.go
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/parser"
|
||||||
|
"go/printer"
|
||||||
|
"go/token"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/gen"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/naming"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/typemap"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/utils"
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
const Version = "v0.1"
|
||||||
|
|
||||||
|
var GoModuleImportPath = "github.com/bilibili/kratos"
|
||||||
|
var GoModuleDirName = "github.com/bilibili/kratos"
|
||||||
|
|
||||||
|
type Base struct {
|
||||||
|
Reg *typemap.Registry
|
||||||
|
|
||||||
|
// Map to record whether we've built each package
|
||||||
|
// pkgName => alias name
|
||||||
|
pkgs map[string]string
|
||||||
|
pkgNamesInUse map[string]bool
|
||||||
|
|
||||||
|
ImportPrefix string // String to prefix to imported package file names.
|
||||||
|
importMap map[string]string // Mapping from .proto file name to import path.
|
||||||
|
|
||||||
|
// Package naming:
|
||||||
|
GenPkgName string // Name of the package that we're generating
|
||||||
|
PackageName string // Name of the proto file package
|
||||||
|
fileToGoPackageName map[*descriptor.FileDescriptorProto]string
|
||||||
|
|
||||||
|
// List of files that were inputs to the generator. We need to hold this in
|
||||||
|
// the struct so we can write a header for the file that lists its inputs.
|
||||||
|
GenFiles []*descriptor.FileDescriptorProto
|
||||||
|
|
||||||
|
// Output buffer that holds the bytes we want to write out for a single file.
|
||||||
|
// Gets reset after working on a file.
|
||||||
|
Output *bytes.Buffer
|
||||||
|
|
||||||
|
// key: pkgName
|
||||||
|
// value: importPath
|
||||||
|
Deps map[string]string
|
||||||
|
|
||||||
|
Params *ParamsBase
|
||||||
|
|
||||||
|
httpInfoCache map[string]*HTTPInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegisterPackageName name is the go package name or proto pkg name
|
||||||
|
// return go pkg alias
|
||||||
|
func (t *Base) RegisterPackageName(name string) (alias string) {
|
||||||
|
alias = name
|
||||||
|
i := 1
|
||||||
|
for t.pkgNamesInUse[alias] {
|
||||||
|
alias = name + strconv.Itoa(i)
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
t.pkgNamesInUse[alias] = true
|
||||||
|
t.pkgs[name] = alias
|
||||||
|
return alias
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Base) Setup(in *plugin.CodeGeneratorRequest, paramsOpt ...GeneratorParamsInterface) {
|
||||||
|
t.httpInfoCache = make(map[string]*HTTPInfo)
|
||||||
|
t.pkgs = make(map[string]string)
|
||||||
|
t.pkgNamesInUse = make(map[string]bool)
|
||||||
|
t.importMap = make(map[string]string)
|
||||||
|
t.Deps = make(map[string]string)
|
||||||
|
t.fileToGoPackageName = make(map[*descriptor.FileDescriptorProto]string)
|
||||||
|
t.Output = bytes.NewBuffer(nil)
|
||||||
|
|
||||||
|
var params GeneratorParamsInterface
|
||||||
|
if len(paramsOpt) > 0 {
|
||||||
|
params = paramsOpt[0]
|
||||||
|
} else {
|
||||||
|
params = &BasicParam{}
|
||||||
|
}
|
||||||
|
err := ParseGeneratorParams(in.GetParameter(), params)
|
||||||
|
if err != nil {
|
||||||
|
gen.Fail("could not parse parameters", err.Error())
|
||||||
|
}
|
||||||
|
t.Params = params.GetBase()
|
||||||
|
t.ImportPrefix = params.GetBase().ImportPrefix
|
||||||
|
t.importMap = params.GetBase().ImportMap
|
||||||
|
|
||||||
|
t.GenFiles = gen.FilesToGenerate(in)
|
||||||
|
|
||||||
|
// Collect information on types.
|
||||||
|
t.Reg = typemap.New(in.ProtoFile)
|
||||||
|
t.RegisterPackageName("context")
|
||||||
|
t.RegisterPackageName("ioutil")
|
||||||
|
t.RegisterPackageName("proto")
|
||||||
|
// Time to figure out package names of objects defined in protobuf. First,
|
||||||
|
// we'll figure out the name for the package we're generating.
|
||||||
|
genPkgName, err := DeduceGenPkgName(t.GenFiles)
|
||||||
|
if err != nil {
|
||||||
|
gen.Fail(err.Error())
|
||||||
|
}
|
||||||
|
t.GenPkgName = genPkgName
|
||||||
|
// Next, we need to pick names for all the files that are dependencies.
|
||||||
|
if len(in.ProtoFile) > 0 {
|
||||||
|
t.PackageName = t.GenFiles[0].GetPackage()
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range in.ProtoFile {
|
||||||
|
if fileDescSliceContains(t.GenFiles, f) {
|
||||||
|
// This is a file we are generating. It gets the shared package name.
|
||||||
|
t.fileToGoPackageName[f] = t.GenPkgName
|
||||||
|
} else {
|
||||||
|
// This is a dependency. Use its package name.
|
||||||
|
name := f.GetPackage()
|
||||||
|
if name == "" {
|
||||||
|
name = utils.BaseName(f.GetName())
|
||||||
|
}
|
||||||
|
name = utils.CleanIdentifier(name)
|
||||||
|
alias := t.RegisterPackageName(name)
|
||||||
|
t.fileToGoPackageName[f] = alias
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, f := range t.GenFiles {
|
||||||
|
deps := t.DeduceDeps(f)
|
||||||
|
for k, v := range deps {
|
||||||
|
t.Deps[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Base) DeduceDeps(file *descriptor.FileDescriptorProto) map[string]string {
|
||||||
|
deps := make(map[string]string) // Map of package name to quoted import path.
|
||||||
|
ourImportPath := path.Dir(naming.GoFileName(file, ""))
|
||||||
|
for _, s := range file.Service {
|
||||||
|
for _, m := range s.Method {
|
||||||
|
defs := []*typemap.MessageDefinition{
|
||||||
|
t.Reg.MethodInputDefinition(m),
|
||||||
|
t.Reg.MethodOutputDefinition(m),
|
||||||
|
}
|
||||||
|
for _, def := range defs {
|
||||||
|
if def.File.GetPackage() == t.PackageName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// By default, import path is the dirname of the Go filename.
|
||||||
|
importPath := path.Dir(naming.GoFileName(def.File, ""))
|
||||||
|
if importPath == ourImportPath {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
importPath = t.SubstituteImportPath(importPath, def.File.GetName())
|
||||||
|
importPath = t.ImportPrefix + importPath
|
||||||
|
pkg := t.GoPackageNameForProtoFile(def.File)
|
||||||
|
deps[pkg] = strconv.Quote(importPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deps
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeduceGenPkgName figures out the go package name to use for generated code.
|
||||||
|
// Will try to use the explicit go_package setting in a file (if set, must be
|
||||||
|
// consistent in all files). If no files have go_package set, then use the
|
||||||
|
// protobuf package name (must be consistent in all files)
|
||||||
|
func DeduceGenPkgName(genFiles []*descriptor.FileDescriptorProto) (string, error) {
|
||||||
|
var genPkgName string
|
||||||
|
for _, f := range genFiles {
|
||||||
|
name, explicit := naming.GoPackageName(f)
|
||||||
|
if explicit {
|
||||||
|
name = utils.CleanIdentifier(name)
|
||||||
|
if genPkgName != "" && genPkgName != name {
|
||||||
|
// Make sure they're all set consistently.
|
||||||
|
return "", errors.Errorf("files have conflicting go_package settings, must be the same: %q and %q", genPkgName, name)
|
||||||
|
}
|
||||||
|
genPkgName = name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if genPkgName != "" {
|
||||||
|
return genPkgName, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there is no explicit setting, then check the implicit package name
|
||||||
|
// (derived from the protobuf package name) of the files and make sure it's
|
||||||
|
// consistent.
|
||||||
|
for _, f := range genFiles {
|
||||||
|
name, _ := naming.GoPackageName(f)
|
||||||
|
name = utils.CleanIdentifier(name)
|
||||||
|
if genPkgName != "" && genPkgName != name {
|
||||||
|
return "", errors.Errorf("files have conflicting package names, must be the same or overridden with go_package: %q and %q", genPkgName, name)
|
||||||
|
}
|
||||||
|
genPkgName = name
|
||||||
|
}
|
||||||
|
|
||||||
|
// All the files have the same name, so we're good.
|
||||||
|
return genPkgName, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Base) GoPackageNameForProtoFile(file *descriptor.FileDescriptorProto) string {
|
||||||
|
return t.fileToGoPackageName[file]
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileDescSliceContains(slice []*descriptor.FileDescriptorProto, f *descriptor.FileDescriptorProto) bool {
|
||||||
|
for _, sf := range slice {
|
||||||
|
if f == sf {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// P forwards to g.gen.P, which prints output.
|
||||||
|
func (t *Base) P(args ...string) {
|
||||||
|
for _, v := range args {
|
||||||
|
t.Output.WriteString(v)
|
||||||
|
}
|
||||||
|
t.Output.WriteByte('\n')
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Base) FormattedOutput() string {
|
||||||
|
// Reformat generated code.
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
raw := t.Output.Bytes()
|
||||||
|
ast, err := parser.ParseFile(fset, "", raw, parser.ParseComments)
|
||||||
|
if err != nil {
|
||||||
|
// Print out the bad code with line numbers.
|
||||||
|
// This should never happen in practice, but it can while changing generated code,
|
||||||
|
// so consider this a debugging aid.
|
||||||
|
var src bytes.Buffer
|
||||||
|
s := bufio.NewScanner(bytes.NewReader(raw))
|
||||||
|
for line := 1; s.Scan(); line++ {
|
||||||
|
fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes())
|
||||||
|
}
|
||||||
|
gen.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
out := bytes.NewBuffer(nil)
|
||||||
|
err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(out, fset, ast)
|
||||||
|
if err != nil {
|
||||||
|
gen.Fail("generated Go source code could not be reformatted:", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Base) PrintComments(comments typemap.DefinitionComments) bool {
|
||||||
|
text := strings.TrimSuffix(comments.Leading, "\n")
|
||||||
|
if len(strings.TrimSpace(text)) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
split := strings.Split(text, "\n")
|
||||||
|
for _, line := range split {
|
||||||
|
t.P("// ", strings.TrimPrefix(line, " "))
|
||||||
|
}
|
||||||
|
return len(split) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsOwnPackage ...
|
||||||
|
// protoName is fully qualified name of a type
|
||||||
|
func (t *Base) IsOwnPackage(protoName string) bool {
|
||||||
|
def := t.Reg.MessageDefinition(protoName)
|
||||||
|
if def == nil {
|
||||||
|
gen.Fail("could not find message for", protoName)
|
||||||
|
}
|
||||||
|
return def.File.GetPackage() == t.PackageName
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a protobuf name for a Message, return the Go name we will use for that
|
||||||
|
// type, including its package prefix.
|
||||||
|
func (t *Base) GoTypeName(protoName string) string {
|
||||||
|
def := t.Reg.MessageDefinition(protoName)
|
||||||
|
if def == nil {
|
||||||
|
gen.Fail("could not find message for", protoName)
|
||||||
|
}
|
||||||
|
|
||||||
|
var prefix string
|
||||||
|
if def.File.GetPackage() != t.PackageName {
|
||||||
|
prefix = t.GoPackageNameForProtoFile(def.File) + "."
|
||||||
|
}
|
||||||
|
|
||||||
|
var name string
|
||||||
|
for _, parent := range def.Lineage() {
|
||||||
|
name += parent.Descriptor.GetName() + "_"
|
||||||
|
}
|
||||||
|
name += def.Descriptor.GetName()
|
||||||
|
return prefix + name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Base) ShouldGenForMethod(file *descriptor.FileDescriptorProto,
|
||||||
|
service *descriptor.ServiceDescriptorProto,
|
||||||
|
method *descriptor.MethodDescriptorProto) bool {
|
||||||
|
if !t.Params.ExplicitHTTP {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
httpInfo := t.GetHttpInfoCached(file, service, method)
|
||||||
|
return httpInfo.HasExplicitHTTPPath
|
||||||
|
}
|
||||||
|
func (t *Base) SubstituteImportPath(importPath string, importFile string) string {
|
||||||
|
if substitution, ok := t.importMap[importFile]; ok {
|
||||||
|
importPath = substitution
|
||||||
|
}
|
||||||
|
return importPath
|
||||||
|
}
|
136
tool/protobuf/pkg/generator/helper.go
Normal file
136
tool/protobuf/pkg/generator/helper.go
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/extensions/gogoproto"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/tag"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/typemap"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetJSONFieldName get name from gogoproto.jsontag
|
||||||
|
// else the original name
|
||||||
|
func GetJSONFieldName(field *descriptor.FieldDescriptorProto) string {
|
||||||
|
if field == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if field.Options != nil {
|
||||||
|
v, err := proto.GetExtension(field.Options, gogoproto.E_Jsontag)
|
||||||
|
if err == nil && v.(*string) != nil {
|
||||||
|
ret := *(v.(*string))
|
||||||
|
i := strings.Index(ret, ",")
|
||||||
|
if i != -1 {
|
||||||
|
ret = ret[:i]
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return field.GetName()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFormOrJSONName get name from form tag, then json tag
|
||||||
|
// then original name
|
||||||
|
func GetFormOrJSONName(field *descriptor.FieldDescriptorProto) string {
|
||||||
|
if field == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
tags := tag.GetMoreTags(field)
|
||||||
|
if tags != nil {
|
||||||
|
tag := reflect.StructTag(*tags)
|
||||||
|
fName := tag.Get("form")
|
||||||
|
if fName != "" {
|
||||||
|
i := strings.Index(fName, ",")
|
||||||
|
if i != -1 {
|
||||||
|
fName = fName[:i]
|
||||||
|
}
|
||||||
|
return fName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return GetJSONFieldName(field)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsScalar Is this field a scalar numeric type?
|
||||||
|
func IsScalar(field *descriptor.FieldDescriptorProto) bool {
|
||||||
|
if field.Type == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
switch *field.Type {
|
||||||
|
case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_FLOAT,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_INT64,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_UINT64,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_INT32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_FIXED64,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_FIXED32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_BOOL,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_UINT32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_ENUM,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_SFIXED32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_SFIXED64,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_SINT32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_SINT64,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_BYTES,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_STRING:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsMap is protocol buffer map
|
||||||
|
func IsMap(field *descriptor.FieldDescriptorProto, reg *typemap.Registry) bool {
|
||||||
|
if field.GetType() != descriptor.FieldDescriptorProto_TYPE_MESSAGE {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
md := reg.MessageDefinition(field.GetTypeName())
|
||||||
|
if md == nil || !md.Descriptor.GetOptions().GetMapEntry() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsRepeated Is this field repeated?
|
||||||
|
func IsRepeated(field *descriptor.FieldDescriptorProto) bool {
|
||||||
|
return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFieldRequired is field required?
|
||||||
|
// eg. validate="required"
|
||||||
|
func GetFieldRequired(
|
||||||
|
f *descriptor.FieldDescriptorProto,
|
||||||
|
reg *typemap.Registry,
|
||||||
|
md *typemap.MessageDefinition,
|
||||||
|
) bool {
|
||||||
|
fComment, _ := reg.FieldComments(md, f)
|
||||||
|
var tags []reflect.StructTag
|
||||||
|
{
|
||||||
|
//get required info from gogoproto.moretags
|
||||||
|
moretags := tag.GetMoreTags(f)
|
||||||
|
if moretags != nil {
|
||||||
|
tags = []reflect.StructTag{reflect.StructTag(*moretags)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(tags) == 0 {
|
||||||
|
tags = tag.GetTagsInComment(fComment.Leading)
|
||||||
|
}
|
||||||
|
validateTag := tag.GetTagValue("validate", tags)
|
||||||
|
var validateRules []string
|
||||||
|
if validateTag != "" {
|
||||||
|
validateRules = strings.Split(validateTag, ",")
|
||||||
|
}
|
||||||
|
required := false
|
||||||
|
for _, rule := range validateRules {
|
||||||
|
if rule == "required" {
|
||||||
|
required = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return required
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeIndentStr(i int) string {
|
||||||
|
return strings.Repeat(" ", i)
|
||||||
|
}
|
145
tool/protobuf/pkg/generator/http.go
Normal file
145
tool/protobuf/pkg/generator/http.go
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/tag"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/typemap"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
"google.golang.org/genproto/googleapis/api/annotations"
|
||||||
|
)
|
||||||
|
|
||||||
|
// HTTPInfo http info for method
|
||||||
|
type HTTPInfo struct {
|
||||||
|
HttpMethod string
|
||||||
|
Path string
|
||||||
|
LegacyPath string
|
||||||
|
NewPath string
|
||||||
|
IsLegacyPath bool
|
||||||
|
Title string
|
||||||
|
Description string
|
||||||
|
// is http path added in the google.api.http option ?
|
||||||
|
HasExplicitHTTPPath bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type googleMethodOptionInfo struct {
|
||||||
|
Method string
|
||||||
|
PathPattern string
|
||||||
|
HTTPRule *annotations.HttpRule
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetHTTPInfo http info of method
|
||||||
|
func GetHTTPInfo(
|
||||||
|
file *descriptor.FileDescriptorProto,
|
||||||
|
service *descriptor.ServiceDescriptorProto,
|
||||||
|
method *descriptor.MethodDescriptorProto,
|
||||||
|
reg *typemap.Registry) *HTTPInfo {
|
||||||
|
var (
|
||||||
|
title string
|
||||||
|
desc string
|
||||||
|
httpMethod string
|
||||||
|
newPath string
|
||||||
|
explicitHTTPPath bool
|
||||||
|
)
|
||||||
|
comment, _ := reg.MethodComments(file, service, method)
|
||||||
|
tags := tag.GetTagsInComment(comment.Leading)
|
||||||
|
cleanComments := tag.GetCommentWithoutTag(comment.Leading)
|
||||||
|
if len(cleanComments) > 0 {
|
||||||
|
title = strings.Trim(cleanComments[0], "\n\r ")
|
||||||
|
if len(cleanComments) > 1 {
|
||||||
|
descLines := cleanComments[1:]
|
||||||
|
desc = strings.Trim(strings.Join(descLines, "\n"), "\r\n ")
|
||||||
|
} else {
|
||||||
|
desc = ""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
title = ""
|
||||||
|
}
|
||||||
|
googleOptionInfo, err := ParseBMMethod(method)
|
||||||
|
if err == nil {
|
||||||
|
httpMethod = strings.ToUpper(googleOptionInfo.Method)
|
||||||
|
p := googleOptionInfo.PathPattern
|
||||||
|
if p != "" {
|
||||||
|
explicitHTTPPath = true
|
||||||
|
newPath = p
|
||||||
|
goto END
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if httpMethod == "" {
|
||||||
|
// resolve http method
|
||||||
|
httpMethod = tag.GetTagValue("method", tags)
|
||||||
|
if httpMethod == "" {
|
||||||
|
httpMethod = "GET"
|
||||||
|
} else {
|
||||||
|
httpMethod = strings.ToUpper(httpMethod)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newPath = "/" + file.GetPackage() + "." + service.GetName() + "/" + method.GetName()
|
||||||
|
END:
|
||||||
|
var p = newPath
|
||||||
|
param := &HTTPInfo{HttpMethod: httpMethod,
|
||||||
|
Path: p,
|
||||||
|
NewPath: newPath,
|
||||||
|
IsLegacyPath: false,
|
||||||
|
Title: title,
|
||||||
|
Description: desc,
|
||||||
|
HasExplicitHTTPPath: explicitHTTPPath,
|
||||||
|
}
|
||||||
|
if title == "" {
|
||||||
|
param.Title = param.Path
|
||||||
|
}
|
||||||
|
return param
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *Base) GetHttpInfoCached(file *descriptor.FileDescriptorProto,
|
||||||
|
service *descriptor.ServiceDescriptorProto,
|
||||||
|
method *descriptor.MethodDescriptorProto) *HTTPInfo {
|
||||||
|
key := file.GetPackage() + service.GetName() + method.GetName()
|
||||||
|
httpInfo, ok := t.httpInfoCache[key]
|
||||||
|
if !ok {
|
||||||
|
httpInfo = GetHTTPInfo(file, service, method, t.Reg)
|
||||||
|
t.httpInfoCache[key] = httpInfo
|
||||||
|
}
|
||||||
|
return httpInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseBMMethod parse BMMethodDescriptor form method descriptor proto
|
||||||
|
func ParseBMMethod(method *descriptor.MethodDescriptorProto) (*googleMethodOptionInfo, error) {
|
||||||
|
ext, err := proto.GetExtension(method.GetOptions(), annotations.E_Http)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get extension error: %s", err)
|
||||||
|
}
|
||||||
|
rule := ext.(*annotations.HttpRule)
|
||||||
|
var httpMethod string
|
||||||
|
var pathPattern string
|
||||||
|
switch pattern := rule.Pattern.(type) {
|
||||||
|
case *annotations.HttpRule_Get:
|
||||||
|
pathPattern = pattern.Get
|
||||||
|
httpMethod = http.MethodGet
|
||||||
|
case *annotations.HttpRule_Put:
|
||||||
|
pathPattern = pattern.Put
|
||||||
|
httpMethod = http.MethodPut
|
||||||
|
case *annotations.HttpRule_Post:
|
||||||
|
pathPattern = pattern.Post
|
||||||
|
httpMethod = http.MethodPost
|
||||||
|
case *annotations.HttpRule_Patch:
|
||||||
|
pathPattern = pattern.Patch
|
||||||
|
httpMethod = http.MethodPatch
|
||||||
|
case *annotations.HttpRule_Delete:
|
||||||
|
pathPattern = pattern.Delete
|
||||||
|
httpMethod = http.MethodDelete
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupport http pattern %s", rule.Pattern)
|
||||||
|
}
|
||||||
|
bmMethod := &googleMethodOptionInfo{
|
||||||
|
Method: httpMethod,
|
||||||
|
PathPattern: pathPattern,
|
||||||
|
HTTPRule: rule,
|
||||||
|
}
|
||||||
|
return bmMethod, nil
|
||||||
|
}
|
27
tool/protobuf/pkg/naming/go_naming.go
Normal file
27
tool/protobuf/pkg/naming/go_naming.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package naming
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GoFileName returns the output name for the generated Go file.
|
||||||
|
func GoFileName(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
|
||||||
|
|
||||||
|
// Does the file have a "go_package" option? If it does, it may override the
|
||||||
|
// filename.
|
||||||
|
if impPath, _, ok := goPackageOption(f); ok && impPath != "" {
|
||||||
|
// Replace the existing dirname with the declared import path.
|
||||||
|
_, name = path.Split(name)
|
||||||
|
name = path.Join(impPath, name)
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
return name
|
||||||
|
}
|
101
tool/protobuf/pkg/naming/naming.go
Normal file
101
tool/protobuf/pkg/naming/naming.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package naming
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/utils"
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/siddontang/go/ioutil2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetVersionPrefix 根据go包名获取api版本前缀
|
||||||
|
// @param pkg 从proto获取到的对应的go报名
|
||||||
|
// @return 如果是v*开始的 返回v*
|
||||||
|
// 否则返回空
|
||||||
|
func GetVersionPrefix(pkg string) string {
|
||||||
|
if pkg == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if pkg[:1] == "v" {
|
||||||
|
return pkg
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func ServiceName(service *descriptor.ServiceDescriptorProto) string {
|
||||||
|
return utils.CamelCase(service.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodName ...
|
||||||
|
func MethodName(method *descriptor.MethodDescriptorProto) string {
|
||||||
|
return utils.CamelCase(method.GetName())
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGoImportPathForPb 得到 proto 文件对应的 go import路径
|
||||||
|
// protoFilename is the proto file name
|
||||||
|
// 可能根本无法得到proto文件的具体路径, 只能假设 proto 的filename 是相对当前目录的
|
||||||
|
// 假设 protoAbsolutePath = wd/protoFilename
|
||||||
|
func GetGoImportPathForPb(protoFilename string, moduleImportPath string, moduleDirName string) (importPath string, err error) {
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
panic("cannot get working directory")
|
||||||
|
}
|
||||||
|
absPath := wd + "/" + protoFilename
|
||||||
|
if !ioutil2.FileExists(absPath) {
|
||||||
|
err = errors.New("Cannot find proto file path of " + protoFilename)
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
index := strings.Index(absPath, moduleDirName)
|
||||||
|
if index == -1 {
|
||||||
|
return "", errors.Errorf("proto file %s is not inside project %s", protoFilename, moduleDirName)
|
||||||
|
}
|
||||||
|
relativePath := absPath[index:]
|
||||||
|
importPath = filepath.Dir(relativePath)
|
||||||
|
return importPath, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoPackageNameForProtoFile returns the Go package name to use in the generated Go file.
|
||||||
|
// The result explicitly reports whether the name came from an option go_package
|
||||||
|
// statement. If explicit is false, the name was derived from the protocol
|
||||||
|
// buffer's package statement or the input file name.
|
||||||
|
func GoPackageName(f *descriptor.FileDescriptorProto) (name string, explicit bool) {
|
||||||
|
// Does the file have a "go_package" option?
|
||||||
|
if _, pkg, ok := goPackageOption(f); ok {
|
||||||
|
return pkg, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does the file have a package clause?
|
||||||
|
if pkg := f.GetPackage(); pkg != "" {
|
||||||
|
return pkg, false
|
||||||
|
}
|
||||||
|
// Use the file base name.
|
||||||
|
return utils.BaseName(f.GetName()), false
|
||||||
|
}
|
||||||
|
|
||||||
|
// goPackageOption interprets the file's go_package option.
|
||||||
|
// If there is no go_package, it returns ("", "", false).
|
||||||
|
// If there's a simple name, it returns ("", pkg, true).
|
||||||
|
// If the option implies an import path, it returns (impPath, pkg, true).
|
||||||
|
func goPackageOption(f *descriptor.FileDescriptorProto) (impPath, pkg string, ok bool) {
|
||||||
|
pkg = f.GetOptions().GetGoPackage()
|
||||||
|
if pkg == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ok = true
|
||||||
|
// The presence of a slash implies there's an import path.
|
||||||
|
slash := strings.LastIndex(pkg, "/")
|
||||||
|
if slash < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
impPath, pkg = pkg, pkg[slash+1:]
|
||||||
|
// A semicolon-delimited suffix overrides the package name.
|
||||||
|
sc := strings.IndexByte(impPath, ';')
|
||||||
|
if sc < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
impPath, pkg = impPath[:sc], impPath[sc+1:]
|
||||||
|
return
|
||||||
|
}
|
119
tool/protobuf/pkg/project/project.go
Normal file
119
tool/protobuf/pkg/project/project.go
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
package project
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/utils"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/siddontang/go/ioutil2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// if proto file is inside a project (that has a /api directory)
|
||||||
|
// this present a project info
|
||||||
|
// 必须假设proto文件的路径就是相对work-dir的路径,否则无法找到proto文件以及对应的project
|
||||||
|
type ProjectInfo struct {
|
||||||
|
// AbsolutePath of the project
|
||||||
|
AbsolutePath string
|
||||||
|
// ImportPath of project
|
||||||
|
ImportPath string
|
||||||
|
// dir name of project
|
||||||
|
Name string
|
||||||
|
// parent dir of project, maybe empty
|
||||||
|
Department string
|
||||||
|
// grandma dir of project , maybe empty
|
||||||
|
Typ string
|
||||||
|
HasInternalPkg bool
|
||||||
|
// 从工作目录(working directory)到project目录的相对路径 比如a/b .. ../a
|
||||||
|
// 作用是什么?
|
||||||
|
// 假设目录结构是
|
||||||
|
// -project
|
||||||
|
// - api/api.proto
|
||||||
|
// - internal/service
|
||||||
|
// 我想在 internal/service下生成一个文件 service.go
|
||||||
|
// work-dir 为 project/api
|
||||||
|
// proto 生成命令为 protoc --xx_out=. api.proto
|
||||||
|
// 那么在 protoc plugin 中的文件输出路径就得是 ../internal/service/ => {pathRefToProj}internal/service
|
||||||
|
//
|
||||||
|
PathRefToProj string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProjInfo(file string, modDirName string, modImportPath string) (projInfo *ProjectInfo, err error) {
|
||||||
|
projInfo = &ProjectInfo{}
|
||||||
|
wd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
panic("cannot get working directory")
|
||||||
|
}
|
||||||
|
protoAbs := wd + "/" + file
|
||||||
|
protoAbs, _ = filepath.Abs(protoAbs)
|
||||||
|
|
||||||
|
if !ioutil2.FileExists(protoAbs) {
|
||||||
|
return nil, errors.Errorf("Cannot find proto file in current dir %s, file: %s ", wd, file)
|
||||||
|
}
|
||||||
|
//appIndex := strings.Index(wd, modDirName)
|
||||||
|
//if appIndex == -1 {
|
||||||
|
// err = errors.New("not in " + modDirName)
|
||||||
|
// return nil, err
|
||||||
|
//}
|
||||||
|
|
||||||
|
projPath := LookupProjPath(protoAbs)
|
||||||
|
|
||||||
|
if projPath == "" {
|
||||||
|
err = errors.New("not in project")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rel, _ := filepath.Rel(wd, projPath)
|
||||||
|
projInfo.PathRefToProj = rel
|
||||||
|
projInfo.AbsolutePath = projPath
|
||||||
|
if ioutil2.FileExists(projPath + "/internal") {
|
||||||
|
projInfo.HasInternalPkg = true
|
||||||
|
}
|
||||||
|
|
||||||
|
i := strings.Index(projInfo.AbsolutePath, modDirName)
|
||||||
|
if i == -1 {
|
||||||
|
err = errors.Errorf("project is not inside module, project=%s, module=%s", projPath, modDirName)
|
||||||
|
}
|
||||||
|
relativePath := projInfo.AbsolutePath[i+len(modDirName):]
|
||||||
|
projInfo.ImportPath = modImportPath + relativePath
|
||||||
|
projInfo.Name = filepath.Base(projPath)
|
||||||
|
if p := filepath.Dir(projPath); p != "/" {
|
||||||
|
projInfo.Department = filepath.Base(p)
|
||||||
|
if p = filepath.Dir(p); p != "/" {
|
||||||
|
projInfo.Typ = filepath.Base(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return projInfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// LookupProjPath get project path by proto absolute path
|
||||||
|
// assume that proto is in the project's api directory
|
||||||
|
func LookupProjPath(protoAbs string) (result string) {
|
||||||
|
f := func(protoAbs string, dirs []string) string {
|
||||||
|
lastIndex := len(protoAbs)
|
||||||
|
curPath := protoAbs
|
||||||
|
|
||||||
|
for lastIndex > 0 {
|
||||||
|
found := true
|
||||||
|
for _, d := range dirs {
|
||||||
|
if !utils.IsDir(curPath + "/" + d) {
|
||||||
|
found = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if found {
|
||||||
|
return curPath
|
||||||
|
}
|
||||||
|
lastIndex = strings.LastIndex(curPath, string(os.PathSeparator))
|
||||||
|
curPath = protoAbs[:lastIndex]
|
||||||
|
}
|
||||||
|
result = ""
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
firstStep := f(protoAbs, []string{"cmd", "api"})
|
||||||
|
if firstStep != "" {
|
||||||
|
return firstStep
|
||||||
|
}
|
||||||
|
return f(protoAbs, []string{"api"})
|
||||||
|
}
|
20
tool/protobuf/pkg/tag/ext_tags.go
Normal file
20
tool/protobuf/pkg/tag/ext_tags.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package tag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/extensions/gogoproto"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetMoreTags(field *descriptor.FieldDescriptorProto) *string {
|
||||||
|
if field == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if field.Options != nil {
|
||||||
|
v, err := proto.GetExtension(field.Options, gogoproto.E_Moretags)
|
||||||
|
if err == nil && v.(*string) != nil {
|
||||||
|
return v.(*string)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
55
tool/protobuf/pkg/tag/tags.go
Normal file
55
tool/protobuf/pkg/tag/tags.go
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package tag
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetCommentWithoutTag strip tags in comment
|
||||||
|
func GetCommentWithoutTag(comment string) []string {
|
||||||
|
var lines []string
|
||||||
|
if comment == "" {
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
split := strings.Split(strings.TrimRight(comment, "\n\r"), "\n")
|
||||||
|
for _, line := range split {
|
||||||
|
tag, _, _ := GetLineTag(line)
|
||||||
|
if tag == "" {
|
||||||
|
lines = append(lines, line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTagsInComment(comment string) []reflect.StructTag {
|
||||||
|
split := strings.Split(comment, "\n")
|
||||||
|
var tagsInComment []reflect.StructTag
|
||||||
|
for _, line := range split {
|
||||||
|
tag, _, _ := GetLineTag(line)
|
||||||
|
if tag != "" {
|
||||||
|
tagsInComment = append(tagsInComment, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tagsInComment
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTagValue(key string, tags []reflect.StructTag) string {
|
||||||
|
for _, t := range tags {
|
||||||
|
val := t.Get(key)
|
||||||
|
if val != "" {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// find tag between backtick, start & end is the position of backtick
|
||||||
|
func GetLineTag(line string) (tag reflect.StructTag, start int, end int) {
|
||||||
|
start = strings.Index(line, "`")
|
||||||
|
end = strings.LastIndex(line, "`")
|
||||||
|
if end <= start {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tag = reflect.StructTag(line[start+1 : end])
|
||||||
|
return
|
||||||
|
}
|
277
tool/protobuf/pkg/typemap/typemap.go
Normal file
277
tool/protobuf/pkg/typemap/typemap.go
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
package typemap
|
||||||
|
|
||||||
|
// Copyright 2018 Twitch Interactive, Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License"). You may not
|
||||||
|
// use this file except in compliance with the License. A copy of the License is
|
||||||
|
// located at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// or in the "license" file accompanying this file. This file is distributed on
|
||||||
|
// an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
|
||||||
|
// express or implied. See the License for the specific language governing
|
||||||
|
// permissions and limitations under the License.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Registry is the place of descriptors resolving
|
||||||
|
type Registry struct {
|
||||||
|
allFiles []*descriptor.FileDescriptorProto
|
||||||
|
filesByName map[string]*descriptor.FileDescriptorProto
|
||||||
|
|
||||||
|
// Mapping of fully-qualified names to their definitions
|
||||||
|
messagesByProtoName map[string]*MessageDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Registry
|
||||||
|
func New(files []*descriptor.FileDescriptorProto) *Registry {
|
||||||
|
r := &Registry{
|
||||||
|
allFiles: files,
|
||||||
|
filesByName: make(map[string]*descriptor.FileDescriptorProto),
|
||||||
|
messagesByProtoName: make(map[string]*MessageDefinition),
|
||||||
|
}
|
||||||
|
|
||||||
|
// First, index the file descriptors by name. We need this so
|
||||||
|
// messageDefsForFile can correctly scan imports.
|
||||||
|
for _, f := range files {
|
||||||
|
r.filesByName[f.GetName()] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next, index all the message definitions by their fully-qualified proto
|
||||||
|
// names.
|
||||||
|
for _, f := range files {
|
||||||
|
defs := messageDefsForFile(f, r.filesByName)
|
||||||
|
for name, def := range defs {
|
||||||
|
r.messagesByProtoName[name] = def
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileComments comment of file
|
||||||
|
func (r *Registry) FileComments(file *descriptor.FileDescriptorProto) (DefinitionComments, error) {
|
||||||
|
return commentsAtPath([]int32{packagePath}, file), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ServiceComments comments of service
|
||||||
|
func (r *Registry) ServiceComments(file *descriptor.FileDescriptorProto, svc *descriptor.ServiceDescriptorProto) (DefinitionComments, error) {
|
||||||
|
for i, s := range file.Service {
|
||||||
|
if s == svc {
|
||||||
|
path := []int32{servicePath, int32(i)}
|
||||||
|
return commentsAtPath(path, file), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DefinitionComments{}, errors.Errorf("service not found in file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// FieldComments ...
|
||||||
|
func (r *Registry) FieldComments(message *MessageDefinition, field *descriptor.FieldDescriptorProto) (DefinitionComments, error) {
|
||||||
|
file := message.File
|
||||||
|
mpath := message.path
|
||||||
|
for i, f := range message.Descriptor.Field {
|
||||||
|
if f == field {
|
||||||
|
path := append(mpath, messageFieldPath, int32(i))
|
||||||
|
return commentsAtPath(path, file), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DefinitionComments{}, errors.Errorf("field not found in msg")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodComments comment of method
|
||||||
|
func (r *Registry) MethodComments(file *descriptor.FileDescriptorProto, svc *descriptor.ServiceDescriptorProto, method *descriptor.MethodDescriptorProto) (DefinitionComments, error) {
|
||||||
|
for i, s := range file.Service {
|
||||||
|
if s == svc {
|
||||||
|
path := []int32{servicePath, int32(i)}
|
||||||
|
for j, m := range s.Method {
|
||||||
|
if m == method {
|
||||||
|
path = append(path, serviceMethodPath, int32(j))
|
||||||
|
return commentsAtPath(path, file), nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DefinitionComments{}, errors.Errorf("service not found in file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodInputDefinition returns MethodInputDefinition
|
||||||
|
func (r *Registry) MethodInputDefinition(method *descriptor.MethodDescriptorProto) *MessageDefinition {
|
||||||
|
return r.messagesByProtoName[method.GetInputType()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodOutputDefinition returns MethodOutputDefinition
|
||||||
|
func (r *Registry) MethodOutputDefinition(method *descriptor.MethodDescriptorProto) *MessageDefinition {
|
||||||
|
return r.messagesByProtoName[method.GetOutputType()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageDefinition by name
|
||||||
|
func (r *Registry) MessageDefinition(name string) *MessageDefinition {
|
||||||
|
return r.messagesByProtoName[name]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MessageDefinition msg info
|
||||||
|
type MessageDefinition struct {
|
||||||
|
// Descriptor is is the DescriptorProto defining the message.
|
||||||
|
Descriptor *descriptor.DescriptorProto
|
||||||
|
// File is the File that the message was defined in. Or, if it has been
|
||||||
|
// publicly imported, what File was that import performed in?
|
||||||
|
File *descriptor.FileDescriptorProto
|
||||||
|
// Parent is the parent message, if this was defined as a nested message. If
|
||||||
|
// this was defiend at the top level, parent is nil.
|
||||||
|
Parent *MessageDefinition
|
||||||
|
// Comments describes the comments surrounding a message's definition. If it
|
||||||
|
// was publicly imported, then these comments are from the actual source file,
|
||||||
|
// not the file that the import was performed in.
|
||||||
|
Comments DefinitionComments
|
||||||
|
|
||||||
|
// path is the 'SourceCodeInfo' path. See the documentation for
|
||||||
|
// github.com/golang/protobuf/protoc-gen-go/descriptor.SourceCodeInfo for an
|
||||||
|
// explanation of its format.
|
||||||
|
path []int32
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProtoName returns the dot-delimited, fully-qualified protobuf name of the
|
||||||
|
// message.
|
||||||
|
func (m *MessageDefinition) ProtoName() string {
|
||||||
|
prefix := "."
|
||||||
|
if pkg := m.File.GetPackage(); pkg != "" {
|
||||||
|
prefix += pkg + "."
|
||||||
|
}
|
||||||
|
|
||||||
|
if lineage := m.Lineage(); len(lineage) > 0 {
|
||||||
|
for _, parent := range lineage {
|
||||||
|
prefix += parent.Descriptor.GetName() + "."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return prefix + m.Descriptor.GetName()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lineage returns m's parental chain all the way back up to a top-level message
|
||||||
|
// definition. The first element of the returned slice is the highest-level
|
||||||
|
// parent.
|
||||||
|
func (m *MessageDefinition) Lineage() []*MessageDefinition {
|
||||||
|
var parents []*MessageDefinition
|
||||||
|
for p := m.Parent; p != nil; p = p.Parent {
|
||||||
|
parents = append([]*MessageDefinition{p}, parents...)
|
||||||
|
}
|
||||||
|
return parents
|
||||||
|
}
|
||||||
|
|
||||||
|
// descendants returns all the submessages defined within m, and all the
|
||||||
|
// descendants of those, recursively.
|
||||||
|
func (m *MessageDefinition) descendants() []*MessageDefinition {
|
||||||
|
descendants := make([]*MessageDefinition, 0)
|
||||||
|
for i, child := range m.Descriptor.NestedType {
|
||||||
|
path := append(m.path, []int32{messageMessagePath, int32(i)}...)
|
||||||
|
childDef := &MessageDefinition{
|
||||||
|
Descriptor: child,
|
||||||
|
File: m.File,
|
||||||
|
Parent: m,
|
||||||
|
Comments: commentsAtPath(path, m.File),
|
||||||
|
path: path,
|
||||||
|
}
|
||||||
|
descendants = append(descendants, childDef)
|
||||||
|
descendants = append(descendants, childDef.descendants()...)
|
||||||
|
}
|
||||||
|
return descendants
|
||||||
|
}
|
||||||
|
|
||||||
|
// messageDefsForFile gathers a mapping of fully-qualified protobuf names to
|
||||||
|
// their definitions. It scans a singles file at a time. It requires a mapping
|
||||||
|
// of .proto file names to their definitions in order to correctly handle
|
||||||
|
// 'import public' declarations; this mapping should include all files
|
||||||
|
// transitively imported by f.
|
||||||
|
func messageDefsForFile(f *descriptor.FileDescriptorProto, filesByName map[string]*descriptor.FileDescriptorProto) map[string]*MessageDefinition {
|
||||||
|
byProtoName := make(map[string]*MessageDefinition)
|
||||||
|
// First, gather all the messages defined at the top level.
|
||||||
|
for i, d := range f.MessageType {
|
||||||
|
path := []int32{messagePath, int32(i)}
|
||||||
|
def := &MessageDefinition{
|
||||||
|
Descriptor: d,
|
||||||
|
File: f,
|
||||||
|
Parent: nil,
|
||||||
|
Comments: commentsAtPath(path, f),
|
||||||
|
path: path,
|
||||||
|
}
|
||||||
|
|
||||||
|
byProtoName[def.ProtoName()] = def
|
||||||
|
// Next, all nested message definitions.
|
||||||
|
for _, child := range def.descendants() {
|
||||||
|
byProtoName[child.ProtoName()] = child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, all messages imported publicly.
|
||||||
|
for _, depIdx := range f.PublicDependency {
|
||||||
|
depFileName := f.Dependency[depIdx]
|
||||||
|
depFile := filesByName[depFileName]
|
||||||
|
depDefs := messageDefsForFile(depFile, filesByName)
|
||||||
|
for _, def := range depDefs {
|
||||||
|
imported := &MessageDefinition{
|
||||||
|
Descriptor: def.Descriptor,
|
||||||
|
File: f,
|
||||||
|
Parent: def.Parent,
|
||||||
|
Comments: commentsAtPath(def.path, depFile),
|
||||||
|
path: def.path,
|
||||||
|
}
|
||||||
|
byProtoName[imported.ProtoName()] = imported
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return byProtoName
|
||||||
|
}
|
||||||
|
|
||||||
|
// // ignored detached comments.
|
||||||
|
type DefinitionComments struct {
|
||||||
|
Leading string
|
||||||
|
Trailing string
|
||||||
|
LeadingDetached []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func commentsAtPath(path []int32, sourceFile *descriptor.FileDescriptorProto) DefinitionComments {
|
||||||
|
if sourceFile.SourceCodeInfo == nil {
|
||||||
|
// The compiler didn't provide us with comments.
|
||||||
|
return DefinitionComments{}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, loc := range sourceFile.SourceCodeInfo.Location {
|
||||||
|
if pathEqual(path, loc.Path) {
|
||||||
|
return DefinitionComments{
|
||||||
|
Leading: strings.TrimSuffix(loc.GetLeadingComments(), "\n"),
|
||||||
|
LeadingDetached: loc.GetLeadingDetachedComments(),
|
||||||
|
Trailing: loc.GetTrailingComments(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DefinitionComments{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func pathEqual(path1, path2 []int32) bool {
|
||||||
|
if len(path1) != len(path2) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i, v := range path1 {
|
||||||
|
if path2[i] != v {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// tag numbers in FileDescriptorProto
|
||||||
|
packagePath = 2 // package
|
||||||
|
messagePath = 4 // message_type
|
||||||
|
servicePath = 6 // service
|
||||||
|
// tag numbers in DescriptorProto
|
||||||
|
messageFieldPath = 2 // field
|
||||||
|
messageMessagePath = 3 // nested_type
|
||||||
|
// tag numbers in ServiceDescriptorProto
|
||||||
|
serviceMethodPath = 2 // method
|
||||||
|
)
|
98
tool/protobuf/pkg/utils/stringutils.go
Normal file
98
tool/protobuf/pkg/utils/stringutils.go
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Is c an ASCII lower-case letter?
|
||||||
|
func isASCIILower(c byte) bool {
|
||||||
|
return 'a' <= c && c <= 'z'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is c an ASCII digit?
|
||||||
|
func isASCIIDigit(c byte) bool {
|
||||||
|
return '0' <= c && c <= '9'
|
||||||
|
}
|
||||||
|
|
||||||
|
// CamelCase converts a string from snake_case to CamelCased.
|
||||||
|
//
|
||||||
|
// If there is an interior underscore followed by a lower case letter, drop the
|
||||||
|
// underscore and convert the letter to upper case. There is a remote
|
||||||
|
// possibility of this rewrite causing a name collision, but it's so remote
|
||||||
|
// we're prepared to pretend it's nonexistent - since the C++ generator
|
||||||
|
// lowercases names, it's extremely unlikely to have two fields with different
|
||||||
|
// capitalizations. In short, _my_field_name_2 becomes XMyFieldName_2.
|
||||||
|
func CamelCase(s string) string {
|
||||||
|
if s == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
t := make([]byte, 0, 32)
|
||||||
|
i := 0
|
||||||
|
if s[0] == '_' {
|
||||||
|
// Need a capital letter; drop the '_'.
|
||||||
|
t = append(t, 'X')
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
// Invariant: if the next letter is lower case, it must be converted
|
||||||
|
// to upper case.
|
||||||
|
//
|
||||||
|
// That is, we process a word at a time, where words are marked by _ or upper
|
||||||
|
// case letter. Digits are treated as words.
|
||||||
|
for ; i < len(s); i++ {
|
||||||
|
c := s[i]
|
||||||
|
if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
|
||||||
|
continue // Skip the underscore in s.
|
||||||
|
}
|
||||||
|
if isASCIIDigit(c) {
|
||||||
|
t = append(t, c)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Assume we have a letter now - if not, it's a bogus identifier. The next
|
||||||
|
// word is a sequence of characters that must start upper case.
|
||||||
|
if isASCIILower(c) {
|
||||||
|
c ^= ' ' // Make it a capital letter.
|
||||||
|
}
|
||||||
|
t = append(t, c) // Guaranteed not lower case.
|
||||||
|
// Accept lower case sequence that follows.
|
||||||
|
for i+1 < len(s) && isASCIILower(s[i+1]) {
|
||||||
|
i++
|
||||||
|
t = append(t, s[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
|
||||||
|
// be joined with "_" and then camelcased.
|
||||||
|
func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
|
||||||
|
|
||||||
|
// BaseName the last path element of a slash-delimited name, with the last
|
||||||
|
// dotted suffix removed.
|
||||||
|
func BaseName(name string) string {
|
||||||
|
// First, find the last element
|
||||||
|
if i := strings.LastIndex(name, "/"); i >= 0 {
|
||||||
|
name = name[i+1:]
|
||||||
|
}
|
||||||
|
// Now drop the suffix
|
||||||
|
if i := strings.LastIndex(name, "."); i >= 0 {
|
||||||
|
name = name[0:i]
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
// AlphaDigitize replaces non-letter, non-digit, non-underscore characters with
|
||||||
|
// underscore.
|
||||||
|
func AlphaDigitize(r rune) rune {
|
||||||
|
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
return '_'
|
||||||
|
}
|
||||||
|
|
||||||
|
// CleanIdentifier makes sure s is a valid 'identifier' string: it contains only
|
||||||
|
// letters, numbers, and underscore.
|
||||||
|
func CleanIdentifier(s string) string {
|
||||||
|
return strings.Map(AlphaDigitize, s)
|
||||||
|
}
|
29
tool/protobuf/pkg/utils/utils.go
Normal file
29
tool/protobuf/pkg/utils/utils.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LcFirst lower the first letter
|
||||||
|
func LcFirst(str string) string {
|
||||||
|
for i, v := range str {
|
||||||
|
return string(unicode.ToLower(v)) + str[i+1:]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsDir(name string) bool {
|
||||||
|
file, err := os.Open(name)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
fi, err := file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return fi.IsDir()
|
||||||
|
}
|
355
tool/protobuf/protoc-gen-bm/generator/generator.go
Normal file
355
tool/protobuf/protoc-gen-bm/generator/generator.go
Normal file
@ -0,0 +1,355 @@
|
|||||||
|
package generator
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/generator"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/naming"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/tag"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/typemap"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/utils"
|
||||||
|
"github.com/golang/protobuf/proto"
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type bm struct {
|
||||||
|
generator.Base
|
||||||
|
filesHandled int
|
||||||
|
}
|
||||||
|
|
||||||
|
// BmGenerator BM generator.
|
||||||
|
func BmGenerator() *bm {
|
||||||
|
t := &bm{}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate ...
|
||||||
|
func (t *bm) 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 *bm) generateForFile(file *descriptor.FileDescriptorProto) *plugin.CodeGeneratorResponse_File {
|
||||||
|
resp := new(plugin.CodeGeneratorResponse_File)
|
||||||
|
//if len(file.Service) == 0 {
|
||||||
|
// return nil
|
||||||
|
//}
|
||||||
|
|
||||||
|
t.generateFileHeader(file, t.GenPkgName)
|
||||||
|
t.generateImports(file)
|
||||||
|
t.generatePathConstants(file)
|
||||||
|
count := 0
|
||||||
|
for i, service := range file.Service {
|
||||||
|
count += t.generateBMInterface(file, service)
|
||||||
|
t.generateBMRoute(file, service, i)
|
||||||
|
}
|
||||||
|
//if count == 0 {
|
||||||
|
// return nil
|
||||||
|
//}
|
||||||
|
|
||||||
|
resp.Name = proto.String(naming.GoFileName(file, ".bm.go"))
|
||||||
|
resp.Content = proto.String(t.FormattedOutput())
|
||||||
|
t.Output.Reset()
|
||||||
|
|
||||||
|
t.filesHandled++
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *bm) generatePathConstants(file *descriptor.FileDescriptorProto) {
|
||||||
|
t.P()
|
||||||
|
for _, service := range file.Service {
|
||||||
|
name := naming.ServiceName(service)
|
||||||
|
for _, method := range service.Method {
|
||||||
|
if !t.ShouldGenForMethod(file, service, method) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
apiInfo := t.GetHttpInfoCached(file, service, method)
|
||||||
|
t.P(`var Path`, name, naming.MethodName(method), ` = "`, apiInfo.Path, `"`)
|
||||||
|
}
|
||||||
|
t.P()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *bm) generateFileHeader(file *descriptor.FileDescriptorProto, pkgName string) {
|
||||||
|
t.P("// Code generated by protoc-gen-bm ", generator.Version, ", DO NOT EDIT.")
|
||||||
|
t.P("// source: ", file.GetName())
|
||||||
|
t.P()
|
||||||
|
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/bmgen/protoc-gen-bm ", generator.Version, ".")
|
||||||
|
t.P()
|
||||||
|
comment, err := t.Reg.FileComments(file)
|
||||||
|
if err == nil && comment.Leading != "" {
|
||||||
|
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 *bm) generateImports(file *descriptor.FileDescriptorProto) {
|
||||||
|
//if len(file.Service) == 0 {
|
||||||
|
// return
|
||||||
|
//}
|
||||||
|
t.P(`import (`)
|
||||||
|
//t.P(` `,t.pkgs["context"], ` "context"`)
|
||||||
|
t.P(` "context"`)
|
||||||
|
t.P()
|
||||||
|
t.P(` bm "github.com/bilibili/kratos/pkg/net/http/blademaster"`)
|
||||||
|
t.P(` "github.com/bilibili/kratos/pkg/net/http/blademaster/binding"`)
|
||||||
|
|
||||||
|
t.P(`)`)
|
||||||
|
// It's legal to import a message and use it as an input or output for a
|
||||||
|
// method. Make sure to import the package of any such message. First, dedupe
|
||||||
|
// them.
|
||||||
|
deps := make(map[string]string) // Map of package name to quoted import path.
|
||||||
|
deps = t.DeduceDeps(file)
|
||||||
|
for pkg, importPath := range deps {
|
||||||
|
for _, service := range file.Service {
|
||||||
|
for _, method := range service.Method {
|
||||||
|
inputType := t.GoTypeName(method.GetInputType())
|
||||||
|
outputType := t.GoTypeName(method.GetOutputType())
|
||||||
|
if strings.HasPrefix(pkg, outputType) || strings.HasPrefix(pkg, inputType) {
|
||||||
|
t.P(`import `, pkg, ` `, importPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(deps) > 0 {
|
||||||
|
t.P()
|
||||||
|
}
|
||||||
|
t.P()
|
||||||
|
t.P(`// to suppressed 'imported but not used warning'`)
|
||||||
|
t.P(`var _ *bm.Context`)
|
||||||
|
t.P(`var _ context.Context`)
|
||||||
|
t.P(`var _ binding.StructValidator`)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Big header comments to makes it easier to visually parse a generated file.
|
||||||
|
func (t *bm) sectionComment(sectionTitle string) {
|
||||||
|
t.P()
|
||||||
|
t.P(`// `, strings.Repeat("=", len(sectionTitle)))
|
||||||
|
t.P(`// `, sectionTitle)
|
||||||
|
t.P(`// `, strings.Repeat("=", len(sectionTitle)))
|
||||||
|
t.P()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *bm) generateBMRoute(
|
||||||
|
file *descriptor.FileDescriptorProto,
|
||||||
|
service *descriptor.ServiceDescriptorProto,
|
||||||
|
index int) {
|
||||||
|
// old mode is generate xx.route.go in the http pkg
|
||||||
|
// new mode is generate route code in the same .bm.go
|
||||||
|
// route rule /x{department}/{project-name}/{path_prefix}/method_name
|
||||||
|
// generate each route method
|
||||||
|
servName := naming.ServiceName(service)
|
||||||
|
versionPrefix := naming.GetVersionPrefix(t.GenPkgName)
|
||||||
|
svcName := utils.LcFirst(utils.CamelCase(versionPrefix)) + servName + "Svc"
|
||||||
|
t.P(`var `, svcName, ` `, servName, `BMServer`)
|
||||||
|
|
||||||
|
type methodInfo struct {
|
||||||
|
midwares []string
|
||||||
|
routeFuncName string
|
||||||
|
apiInfo *generator.HTTPInfo
|
||||||
|
methodName string
|
||||||
|
}
|
||||||
|
var methList []methodInfo
|
||||||
|
var allMidwareMap = make(map[string]bool)
|
||||||
|
var isLegacyPkg = false
|
||||||
|
for _, method := range service.Method {
|
||||||
|
if !t.ShouldGenForMethod(file, service, method) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var midwares []string
|
||||||
|
comments, _ := t.Reg.MethodComments(file, service, method)
|
||||||
|
tags := tag.GetTagsInComment(comments.Leading)
|
||||||
|
if tag.GetTagValue("dynamic", tags) == "true" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
apiInfo := t.GetHttpInfoCached(file, service, method)
|
||||||
|
isLegacyPkg = apiInfo.IsLegacyPath
|
||||||
|
//httpMethod, legacyPath, path := getHttpInfo(file, service, method, t.reg)
|
||||||
|
//if legacyPath != "" {
|
||||||
|
// isLegacyPkg = true
|
||||||
|
//}
|
||||||
|
|
||||||
|
midStr := tag.GetTagValue("midware", tags)
|
||||||
|
if midStr != "" {
|
||||||
|
midwares = strings.Split(midStr, ",")
|
||||||
|
for _, m := range midwares {
|
||||||
|
allMidwareMap[m] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
methName := naming.MethodName(method)
|
||||||
|
inputType := t.GoTypeName(method.GetInputType())
|
||||||
|
|
||||||
|
routeName := utils.LcFirst(utils.CamelCase(servName) +
|
||||||
|
utils.CamelCase(methName))
|
||||||
|
|
||||||
|
methList = append(methList, methodInfo{
|
||||||
|
apiInfo: apiInfo,
|
||||||
|
midwares: midwares,
|
||||||
|
routeFuncName: routeName,
|
||||||
|
methodName: method.GetName(),
|
||||||
|
})
|
||||||
|
|
||||||
|
t.P(fmt.Sprintf("func %s (c *bm.Context) {", routeName))
|
||||||
|
t.P(` p := new(`, inputType, `)`)
|
||||||
|
requestBinding := ""
|
||||||
|
if t.hasHeaderTag(t.Reg.MessageDefinition(method.GetInputType())) {
|
||||||
|
requestBinding = ", binding.Request"
|
||||||
|
}
|
||||||
|
t.P(` if err := c.BindWith(p, binding.Default(c.Request.Method, c.Request.Header.Get("Content-Type"))` +
|
||||||
|
requestBinding + `); err != nil {`)
|
||||||
|
t.P(` return`)
|
||||||
|
t.P(` }`)
|
||||||
|
t.P(` resp, err := `, svcName, `.`, methName, `(c, p)`)
|
||||||
|
t.P(` c.JSON(resp, err)`)
|
||||||
|
t.P(`}`)
|
||||||
|
t.P(``)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate route group
|
||||||
|
var midList []string
|
||||||
|
for m := range allMidwareMap {
|
||||||
|
midList = append(midList, m+" bm.HandlerFunc")
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Strings(midList)
|
||||||
|
|
||||||
|
// 注册老的路由的方法
|
||||||
|
if isLegacyPkg {
|
||||||
|
funcName := `Register` + utils.CamelCase(versionPrefix) + servName + `Service`
|
||||||
|
t.P(`// `, funcName, ` Register the blademaster route with middleware map`)
|
||||||
|
t.P(`// midMap is the middleware map, the key is defined in proto`)
|
||||||
|
t.P(`func `, funcName, `(e *bm.Engine, svc `, servName, "BMServer, midMap map[string]bm.HandlerFunc)", ` {`)
|
||||||
|
var keys []string
|
||||||
|
for m := range allMidwareMap {
|
||||||
|
keys = append(keys, m)
|
||||||
|
}
|
||||||
|
// to keep generated code consistent
|
||||||
|
sort.Strings(keys)
|
||||||
|
for _, m := range keys {
|
||||||
|
t.P(m, ` := midMap["`, m, `"]`)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.P(svcName, ` = svc`)
|
||||||
|
for _, methInfo := range methList {
|
||||||
|
var midArgStr string
|
||||||
|
if len(methInfo.midwares) == 0 {
|
||||||
|
midArgStr = ""
|
||||||
|
} else {
|
||||||
|
midArgStr = strings.Join(methInfo.midwares, ", ") + ", "
|
||||||
|
}
|
||||||
|
t.P(`e.`, methInfo.apiInfo.HttpMethod, `("`, methInfo.apiInfo.LegacyPath, `", `, midArgStr, methInfo.routeFuncName, `)`)
|
||||||
|
}
|
||||||
|
t.P(` }`)
|
||||||
|
} else {
|
||||||
|
// 新的注册路由的方法
|
||||||
|
var bmFuncName = fmt.Sprintf("Register%sBMServer", servName)
|
||||||
|
t.P(`// `, bmFuncName, ` Register the blademaster route`)
|
||||||
|
t.P(`func `, bmFuncName, `(e *bm.Engine, server `, servName, `BMServer) {`)
|
||||||
|
t.P(svcName, ` = server`)
|
||||||
|
for _, methInfo := range methList {
|
||||||
|
t.P(`e.`, methInfo.apiInfo.HttpMethod, `("`, methInfo.apiInfo.NewPath, `",`, methInfo.routeFuncName, ` )`)
|
||||||
|
}
|
||||||
|
t.P(` }`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *bm) hasHeaderTag(md *typemap.MessageDefinition) bool {
|
||||||
|
if md.Descriptor.Field == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, f := range md.Descriptor.Field {
|
||||||
|
t := tag.GetMoreTags(f)
|
||||||
|
if t != nil {
|
||||||
|
st := reflect.StructTag(*t)
|
||||||
|
if st.Get("request") != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if st.Get("header") != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *bm) generateBMInterface(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) int {
|
||||||
|
count := 0
|
||||||
|
servName := naming.ServiceName(service)
|
||||||
|
t.P("// " + servName + "BMServer is the server API for " + servName + " service.")
|
||||||
|
|
||||||
|
comments, err := t.Reg.ServiceComments(file, service)
|
||||||
|
if err == nil {
|
||||||
|
t.PrintComments(comments)
|
||||||
|
}
|
||||||
|
t.P(`type `, servName, `BMServer interface {`)
|
||||||
|
for _, method := range service.Method {
|
||||||
|
if !t.ShouldGenForMethod(file, service, method) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
count++
|
||||||
|
t.generateInterfaceMethod(file, service, method, comments)
|
||||||
|
t.P()
|
||||||
|
}
|
||||||
|
t.P(`}`)
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *bm) generateInterfaceMethod(file *descriptor.FileDescriptorProto,
|
||||||
|
service *descriptor.ServiceDescriptorProto,
|
||||||
|
method *descriptor.MethodDescriptorProto,
|
||||||
|
comments typemap.DefinitionComments) {
|
||||||
|
comments, err := t.Reg.MethodComments(file, service, method)
|
||||||
|
|
||||||
|
methName := naming.MethodName(method)
|
||||||
|
outputType := t.GoTypeName(method.GetOutputType())
|
||||||
|
inputType := t.GoTypeName(method.GetInputType())
|
||||||
|
tags := tag.GetTagsInComment(comments.Leading)
|
||||||
|
if tag.GetTagValue("dynamic", tags) == "true" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.PrintComments(comments)
|
||||||
|
}
|
||||||
|
|
||||||
|
respDynamic := tag.GetTagValue("dynamic_resp", tags) == "true"
|
||||||
|
if respDynamic {
|
||||||
|
t.P(fmt.Sprintf(` %s(ctx context.Context, req *%s) (resp interface{}, err error)`,
|
||||||
|
methName, inputType))
|
||||||
|
} else {
|
||||||
|
t.P(fmt.Sprintf(` %s(ctx context.Context, req *%s) (resp *%s, err error)`,
|
||||||
|
methName, inputType, outputType))
|
||||||
|
}
|
||||||
|
}
|
27
tool/protobuf/protoc-gen-bm/generator/generator_test.go
Normal file
27
tool/protobuf/protoc-gen-bm/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 := &bm{}
|
||||||
|
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-bm/main.go
Normal file
23
tool/protobuf/protoc-gen-bm/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"
|
||||||
|
bmgen "github.com/bilibili/kratos/tool/protobuf/protoc-gen-bm/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
versionFlag := flag.Bool("version", false, "print version and exit")
|
||||||
|
flag.Parse()
|
||||||
|
if *versionFlag {
|
||||||
|
fmt.Println(generator.Version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
g := bmgen.BmGenerator()
|
||||||
|
gen.Main(g)
|
||||||
|
}
|
303
tool/protobuf/protoc-gen-bswagger/generator.go
Normal file
303
tool/protobuf/protoc-gen-bswagger/generator.go
Normal file
@ -0,0 +1,303 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/gen"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/generator"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/naming"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/tag"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/typemap"
|
||||||
|
"github.com/golang/protobuf/protoc-gen-go/descriptor"
|
||||||
|
plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type swaggerGen struct {
|
||||||
|
generator.Base
|
||||||
|
// defsMap will fill into swagger's definitions
|
||||||
|
// key is full qualified proto name
|
||||||
|
defsMap map[string]*typemap.MessageDefinition
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSwaggerGenerator a swagger generator
|
||||||
|
func NewSwaggerGenerator() *swaggerGen {
|
||||||
|
return &swaggerGen{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *swaggerGen) Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse {
|
||||||
|
t.Setup(in)
|
||||||
|
resp := &plugin.CodeGeneratorResponse{}
|
||||||
|
for _, f := range t.GenFiles {
|
||||||
|
if len(f.Service) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
respFile := t.generateSwagger(f)
|
||||||
|
if respFile != nil {
|
||||||
|
resp.File = append(resp.File, respFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return resp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *swaggerGen) generateSwagger(file *descriptor.FileDescriptorProto) *plugin.CodeGeneratorResponse_File {
|
||||||
|
var pkg = file.GetPackage()
|
||||||
|
r := regexp.MustCompile("v(\\d+)$")
|
||||||
|
strs := r.FindStringSubmatch(pkg)
|
||||||
|
var vStr string
|
||||||
|
if len(strs) >= 2 {
|
||||||
|
vStr = strs[1]
|
||||||
|
} else {
|
||||||
|
vStr = ""
|
||||||
|
}
|
||||||
|
var swaggerObj = &swaggerObject{
|
||||||
|
Paths: swaggerPathsObject{},
|
||||||
|
Swagger: "2.0",
|
||||||
|
Info: swaggerInfoObject{
|
||||||
|
Title: file.GetName(),
|
||||||
|
Version: vStr,
|
||||||
|
},
|
||||||
|
Schemes: []string{"http", "https"},
|
||||||
|
Consumes: []string{"application/json", "multipart/form-data"},
|
||||||
|
Produces: []string{"application/json"},
|
||||||
|
}
|
||||||
|
t.defsMap = map[string]*typemap.MessageDefinition{}
|
||||||
|
|
||||||
|
out := &plugin.CodeGeneratorResponse_File{}
|
||||||
|
name := naming.GoFileName(file, ".swagger.json")
|
||||||
|
for _, svc := range file.Service {
|
||||||
|
for _, meth := range svc.Method {
|
||||||
|
if !t.ShouldGenForMethod(file, svc, meth) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
apiInfo := t.GetHttpInfoCached(file, svc, meth)
|
||||||
|
pathItem := swaggerPathItemObject{}
|
||||||
|
|
||||||
|
op := t.getOperationByHTTPMethod(apiInfo.HttpMethod, &pathItem)
|
||||||
|
op.Summary = apiInfo.Title
|
||||||
|
op.Description = apiInfo.Description
|
||||||
|
swaggerObj.Paths[apiInfo.Path] = pathItem
|
||||||
|
op.Tags = []string{pkg + "." + svc.GetName()}
|
||||||
|
|
||||||
|
// request
|
||||||
|
request := t.Reg.MessageDefinition(meth.GetInputType())
|
||||||
|
// request cannot represent by simple form
|
||||||
|
isComplexRequest := false
|
||||||
|
for _, field := range request.Descriptor.Field {
|
||||||
|
if !generator.IsScalar(field) {
|
||||||
|
isComplexRequest = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !isComplexRequest && apiInfo.HttpMethod == "GET" {
|
||||||
|
for _, field := range request.Descriptor.Field {
|
||||||
|
if !generator.IsScalar(field) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p := t.getQueryParameter(file, request, field)
|
||||||
|
op.Parameters = append(op.Parameters, p)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p := swaggerParameterObject{}
|
||||||
|
p.In = "body"
|
||||||
|
p.Required = true
|
||||||
|
p.Name = "body"
|
||||||
|
p.Schema = &swaggerSchemaObject{}
|
||||||
|
p.Schema.Ref = "#/definitions/" + meth.GetInputType()
|
||||||
|
op.Parameters = []swaggerParameterObject{p}
|
||||||
|
}
|
||||||
|
|
||||||
|
// response
|
||||||
|
resp := swaggerResponseObject{}
|
||||||
|
resp.Description = "A successful response."
|
||||||
|
|
||||||
|
// proto 里面的response只定义data里面的
|
||||||
|
// 所以需要把code msg data 这一级加上
|
||||||
|
resp.Schema.Type = "object"
|
||||||
|
resp.Schema.Properties = &swaggerSchemaObjectProperties{}
|
||||||
|
p := keyVal{Key: "code", Value: &schemaCore{Type: "integer"}}
|
||||||
|
*resp.Schema.Properties = append(*resp.Schema.Properties, p)
|
||||||
|
p = keyVal{Key: "message", Value: &schemaCore{Type: "string"}}
|
||||||
|
*resp.Schema.Properties = append(*resp.Schema.Properties, p)
|
||||||
|
p = keyVal{Key: "data", Value: schemaCore{Ref: "#/definitions/" + meth.GetOutputType()}}
|
||||||
|
*resp.Schema.Properties = append(*resp.Schema.Properties, p)
|
||||||
|
op.Responses = swaggerResponsesObject{"200": resp}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// walk though definitions
|
||||||
|
t.walkThroughFileDefinition(file)
|
||||||
|
defs := swaggerDefinitionsObject{}
|
||||||
|
swaggerObj.Definitions = defs
|
||||||
|
for typ, msg := range t.defsMap {
|
||||||
|
def := swaggerSchemaObject{}
|
||||||
|
def.Properties = new(swaggerSchemaObjectProperties)
|
||||||
|
def.Description = strings.Trim(msg.Comments.Leading, "\n\r ")
|
||||||
|
for _, field := range msg.Descriptor.Field {
|
||||||
|
p := keyVal{Key: generator.GetFormOrJSONName(field)}
|
||||||
|
schema := t.schemaForField(file, msg, field)
|
||||||
|
if generator.GetFieldRequired(field, t.Reg, msg) {
|
||||||
|
def.Required = append(def.Required, p.Key)
|
||||||
|
}
|
||||||
|
p.Value = schema
|
||||||
|
*def.Properties = append(*def.Properties, p)
|
||||||
|
}
|
||||||
|
def.Type = "object"
|
||||||
|
defs[typ] = def
|
||||||
|
}
|
||||||
|
b, _ := json.MarshalIndent(swaggerObj, "", " ")
|
||||||
|
str := string(b)
|
||||||
|
out.Name = &name
|
||||||
|
out.Content = &str
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *swaggerGen) getOperationByHTTPMethod(httpMethod string, pathItem *swaggerPathItemObject) *swaggerOperationObject {
|
||||||
|
var op = &swaggerOperationObject{}
|
||||||
|
switch httpMethod {
|
||||||
|
case http.MethodGet:
|
||||||
|
pathItem.Get = op
|
||||||
|
case http.MethodPost:
|
||||||
|
pathItem.Post = op
|
||||||
|
case http.MethodPut:
|
||||||
|
pathItem.Put = op
|
||||||
|
case http.MethodDelete:
|
||||||
|
pathItem.Put = op
|
||||||
|
case http.MethodPatch:
|
||||||
|
pathItem.Patch = op
|
||||||
|
default:
|
||||||
|
pathItem.Get = op
|
||||||
|
}
|
||||||
|
return op
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *swaggerGen) getQueryParameter(file *descriptor.FileDescriptorProto,
|
||||||
|
input *typemap.MessageDefinition,
|
||||||
|
field *descriptor.FieldDescriptorProto) swaggerParameterObject {
|
||||||
|
p := swaggerParameterObject{}
|
||||||
|
p.Name = generator.GetFormOrJSONName(field)
|
||||||
|
fComment, _ := t.Reg.FieldComments(input, field)
|
||||||
|
cleanComment := tag.GetCommentWithoutTag(fComment.Leading)
|
||||||
|
|
||||||
|
p.Description = strings.Trim(strings.Join(cleanComment, "\n"), "\n\r ")
|
||||||
|
p.In = "query"
|
||||||
|
p.Required = generator.GetFieldRequired(field, t.Reg, input)
|
||||||
|
typ, isArray, format := getFieldSwaggerType(field)
|
||||||
|
if isArray {
|
||||||
|
p.Items = &swaggerItemsObject{}
|
||||||
|
p.Type = "array"
|
||||||
|
p.Items.Type = typ
|
||||||
|
p.Items.Format = format
|
||||||
|
} else {
|
||||||
|
p.Type = typ
|
||||||
|
p.Format = format
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *swaggerGen) schemaForField(file *descriptor.FileDescriptorProto,
|
||||||
|
msg *typemap.MessageDefinition,
|
||||||
|
field *descriptor.FieldDescriptorProto) swaggerSchemaObject {
|
||||||
|
schema := swaggerSchemaObject{}
|
||||||
|
fComment, err := t.Reg.FieldComments(msg, field)
|
||||||
|
if err != nil {
|
||||||
|
gen.Error(err, "comment not found err %+v")
|
||||||
|
}
|
||||||
|
schema.Description = strings.Trim(fComment.Leading, "\n\r ")
|
||||||
|
typ, isArray, format := getFieldSwaggerType(field)
|
||||||
|
if !generator.IsScalar(field) {
|
||||||
|
if generator.IsMap(field, t.Reg) {
|
||||||
|
schema.Type = "object"
|
||||||
|
mapMsg := t.Reg.MessageDefinition(field.GetTypeName())
|
||||||
|
mapValueField := mapMsg.Descriptor.Field[1]
|
||||||
|
valSchema := t.schemaForField(file, mapMsg, mapValueField)
|
||||||
|
schema.AdditionalProperties = &valSchema
|
||||||
|
} else {
|
||||||
|
if isArray {
|
||||||
|
schema.Items = &swaggerItemsObject{}
|
||||||
|
schema.Type = "array"
|
||||||
|
schema.Items.Ref = "#/definitions/" + field.GetTypeName()
|
||||||
|
} else {
|
||||||
|
schema.Ref = "#/definitions/" + field.GetTypeName()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if isArray {
|
||||||
|
schema.Items = &swaggerItemsObject{}
|
||||||
|
schema.Type = "array"
|
||||||
|
schema.Items.Type = typ
|
||||||
|
schema.Items.Format = format
|
||||||
|
} else {
|
||||||
|
schema.Type = typ
|
||||||
|
schema.Format = format
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *swaggerGen) walkThroughFileDefinition(file *descriptor.FileDescriptorProto) {
|
||||||
|
for _, svc := range file.Service {
|
||||||
|
for _, meth := range svc.Method {
|
||||||
|
shouldGen := t.ShouldGenForMethod(file, svc, meth)
|
||||||
|
if !shouldGen {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.walkThroughMessages(t.Reg.MessageDefinition(meth.GetOutputType()))
|
||||||
|
t.walkThroughMessages(t.Reg.MessageDefinition(meth.GetInputType()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *swaggerGen) walkThroughMessages(msg *typemap.MessageDefinition) {
|
||||||
|
_, ok := t.defsMap[msg.ProtoName()]
|
||||||
|
if ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !msg.Descriptor.GetOptions().GetMapEntry() {
|
||||||
|
t.defsMap[msg.ProtoName()] = msg
|
||||||
|
}
|
||||||
|
for _, field := range msg.Descriptor.Field {
|
||||||
|
if field.GetType() == descriptor.FieldDescriptorProto_TYPE_MESSAGE {
|
||||||
|
t.walkThroughMessages(t.Reg.MessageDefinition(field.GetTypeName()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFieldSwaggerType(field *descriptor.FieldDescriptorProto) (typeName string, isArray bool, formatName string) {
|
||||||
|
typeName = "unknown"
|
||||||
|
switch field.GetType() {
|
||||||
|
case descriptor.FieldDescriptorProto_TYPE_BOOL:
|
||||||
|
typeName = "boolean"
|
||||||
|
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
|
||||||
|
typeName = "number"
|
||||||
|
formatName = "double"
|
||||||
|
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
|
||||||
|
typeName = "number"
|
||||||
|
formatName = "float"
|
||||||
|
case
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_INT64,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_UINT64,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_INT32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_FIXED64,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_FIXED32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_ENUM,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_UINT32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_SFIXED32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_SFIXED64,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_SINT32,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_SINT64:
|
||||||
|
typeName = "integer"
|
||||||
|
case
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_STRING,
|
||||||
|
descriptor.FieldDescriptorProto_TYPE_BYTES:
|
||||||
|
typeName = "string"
|
||||||
|
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
|
||||||
|
typeName = "object"
|
||||||
|
}
|
||||||
|
if field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
|
||||||
|
isArray = true
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
22
tool/protobuf/protoc-gen-bswagger/main.go
Normal file
22
tool/protobuf/protoc-gen-bswagger/main.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/gen"
|
||||||
|
"github.com/bilibili/kratos/tool/protobuf/pkg/generator"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
versionFlag := flag.Bool("version", false, "print version and exit")
|
||||||
|
flag.Parse()
|
||||||
|
if *versionFlag {
|
||||||
|
fmt.Println(generator.Version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
g := NewSwaggerGenerator()
|
||||||
|
gen.Main(g)
|
||||||
|
}
|
218
tool/protobuf/protoc-gen-bswagger/types.go
Normal file
218
tool/protobuf/protoc-gen-bswagger/types.go
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#infoObject
|
||||||
|
type swaggerInfoObject struct {
|
||||||
|
Title string `json:"title"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
TermsOfService string `json:"termsOfService,omitempty"`
|
||||||
|
Version string `json:"version"`
|
||||||
|
|
||||||
|
Contact *swaggerContactObject `json:"contact,omitempty"`
|
||||||
|
License *swaggerLicenseObject `json:"license,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#contactObject
|
||||||
|
type swaggerContactObject struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
Email string `json:"email,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#licenseObject
|
||||||
|
type swaggerLicenseObject struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#externalDocumentationObject
|
||||||
|
type swaggerExternalDocumentationObject struct {
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
URL string `json:"url,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#swaggerObject
|
||||||
|
type swaggerObject struct {
|
||||||
|
Swagger string `json:"swagger"`
|
||||||
|
Info swaggerInfoObject `json:"info"`
|
||||||
|
Host string `json:"host,omitempty"`
|
||||||
|
BasePath string `json:"basePath,omitempty"`
|
||||||
|
Schemes []string `json:"schemes"`
|
||||||
|
Consumes []string `json:"consumes"`
|
||||||
|
Produces []string `json:"produces"`
|
||||||
|
Paths swaggerPathsObject `json:"paths"`
|
||||||
|
Definitions swaggerDefinitionsObject `json:"definitions"`
|
||||||
|
StreamDefinitions swaggerDefinitionsObject `json:"x-stream-definitions,omitempty"`
|
||||||
|
SecurityDefinitions swaggerSecurityDefinitionsObject `json:"securityDefinitions,omitempty"`
|
||||||
|
Security []swaggerSecurityRequirementObject `json:"security,omitempty"`
|
||||||
|
ExternalDocs *swaggerExternalDocumentationObject `json:"externalDocs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#securityDefinitionsObject
|
||||||
|
type swaggerSecurityDefinitionsObject map[string]swaggerSecuritySchemeObject
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#securitySchemeObject
|
||||||
|
type swaggerSecuritySchemeObject struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
In string `json:"in,omitempty"`
|
||||||
|
Flow string `json:"flow,omitempty"`
|
||||||
|
AuthorizationURL string `json:"authorizationUrl,omitempty"`
|
||||||
|
TokenURL string `json:"tokenUrl,omitempty"`
|
||||||
|
Scopes swaggerScopesObject `json:"scopes,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#scopesObject
|
||||||
|
type swaggerScopesObject map[string]string
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#securityRequirementObject
|
||||||
|
type swaggerSecurityRequirementObject map[string][]string
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#pathsObject
|
||||||
|
type swaggerPathsObject map[string]swaggerPathItemObject
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#pathItemObject
|
||||||
|
type swaggerPathItemObject struct {
|
||||||
|
Get *swaggerOperationObject `json:"get,omitempty"`
|
||||||
|
Delete *swaggerOperationObject `json:"delete,omitempty"`
|
||||||
|
Post *swaggerOperationObject `json:"post,omitempty"`
|
||||||
|
Put *swaggerOperationObject `json:"put,omitempty"`
|
||||||
|
Patch *swaggerOperationObject `json:"patch,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#operationObject
|
||||||
|
type swaggerOperationObject struct {
|
||||||
|
Summary string `json:"summary,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
OperationID string `json:"operationId,omitempty"`
|
||||||
|
Responses swaggerResponsesObject `json:"responses"`
|
||||||
|
Parameters swaggerParametersObject `json:"parameters,omitempty"`
|
||||||
|
Tags []string `json:"tags,omitempty"`
|
||||||
|
Deprecated bool `json:"deprecated,omitempty"`
|
||||||
|
|
||||||
|
Security *[]swaggerSecurityRequirementObject `json:"security,omitempty"`
|
||||||
|
ExternalDocs *swaggerExternalDocumentationObject `json:"externalDocs,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type swaggerParametersObject []swaggerParameterObject
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#parameterObject
|
||||||
|
type swaggerParameterObject struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
In string `json:"in,omitempty"`
|
||||||
|
Required bool `json:"required"`
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Format string `json:"format,omitempty"`
|
||||||
|
Items *swaggerItemsObject `json:"items,omitempty"`
|
||||||
|
Enum []string `json:"enum,omitempty"`
|
||||||
|
CollectionFormat string `json:"collectionFormat,omitempty"`
|
||||||
|
Default string `json:"default,omitempty"`
|
||||||
|
MinItems *int `json:"minItems,omitempty"`
|
||||||
|
|
||||||
|
// Or you can explicitly refer to another type. If this is defined all
|
||||||
|
// other fields should be empty
|
||||||
|
Schema *swaggerSchemaObject `json:"schema,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// core part of schema, which is common to itemsObject and schemaObject.
|
||||||
|
// http://swagger.io/specification/#itemsObject
|
||||||
|
type schemaCore struct {
|
||||||
|
Type string `json:"type,omitempty"`
|
||||||
|
Format string `json:"format,omitempty"`
|
||||||
|
Ref string `json:"$ref,omitempty"`
|
||||||
|
Example json.RawMessage `json:"example,omitempty"`
|
||||||
|
|
||||||
|
Items *swaggerItemsObject `json:"items,omitempty"`
|
||||||
|
|
||||||
|
// If the item is an enumeration include a list of all the *NAMES* of the
|
||||||
|
// enum values. I'm not sure how well this will work but assuming all enums
|
||||||
|
// start from 0 index it will be great. I don't think that is a good assumption.
|
||||||
|
Enum []string `json:"enum,omitempty"`
|
||||||
|
Default string `json:"default,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type swaggerItemsObject schemaCore
|
||||||
|
|
||||||
|
func (o *swaggerItemsObject) getType() string {
|
||||||
|
if o == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return o.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#responsesObject
|
||||||
|
type swaggerResponsesObject map[string]swaggerResponseObject
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#responseObject
|
||||||
|
type swaggerResponseObject struct {
|
||||||
|
Description string `json:"description"`
|
||||||
|
Schema swaggerSchemaObject `json:"schema"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type keyVal struct {
|
||||||
|
Key string
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type swaggerSchemaObjectProperties []keyVal
|
||||||
|
|
||||||
|
func (op swaggerSchemaObjectProperties) MarshalJSON() ([]byte, error) {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.WriteString("{")
|
||||||
|
for i, kv := range op {
|
||||||
|
if i != 0 {
|
||||||
|
buf.WriteString(",")
|
||||||
|
}
|
||||||
|
key, err := json.Marshal(kv.Key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buf.Write(key)
|
||||||
|
buf.WriteString(":")
|
||||||
|
val, err := json.Marshal(kv.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
buf.Write(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.WriteString("}")
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#schemaObject
|
||||||
|
type swaggerSchemaObject struct {
|
||||||
|
schemaCore
|
||||||
|
// Properties can be recursively defined
|
||||||
|
Properties *swaggerSchemaObjectProperties `json:"properties,omitempty"`
|
||||||
|
AdditionalProperties *swaggerSchemaObject `json:"additionalProperties,omitempty"`
|
||||||
|
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Title string `json:"title,omitempty"`
|
||||||
|
|
||||||
|
ExternalDocs *swaggerExternalDocumentationObject `json:"externalDocs,omitempty"`
|
||||||
|
|
||||||
|
MultipleOf float64 `json:"multipleOf,omitempty"`
|
||||||
|
Maximum float64 `json:"maximum,omitempty"`
|
||||||
|
ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty"`
|
||||||
|
Minimum float64 `json:"minimum,omitempty"`
|
||||||
|
ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty"`
|
||||||
|
MaxLength uint64 `json:"maxLength,omitempty"`
|
||||||
|
MinLength uint64 `json:"minLength,omitempty"`
|
||||||
|
Pattern string `json:"pattern,omitempty"`
|
||||||
|
MaxItems uint64 `json:"maxItems,omitempty"`
|
||||||
|
MinItems uint64 `json:"minItems,omitempty"`
|
||||||
|
UniqueItems bool `json:"uniqueItems,omitempty"`
|
||||||
|
MaxProperties uint64 `json:"maxProperties,omitempty"`
|
||||||
|
MinProperties uint64 `json:"minProperties,omitempty"`
|
||||||
|
Required []string `json:"required,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://swagger.io/specification/#definitionsObject
|
||||||
|
type swaggerDefinitionsObject map[string]swaggerSchemaObject
|
Loading…
x
Reference in New Issue
Block a user