func (p *plugin) Generate(file *generator.FileDescriptor) { proto3 := gogoproto.IsProto3(file.FileDescriptorProto) for _, msg := range file.Messages() { getters := gogoproto.HasGoGetters(file.FileDescriptorProto, msg.DescriptorProto) face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto) for _, field := range msg.GetField() { if len(field.GetDefaultValue()) > 0 { if !getters { fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value and not have a getter method", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) os.Exit(1) } if face { fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value be in a face", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) os.Exit(1) } } if gogoproto.IsNullable(field) { continue } if len(field.GetDefaultValue()) > 0 { fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and have a default value", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) os.Exit(1) } if !field.IsMessage() && !gogoproto.IsCustomType(field) { if field.IsRepeated() { fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a repeated non-nullable native type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) } else if proto3 { fmt.Fprintf(os.Stderr, "ERROR: field %v.%v is a native type and in proto3 syntax with nullable=false there exists conflicting implementations when encoding zero values", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) os.Exit(1) } if field.IsBytes() { fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a non-nullable bytes type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name)) } } if !field.IsEnum() { continue } enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor) if len(enum.Value) == 0 || enum.Value[0].GetNumber() != 0 { fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and be an enum type %v which does not start with zero", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name), enum.GetName()) os.Exit(1) } } } for _, e := range file.GetExtension() { if !gogoproto.IsNullable(e) { fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be nullable %v", generator.CamelCase(e.GetName()), generator.CamelCase(*e.Name)) os.Exit(1) } } }
func (p *plugin) Generate(file *generator.FileDescriptor) { p.PluginImports = generator.NewPluginImports(p.Generator) protoPkg := p.NewImport("limbo.services/protobuf/proto") if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) { protoPkg = p.NewImport("github.com/golang/protobuf/proto") } for _, message := range file.Messages() { if !gogoproto.IsFace(file.FileDescriptorProto, message.DescriptorProto) { continue } if message.DescriptorProto.GetOptions().GetMapEntry() { continue } if message.DescriptorProto.HasExtension() { panic("face does not support message with extensions") } if gogoproto.HasGoGetters(file.FileDescriptorProto, message.DescriptorProto) { panic("face requires getters to be disabled please use gogoproto.getters or gogoproto.getters_all and set it to false") } ccTypeName := generator.CamelCaseSlice(message.TypeName()) p.P(`type `, ccTypeName, `Face interface{`) p.In() p.P(`Proto() `, protoPkg.Use(), `.Message`) for _, field := range message.Field { fieldname := p.GetFieldName(message, field) goTyp, _ := p.GoType(message, field) if p.IsMap(field) { m := p.GoMapType(nil, field) goTyp = m.GoType } p.P(`Get`, fieldname, `() `, goTyp) } p.Out() p.P(`}`) p.P(``) p.P(`func (this *`, ccTypeName, `) Proto() `, protoPkg.Use(), `.Message {`) p.In() p.P(`return this`) p.Out() p.P(`}`) p.P(``) p.P(`func (this *`, ccTypeName, `) TestProto() `, protoPkg.Use(), `.Message {`) p.In() p.P(`return New`, ccTypeName, `FromFace(this)`) p.Out() p.P(`}`) p.P(``) for _, field := range message.Field { fieldname := p.GetFieldName(message, field) goTyp, _ := p.GoType(message, field) if p.IsMap(field) { m := p.GoMapType(nil, field) goTyp = m.GoType } p.P(`func (this *`, ccTypeName, `) Get`, fieldname, `() `, goTyp, `{`) p.In() p.P(` return this.`, fieldname) p.Out() p.P(`}`) p.P(``) } p.P(``) p.P(`func New`, ccTypeName, `FromFace(that `, ccTypeName, `Face) *`, ccTypeName, ` {`) p.In() p.P(`this := &`, ccTypeName, `{}`) for _, field := range message.Field { fieldname := p.GetFieldName(message, field) p.P(`this.`, fieldname, ` = that.Get`, fieldname, `()`) } p.P(`return this`) p.Out() p.P(`}`) p.P(``) } }