123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- // Copyright (C) 2020 The Syncthing Authors.
- //
- // This Source Code Form is subject to the terms of the Mozilla Public
- // License, v. 2.0. If a copy of the MPL was not distributed with this file,
- // You can obtain one at https://mozilla.org/MPL/2.0/.
- //go:build ignore
- // +build ignore
- package main
- import (
- "fmt"
- "path/filepath"
- "strings"
- "unicode"
- "github.com/syncthing/syncthing/proto/ext"
- "github.com/gogo/protobuf/gogoproto"
- "github.com/gogo/protobuf/proto"
- "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
- "github.com/gogo/protobuf/vanity"
- "github.com/gogo/protobuf/vanity/command"
- )
- func main() {
- req := command.Read()
- files := req.GetProtoFile()
- files = vanity.FilterFiles(files, vanity.NotGoogleProtobufDescriptorProto)
- vanity.ForEachFile(files, vanity.TurnOffGoGettersAll)
- vanity.ForEachFile(files, TurnOnProtoSizerAll)
- vanity.ForEachFile(files, vanity.TurnOffGoEnumPrefixAll)
- vanity.ForEachFile(files, vanity.TurnOffGoUnrecognizedAll)
- vanity.ForEachFile(files, vanity.TurnOffGoUnkeyedAll)
- vanity.ForEachFile(files, vanity.TurnOffGoSizecacheAll)
- vanity.ForEachFile(files, vanity.TurnOnMarshalerAll)
- vanity.ForEachFile(files, vanity.TurnOnUnmarshalerAll)
- vanity.ForEachEnumInFiles(files, HandleCustomEnumExtensions)
- vanity.ForEachFile(files, SetPackagePrefix("github.com/syncthing/syncthing"))
- vanity.ForEachFile(files, HandleFile)
- vanity.ForEachFieldInFilesExcludingExtensions(files, TurnOffNullableForMessages)
- resp := command.Generate(req)
- command.Write(resp)
- }
- func TurnOnProtoSizerAll(file *descriptor.FileDescriptorProto) {
- vanity.SetBoolFileOption(gogoproto.E_ProtosizerAll, true)(file)
- }
- func TurnOffNullableForMessages(field *descriptor.FieldDescriptorProto) {
- if !vanity.FieldHasBoolExtension(field, gogoproto.E_Nullable) {
- _, hasCustomType := GetFieldStringExtension(field, gogoproto.E_Customtype)
- if field.IsMessage() || hasCustomType {
- vanity.SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
- }
- }
- }
- func HandleCustomEnumExtensions(enum *descriptor.EnumDescriptorProto) {
- for _, field := range enum.Value {
- if field == nil {
- continue
- }
- if field.Options == nil {
- field.Options = &descriptor.EnumValueOptions{}
- }
- customName := gogoproto.GetEnumValueCustomName(field)
- if customName != "" {
- continue
- }
- if v, ok := GetEnumValueStringExtension(field, ext.E_Enumgoname); ok {
- SetEnumValueStringFieldOption(field, gogoproto.E_EnumvalueCustomname, v)
- } else {
- SetEnumValueStringFieldOption(field, gogoproto.E_EnumvalueCustomname, toCamelCase(*field.Name, true))
- }
- }
- }
- func SetPackagePrefix(prefix string) func(file *descriptor.FileDescriptorProto) {
- return func(file *descriptor.FileDescriptorProto) {
- if file.Options.GoPackage == nil {
- pkg, _ := filepath.Split(file.GetName())
- fullPkg := prefix + "/" + strings.TrimSuffix(pkg, "/")
- file.Options.GoPackage = &fullPkg
- }
- }
- }
- func toCamelCase(input string, firstUpper bool) string {
- runes := []rune(strings.ToLower(input))
- outputRunes := make([]rune, 0, len(runes))
- nextUpper := false
- for i, rune := range runes {
- if rune == '_' {
- nextUpper = true
- continue
- }
- if (firstUpper && i == 0) || nextUpper {
- rune = unicode.ToUpper(rune)
- nextUpper = false
- }
- outputRunes = append(outputRunes, rune)
- }
- return string(outputRunes)
- }
- func SetStringFieldOption(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc, value string) {
- if _, ok := GetFieldStringExtension(field, extension); ok {
- return
- }
- if field.Options == nil {
- field.Options = &descriptor.FieldOptions{}
- }
- if err := proto.SetExtension(field.Options, extension, &value); err != nil {
- panic(err)
- }
- }
- func SetEnumValueStringFieldOption(field *descriptor.EnumValueDescriptorProto, extension *proto.ExtensionDesc, value string) {
- if _, ok := GetEnumValueStringExtension(field, extension); ok {
- return
- }
- if field.Options == nil {
- field.Options = &descriptor.EnumValueOptions{}
- }
- if err := proto.SetExtension(field.Options, extension, &value); err != nil {
- panic(err)
- }
- }
- func GetEnumValueStringExtension(enumValue *descriptor.EnumValueDescriptorProto, extension *proto.ExtensionDesc) (string, bool) {
- if enumValue.Options == nil {
- return "", false
- }
- value, err := proto.GetExtension(enumValue.Options, extension)
- if err != nil {
- return "", false
- }
- if value == nil {
- return "", false
- }
- if v, ok := value.(*string); !ok || v == nil {
- return "", false
- } else {
- return *v, true
- }
- }
- func GetFieldStringExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) (string, bool) {
- if field.Options == nil {
- return "", false
- }
- value, err := proto.GetExtension(field.Options, extension)
- if err != nil {
- return "", false
- }
- if value == nil {
- return "", false
- }
- if v, ok := value.(*string); !ok || v == nil {
- return "", false
- } else {
- return *v, true
- }
- }
- func GetFieldBooleanExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) (bool, bool) {
- if field.Options == nil {
- return false, false
- }
- value, err := proto.GetExtension(field.Options, extension)
- if err != nil {
- return false, false
- }
- if value == nil {
- return false, false
- }
- if v, ok := value.(*bool); !ok || v == nil {
- return false, false
- } else {
- return *v, true
- }
- }
- func GetMessageBoolExtension(msg *descriptor.DescriptorProto, extension *proto.ExtensionDesc) (bool, bool) {
- if msg.Options == nil {
- return false, false
- }
- value, err := proto.GetExtension(msg.Options, extension)
- if err != nil {
- return false, false
- }
- if value == nil {
- return false, false
- }
- val, ok := value.(*bool)
- if !ok || val == nil {
- return false, false
- }
- return *val, true
- }
- func HandleFile(file *descriptor.FileDescriptorProto) {
- vanity.ForEachMessageInFiles([]*descriptor.FileDescriptorProto{file}, HandleCustomExtensions(file))
- }
- func HandleCustomExtensions(file *descriptor.FileDescriptorProto) func(msg *descriptor.DescriptorProto) {
- return func(msg *descriptor.DescriptorProto) {
- generateXmlTags := true
- if generate, ok := GetMessageBoolExtension(msg, ext.E_XmlTags); ok {
- generateXmlTags = generate
- }
- vanity.ForEachField([]*descriptor.DescriptorProto{msg}, func(field *descriptor.FieldDescriptorProto) {
- if field.Options == nil {
- field.Options = &descriptor.FieldOptions{}
- }
- deprecated := field.Options.Deprecated != nil && *field.Options.Deprecated == true
- if field.Type != nil && *field.Type == descriptor.FieldDescriptorProto_TYPE_INT32 {
- SetStringFieldOption(field, gogoproto.E_Casttype, "int")
- }
- if field.TypeName != nil && *field.TypeName == ".google.protobuf.Timestamp" {
- vanity.SetBoolFieldOption(gogoproto.E_Stdtime, true)(field)
- }
- if goName, ok := GetFieldStringExtension(field, ext.E_Goname); ok {
- SetStringFieldOption(field, gogoproto.E_Customname, goName)
- } else if deprecated {
- SetStringFieldOption(field, gogoproto.E_Customname, "Deprecated"+toCamelCase(*field.Name, true))
- }
- if goType, ok := GetFieldStringExtension(field, ext.E_Gotype); ok {
- SetStringFieldOption(field, gogoproto.E_Customtype, goType)
- }
- if val, ok := GetFieldBooleanExtension(field, ext.E_DeviceId); ok && val {
- if *file.Options.GoPackage != "github.com/syncthing/syncthing/lib/protocol" {
- SetStringFieldOption(field, gogoproto.E_Customtype, "github.com/syncthing/syncthing/lib/protocol.DeviceID")
- } else {
- SetStringFieldOption(field, gogoproto.E_Customtype, "DeviceID")
- }
- }
- if jsonValue, ok := GetFieldStringExtension(field, ext.E_Json); ok {
- SetStringFieldOption(field, gogoproto.E_Jsontag, jsonValue)
- } else if deprecated {
- SetStringFieldOption(field, gogoproto.E_Jsontag, "-")
- } else {
- SetStringFieldOption(field, gogoproto.E_Jsontag, toCamelCase(*field.Name, false))
- }
- current := ""
- if v, ok := GetFieldStringExtension(field, gogoproto.E_Moretags); ok {
- current = v
- }
- if generateXmlTags {
- if len(current) > 0 {
- current += " "
- }
- if xmlValue, ok := GetFieldStringExtension(field, ext.E_Xml); ok {
- current += fmt.Sprintf(`xml:"%s"`, xmlValue)
- } else {
- xmlValue = toCamelCase(*field.Name, false)
- // XML dictates element name within the collection, not collection name, so trim plural suffix.
- if field.IsRepeated() {
- if strings.HasSuffix(xmlValue, "ses") {
- // addresses -> address
- xmlValue = strings.TrimSuffix(xmlValue, "es")
- } else {
- // devices -> device
- xmlValue = strings.TrimSuffix(xmlValue, "s")
- }
- }
- if deprecated {
- xmlValue += ",omitempty"
- }
- current += fmt.Sprintf(`xml:"%s"`, xmlValue)
- }
- }
- if defaultValue, ok := GetFieldStringExtension(field, ext.E_Default); ok {
- if len(current) > 0 {
- current += " "
- }
- current += fmt.Sprintf(`default:"%s"`, defaultValue)
- }
- if nodefaultValue, ok := GetFieldBooleanExtension(field, ext.E_Nodefault); ok {
- if len(current) > 0 {
- current += " "
- }
- current += fmt.Sprintf(`nodefault:"%t"`, nodefaultValue)
- }
- if restartValue, ok := GetFieldBooleanExtension(field, ext.E_Restart); ok {
- if len(current) > 0 {
- current += " "
- }
- current += fmt.Sprintf(`restart:"%t"`, restartValue)
- }
- SetStringFieldOption(field, gogoproto.E_Moretags, current)
- })
- }
- }
|