func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool { used := false randPkg := imports.NewImport("math/rand") timePkg := imports.NewImport("time") testingPkg := imports.NewImport("testing") fmtPkg := imports.NewImport("fmt") for _, message := range file.Messages() { ccTypeName := generator.CamelCaseSlice(message.TypeName()) if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) { continue } if message.DescriptorProto.GetOptions().GetMapEntry() { continue } if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) { used = true p.P(`func Test`, ccTypeName, `Stringer(t *`, testingPkg.Use(), `.T) {`) p.In() p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`) p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`) p.P(`s1 := p.String()`) p.P(`s2 := `, fmtPkg.Use(), `.Sprintf("%v", p)`) p.P(`if s1 != s2 {`) p.In() p.P(`t.Fatalf("String want %v got %v", s1, s2)`) p.Out() p.P(`}`) p.Out() p.P(`}`) } } return used }
func (p *stringer) Generate(file *generator.FileDescriptor) { proto3 := gogoproto.IsProto3(file.FileDescriptorProto) p.PluginImports = generator.NewPluginImports(p.Generator) p.atleastOne = false p.localName = generator.FileName(file) fmtPkg := p.NewImport("fmt") stringsPkg := p.NewImport("strings") reflectPkg := p.NewImport("reflect") sortKeysPkg := p.NewImport("github.com/yoyowallet/protobuf/sortkeys") for _, message := range file.Messages() { if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) { continue } if gogoproto.EnabledGoStringer(file.FileDescriptorProto, message.DescriptorProto) { panic("old string method needs to be disabled, please use gogoproto.goproto_stringer or gogoproto.goproto_stringer_all and set it to false") } if message.DescriptorProto.GetOptions().GetMapEntry() { continue } p.atleastOne = true ccTypeName := generator.CamelCaseSlice(message.TypeName()) p.P(`func (this *`, ccTypeName, `) String() string {`) p.In() p.P(`if this == nil {`) p.In() p.P(`return "nil"`) p.Out() p.P(`}`) for _, field := range message.Field { if !generator.IsMap(file.FileDescriptorProto, field) { continue } fieldname := p.GetFieldName(message, field) mapMsg := generator.GetMap(file.FileDescriptorProto, field) keyField, valueField := mapMsg.GetMapFields() keysName := `keysFor` + fieldname keygoTyp, _ := p.GoType(nil, keyField) keygoTyp = strings.Replace(keygoTyp, "*", "", 1) keyCapTyp := generator.CamelCase(keygoTyp) valuegoTyp, _ := p.GoType(nil, valueField) p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`) p.P(`for k, _ := range this.`, fieldname, ` {`) p.In() p.P(keysName, ` = append(`, keysName, `, k)`) p.Out() p.P(`}`) p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`) mapName := `mapStringFor` + fieldname p.P(mapName, ` := "map[`, keygoTyp, `]`, valuegoTyp, `{"`) p.P(`for _, k := range `, keysName, ` {`) p.In() p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[k])`) p.Out() p.P(`}`) p.P(mapName, ` += "}"`) } p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,") oneofs := make(map[string]struct{}) for _, field := range message.Field { nullable := gogoproto.IsNullable(field) repeated := field.IsRepeated() fieldname := p.GetFieldName(message, field) oneof := field.OneofIndex != nil if oneof { if _, ok := oneofs[fieldname]; ok { continue } else { oneofs[fieldname] = struct{}{} } p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,") } else if generator.IsMap(file.FileDescriptorProto, field) { mapName := `mapStringFor` + fieldname p.P("`", fieldname, ":`", ` + `, mapName, " + `,", "`,") } else if field.IsMessage() || p.IsGroup(field) { desc := p.ObjectNamed(field.GetTypeName()) msgname := p.TypeName(desc) msgnames := strings.Split(msgname, ".") typeName := msgnames[len(msgnames)-1] if nullable { p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,") } else if repeated { p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1) + `,", "`,") } else { p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(this.`, fieldname, `.String(), "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1) + `,", "`,") } } else { if nullable && !repeated && !proto3 { p.P("`", fieldname, ":`", ` + valueToString`, p.localName, `(this.`, fieldname, ") + `,", "`,") } else { p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,") } } } if message.DescriptorProto.HasExtension() { if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) { p.P("`XXX_extensions:` + proto.StringFromExtensionsMap(this.XXX_extensions) + `,`,") } else { p.P("`XXX_extensions:` + proto.StringFromExtensionsBytes(this.XXX_extensions) + `,`,") } } if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) { p.P("`XXX_unrecognized:` + ", fmtPkg.Use(), `.Sprintf("%v", this.XXX_unrecognized) + `, "`,`,") } p.P("`}`,") p.P(`}`, `,""`, ")") p.P(`return s`) p.Out() p.P(`}`) //Generate String methods for oneof fields for _, field := range message.Field { oneof := field.OneofIndex != nil if !oneof { continue } ccTypeName := p.OneOfTypeName(message, field) p.P(`func (this *`, ccTypeName, `) String() string {`) p.In() p.P(`if this == nil {`) p.In() p.P(`return "nil"`) p.Out() p.P(`}`) p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,") fieldname := p.GetOneOfFieldName(message, field) if field.IsMessage() || p.IsGroup(field) { desc := p.ObjectNamed(field.GetTypeName()) msgname := p.TypeName(desc) msgnames := strings.Split(msgname, ".") typeName := msgnames[len(msgnames)-1] p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,") } else { p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,") } p.P("`}`,") p.P(`}`, `,""`, ")") p.P(`return s`) p.Out() p.P(`}`) } } if !p.atleastOne { return } p.P(`func valueToString`, p.localName, `(v interface{}) string {`) p.In() p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`) p.P(`if rv.IsNil() {`) p.In() p.P(`return "nil"`) p.Out() p.P(`}`) p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`) p.P(`return `, fmtPkg.Use(), `.Sprintf("*%v", pv)`) p.Out() p.P(`}`) }