Best Go-testdeep code snippet using json.popPos
codegen.go
Source:codegen.go
...116func (g *Codegen) pushPos(pos token.Pos) {117 g.posstack = append(g.posstack, g.pos)118 g.pos = pos119}120func (g *Codegen) popPos() {121 g.pos = g.posstack[len(g.posstack)-1]122 g.posstack = g.posstack[:len(g.posstack)-1]123}124// isMutableRefType returns true if t is a type which underlying value may be changed without125// assignment. For example a slice.126func isMutableRefType(typ types.Type) bool {127 for {128 switch t := typ.(type) {129 case *types.Array, *types.Slice, *types.Map, *types.Pointer, *types.Struct:130 return true131 case *types.Named:132 typ = t.Underlying()133 default:134 return false135 }136 }137 return false138}139// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ140// encode141func (g *Codegen) codegenEncodeField(f *EntField) error {142 cvar := "c"143 expr, err := g.genFieldEncoder(f, cvar, "e."+f.sname)144 if err != nil {145 return err146 }147 g.f(" %s.Key(%#v)\n", cvar, f.name)148 g.f(" %s\n", expr)149 return nil150}151func (g *Codegen) genFieldEncoder(f *EntField, cvar, valexpr string) (string, error) {152 g.pushPos(f.t.pos)153 defer g.popPos()154 expr, err := g.encoderExpr(f.t.Type, cvar, valexpr)155 if err == ErrUnsupportedType {156 g.logErrUnsupportedType(f)157 }158 return expr, err159}160func (g *Codegen) encoderExpr(typ types.Type, cvar, valexpr string) (expr string, err error) {161 typ, cast := g.unwrapNamedType(typ)162 if cast != "" {163 // flip cast164 cast = g.goTypeName(typ)165 }166 switch t := typ.(type) {167 case *types.Basic:168 m, cast, advice := g.basicCodecCall(t, codecEncode, cast != "")169 if advice != "" {170 advice = ", " + advice171 }172 expr = fmt.Sprintf("%s.%s(%s%s)", cvar, m, wrapstr(valexpr, cast), advice)173 return174 case *types.Slice, *types.Array:175 if cast != "" {176 cast = ""177 }178 var elemt types.Type179 if st, ok := t.(*types.Slice); ok {180 elemt = st.Elem()181 } else {182 elemt = t.(*types.Array).Elem()183 // use slice of all arrays (even those that are not [N]byte)184 valexpr += "[:]"185 // convert to slice so that genComplexEncoder uses slice encoders instead of generating186 // array encoders.187 typ = types.NewSlice(elemt)188 }189 // special case for []byte190 if bt, ok := elemt.(*types.Basic); ok && bt.Kind() == types.Uint8 {191 expr = fmt.Sprintf("%s.Blob(%s)", cvar, wrapstr(valexpr, cast))192 return193 }194 }195 expr, err = g.getOrBuildTypeHelper(typ, cvar, "ent_encode_", g.genComplexEncoder)196 expr += "(" + cvar + ", " + wrapstr(valexpr, cast) + ")"197 return198}199func (g *Codegen) genComplexEncoder(typ types.Type, cvar string, buf *bytes.Buffer) error {200 wf := func(format string, args ...interface{}) {201 fmt.Fprintf(buf, format, args...)202 }203 goType := g.goTypeName(typ)204 wf("(%s ent.Encoder, v %s) {\n", cvar, goType)205 switch t := typ.(type) {206 case *types.Slice:207 expr, err := g.encoderExpr(t.Elem(), cvar, "val")208 if err != nil {209 return err210 }211 wf(" %s.BeginList(len(v))\n", cvar)212 wf(" for _, val := range v {\n")213 wf(" %s\n", expr)214 wf(" }\n")215 wf(" %s.EndList()\n", cvar)216 case *types.Map:217 expr, err := g.encoderExpr(t.Elem(), cvar, "val")218 if err != nil {219 return err220 }221 if kt, ok := t.Key().(*types.Basic); !ok || kt.Kind() != types.String {222 g.logSrcErr("unsupported map key type %s; only string map keys are supported", t.Key())223 return ErrUnsupportedType224 }225 wf(" %s.BeginDict(len(v))\n", cvar)226 wf(" for k, val := range v {\n")227 wf(" %s.Key(k)\n", cvar)228 wf(" %s\n", expr)229 wf(" }\n")230 wf(" %s.EndDict()\n", cvar)231 default:232 return ErrUnsupportedType233 } // switch typ234 wf("}\n")235 return nil236}237// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ238// decode239func (g *Codegen) codegenDecodeField(f *EntField) error {240 g.pushPos(f.t.pos)241 defer g.popPos()242 expr, cast, err := g.decoderExpr(f.t.Type, "c")243 if err != nil {244 if err == ErrUnsupportedType {245 g.logErrUnsupportedType(f)246 }247 return err248 }249 g.f(" e.%s = %s\n", f.sname, wrapstr(expr, cast))250 return nil251}252// decoderExpr generates & returns a "decode" expression like "c.Int(64)"253func (g *Codegen) decoderExpr(typ types.Type, cvar string) (expr, cast string, err error) {254 typ, cast = g.unwrapNamedType(typ)255 switch t := typ.(type) {256 case *types.Basic:257 m, basicCast, advice := g.basicCodecCall(t, codecDecode, false)258 if cast == "" {259 cast = basicCast260 }261 expr = fmt.Sprintf("%s.%s(%s)", cvar, m, advice)262 return263 case *types.Slice:264 // special case for []byte265 if bt, ok := t.Elem().(*types.Basic); ok && bt.Kind() == types.Uint8 {266 expr = cvar + ".Blob()"267 return268 }269 case *types.Array:270 // arrays are decoded as slices then copied into arrays via a ent_slice_to_AN_T helper271 expr, err = g.getOrBuildTypeHelper(typ, cvar, "ent_slice_to_", g.genCopyHelper)272 if bt, ok := t.Elem().(*types.Basic); ok && bt.Kind() == types.Uint8 {273 // special case for [N]byte274 expr += "(" + cvar + ".Blob())"275 } else {276 slicet := types.NewSlice(t.Elem())277 expr2, err2 := g.getOrBuildTypeHelper(slicet, cvar, "ent_decode_", g.genComplexDecoder)278 err = err2279 expr += "(" + expr2 + "(" + cvar + "))"280 }281 return282 } // switch t:=typ.(type)283 expr, err = g.getOrBuildTypeHelper(typ, cvar, "ent_decode_", g.genComplexDecoder)284 expr += "(" + cvar + ")"285 return286}287// genCopyHelper assumes typ is *types.Array288func (g *Codegen) genCopyHelper(typ types.Type, cvar string, buf *bytes.Buffer) error {289 wf := func(format string, args ...interface{}) {290 fmt.Fprintf(buf, format, args...)291 }292 elemt := typ.(*types.Array).Elem()293 goType := g.goTypeName(typ)294 elemGoType := g.goTypeName(elemt)295 wf("(s []%s) (r %s) {\n", elemGoType, goType)296 wf(" copy(r[:], s)\n")297 wf(" return\n" +298 "}\n")299 return nil300}301func (g *Codegen) genComplexDecoder(typ types.Type, cvar string, buf *bytes.Buffer) error {302 wf := func(format string, args ...interface{}) {303 fmt.Fprintf(buf, format, args...)304 }305 goType := g.goTypeName(typ)306 wf("(%s ent.Decoder) (r %s) {\n", cvar, goType)307 switch t := typ.(type) {308 case *types.Slice:309 expr, cast, err := g.decoderExpr(t.Elem(), cvar)310 if err != nil {311 return err312 }313 wf(" n := %s.ListHeader()\n", cvar)314 wf(" if n > -1 {\n")315 wf(" r = make(%s, 0, n)\n", goType)316 wf(" for i := 0; i < n; i++ {\n")317 wf(" r = append(r, %s)\n", wrapstr(expr, cast))318 wf(" }\n")319 wf(" } else {\n")320 wf(" for %s.More() {\n", cvar)321 wf(" r = append(r, %s)\n", wrapstr(expr, cast))322 wf(" }\n")323 wf(" }\n")324 case *types.Map:325 expr, cast, err := g.decoderExpr(t.Elem(), cvar)326 if err != nil {327 return err328 }329 // note: we don't check that key type is string since we already check for that in330 // genComplexEncoder331 valueGoType := g.goTypeName(t.Elem())332 wf(" n := %s.DictHeader()\n", cvar)333 wf(" r = make(map[string]%s, n)\n", valueGoType)334 wf(" if n > -1 {\n")335 wf(" for i := 0; i < n; i++ {\n")336 wf(" k := %s.Key()\n", cvar)337 wf(" r[k] = %s\n", wrapstr(expr, cast))338 wf(" }\n")339 wf(" } else {\n")340 wf(" for %s.More() {\n", cvar)341 wf(" k := %s.Key()\n", cvar)342 wf(" r[k] = %s\n", wrapstr(expr, cast))343 wf(" }\n")344 wf(" }\n")345 // case *types.Array:346 // expr, cast, err := g.decoderExpr(t.Elem())347 // if err != nil {348 // return err349 // }350 // wf(" n := c.ListHeader()\n")351 // wf(" if n < 0 {\n")352 // wf(" for i := 0; c.More(); i++ {\n")353 // wf(" if i < %d {\n", t.Len())354 // wf(" r[i] = %s\n", wrapstr(expr, cast))355 // wf(" } else {\n")356 // wf(" c.Discard()\n")357 // wf(" }\n")358 // wf(" }\n")359 // wf(" } else {\n")360 // wf(" if n > %d { n = %d }\n", t.Len(), t.Len())361 // wf(" for i := 0; i < n; i++ {\n")362 // wf(" r[i] = %s\n", wrapstr(expr, cast))363 // wf(" }\n")364 // wf(" }\n")365 default:366 return ErrUnsupportedType367 } // switch typ368 wf(" return\n}\n") // end of `func {fname}(cvar ent.Decoder) ...`369 return nil370}371// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ372// both encoding & decoding373type HelperBuilder = func(t types.Type, cvar string, b *bytes.Buffer) error374func (g *Codegen) getOrBuildTypeHelper(375 typ types.Type,376 cvar, fnamePrefix string,377 builder HelperBuilder,378) (string, error) {379 fname, err := Typemangle(g.pkg.Types, typ)380 if err != nil {381 return "", err382 }383 fname = fnamePrefix + fname384 err = g.getOrBuildHelper(fname, cvar, typ, builder)385 return fname, err386}387func (g *Codegen) getOrBuildHelper(fname, cvar string, t types.Type, builder HelperBuilder) error {388 if g.helperm == nil {389 g.helperm = map[string]error{}390 } else {391 err, ok := g.helperm[fname]392 if ok {393 return err394 }395 }396 log.Debug("codegen helper %s", fname)397 var buf bytes.Buffer398 buf.WriteString("\nfunc ")399 buf.WriteString(fname)400 err := builder(t, cvar, &buf)401 g.helperm[fname] = err402 if err == nil {403 g.helperw.Write(buf.Bytes())404 }405 return err406}407func (g *Codegen) unwrapNamedType(typ types.Type) (canonical types.Type, cast string) {408 // unwrap named type (does not include aliases, which do not need casting)409 canonical = typ410 for {411 t, ok := canonical.(*types.Named)412 if !ok {413 break414 }415 canonical = t.Underlying()416 if canonical == typ {417 break418 }419 if cast == "" {420 cast = g.goTypeName(typ)421 }422 }423 return424}425func (g *Codegen) basicCodecCall(426 t *types.Basic, cdir codecDir, mustcast bool,427) (m, cast, advice string) {428 kind := t.Kind()429 var wantadvice bool430 setcast := func(enccast string) {431 if cdir == codecDecode {432 cast = g.goTypeName(t)433 } else {434 cast = enccast435 }436 }437 switch kind {438 case types.Bool, types.UntypedBool:439 m = "Bool"440 case types.Int, types.UntypedInt, types.Int8, types.Int16, types.Int32, types.Int64,441 types.UntypedRune:442 if mustcast || kind != types.Int64 {443 setcast("int64")444 }445 m = "Int"446 wantadvice = true447 case types.Uint, types.Uint8, types.Uint16, types.Uint32, types.Uint64,448 types.Uintptr, types.UnsafePointer:449 if mustcast || kind != types.Uint64 {450 setcast("uint64")451 }452 m = "Uint"453 wantadvice = true454 case types.UntypedFloat, types.Float32, types.Float64:455 if mustcast || kind != types.Float64 {456 setcast("float64")457 }458 m = "Float"459 wantadvice = true460 case types.UntypedComplex, types.Complex64, types.Complex128:461 if mustcast || kind != types.Complex128 {462 setcast("complex128")463 }464 m = "Complex"465 wantadvice = true466 case types.String, types.UntypedString:467 m = "Str"468 }469 if wantadvice {470 advice = basicKindSizeAdvice(t.Kind())471 }472 return473}474// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ475// ent476func (g *Codegen) codegenEnt(e *EntInfo) error {477 w := g.w478 g.pushPos(e.pos)479 defer g.popPos()480 log.Info("codegen ent %q (%s.%s)", e.name, e.pkg.Name, e.sname)481 linefeed := []byte{'\n'}482 wstr := func(s string) { w.Write([]byte(s)) }483 wline := func() { w.Write(linefeed) }484 // wbyte := func(b byte) { w.Write([]byte{b}) }485 userMethods := e.getUserMethods()486 generatedMethods := map[string]bool{}487 var err error488 // methodIsUndefined checks if user has defined "name" method489 methodIsUndefined := func(name string) bool {490 return userMethods[name] == nil && !generatedMethods[name]491 }492 // methodMustBeUndefined checks if user has defined "name" method. If not, returns true.493 // If there is a definition, logs an error and returns false.494 methodMustBeUndefined := func(name, help string) bool {495 m := userMethods[name]496 if m == nil {497 if generatedMethods[name] {498 panic("trying to generate method " + name + " twice")499 }500 return true501 }502 if help != "" {503 help = " " + help504 }505 e.logSrcErr(m.pos, "ent method %s already defined for %s.%s", name, e.sname, help)506 if err == nil {507 err = fmt.Errorf("method definition conflict")508 }509 // TODO error510 return false511 }512 methodWarnIfDefinedAlt := func(name, help string) string {513 if m := userMethods[name]; m != nil {514 lname := inverseCapitalize(name)515 if lname != name {516 if help != "" {517 help = " " + help518 }519 e.logSrcWarn(m.pos,520 "ent method %s is already defined for %s. Naming the generated method %s instead.%s",521 name, e.sname, lname, help)522 help = "" // so we don't print it twice in case there's an error next523 }524 name = lname525 methodMustBeUndefined(name, help)526 } else if generatedMethods[name] {527 panic("trying to generate method " + name + " twice")528 }529 return name530 }531 funcIsUndefined := func(name string) bool {532 // TODO user functions533 return !g.generatedFunctions[name]534 }535 // compile indexes536 fieldIndexes := g.collectFieldIndexes(e.fields)537 g.f(538 "// ----------------------------------------------------------------------------\n// %s\n\n",539 e.sname)540 // // replicate original struct documentation541 // if len(e.doc) > 0 {542 // wstr("// ")543 // wstr(strings.Join(e.doc, "\n// "))544 // wline()545 // }546 // variables & constants547 // // ent.Register548 // wline()549 // g.f("var _ = ent.Register(&%s{})\n", e.sname)550 // wline()551 // LoadTYPEById(s ent.Storage, id uint64) (*TYPE, error)552 fname := "Load" + e.sname + "ById"553 if funcIsUndefined(fname) {554 g.generatedFunctions[fname] = true555 g.f("// %s loads %s with id from storage\n"+556 "func %s(storage ent.Storage, id uint64) (*%s, error)\t{\n"+557 " e := &%s{}\n"+558 " return e, ent.LoadEntById(e, storage, id)\n"+559 "}\n\n",560 fname, e.sname,561 fname, e.sname,562 e.sname)563 }564 // FindTYPEByINDEX565 // LoadTYPEByINDEX566 for _, fx := range fieldIndexes {567 if err := g.genFindTYPEByINDEX(e, fx); err != nil {568 return err569 }570 }571 mname := "EntTypeName"572 if methodMustBeUndefined(mname, "Use tag on EntBase field instead (e.g. `typename`)") {573 generatedMethods[mname] = true574 g.f("// %s returns the ent's storage name (%q)\n"+575 "func (e %s) %s() string\t{ return %#v }\n\n",576 mname, e.name,577 e.sname, mname, e.name)578 }579 mname = "EntStorage"580 if methodIsUndefined(mname) {581 generatedMethods[mname] = true582 g.f("// %s returns the storage this ent belongs to or nil if it doesn't belong anywhere.\n"+583 "func (e *%s) %s() ent.Storage\t{ return ent.GetStorage(e) }\n\n",584 mname,585 e.sname, mname)586 }587 mname = "EntNew"588 if methodIsUndefined(mname) {589 generatedMethods[mname] = true590 g.f("// %s returns a new empty %s. Used by the ent package for loading ents.\n"+591 "func (e %s) %s() ent.Ent\t{ return &%s{} }\n\n",592 mname, e.sname,593 e.sname, mname, e.sname)594 }595 mname = "MarshalJSON"596 if methodIsUndefined(mname) {597 generatedMethods[mname] = true598 g.f("// %s returns a JSON representation of e. Conforms to json.Marshaler.\n"+599 "func (e *%s) %s() ([]byte, error) { return ent.JsonEncode(e, \"\") }\n\n",600 mname,601 e.sname, mname)602 }603 mname = "UnmarshalJSON"604 if methodIsUndefined(mname) {605 generatedMethods[mname] = true606 g.f("// %s populates the ent from JSON data. Conforms to json.Unmarshaler.\n"+607 "func (e *%s) %s(b []byte) error { return ent.JsonDecode(e, b) }\n\n",608 mname,609 e.sname, mname)610 }611 mname = "String"612 if methodIsUndefined(mname) {613 generatedMethods[mname] = true614 g.f("// %s returns a JSON representation of e.\n"+615 "func (e %s) %s() string { return ent.EntString(&e) }\n\n",616 mname,617 e.sname, mname)618 }619 mname = "Create"620 if methodIsUndefined(mname) {621 generatedMethods[mname] = true622 g.f("// %s a new %s ent in storage\n"+623 "func (e *%s) %s(storage ent.Storage) error\t{ return ent.CreateEnt(e, storage) }\n",624 mname, e.name,625 e.sname, mname)626 }627 mname = "Save"628 if methodIsUndefined(mname) {629 generatedMethods[mname] = true630 g.f("// %s pending changes to whatever storage this ent was created or loaded from\n"+631 "func (e *%s) %s() error\t{ return ent.SaveEnt(e) }\n",632 mname,633 e.sname, mname)634 }635 mname = "Reload"636 if methodIsUndefined(mname) {637 generatedMethods[mname] = true638 g.f("// %s fields to latest values from storage, discarding any unsaved changes\n"+639 "func (e *%s) %s() error\t{ return ent.ReloadEnt(e) }\n",640 mname,641 e.sname, mname)642 }643 mname = "PermanentlyDelete"644 if methodIsUndefined(mname) {645 generatedMethods[mname] = true646 g.f("// %s deletes this ent from storage. This can usually not be undone.\n"+647 "func (e *%s) %s() error\t{ return ent.DeleteEnt(e) }\n",648 mname,649 e.sname, mname)650 }651 mname = "Iterator"652 if methodIsUndefined(mname) {653 generatedMethods[mname] = true654 g.f("// %s returns an iterator over all %s ents. Order is undefined.\n"+655 "func (e %s) %s(s ent.Storage) ent.EntIterator\t{ return s.IterateEnts(&e) }\n",656 mname, e.sname,657 e.sname, mname)658 }659 wline()660 // begin field accessor methods661 if len(e.fields) > 0 {662 wstr("// ---- field accessor methods ----\n\n")663 fieldsWithTags := []*EntField{}664 // field getters665 // func (e *ENTTYPE) Field() { return e.field }666 didGenerateGetters := false667 for _, field := range e.fields {668 if len(field.tags) > 0 {669 fieldsWithTags = append(fieldsWithTags, field)670 }671 // skip gettter if the field has a public name672 if field.uname == field.sname {673 continue674 }675 // skip if user has defined a method with the same name676 if !methodIsUndefined(field.uname) {677 continue678 }679 // sname is lower case; generate getter function680 // if the field has documentation, add it to the getter for nice godoc681 if len(field.doc) > 0 {682 wstr("// ")683 wstr(strings.Join(field.doc, "\n// "))684 wline()685 }686 g.f("func (e *%s) %s() %s\t{ return e.%s }\n",687 e.sname,688 field.uname,689 g.goTypeName(field.t.Type),690 field.sname,691 )692 generatedMethods[field.uname] = true693 didGenerateGetters = true694 }695 if didGenerateGetters {696 wline()697 }698 // field setters699 // func (e *Type) SetField() { e.field }700 fieldSetterPrefix := "Set"701 if g.PrivateFieldSetters {702 fieldSetterPrefix = "set"703 }704 var genChangedSetters []*EntField705 var genConditionalSetters []*EntField706 var genConditionalSettersSetNames []string707 for _, field := range e.fields {708 mname := fieldSetterPrefix + field.uname709 if !methodIsUndefined(mname) {710 if g.PrivateFieldSetters {711 continue712 }713 // If the user has defined a method with the same name, define a private lower-case version714 //715 // This can be useful for the author to use in composition, e.g.716 // // user-defined717 // func (e *Foo) SetThing(v int) {718 // if someCondition() {719 // e.setThing() // call entgen-generated method720 // }721 // }722 //723 mname = "set" + field.uname724 if !methodIsUndefined(mname) {725 // user has defined that one too; they don't want it to be generated.726 continue727 }728 }729 if types.Comparable(field.t.Type) {730 genConditionalSetters = append(genConditionalSetters, field)731 genConditionalSettersSetNames = append(genConditionalSettersSetNames, mname)732 }733 g.f("func (e *%s) %s(v %s)\t{"+734 " e.%s = v;"+735 " e.EntBase.SetEntFieldChanged(%d)"+736 "}\n",737 e.sname, mname, g.goTypeName(field.t.Type),738 field.sname,739 field.index,740 )741 generatedMethods[mname] = true742 if isMutableRefType(field.t.Type) {743 genChangedSetters = append(genChangedSetters, field)744 }745 }746 // SetFIELDIfDifferent()747 if len(genConditionalSetters) > 0 {748 wline()749 for i, field := range genConditionalSetters {750 mname := fieldSetterPrefix + field.uname + "IfDifferent"751 if !methodIsUndefined(mname) {752 continue753 }754 generatedMethods[mname] = true755 setMname := genConditionalSettersSetNames[i]756 g.f("// %s sets %s only if v is different from the current value.\n"+757 "func (e *%s) %s(v %s) bool\t{\n"+758 " if e.%s == v {\n"+759 " return false\n"+760 " }\n"+761 " e.%s(v)\n"+762 " return true\n"+763 "}\n\n",764 mname, field.sname,765 e.sname, mname, g.goTypeName(field.t.Type),766 field.sname,767 setMname,768 )769 }770 }771 // SetFIELDChanged(bool) -- only for fields of referential mutable types772 if len(genChangedSetters) > 0 {773 wline()774 for _, field := range genChangedSetters {775 mname := fieldSetterPrefix + field.uname + "Changed"776 if !methodIsUndefined(mname) {777 continue778 }779 generatedMethods[mname] = true780 g.f("func (e *%s) %s()\t{ e.EntBase.SetEntFieldChanged(%d) }\n",781 e.sname, mname, field.index)782 }783 }784 // EntEncode & EntDecode785 wstr("// ---- encode & decode methods ----\n\n")786 // -- EntEncode --787 mname := methodWarnIfDefinedAlt(788 "EntEncode",789 "Make sure to call entEncode from your EntEncode method",790 )791 generatedMethods[mname] = true792 g.f("\nfunc (e *%s) %s(c ent.Encoder, fields ent.FieldSet) {", e.sname, mname)793 // g.f("\n\teb := &e.EntBase\n")794 for _, field := range e.fields {795 g.pushPos(field.pos)796 // Note: Rather than precomputing (1<<field.index), let the compiler apply constant797 // evaluation instead. This makes the generated code more readable.798 g.f("\tif fields.Has(%d)\t{", field.index)799 err := g.codegenEncodeField(field)800 wstr(" }\n")801 g.popPos()802 if err != nil {803 return err804 }805 }806 wstr("}\n")807 // -- EntDecode --808 mname = methodWarnIfDefinedAlt(809 "EntDecode",810 "Make sure to call entDecode from your EntDecode method",811 )812 generatedMethods[mname] = true813 if err := g.genEntDecode(e, mname); err != nil {814 return err815 }816 }817 // -- EntDecodePartial --818 mname = methodWarnIfDefinedAlt(819 "EntDecodePartial",820 "Make sure to call entDecodeIndexed from your EntDecodePartial method",821 )822 generatedMethods[mname] = true823 if err := g.genEntDecodePartial(e, mname); err != nil {824 return err825 }826 // EntFields827 if methodMustBeUndefined("EntFields", "") {828 g.genEntFields(e)829 }830 // data & methods for ents with indexes831 if len(fieldIndexes) > 0 {832 // -- EntIndexes --833 if methodIsUndefined("EntIndexes") {834 generatedMethods["EntIndexes"] = true835 g.f("\n// Indexes (Name, Fields, Flags)\n")836 g.f("var ent_%s_idx = []ent.EntIndex{\n", e.sname)837 for _, x := range fieldIndexes {838 var flags []string839 if (x.flags & fieldIndexUnique) != 0 {840 flags = append(flags, "ent.EntIndexUnique")841 }842 if len(flags) == 0 {843 flags = append(flags, "0")844 }845 fieldIndices := genFieldmap(e, x.fields)846 g.f("{ %#v, %s, %s },\n", x.name, fieldIndices, strings.Join(flags, "|"))847 }848 g.f("}\n\n")849 g.f("// EntIndexes returns information about secondary indexes\n")850 g.f("func (e *%s) EntIndexes() []ent.EntIndex { return ent_%s_idx }\n",851 e.sname, e.sname)852 }853 } // if len(fieldIndexes) > 0854 if log.RootLogger.Level <= log.LevelDebug {855 log.Debug("methods generated for %s:%s", e.sname, fmtMappedNames(generatedMethods))856 }857 g.scanImportsNeededForEnt(e)858 return err859}860// typePkgName returns the package name for a type that is from an external package.861// E.g:862// package foo863// "int" => ""864// "foo.Thing" => ""865// "bar.Thing" => "bar"866// "[]bar.Thing" => "bar"867//868func (g *Codegen) typePkgName(t types.Type) string {869 if t, ok := t.(*types.Named); ok {870 if o := t.Obj(); o != nil {871 if pkg := o.Pkg(); pkg != nil && pkg != g.pkg.Types && pkg.Path() != g.pkg.Types.Path() {872 return pkg.Name()873 }874 }875 }876 return ""877}878func (g *Codegen) scanImportsNeededForEnt(e *EntInfo) {879 // collect all unique named types which has package information880 uniqueNamedTypes := make(map[*types.Named]*types.TypeName)881 for _, field := range e.fields {882 if t, ok := field.t.Type.(*types.Named); ok {883 if o := t.Obj(); o != nil {884 if o.Pkg() != nil {885 uniqueNamedTypes[t] = o886 }887 }888 }889 }890 // for each unique named type...891 ePkgPath := g.pkg.Types.Path()892 for _, o := range uniqueNamedTypes {893 pkg := o.Pkg() // note: never nil894 // log.Debug("%v\n o.id=%v, o.name=%v, pkg.name=%s, pkg.path=%q", t,895 // o.Id(), o.Name(), pkg.Name(), pkg.Path())896 pkgPath := pkg.Path()897 if pkgPath != ePkgPath && pkgPath != g.entpkgPath {898 g.imports = append(g.imports, PkgImport{Path: pkgPath})899 }900 }901}902func (g *Codegen) genEntFields(e *EntInfo) {903 // entField* constants for symbolic field indices904 var fieldmap uint64905 if len(e.fields) > 0 {906 g.s("// Symbolic field indices, for use with ent.*FieldChanged methods\n")907 g.s("const (\n")908 for _, field := range e.fields {909 fieldmap |= (1 << field.index)910 g.f(" ent_%s_f_%s\t= %d\n", e.sname, field.sname, field.index)911 }912 g.s(")\n\n")913 }914 g.f("// EntFields returns information about %s fields\n", e.sname)915 g.f("var ent_%s_fields = ent.Fields{\n", e.sname)916 g.f(" Names: []string{\n")917 for _, field := range e.fields {918 g.f(" %#v,\n", field.name)919 }920 g.f(" },\n")921 g.f(" FieldSet:\t0b%b,\n", fieldmap)922 g.f("}\n\n")923 g.f("// EntFields returns information about %s fields\n", e.sname)924 g.f("func (e %s) EntFields() ent.Fields { return ent_%s_fields }\n", e.sname, e.sname)925}926func genFieldmap(e *EntInfo, fields []*EntField) string {927 v := make([]string, len(fields))928 for i, field := range fields {929 v[i] = fmt.Sprintf("1<<ent_%s_f_%s", e.sname, field.sname)930 }931 if len(v) == 1 {932 return v[0]933 }934 return "(" + strings.Join(v, ") | (") + ")"935}936func (g *Codegen) genFindTYPEByINDEX(e *EntInfo, fx *EntFieldIndex) error {937 svar, cvar, rvar, evar, errvar, tmpvar := "s", "c", "r", "e", "err", "v"938 limitvar, flagsarg := "limit", "fl"939 // package names940 var pkgnames map[string]struct{}941 for _, f := range fx.fields {942 if pkgname := g.typePkgName(f.t.Type); pkgname != "" {943 if pkgnames == nil {944 pkgnames = make(map[string]struct{})945 }946 pkgnames[pkgname] = struct{}{}947 }948 }949 // log.Debug("package names: %v", pkgnames)950 // args951 var prevGoType string952 argchunks := make([]string, 0, len(fx.fields))953 argnames := make([]string, 0, len(fx.fields))954 for i, f := range fx.fields {955 goType := g.goTypeName(f.t.Type)956 if prevGoType == goType {957 argchunks = append(argchunks[:i-1], inverseCapitalize(fx.fields[i-1].sname))958 }959 argname := inverseCapitalize(f.sname)960 for {961 if _, ok := pkgnames[argname]; !ok {962 break963 }964 argname = argname + "_"965 }966 argchunks = append(argchunks, argname+" "+goType)967 argnames = append(argnames, argname)968 prevGoType = goType969 if argname == svar {970 svar = "_" + svar971 } else if argname == cvar {972 cvar = "_" + cvar973 } else if argname == rvar {974 rvar = "_" + rvar975 } else if argname == evar {976 evar = "_" + evar977 } else if argname == errvar {978 errvar = "_" + errvar979 } else if argname == tmpvar {980 tmpvar = "_" + tmpvar981 } else if argname == limitvar {982 limitvar = "_" + limitvar983 } else if argname == flagsarg {984 flagsarg = "_" + flagsarg985 }986 }987 // fieldIndices := genFieldmap(e, fx.fields)988 params := strings.Join(argchunks, ", ")989 var argsComment string990 if len(fx.fields) == 1 {991 argsComment = "with " + argnames[0]992 } else {993 argsComment = "matching " + strings.Join(argnames, " AND ")994 }995 // use an optimization where the index query is a single field that is a string or byte slice996 useSingleStringKeyOpt := len(fx.fields) == 1 &&997 (isStringType(fx.fields[0].t.Type) || isByteSliceType(fx.fields[0].t.Type))998 // arg0 is used by useSingleStringKeyOpt and is argnames[0] as []byte999 var arg0 string1000 if useSingleStringKeyOpt {1001 arg0 = argnames[0]1002 if isStringType(fx.fields[0].t.Type) {1003 arg0 = "[]byte(" + arg0 + ")"1004 }1005 }1006 // both load and find needs key encoder code, so generate that up front1007 var keyEncoderCode []byte1008 if !useSingleStringKeyOpt {1009 var b bytes.Buffer1010 fmt.Fprintf(&b, "func(%s ent.Encoder) {\n", cvar)1011 for i, f := range fx.fields {1012 expr, err := g.genFieldEncoder(f, cvar, argnames[i])1013 if err != nil {1014 return err1015 }1016 if len(fx.fields) > 1 {1017 fmt.Fprintf(&b, " %s.Key(%#v)\n", cvar, f.name)1018 }1019 fmt.Fprintf(&b, " %s\n", expr)1020 }1021 b.WriteString(" }")1022 keyEncoderCode = b.Bytes()1023 }1024 //1025 // Load__By__1026 fname := "Load" + e.sname + "By" + capitalize(fx.name)1027 if fx.IsUnique() {1028 g.f("// %s loads %s %s\n", fname, e.sname, argsComment)1029 g.f("func %s(%s ent.Storage, %s, %s ...ent.LookupFlags) (*%s, error)\t{\n",1030 fname, svar, params, flagsarg, e.sname)1031 g.f(" %s := &%s{}\n", evar, e.sname)1032 if useSingleStringKeyOpt {1033 g.f(" %s := ent.LoadEntByIndexKey(%s, %s, &ent_%s_idx[%d], %s, %s)\n",1034 errvar, svar, evar, e.sname, fx.index, arg0, flagsarg)1035 } else {1036 g.f(" %s := ent.LoadEntByIndex(%s, %s, &ent_%s_idx[%d], %s, %d, %s)\n",1037 errvar, svar, evar, e.sname, fx.index, flagsarg, len(fx.fields), keyEncoderCode)1038 }1039 g.f(" return %s, %s\n", evar, errvar)1040 g.s("}\n\n")1041 } else {1042 sliceCast, err := g.getEntSliceCastHelper(e)1043 if err != nil {1044 return err1045 }1046 g.f("// %s loads all %s ents %s\n", fname, e.sname, argsComment)1047 g.f("func %s(%s ent.Storage, %s, %s int, %s ...ent.LookupFlags) ([]*%s, error)\t{\n",1048 fname, svar, params, limitvar, flagsarg, e.sname)1049 g.f(" %s := &%s{}\n", evar, e.sname)1050 if useSingleStringKeyOpt {1051 g.f(" %s, %s := ent.LoadEntsByIndexKey(%s, %s, &ent_%s_idx[%d], %s, %s, %s)\n",1052 rvar, errvar, svar, evar, e.sname, fx.index, arg0, limitvar, flagsarg)1053 } else {1054 g.f(" %s, %s := ent.LoadEntsByIndex(%s, %s, &ent_%s_idx[%d], %s, %s, %d, %s)\n",1055 rvar, errvar,1056 svar, evar, e.sname, fx.index, limitvar, flagsarg, len(fx.fields), keyEncoderCode)1057 }1058 g.f(" return %s(%s), %s\n", sliceCast, rvar, errvar)1059 g.s("}\n\n")1060 }1061 //1062 // Find__By__1063 fname = "Find" + e.sname + "By" + capitalize(fx.name)1064 if fx.IsUnique() {1065 g.f("// %s looks up %s id %s\n", fname, e.sname, argsComment)1066 g.f("func %s(%s ent.Storage, %s, %s ...ent.LookupFlags) (uint64, error)\t{\n",1067 fname, svar, params, flagsarg)1068 if useSingleStringKeyOpt {1069 g.f(" return ent.FindIdByIndexKey(%s, %#v, &ent_%s_idx[%d], %s, %s)\n",1070 svar, e.name, e.sname, fx.index, arg0, flagsarg)1071 } else {1072 g.f(" return ent.FindIdByIndex(%s, %#v, &ent_%s_idx[%d], %s, %d, %s)\n",1073 svar, e.name, e.sname, fx.index, flagsarg, len(fx.fields), keyEncoderCode)1074 }1075 g.s("}\n\n")1076 } else {1077 g.f("// %s looks up %s ids %s\n", fname, e.sname, argsComment)1078 g.f("func %s(%s ent.Storage, %s, %s int, %s ...ent.LookupFlags) ([]uint64, error)\t{\n",1079 fname, svar, params, limitvar, flagsarg)1080 if useSingleStringKeyOpt {1081 g.f(" return ent.FindIdsByIndexKey(%s, %#v, &ent_%s_idx[%d], %s, %s, %s)\n",1082 svar, e.name, e.sname, fx.index, arg0, limitvar, flagsarg)1083 } else {1084 g.f(" return ent.FindIdsByIndex(%s, %#v, &ent_%s_idx[%d], %s, %s, %d, %s)\n",1085 svar, e.name, e.sname, fx.index, limitvar, flagsarg, len(fx.fields), keyEncoderCode)1086 }1087 g.s("}\n\n")1088 }1089 return nil1090}1091func (g *Codegen) getEntSliceCastHelper(e *EntInfo) (string, error) {1092 fname := fmt.Sprintf("ent_%s_slice_cast", e.sname)1093 err := g.getOrBuildHelper(fname, "c", nil,1094 func(typ types.Type, cvar string, buf *bytes.Buffer) error {1095 wf := func(format string, args ...interface{}) {1096 fmt.Fprintf(buf, format, args...)1097 }1098 wf("(s []ent.Ent) []*%s {\n", e.sname)1099 wf(" v := make([]*%s, len(s))\n", e.sname)1100 wf(" for i := 0; i < len(s); i++ {\n")1101 wf(" v[i] = s[i].(*%s)\n", e.sname)1102 wf(" }\n")1103 wf(" return v\n")1104 wf("}\n")1105 return nil1106 })1107 return fname, err1108}1109func (g *Codegen) genEntDecode(e *EntInfo, mname string) error {1110 g.f("\n// %s populates fields from a decoder\n", mname)1111 g.f("func (e *%s) %s(c ent.Decoder) (id, version uint64) {\n", e.sname, mname)1112 g.s(" for {\n")1113 g.s(" switch string(c.Key()) {\n")1114 g.s(" case \"\": return\n")1115 g.s(" case ent.FieldNameId: id = c.Uint(64)\n")1116 g.s(" case ent.FieldNameVersion: version = c.Uint(64)\n")1117 for _, field := range e.fields {1118 g.pushPos(field.pos)1119 g.f(" case %#v:\n", field.name)1120 err := g.codegenDecodeField(field)1121 g.popPos()1122 if err != nil {1123 return err1124 }1125 }1126 g.s(" default: c.Discard()\n")1127 g.s(" }\n")1128 g.s(" }\n")1129 g.s(" return\n")1130 g.s("}\n")1131 return nil1132}1133func (g *Codegen) genEntDecodePartial(e *EntInfo, mname string) error {1134 var indexedFields []*EntField1135 for _, field := range e.fields {1136 if field.storageIndex != nil {1137 indexedFields = append(indexedFields, field)1138 }1139 }1140 g.f("\n// %s is used internally by ent.Storage during updates.\n", mname)1141 g.f("func (e *%s) %s(c ent.Decoder, fields ent.FieldSet) (version uint64) {\n", e.sname, mname)1142 g.f(" for n := %d; n > 0; {\n", len(indexedFields))1143 g.s(" switch string(c.Key()) {\n")1144 g.s(" case \"\": return\n")1145 g.s(" case ent.FieldNameVersion: version = c.Uint(64); continue\n")1146 for _, field := range indexedFields {1147 g.pushPos(field.pos)1148 g.f(" case %#v:\n", field.name)1149 g.s(" n--\n")1150 g.f(" if fields.Has(%d) {\n", field.index)1151 err := g.codegenDecodeField(field)1152 g.s(" continue\n")1153 g.s(" }\n")1154 g.popPos()1155 if err != nil {1156 return err1157 }1158 }1159 g.s(" }\n")1160 g.s(" c.Discard()\n")1161 g.s(" }\n")1162 g.s(" return\n")1163 g.s("}\n")1164 return nil1165}1166// âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ1167// collectFieldIndexes builds EntFieldIndex for all indexes defined by field tags.1168// The returned list is sorted on name1169func (g *Codegen) collectFieldIndexes(fields []*EntField) []*EntFieldIndex {1170 // check field tags and pick out fields with an index1171 m := make(map[string]*EntFieldIndex, len(fields))1172 addIndex := func(index *EntFieldIndex) *EntFieldIndex {1173 x := m[index.name]1174 if x == nil {1175 m[index.name] = index1176 x = index1177 } else {1178 x.flags |= index.flags1179 x.fields = append(x.fields, index.fields[0])1180 }1181 return x1182 }1183 for _, field := range fields {1184 if len(field.tags) == 0 {1185 continue1186 }1187 g.pushPos(field.pos)1188 for _, tag := range field.tags {1189 // tag="key=foo=bar" => key="key", val="foo=bar"1190 // tag="key" => key="key", val="fieldname"1191 key, val := tag, field.name1192 if i := strings.IndexByte(key, '='); i != -1 {1193 val = key[i+1:]1194 key = key[:i]1195 }1196 key = strings.ToLower(key)1197 var index *EntFieldIndex1198 switch key {1199 case "index":1200 index = &EntFieldIndex{name: val}1201 case "unique":1202 index = &EntFieldIndex{name: val, flags: fieldIndexUnique}1203 case "":1204 // silently ignore1205 default:1206 g.logSrcWarn("unknown field tag %q on field %s; ignoring", tag, field.sname)1207 }1208 if index != nil {1209 if field.storageIndex != nil {1210 g.logSrcErr("multiple indexes defined for field %s", field.sname)1211 } else {1212 index.fields = []*EntField{field}1213 field.storageIndex = addIndex(index)1214 }1215 }1216 }1217 g.popPos()1218 }1219 if len(m) == 0 {1220 return nil1221 }1222 // sort by name1223 indexes := make([]*EntFieldIndex, 0, len(m))1224 for _, x := range m {1225 indexes = append(indexes, x)1226 }1227 sort.Sort(EntFieldIndexes(indexes))1228 // assign table indices1229 for i, x := range indexes {1230 x.index = i1231 }...
lex.go
Source:lex.go
...104func (j *json) newOperator(name string, params []any) any {105 if name == "" {106 return nil // an operator error is in progress107 }108 opPos := j.popPos()109 op, err := j.getOperator(Operator{Name: name, Params: params}, opPos)110 if err != nil {111 j.fatal(err.Error(), opPos)112 return nil113 }114 return op115}116func (j *json) pushPos(pos Position) {117 j.stackPos = append(j.stackPos, pos)118}119func (j *json) popPos() Position {120 last := len(j.stackPos) - 1121 pos := j.stackPos[last]122 j.stackPos = j.stackPos[:last]123 return pos124}125func (j *json) moveHoriz(bytes int, runes ...int) {126 j.pos = j.pos.incHoriz(bytes, runes...)127 j.curSize = 0128}129func (j *json) getOperator(operator Operator, opPos Position) (any, error) {130 if j.opts.OpFn == nil {131 return nil, fmt.Errorf("unknown operator %q", operator.Name)132 }133 return j.opts.OpFn(operator, opPos)...
popPos
Using AI Code Generation
1import (2func main() {3 var jsonBlob = []byte(`[4 {"Name": "Platypus", "Order": "Monotremata"},5 {"Name": "Quoll", "Order": "Dasyuromorphia"}6 type Animal struct {7 }8 err := json.Unmarshal(jsonBlob, &animals)9 if err != nil {10 fmt.Println("error:", err)11 }12 fmt.Printf("%+v13 animals = animals[:len(animals)-1]14 fmt.Printf("%+v15}16[{{Name:Platypus Order:Monotremata} {Name:Quoll Order:Dasyuromorphia}}]17[{{Name:Platypus Order:Monotremata}}]
popPos
Using AI Code Generation
1import (2func main() {3 j.pushPos(1,2)4 j.pushPos(3,4)5 j.pushPos(5,6)6 j.pushPos(7,8)7 j.pushPos(9,10)8 j.pushPos(11,12)9 j.pushPos(13,14)10 j.pushPos(15,16)11 j.pushPos(17,18)12 j.pushPos(19,20)13 j.pushPos(21,22)14 j.pushPos(23,24)15 j.pushPos(25,26)16 j.pushPos(27,28)17 j.pushPos(29,30)18 j.pushPos(31,32)19 j.pushPos(33,34)20 j.pushPos(35,36)21 j.pushPos(37,38)22 j.pushPos(39,40)23 j.pushPos(41,42)24 j.pushPos(43,44)25 j.pushPos(45,46)26 j.pushPos(47,48)27 j.pushPos(49,50)28 j.pushPos(51,52)29 j.pushPos(53,54)30 j.pushPos(55,56)31 j.pushPos(57,58)32 j.pushPos(59,60)33 j.pushPos(61,62)34 j.pushPos(63,64)35 j.pushPos(65,66)36 j.pushPos(67,68)37 j.pushPos(69,70)38 j.pushPos(71,72)39 j.pushPos(73,74)40 j.pushPos(75,76)41 j.pushPos(77,78)42 j.pushPos(79,80)43 j.pushPos(81,82)44 j.pushPos(83,84)45 j.pushPos(85,86)46 j.pushPos(87,88)47 j.pushPos(89,90)48 j.pushPos(91,92)49 j.pushPos(93,94)50 j.pushPos(95,96)51 j.pushPos(97,98)52 j.pushPos(99,100)53 j.pushPos(101,102)54 j.pushPos(103,104)55 j.pushPos(105,106)56 j.pushPos(107,108)57 j.pushPos(109,110)58 j.pushPos(111,112)59 j.pushPos(113,114)60 j.pushPos(115,116)61 j.pushPos(117,118)62 j.pushPos(119
popPos
Using AI Code Generation
1import (2func main() {3 jsonString := `{"name":"John","age":30,"cars":["Ford","BMW","Fiat"]}`4 byteArray := []byte(jsonString)5 json := json.NewDecoder(byteArray)6 fmt.Println(json.PopPos())
popPos
Using AI Code Generation
1import "fmt"2import "encoding/json"3func main() {4 js = []byte(`{"a": 1, "b": 2}`)5 fmt.Println(js)6 fmt.Println(js.popPos())7}8import "fmt"9import "encoding/json"10func main() {11 js = []byte(`{"a": 1, "b": 2}`)12 fmt.Println(js)13 fmt.Println(js.popPos())14}15import "fmt"16import "encoding/json"17func main() {18 js = []byte(`{"a": 1, "b": 2}`)19 fmt.Println(js)20 fmt.Println(js.popPos())21}22import "fmt"23import "encoding/json"24func main() {25 js = []byte(`{"a": 1, "b": 2}`)26 fmt.Println(js)27 fmt.Println(js.popPos())28}29import "fmt"30import "encoding/json"31func main() {32 js = []byte(`{"a": 1, "b": 2}`)33 fmt.Println(js)34 fmt.Println(js.popPos())35}36import "fmt"37import "encoding/json"38func main() {39 js = []byte(`{"a": 1, "b": 2}`)40 fmt.Println(js)41 fmt.Println(js.popPos())42}43import "fmt"44import "encoding/json"45func main() {46 js = []byte(`{"a": 1, "b": 2}`)47 fmt.Println(js)48 fmt.Println(js.popPos())49}
popPos
Using AI Code Generation
1import (2func main() {3json := []byte(`{"id":1,"name":"golang","age":6}`)4id, err := jsonparser.GetInt(json, "id")5if err != nil {6fmt.Println(err)7}8fmt.Println(id)9name, err := jsonparser.GetString(json, "name")10if err != nil {11fmt.Println(err)12}13fmt.Println(name)14age, err := jsonparser.GetInt(json, "age")15if err != nil {16fmt.Println(err)17}18fmt.Println(age)19}20jsonparser.popPos(data []byte, pos []int, keys ...string) (value []byte, dataType jsonparser.ValueType, offset int, err error)21import (22func main() {23json := []byte(`{"id":1,"name":"golang","age":6}`)24id, err := jsonparser.GetInt(json, "id")25if err != nil {26fmt.Println(err)27}28fmt.Println(id)29name, err := jsonparser.GetString(json, "name")30if err != nil {31fmt.Println(err)32}33fmt.Println(name)34age, err := jsonparser.GetInt(json, "age")35if err != nil {36fmt.Println(err)37}38fmt.Println(age)39}40jsonparser.popArray(data []byte, keys ...string) (value []byte, dataType jsonparser.ValueType, offset int, err error)41import (
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!