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) }