func (p *plugin) hasLoop(field *descriptor.FieldDescriptorProto, visited []*generator.Descriptor, excludes []*generator.Descriptor) *generator.Descriptor { if field.IsMessage() || p.IsGroup(field) || p.IsMap(field) { var fieldMessage *generator.Descriptor if p.IsMap(field) { m := p.GoMapType(nil, field) if !m.ValueField.IsMessage() { return nil } fieldMessage = p.ObjectNamed(m.ValueField.GetTypeName()).(*generator.Descriptor) } else { fieldMessage = p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor) } fieldTypeName := generator.CamelCaseSlice(fieldMessage.TypeName()) for _, message := range visited { messageTypeName := generator.CamelCaseSlice(message.TypeName()) if fieldTypeName == messageTypeName { for _, e := range excludes { if fieldTypeName == generator.CamelCaseSlice(e.TypeName()) { return nil } } return fieldMessage } } for _, f := range fieldMessage.Field { visited = append(visited, fieldMessage) loopTo := p.hasLoop(f, visited, excludes) if loopTo != nil { return loopTo } } } return nil }
func (g *validation) generateTests(msg *generator.Descriptor, field *pb.FieldDescriptorProto, fieldName string, idx int, patterns map[string]string) { if limbo.IsRequiredProperty(field) { g.generateRequiredTest(msg, field, fieldName) } if n, ok := limbo.GetMinItems(field); ok { g.generateMinItemsTest(msg, field, fieldName, int(n)) } if n, ok := limbo.GetMaxItems(field); ok { g.generateMaxItemsTest(msg, field, fieldName, int(n)) } if pattern, ok := limbo.GetPattern(field); ok { patternVar := fmt.Sprintf("valPattern_%s_%d", msg.GetName(), idx) patterns[patternVar] = pattern g.generatePatternTest(msg, field, fieldName, pattern, patternVar) } if n, ok := limbo.GetMinLength(field); ok { g.generateMinLengthTest(msg, field, fieldName, int(n)) } if n, ok := limbo.GetMaxLength(field); ok { g.generateMaxLengthTest(msg, field, fieldName, int(n)) } if field.GetType() == pb.FieldDescriptorProto_TYPE_MESSAGE { g.generateSubMessageTest(msg, field, fieldName) } }
func (p *plugin) checkNameSpace(message *generator.Descriptor) map[string]bool { ccTypeName := generator.CamelCaseSlice(message.TypeName()) names := make(map[string]bool) for _, field := range message.Field { fieldname := generator.CamelCase(*field.Name) if field.IsMessage() && gogoproto.IsEmbed(field) { desc := p.ObjectNamed(field.GetTypeName()) moreNames := p.checkNameSpace(desc.(*generator.Descriptor)) for another := range moreNames { if names[another] { fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName) os.Exit(1) } names[another] = true } } else { if names[fieldname] { fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName) os.Exit(1) } names[fieldname] = true } } return names }
func (g *svcauth) setMessage(inputType *generator.Descriptor, path, input, output string, inputIsNullable bool) { var ( goPath string outputIsNullable bool ) goPath = input if inputIsNullable { g.P(`if `, goPath, `== nil {`) g.P(goPath, `= &`, g.gen.TypeName(inputType), `{}`) g.P(`}`) } for path != "" { // split path part := path idx := strings.IndexByte(path, '.') if idx >= 0 { part = path[:idx] path = path[idx+1:] } else { path = "" } // Get Field field := inputType.GetFieldDescriptor(part) if field == nil { g.gen.Fail("unknown field", part, "in message", inputType.GetName()) } if !field.IsMessage() { g.gen.Fail("expected a message") } // Append code fieldGoName := g.gen.GetFieldName(inputType, field) goPath += "." + fieldGoName inputType = g.messages[strings.TrimPrefix(field.GetTypeName(), ".")] if gogoproto.IsNullable(field) && path != "" { g.P(`if `, goPath, `== nil {`) g.P(goPath, `= &`, g.gen.TypeName(inputType), `{}`) g.P(`}`) } if gogoproto.IsNullable(field) { outputIsNullable = true } else { outputIsNullable = false } } if outputIsNullable { g.P(goPath, ` = `, output) } else { g.P(goPath, ` = &`, output) } }
func (g *jsonschema) generateMessageSchema(file *generator.FileDescriptor, msg *generator.Descriptor, index int) { typeName := file.GetPackage() + "." + strings.Join(msg.TypeName(), ".") typeName = strings.TrimPrefix(typeName, ".") if g.definitions[typeName] == nil { def, deps := g.messageToSchema(file, msg) g.definitions[typeName] = def g.dependencies[typeName] = deps } }
func (g *validation) generateValidator(file *generator.FileDescriptor, msg *generator.Descriptor) { if msg.GetOptions().GetMapEntry() { return } g.P(`func (msg *`, g.gen.TypeName(msg), `) Validate() error {`) var patterns = map[string]string{} for idx, field := range msg.Field { if field.OneofIndex != nil { continue } fieldName := "msg." + g.gen.GetFieldName(msg, field) g.generateTests(msg, field, fieldName, idx, patterns) } for oneofIdx, oneof := range msg.OneofDecl { g.P(`switch c := msg.Get`, generator.CamelCase(oneof.GetName()), `().(type) {`) for idx, field := range msg.Field { if field.OneofIndex == nil { continue } if *field.OneofIndex != int32(oneofIdx) { continue } g.P(`case *`, g.gen.OneOfTypeName(msg, field), `:`) fieldName := "c." + g.gen.GetOneOfFieldName(msg, field) g.generateTests(msg, field, fieldName, idx, patterns) } g.P(`}`) } g.P(`return nil`) g.P(`}`) g.P(``) for name, pattern := range patterns { g.P(`var `, name, ` = `, g.regexpPkg.Use(), `.MustCompile(`, strconv.Quote(pattern), `)`) } g.P(``) }
func (p *plugin) checkRepeated(message *generator.Descriptor) { ccTypeName := generator.CamelCaseSlice(message.TypeName()) for _, field := range message.Field { if !gogoproto.IsEmbed(field) { continue } if field.IsBytes() { fieldname := generator.CamelCase(*field.Name) fmt.Fprintf(os.Stderr, "ERROR: found embedded bytes field %s in message %s\n", fieldname, ccTypeName) os.Exit(1) } if !field.IsRepeated() { continue } fieldname := generator.CamelCase(*field.Name) fmt.Fprintf(os.Stderr, "ERROR: found repeated embedded field %s in message %s\n", fieldname, ccTypeName) os.Exit(1) } }
func (p *plugin) checkOverwrite(message *generator.Descriptor, enablers map[string]gogoproto.EnableFunc) { ccTypeName := generator.CamelCaseSlice(message.TypeName()) names := []string{} for name := range enablers { names = append(names, name) } for _, field := range message.Field { if field.IsMessage() && gogoproto.IsEmbed(field) { fieldname := generator.CamelCase(*field.Name) desc := p.ObjectNamed(field.GetTypeName()) msg := desc.(*generator.Descriptor) for errStr, enabled := range enablers { if enabled(msg.File(), msg.DescriptorProto) { fmt.Fprintf(os.Stderr, "WARNING: found non-%v %v with embedded %v %v\n", names, ccTypeName, errStr, fieldname) } } p.checkOverwrite(msg, enablers) } } }
func (g *gensql) generateStmt(file *generator.FileDescriptor, message *generator.Descriptor) { model := limbo.GetModel(message) g.P(`type `, message.Name, `StmtBuilder interface {`) g.P(`Prepare(scanner string, query string) `, message.Name, `Stmt`) g.P(`PrepareExecer(query string) `, message.Name, `Execer`) g.P(`Err() error`) g.P(`}`) g.P(`type `, message.Name, `Stmt interface {`) g.P(`QueryRow(ctx `, g.contextPkg.Use(), `.Context, args ... interface{}) (`, message.Name, `Row)`) g.P(`Query(ctx `, g.contextPkg.Use(), `.Context, args ... interface{}) (`, message.Name, `Rows, error)`) g.P(`SelectSlice(ctx `, g.contextPkg.Use(), `.Context, dst []*`, message.Name, `, args ... interface{}) ([]*`, message.Name, `, error)`) g.P(`SelectMessageSlice(ctx `, g.contextPkg.Use(), `.Context, dst []interface{}, args ... interface{}) ([]interface{}, error)`) g.P(`ForTx(tx *`, g.sqlPkg.Use(), `.Tx) `, message.Name, `Stmt`) g.P(`}`) g.P(`type `, message.Name, `Execer interface {`) g.P(`Exec(ctx `, g.contextPkg.Use(), `.Context, args ... interface{}) (`, g.sqlPkg.Use(), `.Result, error)`) g.P(`ForTx(tx *`, g.sqlPkg.Use(), `.Tx) `, message.Name, `Execer`) g.P(`}`) g.P(`type `, message.Name, `Row interface {`) g.P(`Scan(out *`, message.Name, `) error`) g.P(`}`) g.P(`type `, message.Name, `Rows interface {`) g.P(`Close() error`) g.P(`Next() bool`) g.P(`Err() error`) g.P(`Scan(out *`, message.Name, `) error`) g.P(`}`) g.P(`type `, unexport(*message.Name), `StmtBuilder struct {`) g.P(`db *`, g.sqlPkg.Use(), `.DB`) g.P(`err error`) g.P(`}`) g.P(`type `, unexport(*message.Name), `Stmt struct {`) g.P(`stmt *`, g.sqlPkg.Use(), `.Stmt`) g.P(`scanner func(func(...interface{}) error, *`, message.Name, `) error`) g.P(`query string`) g.P(`}`) g.P(`type `, unexport(*message.Name), `Execer struct {`) g.P(`stmt *`, g.sqlPkg.Use(), `.Stmt`) g.P(`query string`) g.P(`}`) g.P(`type `, unexport(*message.Name), `Row struct {`) g.P(`row *`, g.sqlPkg.Use(), `.Row`) g.P(`span *`, g.tracePkg.Use(), `.Span`) g.P(`scanner func(func(...interface{}) error, *`, message.Name, `) error`) g.P(`}`) g.P(`type `, unexport(*message.Name), `Rows struct {`) g.P(`*`, g.sqlPkg.Use(), `.Rows`) g.P(`span *`, g.tracePkg.Use(), `.Span`) g.P(`scanner func(func(...interface{}) error, *`, message.Name, `) error`) g.P(`}`) g.P(`func New`, message.Name, `StmtBuilder(db *`, g.sqlPkg.Use(), `.DB) `, message.Name, `StmtBuilder {`) g.P(`return &`, unexport(*message.Name), `StmtBuilder{db: db}`) g.P(`}`) g.P(`func (b *`, unexport(*message.Name), `StmtBuilder) Prepare(scanner string, query string) (`, message.Name, `Stmt) {`) g.P(`if b.err != nil { return nil }`) g.P(`var scannerFunc func(func(...interface{}) error, *`, message.Name, `) error`) g.P(`switch scanner {`) for _, scanner := range model.Scanner { scannerFuncName := `scan_` + message.GetName() if scanner.Name != "" { scannerFuncName += `_` + scanner.Name } g.P(`case `, strconv.Quote(scanner.Name), `:`) g.P(`query = `, scannerFuncName, `SQL + " " + query`) g.P(`scannerFunc = `, scannerFuncName) } g.P(`default:`) g.P(`if b.err == nil { b.err = fmt.Errorf("unknown scanner: %s", scanner) }`) g.P(`}`) g.P(`query = `, g.runtimePkg.Use(), `.CleanSQL(query)`) g.P(`stmt, err := b.db.Prepare(query)`) g.P(`if err != nil { if b.err == nil { b.err = err } }`) g.P(`return &`, unexport(*message.Name), `Stmt{stmt: stmt, query:query, scanner: scannerFunc}`) g.P(`}`) g.P(`func (b *`, unexport(*message.Name), `StmtBuilder) PrepareExecer( query string) (`, message.Name, `Execer) {`) g.P(`if b.err != nil { return nil }`) g.P(`query = `, g.runtimePkg.Use(), `.CleanSQL(query)`) g.P(`stmt, err := b.db.Prepare(query)`) g.P(`if err != nil { if b.err == nil { b.err = err } }`) g.P(`return &`, unexport(*message.Name), `Execer{stmt: stmt, query: query}`) g.P(`}`) g.P(`func (b *`, unexport(*message.Name), `StmtBuilder) Err() (error) {`) g.P(`return b.err`) g.P(`}`) g.P(`func (s *`, unexport(*message.Name), `Stmt) QueryRow(ctx `, g.contextPkg.Use(), `.Context, args ... interface{}) (`, message.Name, `Row) {`) g.P(`span, _ := `, g.tracePkg.Use(), `.New(ctx, "QueryRow("+s.query+")")`) g.P(`row := s.stmt.QueryRow(args...)`) g.P(`return &`, unexport(*message.Name), `Row{row: row, scanner: s.scanner, span: span}`) g.P(`}`) g.P(`func (s *`, unexport(*message.Name), `Stmt) Query(ctx `, g.contextPkg.Use(), `.Context, args ... interface{}) (`, message.Name, `Rows, error) {`) g.P(`span, _ := `, g.tracePkg.Use(), `.New(ctx, "Query("+s.query+")")`) g.P(`rows, err := s.stmt.Query(args...)`) g.P(`if err != nil {`) g.P(`span.Error(err)`) g.P(`span.Close()`) g.P(`return nil, err`) g.P(`}`) g.P(`return &`, unexport(*message.Name), `Rows{Rows: rows, scanner: s.scanner, span: span}, nil`) g.P(`}`) g.P(`func (s *`, unexport(*message.Name), `Stmt) SelectSlice(ctx `, g.contextPkg.Use(), `.Context, dst []*`, message.Name, `, args ... interface{}) ([]*`, message.Name, `, error) {`) g.P(`rows, err := s.Query(ctx, args...)`) g.P(`if err != nil { return nil, err }`) g.P(`defer rows.Close()`) g.P(`for rows.Next() {`) g.P(`var x = &`, message.Name, `{}`) g.P(`err := rows.Scan(x)`) g.P(`if err != nil { return nil, err }`) g.P(`dst = append(dst, x)`) g.P(`}`) g.P(`err = rows.Err()`) g.P(`if err != nil { return nil, err }`) g.P(`return dst, nil`) g.P(`}`) g.P(`func (s *`, unexport(*message.Name), `Stmt) SelectMessageSlice(ctx `, g.contextPkg.Use(), `.Context, dst []interface{}, args ... interface{}) ([]interface{}, error) {`) g.P(`rows, err := s.Query(ctx, args...)`) g.P(`if err != nil { return nil, err }`) g.P(`defer rows.Close()`) g.P(`for rows.Next() {`) g.P(`var x = &`, message.Name, `{}`) g.P(`err := rows.Scan(x)`) g.P(`if err != nil { return nil, err }`) g.P(`dst = append(dst, x)`) g.P(`}`) g.P(`err = rows.Err()`) g.P(`if err != nil { return nil, err }`) g.P(`return dst, nil`) g.P(`}`) g.P(`func (s *`, unexport(*message.Name), `Stmt) ForTx(tx *`, g.sqlPkg.Use(), `.Tx) `, message.Name, `Stmt {`) g.P(`return &`, unexport(*message.Name), `Stmt{stmt: tx.Stmt(s.stmt), scanner: s.scanner, query: s.query}`) g.P(`}`) g.P(`func (s *`, unexport(*message.Name), `Execer) Exec(ctx `, g.contextPkg.Use(), `.Context,args ... interface{}) (`, g.sqlPkg.Use(), `.Result, error) {`) g.P(`span, _ := `, g.tracePkg.Use(), `.New(ctx, "Exec("+s.query+")")`) g.P(`defer span.Close()`) g.P(`res, err := s.stmt.Exec(args...)`) g.P(`if err != nil { span.Error(err) }`) g.P(`return res, err`) g.P(`}`) g.P(`func (s *`, unexport(*message.Name), `Execer) ForTx(tx *`, g.sqlPkg.Use(), `.Tx) `, message.Name, `Execer {`) g.P(`return &`, unexport(*message.Name), `Execer{stmt: tx.Stmt(s.stmt), query: s.query}`) g.P(`}`) g.P(`func (r *`, unexport(*message.Name), `Row) Scan(out *`, message.Name, `) error {`) g.P(`defer r.span.Close()`) g.P(`err := r.scanner(r.row.Scan, out)`) g.P(`if err != nil { r.span.Error(err) }`) g.P(`return err`) g.P(`}`) g.P(`func (r *`, unexport(*message.Name), `Rows) Scan(out *`, message.Name, `) error {`) g.P(`err := r.scanner(r.Rows.Scan, out)`) g.P(`if err != nil { r.span.Error(err) }`) g.P(`return err`) g.P(`}`) g.P(`func (r *`, unexport(*message.Name), `Rows) Close() error {`) g.P(`defer r.span.Close()`) g.P(`err := r.Rows.Close()`) g.P(`if err != nil { r.span.Error(err) }`) g.P(`return err`) g.P(`}`) }
func (g *gensql) generateScanner(file *generator.FileDescriptor, message *generator.Descriptor, scanner *limbo.ScannerDescriptor) { scannerFuncName := `scan_` + message.GetName() if scanner.Name != "" { scannerFuncName += `_` + scanner.Name } joins := map[string]int{} g.P(``) g.P(`const `, scannerFuncName, `SQL = `, strconv.Quote(g.generateQueryPrefix(message, scanner))) g.P(`func `, scannerFuncName, `(scanFunc func(...interface{})error, dst *`, message.Name, `) error {`) g.P(`var (`) for i, column := range scanner.Column { m := g.models[column.MessageType] field := m.GetFieldDescriptor(lastField(column.FieldName)) if field.IsRepeated() { g.P(`b`, i, ` []byte`) continue } switch field.GetType() { case pb.FieldDescriptorProto_TYPE_BOOL: g.P(`b`, i, ` `, g.sqlPkg.Use(), `.NullBool`) case pb.FieldDescriptorProto_TYPE_DOUBLE: g.P(`b`, i, ` `, g.sqlPkg.Use(), `.NullFloat64`) case pb.FieldDescriptorProto_TYPE_FLOAT: g.P(`b`, i, ` `, g.sqlPkg.Use(), `.NullFloat64`) case pb.FieldDescriptorProto_TYPE_FIXED32, pb.FieldDescriptorProto_TYPE_UINT32: g.P(`b`, i, ` `, g.sqlPkg.Use(), `.NullInt64`) case pb.FieldDescriptorProto_TYPE_FIXED64, pb.FieldDescriptorProto_TYPE_UINT64: g.P(`b`, i, ` `, g.sqlPkg.Use(), `.NullInt64`) case pb.FieldDescriptorProto_TYPE_SFIXED32, pb.FieldDescriptorProto_TYPE_INT32, pb.FieldDescriptorProto_TYPE_SINT32: g.P(`b`, i, ` `, g.sqlPkg.Use(), `.NullInt64`) case pb.FieldDescriptorProto_TYPE_SFIXED64, pb.FieldDescriptorProto_TYPE_INT64, pb.FieldDescriptorProto_TYPE_SINT64: g.P(`b`, i, ` `, g.sqlPkg.Use(), `.NullInt64`) case pb.FieldDescriptorProto_TYPE_BYTES: g.P(`b`, i, ` []byte`) case pb.FieldDescriptorProto_TYPE_STRING: g.P(`b`, i, ` `, g.sqlPkg.Use(), `.NullString`) case pb.FieldDescriptorProto_TYPE_ENUM: g.P(`b`, i, ` `, g.sqlPkg.Use(), `.NullInt64`) case pb.FieldDescriptorProto_TYPE_MESSAGE: if field.GetTypeName() == ".google.protobuf.Timestamp" { g.P(`b`, i, ` `, g.mysqlPkg.Use(), `.NullTime`) } else if limbo.IsGoSQLValuer(g.objectNamed(field.GetTypeName()).(*generator.Descriptor)) { g.P(`b`, i, ` Null`, g.typeName(field.GetTypeName())) } else { g.P(`b`, i, ` []byte`) g.P(`m`, i, ` `, g.typeName(field.GetTypeName())) } default: panic("unsuported type: " + field.GetType().String()) } } for i, join := range scanner.Join { m := g.models[join.MessageType] field := m.GetFieldDescriptor(lastField(join.FieldName)) joins[join.FieldName] = i g.P(`j`, i, ` `, g.typeName(field.GetTypeName())) g.P(`j`, i, `Valid bool`) } g.P(`)`) g.P(`err := scanFunc(`) for i := range scanner.Column { g.P(`&b`, i, `,`) } g.P(`)`) g.P(`if err!=nil { return err }`) for i, column := range scanner.Column { var ( m = g.models[column.MessageType] field = m.GetFieldDescriptor(lastField(column.FieldName)) valid string dst = "dst" ) if column.JoinedWith != "" { dst = fmt.Sprintf("j%d", joins[column.JoinedWith]) } if field.IsRepeated() { valid = fmt.Sprintf(`b%d != nil`, i) } else { switch field.GetType() { case pb.FieldDescriptorProto_TYPE_MESSAGE: if field.GetTypeName() == ".google.protobuf.Timestamp" { valid = fmt.Sprintf(`b%d.Valid`, i) } else if limbo.IsGoSQLValuer(g.objectNamed(field.GetTypeName()).(*generator.Descriptor)) { valid = fmt.Sprintf(`b%d.Valid`, i) } else { valid = fmt.Sprintf(`b%d != nil`, i) } case pb.FieldDescriptorProto_TYPE_BYTES: valid = fmt.Sprintf(`b%d != nil`, i) default: valid = fmt.Sprintf(`b%d.Valid`, i) } } fieldName := g.gen.GetFieldName(m, field) g.P(`if `, valid, ` {`) if column.JoinedWith != "" { g.P(dst, `Valid = true`) } if field.IsRepeated() { g.P(`if err:= `, g.jsonPkg.Use(), `.Unmarshal(b`, i, `, &`, dst, `.`, fieldName, `); err!=nil {`) g.P(`return err`) g.P(`}`) } else { switch field.GetType() { case pb.FieldDescriptorProto_TYPE_BOOL: g.P(dst, `.`, fieldName, ` = b`, i, `.Bool`) case pb.FieldDescriptorProto_TYPE_DOUBLE: g.P(dst, `.`, fieldName, ` = float32(b`, i, `.Float64)`) case pb.FieldDescriptorProto_TYPE_FLOAT: g.P(dst, `.`, fieldName, ` = float32(b`, i, `.Float64)`) case pb.FieldDescriptorProto_TYPE_FIXED32, pb.FieldDescriptorProto_TYPE_UINT32: g.P(dst, `.`, fieldName, ` = uint32(b`, i, `.Int64)`) case pb.FieldDescriptorProto_TYPE_FIXED64, pb.FieldDescriptorProto_TYPE_UINT64: g.P(dst, `.`, fieldName, ` = uint64(b`, i, `.Int64)`) case pb.FieldDescriptorProto_TYPE_SFIXED32, pb.FieldDescriptorProto_TYPE_INT32, pb.FieldDescriptorProto_TYPE_SINT32: g.P(dst, `.`, fieldName, ` = int32(b`, i, `.Int64)`) case pb.FieldDescriptorProto_TYPE_SFIXED64, pb.FieldDescriptorProto_TYPE_INT64, pb.FieldDescriptorProto_TYPE_SINT64: g.P(dst, `.`, fieldName, ` = int64(b`, i, `.Int64)`) case pb.FieldDescriptorProto_TYPE_ENUM: g.P(dst, `.`, fieldName, ` = `, g.typeName(field.GetTypeName()), `(b`, i, `.Int64)`) case pb.FieldDescriptorProto_TYPE_BYTES: g.P(dst, `.`, fieldName, ` = b`, i, ``) case pb.FieldDescriptorProto_TYPE_STRING: g.P(dst, `.`, fieldName, ` = b`, i, `.String`) case pb.FieldDescriptorProto_TYPE_MESSAGE: if field.GetTypeName() == ".google.protobuf.Timestamp" { if gogoproto.IsNullable(field) { g.P(dst, `.`, fieldName, ` = &b`, i, `.Time`) } else { g.P(dst, `.`, fieldName, ` = b`, i, `.Time`) } } else if limbo.IsGoSQLValuer(g.objectNamed(field.GetTypeName()).(*generator.Descriptor)) { if gogoproto.IsNullable(field) { g.P(dst, `.`, fieldName, ` = &b`, i, `.`, g.typeName(field.GetTypeName())) } else { g.P(dst, `.`, fieldName, ` = b`, i, `.`, g.typeName(field.GetTypeName())) } } else { g.P(`err := m`, i, `.Unmarshal(b`, i, `)`) g.P(`if err!=nil { return err }`) if gogoproto.IsNullable(field) { g.P(dst, `.`, fieldName, ` = &m`, i, ``) } else { g.P(dst, `.`, fieldName, ` = m`, i, ``) } } } } g.P(`}`) } for i := len(scanner.Join) - 1; i >= 0; i-- { var ( join = scanner.Join[i] m = g.models[join.MessageType] field = m.GetFieldDescriptor(lastField(join.FieldName)) dst = "dst" ) if join.JoinedWith != "" { dst = fmt.Sprintf("j%d", joins[join.JoinedWith]) } fieldName := g.gen.GetFieldName(m, field) g.P(`if j`, i, `Valid {`) if gogoproto.IsNullable(field) { g.P(dst, `.`, fieldName, ` = &j`, i, ``) } else { g.P(dst, `.`, fieldName, ` = j`, i, ``) } g.P(`}`) } g.P(`return nil`) g.P(`}`) g.P(``) }
func (g *gensql) populateMessage(file *generator.FileDescriptor, msg *generator.Descriptor) { model := limbo.GetModel(msg) model.MessageType = "." + file.GetPackage() + "." + msg.GetName() { // default scanner var found bool for _, scanner := range model.Scanner { if scanner.Name == "" { found = true break } } if !found { model.Scanner = append(model.Scanner, &limbo.ScannerDescriptor{Fields: "*"}) } } for _, scanner := range model.Scanner { scanner.MessageType = "." + file.GetPackage() + "." + msg.GetName() } for _, field := range msg.GetField() { if column := limbo.GetColumn(field); column != nil { column.MessageType = "." + file.GetPackage() + "." + msg.GetName() column.FieldName = field.GetName() if column.Name == "" { column.Name = field.GetName() } model.Column = append(model.Column, column) } if join := limbo.GetJoin(field); join != nil { if field.GetType() != pb.FieldDescriptorProto_TYPE_MESSAGE { g.gen.Fail(field.GetName(), "in", msg.GetName(), "must be a message") } join.MessageType = "." + file.GetPackage() + "." + msg.GetName() join.FieldName = field.GetName() join.ForeignMessageType = field.GetTypeName() if join.Name == "" { join.Name = field.GetName() } if join.Key == "" { join.Key = field.GetName() + "_id" } if join.ForeignKey == "" { join.ForeignKey = "id" } model.Join = append(model.Join, join) } } sort.Sort(limbo.SortedColumnDescriptors(model.Column)) sort.Sort(limbo.SortedJoinDescriptors(model.Join)) sort.Sort(limbo.SortedScannerDescriptors(model.Scanner)) }
func (g *jsonschema) messageToSchema(file *generator.FileDescriptor, desc *generator.Descriptor) (interface{}, []string) { typeName := file.GetPackage() + "." + strings.Join(desc.TypeName(), ".") typeName = strings.TrimPrefix(typeName, ".") title := desc.TypeName()[len(desc.TypeName())-1] var ( dependencies []string properties = make(map[string]interface{}) requiredProperties []string ) for i, field := range desc.GetField() { if field.OneofIndex != nil { continue } f, dep := g.fieldToSchema(field) if f == nil { continue } if limbo.IsRequiredProperty(field) { requiredProperties = append(requiredProperties, getJSONName(field)) } { comment := g.gen.Comments(fmt.Sprintf("%s,%d,%d", desc.Path(), 2, i)) comment = strings.TrimSpace(comment) if comment != "" { f["description"] = comment } } properties[getJSONName(field)] = f if dep != "" { dependencies = append(dependencies, dep) } } schema := map[string]interface{}{ "type": "object", "properties": properties, } if len(requiredProperties) > 0 { schema["required"] = requiredProperties } if len(desc.OneofDecl) > 0 { allOffDefs := make([]interface{}, 0, 1+len(desc.OneofDecl)) oneOfDefs := make([][]interface{}, len(desc.OneofDecl)) for i, field := range desc.GetField() { if field.OneofIndex == nil { continue } oneofIndex := *field.OneofIndex f, dep := g.fieldToSchema(field) if f == nil { continue } if field.IsRepeated() { f = map[string]interface{}{ "type": "array", "items": f, } } { comment := g.gen.Comments(fmt.Sprintf("%s,%d,%d", desc.Path(), 2, i)) comment = strings.TrimSpace(comment) if comment != "" { f["description"] = comment } } def := map[string]interface{}{ "type": "object", "properties": map[string]interface{}{ getJSONName(field): f, }, "required": []string{getJSONName(field)}, } oneOfDefs[oneofIndex] = append(oneOfDefs[oneofIndex], def) if dep != "" { dependencies = append(dependencies, dep) } } allOffDefs = append(allOffDefs, schema) for i, defs := range oneOfDefs { def := map[string]interface{}{ "oneOf": defs, } { comment := g.gen.Comments(fmt.Sprintf("%s,%d,%d", desc.Path(), 8, i)) comment = strings.TrimSpace(comment) if comment != "" { def["description"] = comment } } allOffDefs = append(allOffDefs, def) } schema = map[string]interface{}{ "type": "object", "allOf": allOffDefs, } } { comment := g.gen.Comments(desc.Path()) comment = strings.TrimSpace(comment) if comment != "" { schema["description"] = comment } } { schema["title"] = title // schema["id"] = typeName } { dependencies = uniqStrings(dependencies) } return schema, dependencies }
func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor) { ccTypeName := generator.CamelCaseSlice(message.TypeName()) p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`) p.In() p.generateMsgNullAndTypeCheck(ccTypeName) oneofs := make(map[string]struct{}) for _, field := range message.Field { oneof := field.OneofIndex != nil if oneof { fieldname := p.GetFieldName(message, field) if _, ok := oneofs[fieldname]; ok { continue } else { oneofs[fieldname] = struct{}{} } p.P(`if that1.`, fieldname, ` == nil {`) p.In() p.P(`if this.`, fieldname, ` != nil {`) p.In() p.P(`return 1`) p.Out() p.P(`}`) p.Out() p.P(`} else if this.`, fieldname, ` == nil {`) p.In() p.P(`return -1`) p.Out() p.P(`} else if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`) p.In() p.P(`return c`) p.Out() p.P(`}`) } else { p.generateField(file, message, field) } } if message.DescriptorProto.HasExtension() { fieldname := "XXX_extensions" if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) { p.P(`extkeys := make([]int32, 0, len(this.`, fieldname, `)+len(that1.`, fieldname, `))`) p.P(`for k, _ := range this.`, fieldname, ` {`) p.In() p.P(`extkeys = append(extkeys, k)`) p.Out() p.P(`}`) p.P(`for k, _ := range that1.`, fieldname, ` {`) p.In() p.P(`if _, ok := this.`, fieldname, `[k]; !ok {`) p.In() p.P(`extkeys = append(extkeys, k)`) p.Out() p.P(`}`) p.Out() p.P(`}`) p.P(p.sortkeysPkg.Use(), `.Int32s(extkeys)`) p.P(`for _, k := range extkeys {`) p.In() p.P(`if v, ok := this.`, fieldname, `[k]; ok {`) p.In() p.P(`if v2, ok := that1.`, fieldname, `[k]; ok {`) p.In() p.P(`if c := v.Compare(&v2); c != 0 {`) p.In() p.P(`return c`) p.Out() p.P(`}`) p.Out() p.P(`} else {`) p.In() p.P(`return 1`) p.Out() p.P(`}`) p.Out() p.P(`} else {`) p.In() p.P(`return -1`) p.Out() p.P(`}`) p.Out() p.P(`}`) } else { p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`) p.In() p.P(`return c`) p.Out() p.P(`}`) } } if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) { fieldname := "XXX_unrecognized" p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`) p.In() p.P(`return c`) p.Out() p.P(`}`) } p.P(`return 0`) p.Out() p.P(`}`) //Generate Compare methods for oneof fields m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto) for _, field := range m.Field { oneof := field.OneofIndex != nil if !oneof { continue } ccTypeName := p.OneOfTypeName(message, field) p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`) p.In() p.generateMsgNullAndTypeCheck(ccTypeName) vanity.TurnOffNullableForNativeTypesWithoutDefaultsOnly(field) p.generateField(file, message, field) p.P(`return 0`) p.Out() p.P(`}`) } }
func (g *svcauth) getMessage(inputType *generator.Descriptor, path, input, output string, inputIsNullable bool) { var ( checks []string goPath string isNullable = inputIsNullable ) if path == "." { g.P(output, ` = `, input) return } goPath = input if inputIsNullable { checks = append(checks, input+" != nil") } for path != "" { // split path part := path idx := strings.IndexByte(path, '.') if idx >= 0 { part = path[:idx] path = path[idx+1:] } else { path = "" } // Get Field field := inputType.GetFieldDescriptor(part) if field == nil { g.gen.Fail("unknown field", strconv.Quote(part), "in message", inputType.GetName()) } if !field.IsMessage() { g.gen.Fail("expected a message") } // Append code fieldGoName := g.gen.GetFieldName(inputType, field) goPath += "." + fieldGoName if gogoproto.IsNullable(field) { checks = append(checks, goPath+" != nil") isNullable = true } else { isNullable = false } inputType = g.messages[strings.TrimPrefix(field.GetTypeName(), ".")] } if len(checks) > 0 { g.P(`if `, strings.Join(checks, " && "), `{`) if isNullable { g.P(output, ` = `, goPath) } else { g.P(output, ` = &`, goPath) } g.P(`}`) } else { if isNullable { g.P(output, ` = `, goPath) } else { g.P(output, ` = &`, goPath) } } }
func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor, verbose bool) { ccTypeName := generator.CamelCaseSlice(message.TypeName()) if verbose { p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`) } else { p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`) } p.In() p.generateMsgNullAndTypeCheck(ccTypeName, verbose) oneofs := make(map[string]struct{}) for _, field := range message.Field { oneof := field.OneofIndex != nil if oneof { fieldname := p.GetFieldName(message, field) if _, ok := oneofs[fieldname]; ok { continue } else { oneofs[fieldname] = struct{}{} } p.P(`if that1.`, fieldname, ` == nil {`) p.In() p.P(`if this.`, fieldname, ` != nil {`) p.In() if verbose { p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`) } else { p.P(`return false`) } p.Out() p.P(`}`) p.Out() p.P(`} else if this.`, fieldname, ` == nil {`) p.In() if verbose { p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` == nil && that1.`, fieldname, ` != nil")`) } else { p.P(`return false`) } p.Out() if verbose { p.P(`} else if err := this.`, fieldname, `.VerboseEqual(that1.`, fieldname, `); err != nil {`) } else { p.P(`} else if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`) } p.In() if verbose { p.P(`return err`) } else { p.P(`return false`) } p.Out() p.P(`}`) } else { p.generateField(file, message, field, verbose) } } if message.DescriptorProto.HasExtension() { fieldname := "XXX_extensions" if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) { p.P(`for k, v := range this.`, fieldname, ` {`) p.In() p.P(`if v2, ok := that1.`, fieldname, `[k]; ok {`) p.In() p.P(`if !v.Equal(&v2) {`) p.In() if verbose { p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", k, this.`, fieldname, `[k], k, that1.`, fieldname, `[k])`) } else { p.P(`return false`) } p.Out() p.P(`}`) p.Out() p.P(`} else {`) p.In() if verbose { p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In that", k)`) } else { p.P(`return false`) } p.Out() p.P(`}`) p.Out() p.P(`}`) p.P(`for k, _ := range that1.`, fieldname, ` {`) p.In() p.P(`if _, ok := this.`, fieldname, `[k]; !ok {`) p.In() if verbose { p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In this", k)`) } else { p.P(`return false`) } p.Out() p.P(`}`) p.Out() p.P(`}`) } else { p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`) p.In() if verbose { p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`) } else { p.P(`return false`) } p.Out() p.P(`}`) } } if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) { fieldname := "XXX_unrecognized" p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`) p.In() if verbose { p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`) } else { p.P(`return false`) } p.Out() p.P(`}`) } if verbose { p.P(`return nil`) } else { p.P(`return true`) } p.Out() p.P(`}`) //Generate Equal methods for oneof fields m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto) for _, field := range m.Field { oneof := field.OneofIndex != nil if !oneof { continue } ccTypeName := p.OneOfTypeName(message, field) if verbose { p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`) } else { p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`) } p.In() p.generateMsgNullAndTypeCheck(ccTypeName, verbose) vanity.TurnOffNullableForNativeTypesWithoutDefaultsOnly(field) p.generateField(file, message, field, verbose) if verbose { p.P(`return nil`) } else { p.P(`return true`) } p.Out() p.P(`}`) } }