Skip to content

Commit

Permalink
add annotatedOnly flag
Browse files Browse the repository at this point in the history
  • Loading branch information
wubin1989 committed Sep 18, 2024
1 parent 0a7294f commit 6b04728
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 21 deletions.
4 changes: 3 additions & 1 deletion cmd/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

var naming string
var http2grpc bool
var annotatedOnly bool

var grpcCmd = &cobra.Command{
Use: "grpc",
Expand All @@ -22,7 +23,7 @@ var grpcCmd = &cobra.Command{
fn = strcase.ToSnake
}
s := svc.NewSvc("",
svc.WithProtoGenerator(v3.NewProtoGenerator(v3.WithFieldNamingFunc(fn))),
svc.WithProtoGenerator(v3.NewProtoGenerator(v3.WithFieldNamingFunc(fn), v3.WithAnnotatedOnly(annotatedOnly))),
svc.WithHttp2Grpc(http2grpc),
svc.WithAllowGetWithReqBody(allowGetWithReqBody),
svc.WithCaseConverter(fn),
Expand All @@ -38,4 +39,5 @@ func init() {
grpcCmd.Flags().StringVar(&naming, "case", "lowerCamel", `protobuf message field naming strategy, only support "lowerCamel" and "snake"`)
grpcCmd.Flags().BoolVar(&http2grpc, "http2grpc", false, `whether need RESTful api for your grpc service`)
grpcCmd.Flags().BoolVar(&allowGetWithReqBody, "allowGetWithReqBody", false, "Whether allow get http request with request body.")
grpcCmd.Flags().BoolVar(&annotatedOnly, "annotatedOnly", false, "Whether generate grpc api only for method annotated with @grpc or not")
}
6 changes: 5 additions & 1 deletion cmd/internal/svc/codegen/grpcproto.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,11 @@ func GenGrpcProto(dir string, ic astutils.InterfaceCollector, p protov3.ProtoGen
service = p.NewService(svcname, servicePkg+"/transport/grpc")
service.Comments = ic.Interfaces[0].Comments
for _, method := range ic.Interfaces[0].Methods {
service.Rpcs = append(service.Rpcs, p.NewRpc(method))
rpc := p.NewRpc(method)
if rpc == nil {
continue
}
service.Rpcs = append(service.Rpcs, *rpc)
}
for k := range protov3.ImportStore {
service.Imports = append(service.Imports, k)
Expand Down
11 changes: 8 additions & 3 deletions cmd/internal/svc/svc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ package svc_test

import (
"fmt"
"github.com/iancoleman/strcase"
"github.com/unionj-cloud/go-doudou/v2/cmd/internal/svc/codegen"
"github.com/unionj-cloud/go-doudou/v2/cmd/internal/svc/parser"
v3 "github.com/unionj-cloud/go-doudou/v2/toolkit/protobuf/v3"
"os"
"os/exec"
"path/filepath"
Expand Down Expand Up @@ -297,11 +301,12 @@ func Test_checkIc_output_anonystruct(t *testing.T) {
},
},
}
dir := filepath.Join(testDir, "outputanonystruct")
pg := v3.NewProtoGenerator(v3.WithFieldNamingFunc(strcase.ToSnake))
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Panics(t, func() {
validate.RestApi(testDir, ic)
})
parser.ParseDtoGrpc(dir, pg, "dto")
codegen.GenGrpcProto(dir, ic, pg)
})
}
}
Expand Down
107 changes: 107 additions & 0 deletions cmd/internal/svc/testdata/outputanonystruct/dto/dto.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package dto

import "encoding/json"

//go:generate go-doudou name --file $GOFILE -o

// 筛选条件
type PageFilter struct {
// 真实姓名,前缀匹配
Name string
// 所属部门ID
Dept int
}

// 排序条件
type Order struct {
Col string
Sort string
}

type Page struct {
// 排序规则
Orders []Order
// 页码
PageNo int
// 每页行数
Size int
User UserVo
}

// 分页筛选条件
type PageQuery struct {
Filter PageFilter
Page Page
Options []struct {
Label string `json:"label" form:"label"`
Value string `json:"value" form:"value"`
} `json:"options" form:"options"`
}

type PageRet struct {
Items interface{}
PageNo int
PageSize int
Total int
HasNext bool
}

type UserVo struct {
Id int
Name string
Phone string
Dept string
}

type KeyboardLayout int

const (
UNKNOWN KeyboardLayout = iota
QWERTZ
AZERTY
QWERTY
)

func (k *KeyboardLayout) StringSetter(value string) {
switch value {
case "UNKNOWN":
*k = UNKNOWN
case "QWERTY":
*k = QWERTY
case "QWERTZ":
*k = QWERTZ
case "AZERTY":
*k = AZERTY
default:
*k = UNKNOWN
}
}

func (k *KeyboardLayout) StringGetter() string {
switch *k {
case UNKNOWN:
return "UNKNOWN"
case QWERTY:
return "QWERTY"
case QWERTZ:
return "QWERTZ"
case AZERTY:
return "AZERTY"
default:
return "UNKNOWN"
}
}

func (k *KeyboardLayout) UnmarshalJSON(bytes []byte) error {
var _k string
err := json.Unmarshal(bytes, &_k)
if err != nil {
return err
}
k.StringSetter(_k)
return nil
}

func (k KeyboardLayout) MarshalJSON() ([]byte, error) {
return json.Marshal(k.StringGetter())
}
11 changes: 2 additions & 9 deletions cmd/internal/svc/testdata/outputanonystruct/svc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,12 @@ package service

import (
"context"

"github.com/unionj-cloud/go-doudou/v2/framework/testdata/vo"
"github.com/unionj-cloud/go-doudou/v2/cmd/internal/svc/testdata/outputanonystruct/dto"
)

// 用户服务接口
// v1版本
type Usersvc interface {
// You can define your service methods as your need. Below is an example.
PageUsers(ctx context.Context, query vo.PageQuery) (code int, data struct {
Items interface{}
PageNo int
PageSize int
Total int
HasNext bool
}, msg error)
PageUsers(ctx context.Context, query dto.PageQuery) (page dto.Page, msg error)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Generated by go-doudou v2.4.2.
* Don't edit!
*
* Version No.: v20240918
*/
syntax = "proto3";

package usersvc;
option go_package = "github.com/unionj-cloud/go-doudou/v2/cmd/internal/svc/testdata/outputanonystruct/transport/grpc";

import "google/protobuf/any.proto";

enum KeyboardLayout {
UNKNOWN = 0;
QWERTZ = 1;
AZERTY = 2;
QWERTY = 3;
}

message Anonystructkfvagz8uXPWVpn5z9xyjWS {
optional string label = 1 [json_name="label"];
optional string value = 2 [json_name="value"];
}

// 排序条件
message Order {
optional string col = 1 [json_name="col"];
optional string sort = 2 [json_name="sort"];
}

message Page {
// 排序规则
repeated Order orders = 1 [json_name="orders"];
// 页码
optional int32 page_no = 2 [json_name="page_no"];
// 每页行数
optional int32 size = 3 [json_name="size"];
optional UserVo user = 4 [json_name="user"];
}

// 筛选条件
message PageFilter {
// 真实姓名,前缀匹配
optional string name = 1 [json_name="name"];
// 所属部门ID
optional int32 dept = 2 [json_name="dept"];
}

// 分页筛选条件
message PageQuery {
optional PageFilter filter = 1 [json_name="filter"];
optional Page page = 2 [json_name="page"];
repeated Anonystructkfvagz8uXPWVpn5z9xyjWS options = 3 [json_name="options"];
}

message PageRet {
optional google.protobuf.Any items = 1 [json_name="items"];
optional int32 page_no = 2 [json_name="page_no"];
optional int32 page_size = 3 [json_name="page_size"];
optional int32 total = 4 [json_name="total"];
optional bool has_next = 5 [json_name="has_next"];
}

message UserVo {
optional int32 id = 1 [json_name="id"];
optional string name = 2 [json_name="name"];
optional string phone = 3 [json_name="phone"];
optional string dept = 4 [json_name="dept"];
}

service UsersvcService {
// You can define your service methods as your need. Below is an example.
rpc PageUsersRpc(PageQuery) returns (Page);
}
8 changes: 6 additions & 2 deletions framework/testdata/vo/vo.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ type Page struct {

// 分页筛选条件
type PageQuery struct {
Filter PageFilter
Page Page
Filter PageFilter
Page Page
Options []struct {
Label string `json:"label" form:"label"`
Value string `json:"value" form:"value"`
} `json:"options" form:"options"`
}

type PageRet struct {
Expand Down
13 changes: 10 additions & 3 deletions toolkit/protobuf/v3/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"encoding/json"
"fmt"
"github.com/goccy/go-reflect"
"github.com/lithammer/shortuuid/v4"
log "github.com/sirupsen/logrus"
"regexp"
"strings"
"unicode"
Expand Down Expand Up @@ -242,11 +244,13 @@ func (receiver ProtoGenerator) handleDefaultCase(ft string) ProtobufType {
key := ft[4:strings.Index(ft, "]")]
keyMessage := receiver.MessageOf(key)
if reflect.DeepEqual(keyMessage, Float) || reflect.DeepEqual(keyMessage, Double) || reflect.DeepEqual(keyMessage, Bytes) {
panic("floating point types and bytes cannot be key_type of maps, please refer to https://developers.google.com/protocol-buffers/docs/proto3#maps")
log.Error("floating point types and bytes cannot be key_type of maps, please refer to https://developers.google.com/protocol-buffers/docs/proto3#maps")
return Any
}
elemMessage := receiver.MessageOf(elem)
if strings.HasPrefix(elemMessage.GetName(), "map<") {
panic("the value_type cannot be another map, please refer to https://developers.google.com/protocol-buffers/docs/proto3#maps")
log.Error("the value_type cannot be another map, please refer to https://developers.google.com/protocol-buffers/docs/proto3#maps")
return Any
}
return Message{
Name: fmt.Sprintf("map<%s, %s>", keyMessage.GetName(), elemMessage.GetName()),
Expand All @@ -257,7 +261,8 @@ func (receiver ProtoGenerator) handleDefaultCase(ft string) ProtobufType {
elem := ft[strings.Index(ft, "]")+1:]
elemMessage := receiver.MessageOf(elem)
if strings.HasPrefix(elemMessage.GetName(), "map<") {
panic("map fields cannot be repeated, please refer to https://developers.google.com/protocol-buffers/docs/proto3#maps")
log.Error("map fields cannot be repeated, please refer to https://developers.google.com/protocol-buffers/docs/proto3#maps")
return Any
}
messageName := elemMessage.GetName()
if strings.Contains(elemMessage.GetName(), "repeated ") {
Expand Down Expand Up @@ -289,6 +294,8 @@ func (receiver ProtoGenerator) handleDefaultCase(ft string) ProtobufType {
message := receiver.NewMessage(structmeta)
message.IsInner = true
message.IsTopLevel = false
message.Name = "Anonystruct" + shortuuid.NewWithNamespace(result[1])
MessageStore[message.Name] = message
return message
}
var title string
Expand Down
19 changes: 17 additions & 2 deletions toolkit/protobuf/v3/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package v3
import (
"fmt"
"github.com/goccy/go-reflect"
"github.com/samber/lo"
"strings"
"time"

Expand All @@ -15,6 +16,7 @@ import (
type ProtoGenerator struct {
fieldNamingFunc func(string) string
Structs []astutils.StructMeta
annotatedOnly bool
}

type ProtoGeneratorOption func(*ProtoGenerator)
Expand All @@ -25,6 +27,12 @@ func WithFieldNamingFunc(fn func(string) string) ProtoGeneratorOption {
}
}

func WithAnnotatedOnly(annotatedOnly bool) ProtoGeneratorOption {
return func(p *ProtoGenerator) {
p.annotatedOnly = annotatedOnly
}
}

func NewProtoGenerator(options ...ProtoGeneratorOption) ProtoGenerator {
var p ProtoGenerator
p.Structs = make([]astutils.StructMeta, 0)
Expand Down Expand Up @@ -78,7 +86,14 @@ type Rpc struct {
StreamType StreamType
}

func (receiver ProtoGenerator) NewRpc(method astutils.MethodMeta) Rpc {
func (receiver ProtoGenerator) NewRpc(method astutils.MethodMeta) *Rpc {
if receiver.annotatedOnly {
if lo.CountBy(method.Comments, func(item string) bool {
return strings.Contains(item, "@grpc")
}) == 0 {
return nil
}
}
rpcName := strcase.ToCamel(method.Name) + "Rpc"
rpcRequest := receiver.newRequest(rpcName, method.Params)
if reflect.DeepEqual(rpcRequest, Empty) {
Expand Down Expand Up @@ -106,7 +121,7 @@ func (receiver ProtoGenerator) NewRpc(method astutils.MethodMeta) Rpc {
} else if strings.HasPrefix(rpcResponse.Name, "stream ") {
st = serverStream
}
return Rpc{
return &Rpc{
Name: rpcName,
Request: rpcRequest,
Response: rpcResponse,
Expand Down

0 comments on commit 6b04728

Please sign in to comment.