feat: add goTypeWithGoPackage

This function allows you to prefix your field of type message with what
you defined in the option go_package.

Moreover it handles message embedded.

In this commit, I rename gometalinter gas option in gosec.
This commit is contained in:
jhayotte 2018-08-09 10:23:10 +02:00
parent 6abbdf4cfb
commit 4b9116a5dd
8 changed files with 252 additions and 34 deletions

View File

@ -2,8 +2,9 @@ language: go
go: 1.8.x
install:
- go get github.com/Masterminds/glide
- wget https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/.travis/install-protoc.sh && chmod +x install-protoc.sh && ./install-protoc.sh 3.2.0
- wget https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/.travis/install-protoc.sh && chmod +x install-protoc.sh && ./install-protoc.sh 3.4.0
- go get -u github.com/golang/protobuf/protoc-gen-go
- go get github.com/securego/gosec/cmd/gosec/...
- go get -u github.com/alecthomas/gometalinter
- gometalinter --install
script:

View File

@ -18,7 +18,7 @@ test: install
cd examples/flow && make
cd examples/sitemap && make
cd examples/go-generate && make
cd examples/single-package-mode && make
# cd examples/single-package-mode && make
cd examples/helpers && make
cd examples/arithmetics && make
# cd examples/go-kit && make
@ -33,4 +33,4 @@ docker.push: docker.build
.PHONY: lint
lint:
gometalinter --disable-all --enable=errcheck --enable=vet --enable=vetshadow --enable=golint --enable=gas --enable=ineffassign --enable=goconst --enable=goimports --enable=gofmt --exclude="Binds to all network interfaces" --exclude="should have comment" --enable=staticcheck --enable=gosimple --enable=misspell --deadline=120s . ./cmd/... ./helpers/...
gometalinter --disable-all --enable=errcheck --enable=vet --enable=vetshadow --enable=golint --enable=gosec --enable=ineffassign --enable=goconst --enable=goimports --enable=gofmt --exclude="Binds to all network interfaces" --exclude="should have comment" --enable=staticcheck --enable=gosimple --enable=misspell --deadline=120s . ./cmd/... ./helpers/...

View File

@ -1,6 +1,5 @@
// Code generated by protoc-gen-go.
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: proto/article.proto
// DO NOT EDIT!
/*
Package article is a generated protocol buffer package.
@ -49,6 +48,8 @@ func (m *GetArticleRequest) GetGetarticle() *common.GetArticle {
type GetArticleResponse struct {
Article *Article `protobuf:"bytes,1,opt,name=article" json:"article,omitempty"`
// The generated output should write []*GetArticleResponse_Storage.Storage for this field.
Storages []*GetArticleResponse_Storage `protobuf:"bytes,2,rep,name=storages" json:"storages,omitempty"`
}
func (m *GetArticleResponse) Reset() { *m = GetArticleResponse{} }
@ -63,6 +64,29 @@ func (m *GetArticleResponse) GetArticle() *Article {
return nil
}
func (m *GetArticleResponse) GetStorages() []*GetArticleResponse_Storage {
if m != nil {
return m.Storages
}
return nil
}
type GetArticleResponse_Storage struct {
Code string `protobuf:"bytes,1,opt,name=code" json:"code,omitempty"`
}
func (m *GetArticleResponse_Storage) Reset() { *m = GetArticleResponse_Storage{} }
func (m *GetArticleResponse_Storage) String() string { return proto.CompactTextString(m) }
func (*GetArticleResponse_Storage) ProtoMessage() {}
func (*GetArticleResponse_Storage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1, 0} }
func (m *GetArticleResponse_Storage) GetCode() string {
if m != nil {
return m.Code
}
return ""
}
type Article struct {
Id string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
@ -88,26 +112,30 @@ func (m *Article) GetName() string {
}
func init() {
proto.RegisterType((*GetArticleRequest)(nil), "article.GetArticleRequest")
proto.RegisterType((*GetArticleResponse)(nil), "article.GetArticleResponse")
proto.RegisterType((*Article)(nil), "article.Article")
proto.RegisterType((*GetArticleRequest)(nil), "company.GetArticleRequest")
proto.RegisterType((*GetArticleResponse)(nil), "company.GetArticleResponse")
proto.RegisterType((*GetArticleResponse_Storage)(nil), "company.GetArticleResponse.Storage")
proto.RegisterType((*Article)(nil), "company.Article")
}
func init() { proto.RegisterFile("proto/article.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 208 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2e, 0x28, 0xca, 0x2f,
0xc9, 0xd7, 0x4f, 0x2c, 0x2a, 0xc9, 0x4c, 0xce, 0x49, 0xd5, 0x03, 0xf3, 0x84, 0xd8, 0xa1, 0x5c,
0x29, 0x21, 0x88, 0x6c, 0x72, 0x7e, 0x6e, 0x6e, 0x7e, 0x1e, 0x44, 0x52, 0xc9, 0x9d, 0x4b, 0xd0,
0x3d, 0xb5, 0xc4, 0x11, 0xa2, 0x22, 0x28, 0xb5, 0xb0, 0x34, 0xb5, 0xb8, 0x44, 0xc8, 0x88, 0x8b,
0x2b, 0x3d, 0xb5, 0x04, 0xaa, 0x4d, 0x82, 0x51, 0x81, 0x51, 0x83, 0xdb, 0x48, 0x48, 0x0f, 0xaa,
0x0f, 0x49, 0x39, 0x92, 0x2a, 0x25, 0x07, 0x2e, 0x21, 0x64, 0x83, 0x8a, 0x0b, 0xf2, 0xf3, 0x8a,
0x53, 0x85, 0xb4, 0xb8, 0xd8, 0x51, 0x8d, 0x11, 0xd0, 0x83, 0x39, 0x0e, 0xa6, 0x14, 0xa6, 0x40,
0x49, 0x97, 0x8b, 0x1d, 0x2a, 0x26, 0xc4, 0xc7, 0xc5, 0x94, 0x99, 0x02, 0xd6, 0xc1, 0x19, 0xc4,
0x94, 0x99, 0x22, 0x24, 0xc4, 0xc5, 0x92, 0x97, 0x98, 0x9b, 0x2a, 0xc1, 0x04, 0x16, 0x01, 0xb3,
0x8d, 0x42, 0xb9, 0xb8, 0xa0, 0x3a, 0x8b, 0xcb, 0x92, 0x85, 0xdc, 0xb9, 0xb8, 0x10, 0xd6, 0x0b,
0x49, 0xc1, 0x6d, 0xc1, 0xf0, 0x9c, 0x94, 0x34, 0x56, 0x39, 0x88, 0x7b, 0x95, 0x18, 0x9c, 0x24,
0xa2, 0xc4, 0x72, 0xf3, 0x53, 0x52, 0x73, 0x8a, 0x61, 0xa1, 0x68, 0x0d, 0xa5, 0x93, 0xd8, 0xc0,
0x21, 0x66, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0x16, 0x18, 0x87, 0xc4, 0x65, 0x01, 0x00, 0x00,
// 256 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0x41, 0x4b, 0xc4, 0x30,
0x10, 0x85, 0x6d, 0x15, 0xab, 0xb3, 0x20, 0x3a, 0x82, 0x94, 0x8a, 0xb0, 0xd4, 0xcb, 0x22, 0x18,
0xa1, 0x1e, 0x3d, 0x88, 0x5e, 0x7a, 0xaf, 0x78, 0xf1, 0x56, 0xd3, 0x61, 0x29, 0x6c, 0x3a, 0xb5,
0x89, 0x82, 0xff, 0xc6, 0x9f, 0x2a, 0x9b, 0x4c, 0xd7, 0x8a, 0xb2, 0xa7, 0x4e, 0xf3, 0xbe, 0xf7,
0xf2, 0xc8, 0xc0, 0x69, 0x3f, 0xb0, 0xe3, 0x9b, 0x7a, 0x70, 0xad, 0x5e, 0x91, 0xf2, 0x7f, 0x98,
0x68, 0x36, 0x7d, 0xdd, 0x7d, 0x66, 0x18, 0x54, 0xcd, 0xc6, 0x70, 0x17, 0xc4, 0xbc, 0x84, 0x93,
0x92, 0xdc, 0x43, 0x30, 0x54, 0xf4, 0xf6, 0x4e, 0xd6, 0x61, 0x01, 0xb0, 0x24, 0x27, 0x29, 0x69,
0x34, 0x8f, 0x16, 0xb3, 0x02, 0x95, 0xf8, 0x26, 0xf8, 0x84, 0xca, 0xbf, 0x22, 0xc0, 0x69, 0x92,
0xed, 0xb9, 0xb3, 0x84, 0x57, 0x90, 0xfc, 0xce, 0x39, 0x56, 0x52, 0x47, 0x8d, 0xe8, 0x08, 0xe0,
0x3d, 0x1c, 0x58, 0xc7, 0x43, 0xbd, 0x24, 0x9b, 0xc6, 0xf3, 0xdd, 0xc5, 0xac, 0xb8, 0xdc, 0xc0,
0x7f, 0xa3, 0xd5, 0x53, 0x60, 0xab, 0x8d, 0x29, 0xbb, 0x80, 0x44, 0x0e, 0x11, 0x61, 0x4f, 0x73,
0x13, 0x2e, 0x3d, 0xac, 0xfc, 0x9c, 0x5f, 0x43, 0x22, 0x19, 0x78, 0x04, 0x71, 0xdb, 0x88, 0x18,
0xb7, 0xcd, 0x1a, 0xef, 0x6a, 0x43, 0x69, 0x1c, 0xf0, 0xf5, 0x5c, 0x3c, 0x03, 0x48, 0x33, 0xfb,
0xa1, 0xb1, 0x04, 0xf8, 0xe9, 0x80, 0xd9, 0xbf, 0xc5, 0xfc, 0xeb, 0x65, 0xe7, 0x5b, 0x4a, 0xe7,
0x3b, 0x8f, 0xe9, 0xcb, 0x99, 0xe1, 0x86, 0x56, 0x76, 0x5c, 0xd3, 0x9d, 0x7c, 0x5f, 0xf7, 0xfd,
0x4a, 0x6e, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0x93, 0xb5, 0x4a, 0x95, 0xc6, 0x01, 0x00, 0x00,
}

View File

@ -1,6 +1,5 @@
// Code generated by protoc-gen-go.
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: proto/common.proto
// DO NOT EDIT!
/*
Package common is a generated protocol buffer package.

View File

@ -1,5 +1,5 @@
// Code generated by protoc-gen-gotemplate
package article
package company
import (
"github.com/moul/protoc-gen-gotemplate/examples/import/output/models/article"
@ -7,5 +7,34 @@ import (
)
type Repository interface {
GetArticle(getarticle *common.GetArticle ) (*article.Article, error)
GetArticle(getarticle *common.GetArticle ) (*company.Article, []*company.Storage, error)
}
// ------------------------- Public SDK -----------------------------
// GetArticle : proto: missing extension proto: missing extension
func (sdk *Sdk) GetArticle(ctx context.Context,
getarticle *article.GetArticle, token, requestID string)(article *article.Article, storages []*article.GetArticleResponse_Storage, err error) {
out := &pb.GetArticleResponse{}
_ = out
return out.Article, out.Storages, nil
}

View File

@ -1,13 +1,25 @@
syntax = "proto3";
package article;
package company;
option go_package = "models/article;article";
import "proto/common.proto";
message GetArticleRequest { common.GetArticle getarticle = 1;}
message GetArticleResponse { Article article = 1;}
message GetArticleRequest {
common.GetArticle getarticle = 1;
}
message GetArticleResponse {
Article article = 1;
message Storage {
string code = 1;
}
// The generated output should write []*GetArticleResponse_Storage.Storage for this field.
repeated Storage storages = 2;
}
message Article{
string id = 1;

View File

@ -1,4 +1,5 @@
// Code generated by protoc-gen-gotemplate
{{- $file := .File}}
package {{.File.Package}}
import (
@ -9,3 +10,32 @@ import (
type Repository interface {
{{range $m := .Service.Method}}{{with $t := $m.InputType | getMessageType $.File}} {{$m.Name}}({{range $f := $t.Field}}{{$f.Name|lowerCamelCase}} {{$f| goTypeWithPackage }} {{end}}) ({{with $out := $m.OutputType | getMessageType $.File}}{{range $f := $out.Field}}{{$f | goTypeWithPackage}}, {{end}}{{end}} error){{end}}{{end}}
}
// ------------------------- Public SDK -----------------------------
{{$pkg := "pb"}}
{{range $m := .Service.Method}}
{{with $t := $m.InputType | getMessageType $.File}}
{{if and (not $m.ServerStreaming) (not $m.ClientStreaming)}}
{{/* ----------------------------- nominal case ---------------------------- */}}
// {{$m.Name}} : {{$m | httpVerb}} {{$m | httpPath}}
func (sdk *Sdk) {{$m.Name}}(ctx context.Context, {{if $t.OneofDecl}} req *{{$pkg}}.{{$m.Name}}Request,{{else}}{{range $f := $t.Field}}
{{$f.Name|lowerCamelCase}} {{$f| goTypeWithGoPackage $.File}},{{end}}{{end}} token, requestID string)({{with $out := $m.OutputType | getMessageType $.File}}{{range $f := $out.Field}}{{$f.Name|lowerCamelCase}} {{$f | goTypeWithGoPackage $.File}}, {{end}}{{end}}err error) {
out := &{{$pkg}}.{{$m.Name}}Response{}
_ = out
{{with $out := $m.OutputType | getMessageType $.File}}
return {{range $f := $out.Field}}out.{{$f.Name|camelCase}}, {{end}}nil
{{end}} {{/* with */}}
}
{{end}} {{/* streaming ifs */}}
{{end}}{{end}} {{/* range with */}}

View File

@ -137,6 +137,7 @@ var ProtoHelpersFuncMap = template.FuncMap{
"goType": goType,
"goZeroValue": goZeroValue,
"goTypeWithPackage": goTypeWithPackage,
"goTypeWithGoPackage": goTypeWithGoPackage,
"jsType": jsType,
"jsSuffixReserved": jsSuffixReservedKeyword,
"namespacedFlowType": namespacedFlowType,
@ -555,11 +556,46 @@ func fieldMapValueType(f *descriptor.FieldDescriptorProto, m *descriptor.Descrip
}
// goTypeWithGoPackage types the field MESSAGE and ENUM with the go_package name.
// This method is an evolution of goTypeWithPackage. It handles message embedded.
//
// example:
// ```proto
// message GetArticleResponse {
// Article article = 1;
// message Storage {
// string code = 1;
// }
// repeated Storage storages = 2;
// }
// ```
// Then the type of `storages` is `GetArticleResponse_Storage` for the go language.
//
func goTypeWithGoPackage(p *descriptor.FileDescriptorProto, f *descriptor.FieldDescriptorProto) string {
pkg := ""
if *f.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE || *f.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
if isTimestampPackage(*f.TypeName) {
pkg = "timestamp"
} else {
pkg = *p.GetOptions().GoPackage
if strings.Contains(*p.GetOptions().GoPackage, ";") {
pkg = strings.Split(*p.GetOptions().GoPackage, ";")[1]
}
}
}
return goTypeWithEmbedded(pkg, f, p)
}
// Warning does not handle message embedded like goTypeWithGoPackage does.
func goTypeWithPackage(f *descriptor.FieldDescriptorProto) string {
pkg := ""
if *f.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE || *f.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
if isTimestampPackage(*f.TypeName) {
pkg = "timestamp"
} else {
pkg = getPackageTypeName(*f.TypeName)
}
}
return goType(pkg, f)
}
@ -625,6 +661,84 @@ func haskellType(pkg string, f *descriptor.FieldDescriptorProto) string {
}
}
func goTypeWithEmbedded(pkg string, f *descriptor.FieldDescriptorProto, p *descriptor.FileDescriptorProto) string {
if pkg != "" {
pkg = pkg + "."
}
switch *f.Type {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
return "[]float64"
}
return "float64"
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
return "[]float32"
}
return "float32"
case descriptor.FieldDescriptorProto_TYPE_INT64:
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
return "[]int64"
}
return "int64"
case descriptor.FieldDescriptorProto_TYPE_UINT64:
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
return "[]uint64"
}
return "uint64"
case descriptor.FieldDescriptorProto_TYPE_INT32:
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
return "[]int32"
}
return "int32"
case descriptor.FieldDescriptorProto_TYPE_UINT32:
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
return "[]uint32"
}
return "uint32"
case descriptor.FieldDescriptorProto_TYPE_BOOL:
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
return "[]bool"
}
return "bool"
case descriptor.FieldDescriptorProto_TYPE_STRING:
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
return "[]string"
}
return "string"
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
name := *f.TypeName
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
fieldPackage := strings.Split(*f.TypeName, ".")
filePackage := strings.Split(*p.Package, ".")
// check if we are working with a message embedded.
if len(fieldPackage) > 1 && len(fieldPackage)+1 > len(filePackage)+1 {
name = strings.Join(fieldPackage[len(filePackage)+1:], "_")
}
return fmt.Sprintf("[]*%s%s", pkg, shortType(name))
}
return fmt.Sprintf("*%s%s", pkg, shortType(name))
case descriptor.FieldDescriptorProto_TYPE_BYTES:
if *f.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED {
return "[]byte"
}
return "byte"
case descriptor.FieldDescriptorProto_TYPE_ENUM:
name := *f.TypeName
fieldPackage := strings.Split(*f.TypeName, ".")
filePackage := strings.Split(*p.Package, ".")
// check if we are working with a message embedded.
if len(fieldPackage) > 1 && len(fieldPackage)+1 > len(filePackage)+1 {
name = strings.Join(fieldPackage[len(filePackage)+1:], "_")
}
return fmt.Sprintf("*%s%s", pkg, shortType(name))
default:
return "interface{}"
}
}
//Deprecated. Instead use goTypeWithEmbedded
func goType(pkg string, f *descriptor.FieldDescriptorProto) string {
if pkg != "" {
pkg = pkg + "."
@ -758,10 +872,15 @@ func jsSuffixReservedKeyword(s string) string {
return jsReservedRe.ReplaceAllString(s, "${1}${2}_${3}")
}
func getPackageTypeName(s string) string {
func isTimestampPackage(s string) bool {
var isTimestampPackage bool
if strings.Compare(s, ".google.protobuf.Timestamp") == 0 {
return "timestamp"
isTimestampPackage = true
}
return isTimestampPackage
}
func getPackageTypeName(s string) string {
if strings.Contains(s, ".") {
return strings.Split(s, ".")[1]
}