func argsFromType(t *types.Type) generator.Args { return generator.Args{ "type": t, "OpenAPIDefinitions": types.Ref(openAPICommonPackagePath, "OpenAPIDefinitions"), "OpenAPIDefinition": types.Ref(openAPICommonPackagePath, "OpenAPIDefinition"), "SpecSchemaType": types.Ref(specPackagePath, "Schema"), } }
// Returns all manually-defined conversion functions in the package. func getManualConversionFunctions(context *generator.Context, pkg *types.Package, manualMap conversionFuncMap) { scopeName := types.Ref(conversionPackagePath, "Scope").Name errorName := types.Ref("", "error").Name buffer := &bytes.Buffer{} sw := generator.NewSnippetWriter(buffer, context, "$", "$") for _, f := range pkg.Functions { if f.Underlying == nil || f.Underlying.Kind != types.Func { glog.Errorf("Malformed function: %#v", f) continue } if f.Underlying.Signature == nil { glog.Errorf("Function without signature: %#v", f) continue } signature := f.Underlying.Signature // Check whether the function is conversion function. // Note that all of them have signature: // func Convert_inType_To_outType(inType, outType, conversion.Scope) error if signature.Receiver != nil { continue } if len(signature.Parameters) != 3 || signature.Parameters[2].Name != scopeName { continue } if len(signature.Results) != 1 || signature.Results[0].Name != errorName { continue } inType := signature.Parameters[0] outType := signature.Parameters[1] if inType.Kind != types.Pointer || outType.Kind != types.Pointer { continue } // Now check if the name satisfies the convention. // TODO: This should call the Namer directly. args := argsFromType(inType.Elem, outType.Elem) sw.Do("Convert_$.inType|public$_To_$.outType|public$", args) if f.Name.Name == buffer.String() { key := conversionPair{inType.Elem, outType.Elem} // We might scan the same package twice, and that's OK. if v, ok := manualMap[key]; ok && v != nil && v.Name.Package != pkg.Path { panic(fmt.Sprintf("duplicate static conversion defined: %#v", key)) } manualMap[key] = f } buffer.Reset() } }
func (g *genConversion) generateConversion(inType, outType *types.Type, sw *generator.SnippetWriter) { args := argsFromType(inType, outType). With("Scope", types.Ref(conversionPackagePath, "Scope")) sw.Do("func auto"+nameTmpl+"(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", args) // if no defaulter of form SetDefaults_XXX is defined, do not inline a check for defaulting. if function, ok := g.manualDefaulters[inType]; ok { sw.Do("$.|raw$(in)\n", function) } g.generateFor(inType, outType, sw) sw.Do("return nil\n", nil) sw.Do("}\n\n", nil) if _, found := g.preexists(inType, outType); found { // There is a public manual Conversion method: use it. } else if skipped := g.skippedFields[inType]; len(skipped) != 0 { // The inType had some fields we could not generate. glog.Errorf("Warning: could not find nor generate a final Conversion function for %v -> %v", inType, outType) glog.Errorf(" the following fields need manual conversion:") for _, f := range skipped { glog.Errorf(" - %v", f) } } else { // Emit a public conversion function. sw.Do("func "+nameTmpl+"(in *$.inType|raw$, out *$.outType|raw$, s $.Scope|raw$) error {\n", args) sw.Do("return auto"+nameTmpl+"(in, out, s)\n", args) sw.Do("}\n\n", nil) } }
func (g *genDeepCopy) GenerateType(c *generator.Context, t *types.Type, w io.Writer) error { if !g.needsGeneration(t) { return nil } glog.V(5).Infof("generating for type %v", t) sw := generator.NewSnippetWriter(w, c, "$", "$") args := argsFromType(t). With("clonerType", types.Ref(conversionPackagePath, "Cloner")) sw.Do("func $.type|dcFnName$(in interface{}, out interface{}, c *$.clonerType|raw$) error {{\n", args) sw.Do("in := in.(*$.type|raw$)\nout := out.(*$.type|raw$)\n", argsFromType(t)) g.generateFor(t, sw) sw.Do("return nil\n", nil) sw.Do("}}\n\n", nil) return sw.Error() }