func makeCodegenModel(name, pkg string, schema spec.Schema, specDoc *spec.Document) *genModel { receiver := "m" props := make(map[string]genModelProperty) for pn, p := range schema.Properties { var required bool for _, v := range schema.Required { if v == pn { required = true break } } props[swag.ToJSONName(pn)] = makeGenModelProperty( "\""+pn+"\"", swag.ToJSONName(pn), swag.ToGoName(pn), receiver, "i", receiver+"."+swag.ToGoName(pn), p, required) } for _, p := range schema.AllOf { if p.Ref.GetURL() != nil { tn := filepath.Base(p.Ref.GetURL().Fragment) p = specDoc.Spec().Definitions[tn] } mod := makeCodegenModel(name, pkg, p, specDoc) if mod != nil { for _, prop := range mod.Properties { props[prop.ParamName] = prop } } } var properties []genModelProperty var hasValidations bool for _, v := range props { if v.HasValidations { hasValidations = v.HasValidations } properties = append(properties, v) } return &genModel{ Package: filepath.Base(pkg), ClassName: swag.ToGoName(name), Name: swag.ToJSONName(name), ReceiverName: receiver, Properties: properties, Description: schema.Description, DocString: modelDocString(swag.ToGoName(name), schema.Description), HumanClassName: swag.ToHumanNameLower(swag.ToGoName(name)), HasValidations: hasValidations, } }
func makeCodegenParameter(receiver, modelsPkg string, param spec.Parameter) genParameter { var ctx sharedParam var child *genParameterItem if param.In == "body" { ctx = makeGenValidations(modelValidations( "\""+swag.ToJSONName(param.Name)+"\"", swag.ToJSONName(param.Name), swag.ToGoName(param.Name), "i", receiver+"."+swag.ToGoName(param.Name), modelsPkg, param.Required, *param.Schema)) } else { ctx = makeGenValidations(paramValidations(receiver, param)) thisItem := genParameterItem{} thisItem.sharedParam = ctx thisItem.ValueExpression = ctx.IndexVar + "c" thisItem.CollectionFormat = param.CollectionFormat thisItem.Converter = stringConverters[ctx.Type] thisItem.Location = param.In if param.Items != nil { it := makeCodegenParamItem( "fmt.Sprintf(\"%s.%v\", "+ctx.Path+", "+ctx.IndexVar+")", ctx.ParamName, ctx.PropertyName, ctx.IndexVar+"i", ctx.IndexVar+"c["+ctx.IndexVar+"]", thisItem, *param.Items, ) child = &it } } return genParameter{ sharedParam: ctx, Description: param.Description, ReceiverName: receiver, IsQueryParam: param.In == "query", IsBodyParam: param.In == "body", IsHeaderParam: param.In == "header", IsPathParam: param.In == "path", IsFormParam: param.In == "formData", IsFileParam: param.Type == "file", CollectionFormat: param.CollectionFormat, Child: child, Location: param.In, Converter: stringConverters[ctx.Type], } }
func paramValidations(receiver string, param spec.Parameter) commonValidations { accessor := swag.ToGoName(param.Name) paramName := swag.ToJSONName(param.Name) tpe := typeForParameter(param) _, isPrimitive := primitives[tpe] _, isCustomFormatter := customFormatters[tpe] return commonValidations{ propertyDescriptor: propertyDescriptor{ PropertyName: accessor, ParamName: paramName, ValueExpression: fmt.Sprintf("%s.%s", receiver, accessor), IndexVar: "i", Path: "\"" + paramName + "\"", IsContainer: param.Items != nil || tpe == "array", IsPrimitive: isPrimitive, IsCustomFormatter: isCustomFormatter, IsMap: strings.HasPrefix(tpe, "map"), }, Required: param.Required, Type: tpe, Format: param.Format, Items: param.Items, Default: param.Default, Maximum: param.Maximum, ExclusiveMaximum: param.ExclusiveMaximum, Minimum: param.Minimum, ExclusiveMinimum: param.ExclusiveMinimum, MaxLength: param.MaxLength, MinLength: param.MinLength, Pattern: param.Pattern, MaxItems: param.MaxItems, MinItems: param.MinItems, UniqueItems: param.UniqueItems, MultipleOf: param.MultipleOf, Enum: param.Enum, } }
// func makeCodegenApp(operations map[string]spec.Operation, includeUI bool) genApp { func (a *appGenerator) makeCodegenApp() genApp { sw := a.SpecDoc.Spec() // app := makeCodegenApp(a.Operations, a.IncludeUI) receiver := strings.ToLower(a.Name[:1]) appName := swag.ToGoName(a.Name) var defaultImports []string jsonb, _ := json.MarshalIndent(a.SpecDoc.Spec(), "", " ") consumesJSON := false var consumes []genSerGroup for _, cons := range a.SpecDoc.RequiredConsumes() { cn, ok := mediaTypeNames[cons] if !ok { continue } nm := swag.ToJSONName(cn) if nm == "json" { consumesJSON = true } if ser, ok := getSerializer(consumes, cn); ok { ser.AllSerializers = append(ser.AllSerializers, genSerializer{ AppName: ser.AppName, ReceiverName: ser.ReceiverName, ClassName: ser.ClassName, HumanClassName: ser.HumanClassName, Name: ser.Name, MediaType: cons, Implementation: knownConsumers[nm], }) continue } ser := genSerializer{ AppName: appName, ReceiverName: receiver, ClassName: swag.ToGoName(cn), HumanClassName: swag.ToHumanNameLower(cn), Name: nm, MediaType: cons, Implementation: knownConsumers[nm], } consumes = append(consumes, genSerGroup{ AppName: ser.AppName, ReceiverName: ser.ReceiverName, ClassName: ser.ClassName, HumanClassName: ser.HumanClassName, Name: ser.Name, MediaType: cons, AllSerializers: []genSerializer{ser}, Implementation: ser.Implementation, }) } producesJSON := false var produces []genSerGroup for _, prod := range a.SpecDoc.RequiredProduces() { pn, ok := mediaTypeNames[prod] if !ok { continue } nm := swag.ToJSONName(pn) if nm == "json" { producesJSON = true } if ser, ok := getSerializer(produces, pn); ok { ser.AllSerializers = append(ser.AllSerializers, genSerializer{ AppName: ser.AppName, ReceiverName: ser.ReceiverName, ClassName: ser.ClassName, HumanClassName: ser.HumanClassName, Name: ser.Name, MediaType: prod, Implementation: knownProducers[nm], }) continue } ser := genSerializer{ AppName: appName, ReceiverName: receiver, ClassName: swag.ToGoName(pn), HumanClassName: swag.ToHumanNameLower(pn), Name: nm, MediaType: prod, Implementation: knownProducers[nm], } produces = append(produces, genSerGroup{ AppName: ser.AppName, ReceiverName: ser.ReceiverName, ClassName: ser.ClassName, HumanClassName: ser.HumanClassName, Name: ser.Name, MediaType: prod, Implementation: ser.Implementation, AllSerializers: []genSerializer{ser}, }) } var security []genSecurityScheme for _, scheme := range a.SpecDoc.RequiredSchemes() { if req, ok := a.SpecDoc.Spec().SecurityDefinitions[scheme]; ok { if req.Type == "basic" || req.Type == "apiKey" { security = append(security, genSecurityScheme{ AppName: appName, ReceiverName: receiver, ClassName: swag.ToGoName(req.Name), HumanClassName: swag.ToHumanNameLower(req.Name), Name: swag.ToJSONName(req.Name), IsBasicAuth: strings.ToLower(req.Type) == "basic", IsAPIKeyAuth: strings.ToLower(req.Type) == "apikey", Principal: a.Principal, Source: req.In, }) } } } var genMods []genModel defaultImports = append(defaultImports, filepath.Join(baseImport(a.Target), a.ModelsPackage)) for mn, m := range a.Models { mod := *makeCodegenModel( mn, a.ModelsPackage, m, a.SpecDoc, ) mod.ReceiverName = receiver genMods = append(genMods, mod) } var genOps []genOperation tns := make(map[string]struct{}) for on, o := range a.Operations { authed := len(a.SpecDoc.SecurityRequirementsFor(&o)) > 0 ap := a.APIPackage if a.APIPackage == a.Package { ap = "" } if len(o.Tags) > 0 { for _, tag := range o.Tags { tns[tag] = struct{}{} op := makeCodegenOperation(on, tag, a.ModelsPackage, a.Principal, a.Target, o, authed) op.ReceiverName = receiver genOps = append(genOps, op) } } else { op := makeCodegenOperation(on, ap, a.ModelsPackage, a.Principal, a.Target, o, authed) op.ReceiverName = receiver genOps = append(genOps, op) } } for k := range tns { defaultImports = append(defaultImports, filepath.Join(baseImport(a.Target), a.ServerPackage, a.APIPackage, k)) } defaultConsumes := "application/json" rc := a.SpecDoc.RequiredConsumes() if !consumesJSON && len(rc) > 0 { defaultConsumes = rc[0] } defaultProduces := "application/json" rp := a.SpecDoc.RequiredProduces() if !producesJSON && len(rp) > 0 { defaultProduces = rp[0] } return genApp{ Package: a.Package, ReceiverName: receiver, AppName: swag.ToGoName(a.Name), HumanAppName: swag.ToHumanNameLower(a.Name), Name: swag.ToJSONName(a.Name), ExternalDocs: sw.ExternalDocs, Info: sw.Info, Consumes: consumes, Produces: produces, DefaultConsumes: defaultConsumes, DefaultProduces: defaultProduces, DefaultImports: defaultImports, SecurityDefinitions: security, Models: genMods, Operations: genOps, IncludeUI: a.IncludeUI, Principal: a.Principal, SwaggerJSON: fmt.Sprintf("%#v", jsonb), } }
func makeCodegenOperation(name, pkg, modelsPkg, principal, target string, operation spec.Operation, authorized bool) genOperation { receiver := "o" var params, qp, pp, hp, fp []genParameter var hasQueryParams bool for _, p := range operation.Parameters { cp := makeCodegenParameter(receiver, modelsPkg, p) if cp.IsQueryParam { hasQueryParams = true qp = append(qp, cp) } if cp.IsFormParam { fp = append(fp, cp) } if cp.IsPathParam { pp = append(pp, cp) } if cp.IsHeaderParam { hp = append(hp, cp) } params = append(params, cp) } var successModel string var returnsPrimitive, returnsFormatted, returnsContainer, returnsMap bool if operation.Responses != nil { if r, ok := operation.Responses.StatusCodeResponses[200]; ok { tn := typeForSchema(r.Schema, modelsPkg) _, returnsPrimitive = primitives[tn] _, returnsFormatted = customFormatters[tn] returnsContainer = r.Schema.Items != nil || r.Schema.Type.Contains("array") returnsMap = strings.HasPrefix(tn, "map") successModel = tn } } prin := principal if prin == "" { prin = "interface{}" } zero, ok := zeroes[successModel] if !ok { zero = "nil" } return genOperation{ Package: pkg, ClassName: swag.ToGoName(name), Name: swag.ToJSONName(name), Description: operation.Description, DocString: operationDocString(swag.ToGoName(name), operation), ReceiverName: receiver, HumanClassName: swag.ToHumanNameLower(swag.ToGoName(name)), DefaultImports: []string{filepath.Join(baseImport(filepath.Join(target, "..")), modelsPkg)}, Params: params, Summary: operation.Summary, QueryParams: qp, PathParams: pp, HeaderParams: hp, FormParams: fp, HasQueryParams: hasQueryParams, SuccessModel: successModel, SuccessZero: zero, ReturnsPrimitive: returnsPrimitive, ReturnsFormatted: returnsFormatted, ReturnsContainer: returnsContainer, ReturnsMap: returnsMap, ReturnsComplexObject: !returnsPrimitive && !returnsFormatted && !returnsContainer && !returnsMap, Authorized: authorized, Principal: prin, } }