func newDiscriminatorImpl(tpeImpl GenSchema) GenSchema { tpeImpl.IsBaseType = true tpeImpl.IsExported = false tpeImpl.Name = swag.ToJSONName(tpeImpl.Name) tpeImpl.GoType = swag.ToJSONName(tpeImpl.GoType) return tpeImpl }
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) } sort.Sort(genModelPropertySlice(properties)) 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)), DefaultImports: []string{"github.com/go-swagger/go-swagger/strfmt"}, 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 (sg *schemaGenContext) NewSliceBranch(schema *spec.Schema) *schemaGenContext { if Debug { log.Printf("new slice branch %s (model: %s)", sg.Name, sg.TypeResolver.ModelName) } pg := sg.shallowClone() indexVar := pg.IndexVar if pg.Path == "" { pg.Path = "strconv.Itoa(" + indexVar + ")" } else { pg.Path = pg.Path + "+ \".\" + strconv.Itoa(" + indexVar + ")" } // check who is parent, if it's a base type then rewrite the value expression var rewriteValueExpr bool if sg.Discrimination != nil && sg.Discrimination.Discriminators != nil { _, rewriteValueExpr = sg.Discrimination.Discriminators["#/definitions/"+sg.TypeResolver.ModelName] if pg.IndexVar == "i" && rewriteValueExpr { pg.ValueExpr = sg.Receiver + "." + swag.ToJSONName(sg.GenSchema.Name) + "Field" } } pg.IndexVar = indexVar + "i" pg.ValueExpr = pg.ValueExpr + "[" + indexVar + "]" pg.Schema = *schema pg.Required = false if sg.IsVirtual { resolver := newTypeResolver(sg.TypeResolver.ModelsPackage, sg.TypeResolver.Doc) resolver.ModelName = sg.TypeResolver.ModelName pg.TypeResolver = resolver } // when this is an anonymous complex object, this needs to become a ref return pg }
func (t *Repository) addFile(name, data string, allowOverride bool) error { fileName := name name = swag.ToJSONName(strings.TrimSuffix(name, ".gotmpl")) templ, err := template.New(name).Funcs(t.funcs).Parse(data) if err != nil { return err } // check if any protected templates are defined if !allowOverride { for _, template := range templ.Templates() { if protectedTemplates[template.Name()] { return fmt.Errorf("Cannot overwrite protected template %s", template.Name()) } } } // Add each defined tempalte into the cache for _, template := range templ.Templates() { t.files[template.Name()] = fileName t.templates[template.Name()] = template.Lookup(template.Name()) } return nil }
func (a *appGenerator) makeConsumes() (consumes []GenSerGroup, consumesJSON bool) { for _, cons := range a.SpecDoc.RequiredConsumes() { cn, ok := mediaTypeName(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, Name: ser.Name, MediaType: cons, Implementation: knownConsumers[nm], }) continue } ser := GenSerializer{ AppName: a.Name, ReceiverName: a.Receiver, Name: nm, MediaType: cons, Implementation: knownConsumers[nm], } consumes = append(consumes, GenSerGroup{ AppName: ser.AppName, ReceiverName: ser.ReceiverName, Name: ser.Name, MediaType: cons, AllSerializers: []GenSerializer{ser}, Implementation: ser.Implementation, }) } if len(consumes) == 0 { consumes = append(consumes, GenSerGroup{ AppName: a.Name, ReceiverName: a.Receiver, Name: "json", MediaType: httpkit.JSONMime, AllSerializers: []GenSerializer{GenSerializer{ AppName: a.Name, ReceiverName: a.Receiver, Name: "json", MediaType: httpkit.JSONMime, Implementation: knownConsumers["json"], }}, Implementation: knownConsumers["json"], }) consumesJSON = true } return }
func (a *appGenerator) makeProduces() (produces []GenSerGroup, producesJSON bool) { for _, prod := range a.SpecDoc.RequiredProduces() { pn, ok := mediaTypeName(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, Name: ser.Name, MediaType: prod, Implementation: knownProducers[nm], }) continue } ser := GenSerializer{ AppName: a.Name, ReceiverName: a.Receiver, Name: nm, MediaType: prod, Implementation: knownProducers[nm], } produces = append(produces, GenSerGroup{ AppName: ser.AppName, ReceiverName: ser.ReceiverName, Name: ser.Name, MediaType: prod, Implementation: ser.Implementation, AllSerializers: []GenSerializer{ser}, }) } if len(produces) == 0 { produces = append(produces, GenSerGroup{ AppName: a.Name, ReceiverName: a.Receiver, Name: "json", MediaType: httpkit.JSONMime, AllSerializers: []GenSerializer{GenSerializer{ AppName: a.Name, ReceiverName: a.Receiver, Name: "json", MediaType: httpkit.JSONMime, Implementation: knownProducers["json"], }}, Implementation: knownProducers["json"], }) producesJSON = true } return }
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"), }, sharedValidations: sharedValidations{ Required: param.Required, 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, }, Type: tpe, Format: param.Format, Items: param.Items, Default: param.Default, } }
// 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 importPath := filepath.ToSlash(filepath.Join(baseImport(a.Target), a.ModelsPackage)) defaultImports = append(defaultImports, importPath) 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 { importPath := filepath.ToSlash(filepath.Join(baseImport(a.Target), a.ServerPackage, a.APIPackage, k)) defaultImports = append(defaultImports, importPath) } sort.Sort(genOperationSlice(genOps)) 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 (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) { resolver := typeResolver{ModelsPackage: b.ModelsPackage, Doc: b.Doc} receiver := "o" operation := b.Operation var params, qp, pp, hp, fp GenParameters var hasQueryParams bool for _, p := range b.Doc.ParametersFor(operation.ID) { cp, err := b.MakeParameter(receiver, &resolver, p) if err != nil { return GenOperation{}, err } 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) } sort.Sort(params) sort.Sort(qp) sort.Sort(pp) sort.Sort(hp) sort.Sort(fp) var responses map[int]GenResponse var defaultResponse *GenResponse var successResponse *GenResponse if operation.Responses != nil { for k, v := range operation.Responses.StatusCodeResponses { isSuccess := k/100 == 2 gr, err := b.MakeResponse(receiver, swag.ToJSONName(b.Name+" "+httpkit.Statuses[k]), isSuccess, &resolver, k, v) if err != nil { return GenOperation{}, err } if isSuccess { successResponse = &gr } if responses == nil { responses = make(map[int]GenResponse) } responses[k] = gr } if operation.Responses.Default != nil { gr, err := b.MakeResponse(receiver, b.Name+" default", false, &resolver, -1, *operation.Responses.Default) if err != nil { return GenOperation{}, err } defaultResponse = &gr } } prin := b.Principal if prin == "" { prin = "interface{}" } var extra []GenSchema for _, sch := range b.ExtraSchemas { extra = append(extra, sch) } schemes := concatUnique(resolver.Doc.Spec().Schemes, operation.Schemes) return GenOperation{ Package: b.APIPackage, Name: b.Name, Method: b.Method, Path: b.Path, Tags: operation.Tags[:], Description: operation.Description, ReceiverName: receiver, DefaultImports: b.DefaultImports, Params: params, Summary: operation.Summary, QueryParams: qp, PathParams: pp, HeaderParams: hp, FormParams: fp, HasQueryParams: hasQueryParams, Authorized: b.Authed, Principal: prin, Responses: responses, DefaultResponse: defaultResponse, SuccessResponse: successResponse, ExtraSchemas: extra, Schemes: schemeOrDefault(schemes, b.DefaultScheme), }, nil }
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.ToSlash(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, } }
func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) { if Debug { log.Printf("[%s %s] parsing operation (id: %q)", b.Method, b.Path, b.Operation.ID) } resolver := newTypeResolver(b.ModelsPackage, b.Doc.ResetDefinitions()) receiver := "o" operation := b.Operation var params, qp, pp, hp, fp GenParameters var hasQueryParams, hasFormParams, hasFileParams bool for _, p := range b.Doc.ParamsFor(b.Method, b.Path) { cp, err := b.MakeParameter(receiver, resolver, p) if err != nil { return GenOperation{}, err } if cp.IsQueryParam() { hasQueryParams = true qp = append(qp, cp) } if cp.IsFormParam() { if p.Type == "file" { hasFileParams = true } hasFormParams = true fp = append(fp, cp) } if cp.IsPathParam() { pp = append(pp, cp) } if cp.IsHeaderParam() { hp = append(hp, cp) } params = append(params, cp) } sort.Sort(params) sort.Sort(qp) sort.Sort(pp) sort.Sort(hp) sort.Sort(fp) var responses map[int]GenResponse var defaultResponse *GenResponse var successResponse *GenResponse if operation.Responses != nil { for k, v := range operation.Responses.StatusCodeResponses { isSuccess := k/100 == 2 gr, err := b.MakeResponse(receiver, swag.ToJSONName(b.Name+" "+httpkit.Statuses[k]), isSuccess, resolver, k, v) if err != nil { return GenOperation{}, err } if isSuccess { successResponse = &gr } if responses == nil { responses = make(map[int]GenResponse) } responses[k] = gr } if operation.Responses.Default != nil { gr, err := b.MakeResponse(receiver, b.Name+" default", false, resolver, -1, *operation.Responses.Default) if err != nil { return GenOperation{}, err } defaultResponse = &gr } } prin := b.Principal if prin == "" { prin = "interface{}" } var extra []GenSchema for _, sch := range b.ExtraSchemas { extra = append(extra, sch) } var extraSchemes []string if ess, ok := operation.Extensions.GetStringSlice("x-schemes"); ok { extraSchemes = append(extraSchemes, ess...) } if ess1, ok := resolver.Doc.Spec().Extensions.GetStringSlice("x-schemes"); ok { extraSchemes = concatUnique(ess1, extraSchemes) } sort.Strings(extraSchemes) schemes := concatUnique(resolver.Doc.Spec().Schemes, operation.Schemes) sort.Strings(schemes) produces := concatUnique(resolver.Doc.Spec().Produces, operation.Produces) sort.Strings(produces) return GenOperation{ Package: b.APIPackage, RootPackage: b.RootAPIPackage, Name: b.Name, Method: b.Method, Path: b.Path, Tags: operation.Tags[:], Description: operation.Description, ReceiverName: receiver, DefaultImports: b.DefaultImports, Params: params, Summary: operation.Summary, QueryParams: qp, PathParams: pp, HeaderParams: hp, FormParams: fp, HasQueryParams: hasQueryParams, HasFormParams: hasFormParams, HasFileParams: hasFileParams, Authorized: b.Authed, Principal: prin, Responses: responses, DefaultResponse: defaultResponse, SuccessResponse: successResponse, ExtraSchemas: extra, Schemes: schemeOrDefault(schemes, b.DefaultScheme), ProducesMediaTypes: producesOrDefault(produces, b.DefaultProduces), ExtraSchemes: extraSchemes, }, nil }