Пример #1
0
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
}
Пример #2
0
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)
	}

}
Пример #3
0
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
}
Пример #4
0
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)
	}
}
Пример #5
0
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
	}
}
Пример #6
0
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(``)
}
Пример #7
0
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)
	}
}
Пример #8
0
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)
		}
	}
}
Пример #9
0
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(`}`)
}
Пример #10
0
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(``)
}
Пример #11
0
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))
}
Пример #12
0
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
}
Пример #13
0
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(`}`)
	}
}
Пример #14
0
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)
		}
	}
}
Пример #15
0
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(`}`)
	}
}