How to use IsConvertible method of types Package

Best Go-testdeep code snippet using types.IsConvertible

conversion.go

Source:conversion.go Github

copy

Full Screen

1/*2Copyright 2016 The Kubernetes Authors.3Licensed under the Apache License, Version 2.0 (the "License");4you may not use this file except in compliance with the License.5You may obtain a copy of the License at6 http://www.apache.org/licenses/LICENSE-2.07Unless required by applicable law or agreed to in writing, software8distributed under the License is distributed on an "AS IS" BASIS,9WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.10See the License for the specific language governing permissions and11limitations under the License.12*/13package generators14import (15 "bytes"16 "fmt"17 "io"18 "path/filepath"19 "strings"20 "k8s.io/kubernetes/cmd/libs/go2idl/args"21 "k8s.io/kubernetes/cmd/libs/go2idl/generator"22 "k8s.io/kubernetes/cmd/libs/go2idl/namer"23 "k8s.io/kubernetes/cmd/libs/go2idl/types"24 "k8s.io/kubernetes/pkg/util/sets"25 "github.com/golang/glog"26)27// CustomArgs is used tby the go2idl framework to pass args specific to this28// generator.29type CustomArgs struct {30 ExtraPeerDirs []string // Always consider these as last-ditch possibilities for conversions.31}32// This is the comment tag that carries parameters for conversion generation.33const tagName = "k8s:conversion-gen"34func extractTag(comments []string) []string {35 return types.ExtractCommentTags("+", comments)[tagName]36}37// TODO: This is created only to reduce number of changes in a single PR.38// Remove it and use PublicNamer instead.39func conversionNamer() *namer.NameStrategy {40 return &namer.NameStrategy{41 Join: func(pre string, in []string, post string) string {42 return strings.Join(in, "_")43 },44 PrependPackageNames: 1,45 }46}47func defaultFnNamer() *namer.NameStrategy {48 return &namer.NameStrategy{49 Prefix: "SetDefaults_",50 Join: func(pre string, in []string, post string) string {51 return pre + strings.Join(in, "_") + post52 },53 }54}55// NameSystems returns the name system used by the generators in this package.56func NameSystems() namer.NameSystems {57 return namer.NameSystems{58 "public": conversionNamer(),59 "raw": namer.NewRawNamer("", nil),60 "defaultfn": defaultFnNamer(),61 }62}63// DefaultNameSystem returns the default name system for ordering the types to be64// processed by the generators in this package.65func DefaultNameSystem() string {66 return "public"67}68func getPeerTypeFor(context *generator.Context, t *types.Type, potenialPeerPkgs []string) *types.Type {69 for _, ppp := range potenialPeerPkgs {70 p := context.Universe.Package(ppp)71 if p == nil {72 continue73 }74 if p.Has(t.Name.Name) {75 return p.Type(t.Name.Name)76 }77 }78 return nil79}80type conversionPair struct {81 inType *types.Type82 outType *types.Type83}84// All of the types in conversions map are of type "DeclarationOf" with85// the underlying type being "Func".86type conversionFuncMap map[conversionPair]*types.Type87// Returns all manually-defined conversion functions in the package.88func getManualConversionFunctions(context *generator.Context, pkg *types.Package, manualMap conversionFuncMap) {89 scopeName := types.Name{Package: conversionPackagePath, Name: "Scope"}90 errorName := types.Name{Package: "", Name: "error"}91 buffer := &bytes.Buffer{}92 sw := generator.NewSnippetWriter(buffer, context, "$", "$")93 for _, f := range pkg.Functions {94 if f.Underlying == nil || f.Underlying.Kind != types.Func {95 glog.Errorf("Malformed function: %#v", f)96 continue97 }98 if f.Underlying.Signature == nil {99 glog.Errorf("Function without signature: %#v", f)100 continue101 }102 signature := f.Underlying.Signature103 // Check whether the function is conversion function.104 // Note that all of them have signature:105 // func Convert_inType_To_outType(inType, outType, conversion.Scope) error106 if signature.Receiver != nil {107 continue108 }109 if len(signature.Parameters) != 3 || signature.Parameters[2].Name != scopeName {110 continue111 }112 if len(signature.Results) != 1 || signature.Results[0].Name != errorName {113 continue114 }115 inType := signature.Parameters[0]116 outType := signature.Parameters[1]117 if inType.Kind != types.Pointer || outType.Kind != types.Pointer {118 continue119 }120 // Now check if the name satisfies the convention.121 args := argsFromType(inType.Elem, outType.Elem)122 sw.Do("Convert_$.inType|public$_To_$.outType|public$", args)123 if f.Name.Name == buffer.String() {124 key := conversionPair{inType.Elem, outType.Elem}125 // We might scan the same package twice, and that's OK.126 if v, ok := manualMap[key]; ok && v != nil && v.Name.Package != pkg.Path {127 panic(fmt.Sprintf("duplicate static conversion defined: %#v", key))128 }129 manualMap[key] = f130 }131 buffer.Reset()132 }133}134// All of the types in conversions map are of type "DeclarationOf" with135// the underlying type being "Func".136type defaulterFuncMap map[*types.Type]*types.Type137// Returns all manually-defined defaulting functions in the package.138func getManualDefaultingFunctions(context *generator.Context, pkg *types.Package, manualMap defaulterFuncMap) {139 buffer := &bytes.Buffer{}140 sw := generator.NewSnippetWriter(buffer, context, "$", "$")141 for _, f := range pkg.Functions {142 if f.Underlying == nil || f.Underlying.Kind != types.Func {143 glog.Errorf("Malformed function: %#v", f)144 continue145 }146 if f.Underlying.Signature == nil {147 glog.Errorf("Function without signature: %#v", f)148 continue149 }150 signature := f.Underlying.Signature151 // Check whether the function is conversion function.152 // Note that all of them have signature:153 // func Convert_inType_To_outType(inType, outType, conversion.Scope) error154 if signature.Receiver != nil {155 continue156 }157 if len(signature.Parameters) != 1 {158 continue159 }160 if len(signature.Results) != 0 {161 continue162 }163 inType := signature.Parameters[0]164 if inType.Kind != types.Pointer {165 continue166 }167 // Now check if the name satisfies the convention.168 args := defaultingArgsFromType(inType.Elem)169 sw.Do("$.inType|defaultfn$", args)170 if f.Name.Name == buffer.String() {171 key := inType.Elem172 // We might scan the same package twice, and that's OK.173 if v, ok := manualMap[key]; ok && v != nil && v.Name.Package != pkg.Path {174 panic(fmt.Sprintf("duplicate static defaulter defined: %#v", key))175 }176 manualMap[key] = f177 }178 buffer.Reset()179 }180}181func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages {182 boilerplate, err := arguments.LoadGoBoilerplate()183 if err != nil {184 glog.Fatalf("Failed loading boilerplate: %v", err)185 }186 inputs := sets.NewString(context.Inputs...)187 packages := generator.Packages{}188 header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...)189 header = append(header, []byte(190 `191// This file was autogenerated by conversion-gen. Do not edit it manually!192`)...)193 // Accumulate pre-existing conversion and default functions.194 // TODO: This is too ad-hoc. We need a better way.195 manualConversions := conversionFuncMap{}196 manualDefaults := defaulterFuncMap{}197 // We are generating conversions only for packages that are explicitly198 // passed as InputDir.199 for i := range inputs {200 glog.V(5).Infof("considering pkg %q", i)201 pkg := context.Universe[i]202 if pkg == nil {203 // If the input had no Go files, for example.204 continue205 }206 // Add conversion and defaulting functions.207 getManualConversionFunctions(context, pkg, manualConversions)208 getManualDefaultingFunctions(context, pkg, manualDefaults)209 // Only generate conversions for packages which explicitly request it210 // by specifying one or more "+k8s:conversion-gen=<peer-pkg>"211 // in their doc.go file.212 peerPkgs := extractTag(pkg.Comments)213 if peerPkgs != nil {214 glog.V(5).Infof(" tags: %q", peerPkgs)215 } else {216 glog.V(5).Infof(" no tag")217 continue218 }219 if customArgs, ok := arguments.CustomArgs.(*CustomArgs); ok {220 if len(customArgs.ExtraPeerDirs) > 0 {221 peerPkgs = append(peerPkgs, customArgs.ExtraPeerDirs...)222 }223 }224 // Make sure our peer-packages are added and fully parsed.225 for _, pp := range peerPkgs {226 context.AddDir(pp)227 getManualConversionFunctions(context, context.Universe[pp], manualConversions)228 getManualDefaultingFunctions(context, context.Universe[pp], manualDefaults)229 }230 pkgNeedsGeneration := false231 for _, t := range pkg.Types {232 // Check whether this type can be auto-converted to the peer233 // package type.234 peerType := getPeerTypeFor(context, t, peerPkgs)235 if peerType == nil {236 // We did not find a corresponding type.237 continue238 }239 if namer.IsPrivateGoName(peerType.Name.Name) {240 // We won't be able to convert to a private type.241 glog.V(5).Infof(" found a peer type %v, but it is a private name", t)242 continue243 }244 // If we can generate conversion in any direction, we should245 // generate this package.246 if isConvertible(t, peerType, manualConversions) || isConvertible(peerType, t, manualConversions) {247 pkgNeedsGeneration = true248 break249 }250 }251 if !pkgNeedsGeneration {252 glog.V(5).Infof(" no viable conversions, not generating for this package")253 continue254 }255 packages = append(packages,256 &generator.DefaultPackage{257 PackageName: filepath.Base(pkg.Path),258 PackagePath: pkg.Path,259 HeaderText: header,260 GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {261 generators = []generator.Generator{}262 generators = append(263 generators, NewGenConversion(arguments.OutputFileBaseName, pkg.Path, manualConversions, manualDefaults, peerPkgs))264 return generators265 },266 FilterFunc: func(c *generator.Context, t *types.Type) bool {267 return t.Name.Package == pkg.Path268 },269 })270 }271 return packages272}273func findMember(t *types.Type, name string) (types.Member, bool) {274 if t.Kind != types.Struct {275 return types.Member{}, false276 }277 for _, member := range t.Members {278 if member.Name == name {279 return member, true280 }281 }282 return types.Member{}, false283}284func isConvertible(in, out *types.Type, manualConversions conversionFuncMap) bool {285 // If there is pre-existing conversion function, return true immediately.286 if _, ok := manualConversions[conversionPair{in, out}]; ok {287 return true288 }289 return isDirectlyConvertible(in, out, manualConversions)290}291func isDirectlyConvertible(in, out *types.Type, manualConversions conversionFuncMap) bool {292 // If one of the types is Alias, resolve it.293 if in.Kind == types.Alias {294 return isConvertible(in.Underlying, out, manualConversions)295 }296 if out.Kind == types.Alias {297 return isConvertible(in, out.Underlying, manualConversions)298 }299 if in == out {300 return true301 }302 if in.Kind != out.Kind {303 return false304 }305 switch in.Kind {306 case types.Builtin, types.Struct, types.Map, types.Slice, types.Pointer:307 default:308 // We don't support conversion of other types yet.309 return false310 }311 switch in.Kind {312 case types.Builtin:313 // TODO: Support more conversion types.314 return types.IsInteger(in) && types.IsInteger(out)315 case types.Struct:316 convertible := true317 for _, inMember := range in.Members {318 // Check if this member is excluded from conversion319 if tagvals := extractTag(inMember.CommentLines); tagvals != nil && tagvals[0] == "false" {320 continue321 }322 // Check if there is an out member with that name.323 outMember, found := findMember(out, inMember.Name)324 if !found {325 return false326 }327 convertible = convertible && isConvertible(inMember.Type, outMember.Type, manualConversions)328 }329 return convertible330 case types.Map:331 return isConvertible(in.Key, out.Key, manualConversions) && isConvertible(in.Elem, out.Elem, manualConversions)332 case types.Slice:333 return isConvertible(in.Elem, out.Elem, manualConversions)334 case types.Pointer:335 return isConvertible(in.Elem, out.Elem, manualConversions)336 }337 glog.Fatalf("All other types should be filtered before")338 return false339}340// unwrapAlias recurses down aliased types to find the bedrock type.341func unwrapAlias(in *types.Type) *types.Type {342 if in.Kind == types.Alias {343 return unwrapAlias(in.Underlying)344 }345 return in346}347func areTypesAliased(in, out *types.Type) bool {348 // If one of the types is Alias, resolve it.349 if in.Kind == types.Alias {350 return areTypesAliased(in.Underlying, out)351 }352 if out.Kind == types.Alias {353 return areTypesAliased(in, out.Underlying)354 }355 return in == out356}357const (358 apiPackagePath = "k8s.io/kubernetes/pkg/api"359 conversionPackagePath = "k8s.io/kubernetes/pkg/conversion"360)361// genConversion produces a file with a autogenerated conversions.362type genConversion struct {363 generator.DefaultGen364 targetPackage string365 peerPackages []string366 manualConversions conversionFuncMap367 manualDefaulters defaulterFuncMap368 imports namer.ImportTracker369 typesForInit []conversionPair370 globalVariables map[string]interface{}371}372func NewGenConversion(sanitizedName, targetPackage string, manualConversions conversionFuncMap, manualDefaulters defaulterFuncMap, peerPkgs []string) generator.Generator {373 return &genConversion{374 DefaultGen: generator.DefaultGen{375 OptionalName: sanitizedName,376 },377 targetPackage: targetPackage,378 peerPackages: peerPkgs,379 manualConversions: manualConversions,380 manualDefaulters: manualDefaulters,381 imports: generator.NewImportTracker(),382 typesForInit: make([]conversionPair, 0),383 }384}385func (g *genConversion) Namers(c *generator.Context) namer.NameSystems {386 // Have the raw namer for this file track what it imports.387 return namer.NameSystems{"raw": namer.NewRawNamer(g.targetPackage, g.imports)}388}389func (g *genConversion) convertibleOnlyWithinPackage(inType, outType *types.Type) bool {390 var t *types.Type391 var other *types.Type392 if inType.Name.Package == g.targetPackage {393 t, other = inType, outType394 } else {395 t, other = outType, inType396 }397 if t.Name.Package != g.targetPackage {398 return false399 }400 // If the type has opted out, skip it.401 tagvals := extractTag(t.CommentLines)402 if tagvals != nil {403 if tagvals[0] != "false" {404 glog.Fatalf("Type %v: unsupported %s value: %q", t, tagName, tagvals[0])405 }406 glog.V(5).Infof("type %v requests no conversion generation, skipping", t)407 return false408 }409 // TODO: Consider generating functions for other kinds too.410 if t.Kind != types.Struct {411 return false412 }413 // Also, filter out private types.414 if namer.IsPrivateGoName(other.Name.Name) {415 return false416 }417 return true418}419func (g *genConversion) Filter(c *generator.Context, t *types.Type) bool {420 peerType := getPeerTypeFor(c, t, g.peerPackages)421 if peerType == nil {422 return false423 }424 if !g.convertibleOnlyWithinPackage(t, peerType) {425 return false426 }427 // We explicitly return true if any conversion is possible - this needs428 // to be checked again while generating code for that type.429 convertible := false430 if isConvertible(t, peerType, g.manualConversions) {431 g.typesForInit = append(g.typesForInit, conversionPair{t, peerType})432 convertible = true433 }434 if isConvertible(peerType, t, g.manualConversions) {435 g.typesForInit = append(g.typesForInit, conversionPair{peerType, t})436 convertible = true437 }438 return convertible439}440func (g *genConversion) isOtherPackage(pkg string) bool {441 if pkg == g.targetPackage {442 return false443 }444 if strings.HasSuffix(pkg, `"`+g.targetPackage+`"`) {445 return false446 }447 return true448}449func (g *genConversion) Imports(c *generator.Context) (imports []string) {450 var importLines []string451 for _, singleImport := range g.imports.ImportLines() {452 if g.isOtherPackage(singleImport) {453 importLines = append(importLines, singleImport)454 }455 }456 return importLines457}458func (g *genConversion) withGlobals(args map[string]interface{}) map[string]interface{} {459 for k, v := range g.globalVariables {460 if _, ok := args[k]; !ok {461 args[k] = v462 }463 }464 return args465}466func argsFromType(inType, outType *types.Type) map[string]interface{} {467 return map[string]interface{}{468 "inType": inType,469 "outType": outType,470 }471}472func defaultingArgsFromType(inType *types.Type) interface{} {473 return map[string]interface{}{474 "inType": inType,475 }476}477func (g *genConversion) funcNameTmpl(inType, outType *types.Type) string {478 tmpl := "Convert_$.inType|public$_To_$.outType|public$"479 g.imports.AddType(inType)480 g.imports.AddType(outType)481 return tmpl482}483func (g *genConversion) preexists(inType, outType *types.Type) (*types.Type, bool) {484 function, ok := g.manualConversions[conversionPair{inType, outType}]485 return function, ok486}487func (g *genConversion) Init(c *generator.Context, w io.Writer) error {488 scheme := c.Universe.Variable(types.Name{Package: apiPackagePath, Name: "Scheme"})489 g.imports.AddType(scheme)490 scope := c.Universe.Type(types.Name{Package: conversionPackagePath, Name: "Scope"})491 g.imports.AddType(scope)492 g.globalVariables = map[string]interface{}{493 "scheme": scheme,494 "Scope": scope,495 }496 sw := generator.NewSnippetWriter(w, c, "$", "$")497 sw.Do("func init() {\n", nil)498 sw.Do("if err := $.scheme|raw$.AddGeneratedConversionFuncs(\n", map[string]interface{}{499 "scheme": scheme,500 })501 for _, conv := range g.typesForInit {502 funcName := g.funcNameTmpl(conv.inType, conv.outType)503 sw.Do(fmt.Sprintf("%s,\n", funcName), argsFromType(conv.inType, conv.outType))504 }505 sw.Do("); err != nil {\n", nil)506 sw.Do("// if one of the conversion functions is malformed, detect it immediately.\n", nil)507 sw.Do("panic(err)\n", nil)508 sw.Do("}\n", nil)509 sw.Do("}\n\n", nil)510 return sw.Error()511}512func (g *genConversion) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error {513 glog.V(5).Infof("generating for type %v", t)514 sw := generator.NewSnippetWriter(w, c, "$", "$")515 peerType := getPeerTypeFor(c, t, g.peerPackages)516 didForward, didBackward := false, false517 if isDirectlyConvertible(t, peerType, g.manualConversions) {518 didForward = true519 g.generateConversion(t, peerType, sw)520 }521 if isDirectlyConvertible(peerType, t, g.manualConversions) {522 didBackward = true523 g.generateConversion(peerType, t, sw)524 }525 if didForward != didBackward {526 glog.Fatalf("Could only generate one direction of conversion for %v <-> %v", t, peerType)527 }528 if !didForward && !didBackward {529 // TODO: This should be fatal but we have at least 8 types that530 // currently fail this. The right thing to do is to figure out why they531 // can't be generated and mark those fields as532 // +k8s:conversion-gen=false, and ONLY do manual conversions for those533 // fields, with the manual Convert_...() calling autoConvert_...()534 // first.535 glog.Errorf("Warning: could not generate autoConvert functions for %v <-> %v", t, peerType)536 }537 return sw.Error()538}539func (g *genConversion) generateConversion(inType, outType *types.Type, sw *generator.SnippetWriter) {540 funcName := g.funcNameTmpl(inType, outType)541 sw.Do(fmt.Sprintf("func auto%s(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", funcName), g.withGlobals(argsFromType(inType, outType)))542 // if no defaulter of form SetDefaults_XXX is defined, do not inline a check for defaulting.543 if function, ok := g.manualDefaulters[inType]; ok {544 sw.Do("$.|raw$(in)\n", function)545 }546 g.generateFor(inType, outType, sw)547 sw.Do("return nil\n", nil)548 sw.Do("}\n\n", nil)549 // If there is no public manual Conversion method, generate it.550 if _, ok := g.preexists(inType, outType); !ok {551 sw.Do(fmt.Sprintf("func %s(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", funcName), g.withGlobals(argsFromType(inType, outType)))552 sw.Do(fmt.Sprintf("return auto%s(in, out, s)\n", funcName), argsFromType(inType, outType))553 sw.Do("}\n\n", nil)554 }555}556// we use the system of shadowing 'in' and 'out' so that the same code is valid557// at any nesting level. This makes the autogenerator easy to understand, and558// the compiler shouldn't care.559func (g *genConversion) generateFor(inType, outType *types.Type, sw *generator.SnippetWriter) {560 var f func(*types.Type, *types.Type, *generator.SnippetWriter)561 switch inType.Kind {562 case types.Builtin:563 f = g.doBuiltin564 case types.Map:565 f = g.doMap566 case types.Slice:567 f = g.doSlice568 case types.Struct:569 f = g.doStruct570 case types.Pointer:571 f = g.doPointer572 case types.Alias:573 f = g.doAlias574 default:575 f = g.doUnknown576 }577 f(inType, outType, sw)578}579func (g *genConversion) doBuiltin(inType, outType *types.Type, sw *generator.SnippetWriter) {580 if inType == outType {581 sw.Do("*out = *in\n", nil)582 } else {583 sw.Do("*out = $.|raw$(*in)\n", outType)584 }585}586func (g *genConversion) doMap(inType, outType *types.Type, sw *generator.SnippetWriter) {587 sw.Do("*out = make($.|raw$, len(*in))\n", outType)588 if isDirectlyAssignable(inType.Key, outType.Key) {589 sw.Do("for key, val := range *in {\n", nil)590 if isDirectlyAssignable(inType.Elem, outType.Elem) {591 if inType.Key == outType.Key {592 sw.Do("(*out)[key] = ", nil)593 } else {594 sw.Do("(*out)[$.|raw$(key)] = ", outType.Key)595 }596 if inType.Elem == outType.Elem {597 sw.Do("val\n", nil)598 } else {599 sw.Do("$.|raw$(val)\n", outType.Elem)600 }601 } else {602 sw.Do("newVal := new($.|raw$)\n", outType.Elem)603 if function, ok := g.preexists(inType.Elem, outType.Elem); ok {604 sw.Do("if err := $.|raw$(&val, newVal, s); err != nil {\n", function)605 } else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {606 funcName := g.funcNameTmpl(inType.Elem, outType.Elem)607 sw.Do(fmt.Sprintf("if err := %s(&val, newVal, s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))608 } else {609 sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)610 sw.Do("if err := s.Convert(&val, newVal, 0); err != nil {\n", nil)611 }612 sw.Do("return err\n", nil)613 sw.Do("}\n", nil)614 if inType.Key == outType.Key {615 sw.Do("(*out)[key] = *newVal\n", nil)616 } else {617 sw.Do("(*out)[$.|raw$(key)] = *newVal\n", outType.Key)618 }619 }620 } else {621 // TODO: Implement it when necessary.622 sw.Do("for range *in {\n", nil)623 sw.Do("// FIXME: Converting unassignable keys unsupported $.|raw$\n", inType.Key)624 }625 sw.Do("}\n", nil)626}627func (g *genConversion) doSlice(inType, outType *types.Type, sw *generator.SnippetWriter) {628 sw.Do("*out = make($.|raw$, len(*in))\n", outType)629 if inType.Elem == outType.Elem && inType.Elem.Kind == types.Builtin {630 sw.Do("copy(*out, *in)\n", nil)631 } else {632 sw.Do("for i := range *in {\n", nil)633 if isDirectlyAssignable(inType.Elem, outType.Elem) {634 if inType.Elem == outType.Elem {635 sw.Do("(*out)[i] = (*in)[i]\n", nil)636 } else {637 sw.Do("(*out)[i] = $.|raw$((*in)[i])\n", outType.Elem)638 }639 } else {640 if function, ok := g.preexists(inType.Elem, outType.Elem); ok {641 sw.Do("if err := $.|raw$(&(*in)[i], &(*out)[i], s); err != nil {\n", function)642 } else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {643 funcName := g.funcNameTmpl(inType.Elem, outType.Elem)644 sw.Do(fmt.Sprintf("if err := %s(&(*in)[i], &(*out)[i], s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))645 } else {646 // TODO: This triggers on v1.ObjectMeta <-> api.ObjectMeta and647 // similar because neither package is the target package, and648 // we really don't know which package will have the conversion649 // function defined. This fires on basically every object650 // conversion outside of pkg/api/v1.651 sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)652 sw.Do("if err := s.Convert(&(*in)[i], &(*out)[i], 0); err != nil {\n", nil)653 }654 sw.Do("return err\n", nil)655 sw.Do("}\n", nil)656 }657 sw.Do("}\n", nil)658 }659}660func (g *genConversion) doStruct(inType, outType *types.Type, sw *generator.SnippetWriter) {661 for _, m := range inType.Members {662 // Check if this member is excluded from conversion663 if tagvals := extractTag(m.CommentLines); tagvals != nil && tagvals[0] == "false" {664 continue665 }666 outMember, isOutMember := findMember(outType, m.Name)667 if !isOutMember {668 // Since this object wasn't filtered out, this means that669 // this field has "+k8s:conversion-gen=false" comment to ignore it.670 continue671 }672 t, outT := m.Type, outMember.Type673 // create a copy of both underlying types but give them the top level alias name (since aliases674 // are assignable)675 if underlying := unwrapAlias(t); underlying != t {676 copied := *underlying677 copied.Name = t.Name678 t = &copied679 }680 if underlying := unwrapAlias(outT); underlying != outT {681 copied := *underlying682 copied.Name = outT.Name683 outT = &copied684 }685 args := map[string]interface{}{686 "inType": t,687 "outType": outT,688 "name": m.Name,689 }690 // check based on the top level name, not the underlying names691 if function, ok := g.preexists(m.Type, outMember.Type); ok {692 args["function"] = function693 sw.Do("if err := $.function|raw$(&in.$.name$, &out.$.name$, s); err != nil {\n", args)694 sw.Do("return err\n", nil)695 sw.Do("}\n", nil)696 continue697 }698 switch t.Kind {699 case types.Builtin:700 if t == outT {701 sw.Do("out.$.name$ = in.$.name$\n", args)702 } else {703 sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)704 }705 case types.Map, types.Slice, types.Pointer:706 if g.isDirectlyAssignable(t, outT) {707 sw.Do("out.$.name$ = in.$.name$\n", args)708 continue709 }710 sw.Do("if in.$.name$ != nil {\n", args)711 sw.Do("in, out := &in.$.name$, &out.$.name$\n", args)712 g.generateFor(t, outT, sw)713 sw.Do("} else {\n", nil)714 sw.Do("out.$.name$ = nil\n", args)715 sw.Do("}\n", nil)716 case types.Struct:717 if g.isDirectlyAssignable(t, outT) {718 sw.Do("out.$.name$ = in.$.name$\n", args)719 continue720 }721 if g.convertibleOnlyWithinPackage(t, outT) {722 funcName := g.funcNameTmpl(t, outT)723 sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)724 } else {725 sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)726 sw.Do("if err := s.Convert(&in.$.name$, &out.$.name$, 0); err != nil {\n", args)727 }728 sw.Do("return err\n", nil)729 sw.Do("}\n", nil)730 case types.Alias:731 if isDirectlyAssignable(t, outT) {732 if t == outT {733 sw.Do("out.$.name$ = in.$.name$\n", args)734 } else {735 sw.Do("out.$.name$ = $.outType|raw$(in.$.name$)\n", args)736 }737 } else {738 if g.convertibleOnlyWithinPackage(t, outT) {739 funcName := g.funcNameTmpl(t, outT)740 sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)741 } else {742 sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)743 sw.Do("if err := s.Convert(&in.$.name$, &out.$.name$, 0); err != nil {\n", args)744 }745 sw.Do("return err\n", nil)746 sw.Do("}\n", nil)747 }748 default:749 if g.convertibleOnlyWithinPackage(t, outT) {750 funcName := g.funcNameTmpl(t, outT)751 sw.Do(fmt.Sprintf("if err := %s(&in.$.name$, &out.$.name$, s); err != nil {\n", funcName), args)752 } else {753 sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)754 sw.Do("if err := s.Convert(&in.$.name$, &out.$.name$, 0); err != nil {\n", args)755 }756 sw.Do("return err\n", nil)757 sw.Do("}\n", nil)758 }759 }760}761func (g *genConversion) isDirectlyAssignable(inType, outType *types.Type) bool {762 return inType == outType || areTypesAliased(inType, outType)763}764func (g *genConversion) doPointer(inType, outType *types.Type, sw *generator.SnippetWriter) {765 sw.Do("*out = new($.Elem|raw$)\n", outType)766 if isDirectlyAssignable(inType.Elem, outType.Elem) {767 if inType.Elem == outType.Elem {768 sw.Do("**out = **in\n", nil)769 } else {770 sw.Do("**out = $.|raw$(**in)\n", outType.Elem)771 }772 } else {773 if function, ok := g.preexists(inType.Elem, outType.Elem); ok {774 sw.Do("if err := $.|raw$(*in, *out, s); err != nil {\n", function)775 } else if g.convertibleOnlyWithinPackage(inType.Elem, outType.Elem) {776 funcName := g.funcNameTmpl(inType.Elem, outType.Elem)777 sw.Do(fmt.Sprintf("if err := %s(*in, *out, s); err != nil {\n", funcName), argsFromType(inType.Elem, outType.Elem))778 } else {779 sw.Do("// TODO: Inefficient conversion - can we improve it?\n", nil)780 sw.Do("if err := s.Convert(*in, *out, 0); err != nil {\n", nil)781 }782 sw.Do("return err\n", nil)783 sw.Do("}\n", nil)784 }785}786func (g *genConversion) doAlias(inType, outType *types.Type, sw *generator.SnippetWriter) {787 // TODO: Add support for aliases.788 g.doUnknown(inType, outType, sw)789}790func (g *genConversion) doUnknown(inType, outType *types.Type, sw *generator.SnippetWriter) {791 sw.Do("// FIXME: Type $.|raw$ is unsupported.\n", inType)792}793func isDirectlyAssignable(inType, outType *types.Type) bool {794 // TODO: This should maybe check for actual assignability between the two795 // types, rather than superficial traits that happen to indicate it is796 // assignable in the ways we currently use this code.797 return inType.IsAssignable() && (inType.IsPrimitive() || isSamePackage(inType, outType))798}799func isSamePackage(inType, outType *types.Type) bool {800 return inType.Name.Package == outType.Name.Package801}...

Full Screen

Full Screen

IsConvertible

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("type:", reflect.TypeOf(x))4 v := reflect.ValueOf(x)5 fmt.Println("value:", v)6 fmt.Println("type:", v.Type())7 fmt.Println("kind is float64:", v.Kind() == reflect.Float64)8 fmt.Println("value:", v.Float())9 fmt.Println(v.Interface())10 fmt.Println(v.Interface().(float64))11}12import (13func main() {14 fmt.Println("type:", reflect.TypeOf(x))15 v := reflect.ValueOf(x)16 fmt.Println("value:", v)17 fmt.Println("type:", v.Type())18 fmt.Println("kind is float64:", v.Kind() == reflect.Float64)19 y := v.Interface().(float64)20 fmt.Println(y)21 fmt.Println(v.Float())22}23import (24func main() {25 fmt.Println("type:", reflect.TypeOf(x))26 v := reflect.ValueOf(x)27 fmt.Println("value:", v)28 fmt.Println("type:", v.Type())29 fmt.Println("kind is float64:", v.Kind() == reflect.Float64)30 fmt.Println(v.Float())31 y := v.Interface().(float64)32 fmt.Println(y)33}34import (35func main() {

Full Screen

Full Screen

IsConvertible

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("type:", reflect.TypeOf(x))4 v := reflect.ValueOf(x)5 fmt.Println("value:", v)6 fmt.Println("kind is float64:", v.Kind() == reflect.Float64)7 fmt.Println("value:", v.Float())8 fmt.Println(v.Type())9 fmt.Println(v.Kind())10 y := v.Interface().(float64)11 fmt.Println(y)12}13import (14func main() {15 fmt.Println("type:", reflect.TypeOf(x))16 v := reflect.ValueOf(x)17 fmt.Println("value:", v)18 fmt.Println("kind is float64:", v.Kind() == reflect.Float64)19 fmt.Println("value:", v.Float())20 fmt.Println(v.Type())21 fmt.Println(v.Kind())22 y := v.Interface().(float64)23 fmt.Println(y)24}25import (26func main() {27 fmt.Println("type:", reflect.TypeOf(x))28 v := reflect.ValueOf(x)29 fmt.Println("value:", v)30 fmt.Println("kind is float64:", v.Kind() == reflect.Float64)31 fmt.Println("value:", v.Float())32 fmt.Println(v.Type())33 fmt.Println(v.Kind())34 y := v.Interface().(float64)35 fmt.Println(y)

Full Screen

Full Screen

IsConvertible

Using AI Code Generation

copy

Full Screen

1import (2type A struct {3}4type B struct {5}6func main() {7 fmt.Println(reflect.TypeOf(a).ConvertibleTo(reflect.TypeOf(b)))8 fmt.Println(reflect.TypeOf(a).ConvertibleTo(reflect.TypeOf(a)))9}

Full Screen

Full Screen

IsConvertible

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 t1 := reflect.TypeOf(a)4 t2 := reflect.TypeOf(b)5 fmt.Println(t1.IsConvertibleTo(t2))6}

Full Screen

Full Screen

IsConvertible

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("Is a convertible to b?", reflect.TypeOf(a).ConvertibleTo(reflect.TypeOf(b)))4 fmt.Println("Is a convertible to c?", reflect.TypeOf(a).ConvertibleTo(reflect.TypeOf(c)))5 fmt.Println("Is a convertible to d?", reflect.TypeOf(a).ConvertibleTo(reflect.TypeOf(d)))6 fmt.Println("Is a convertible to e?", reflect.TypeOf(a).ConvertibleTo(reflect.TypeOf(e)))7 fmt.Println("Is b convertible to a?", reflect.TypeOf(b).ConvertibleTo(reflect.TypeOf(a)))8 fmt.Println("Is b convertible to c?", reflect.TypeOf(b).ConvertibleTo(reflect.TypeOf(c)))9 fmt.Println("Is b convertible to d?", reflect.TypeOf(b).ConvertibleTo(reflect.TypeOf(d)))10 fmt.Println("Is b convertible to e?", reflect.TypeOf(b).ConvertibleTo(reflect.TypeOf(e)))11 fmt.Println("Is c convertible to a?", reflect.TypeOf(c).ConvertibleTo(reflect.TypeOf(a)))12 fmt.Println("Is c convertible to b?", reflect.TypeOf(c).ConvertibleTo(reflect.TypeOf(b)))13 fmt.Println("Is c convertible to d?", reflect.TypeOf(c).ConvertibleTo(reflect.TypeOf(d)))14 fmt.Println("Is c convertible to e?", reflect.TypeOf(c).ConvertibleTo(reflect.TypeOf(e)))15 fmt.Println("Is d convertible to a?", reflect.TypeOf(d).ConvertibleTo(reflect.TypeOf(a)))16 fmt.Println("Is d convertible to b?", reflect.TypeOf(d).ConvertibleTo(reflect.TypeOf(b)))17 fmt.Println("Is d convertible to c?", reflect.TypeOf(d).ConvertibleTo(reflect.TypeOf(c)))18 fmt.Println("Is d convertible to e?", reflect.TypeOf(d).ConvertibleTo(reflect.TypeOf(e)))19 fmt.Println("Is e convertible to a?", reflect.TypeOf(e).ConvertibleTo(reflect.TypeOf(a)))20 fmt.Println("Is e convertible to b?", reflect.TypeOf(e).ConvertibleTo(reflect.TypeOf(b)))21 fmt.Println("Is e convertible to c?", reflect.TypeOf(e).ConvertibleTo(reflect.TypeOf(c)))22 fmt.Println("Is e convertible to d?", reflect.TypeOf(e).ConvertibleTo(reflect.TypeOf(d)))23}

Full Screen

Full Screen

IsConvertible

Using AI Code Generation

copy

Full Screen

1import "fmt"2import "reflect"3func main() {4 fmt.Println(reflect.TypeOf(a).IsConvertibleTo(reflect.TypeOf(b)))5 fmt.Println(reflect.TypeOf(a).IsConvertibleTo(reflect.TypeOf(c)))6 fmt.Println(reflect.TypeOf(a).IsConvertibleTo(reflect.TypeOf(d)))7 fmt.Println(reflect.TypeOf(a).IsConvertibleTo(reflect.TypeOf(e)))8 fmt.Println(reflect.TypeOf(a).IsConvertibleTo(reflect.TypeOf(f)))9 fmt.Println(reflect.TypeOf(b).IsConvertibleTo(reflect.TypeOf(a)))10 fmt.Println(reflect.TypeOf(c).IsConvertibleTo(reflect.TypeOf(a)))11 fmt.Println(reflect.TypeOf(d).IsConvertibleTo(reflect.TypeOf(a)))12 fmt.Println(reflect.TypeOf(e).IsConvertibleTo(reflect.TypeOf(a)))13 fmt.Println(reflect.TypeOf(f).IsConvertibleTo(reflect.TypeOf(a)))14}

Full Screen

Full Screen

IsConvertible

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 v := reflect.ValueOf(x)4 t := reflect.TypeOf(x)5 t1 := reflect.TypeOf(10.0)6 b := t.ConvertibleTo(t1)7 v1 := v.Convert(t1)8}

Full Screen

Full Screen

IsConvertible

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 fmt.Println("Is a convertible to b?", reflect.TypeOf(a).ConvertibleTo(reflect.TypeOf(b)))4 fmt.Println("Is b convertible to c?", reflect.TypeOf(b).ConvertibleTo(reflect.TypeOf(c)))5 fmt.Println("Is c convertible to a?", reflect.TypeOf(c).ConvertibleTo(reflect.TypeOf(a)))6}

Full Screen

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Go-testdeep automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful