Example #1
0
func pascalize(arg string) string {
	if len(arg) == 0 || arg[0] > '9' {
		return swag.ToGoName(arg)
	}

	return swag.ToGoName("Nr " + arg)
}
Example #2
0
func (a *appGenerator) generateAPIBuilder(app *GenApp) error {
	buf := bytes.NewBuffer(nil)
	if err := builderTemplate.Execute(buf, app); err != nil {
		return err
	}
	log.Println("rendered builder template:", app.Package+"."+swag.ToGoName(app.Name))
	return writeToFile(filepath.Join(a.Target, a.ServerPackage, app.Package), swag.ToGoName(app.Name)+"Api", buf.Bytes())
}
Example #3
0
func (t *typeResolver) goTypeName(nm string) string {
	if t.ModelsPackage == "" {
		return swag.ToGoName(nm)
	}
	if _, ok := t.KnownDefs[nm]; ok {
		return strings.Join([]string{t.ModelsPackage, swag.ToGoName(nm)}, ".")
	}
	return swag.ToGoName(nm)
}
Example #4
0
func (c *clientGenerator) generateEmbeddedSwaggerJSON(app *GenApp) error {
	buf := bytes.NewBuffer(nil)

	if err := embeddedSpecTemplate.Execute(buf, app); err != nil {
		return err
	}
	log.Println("rendered client embedded swagger JSON template:", c.ClientPackage+"."+swag.ToGoName(app.Name)+"Client")

	fp := filepath.Join(c.Target, c.ClientPackage)
	return writeToFile(fp, swag.ToGoName(app.Name)+"EmbeddedSpec", buf.Bytes())
}
Example #5
0
func (c *clientGenerator) generateGroupClient(opGroup GenOperationGroup) error {
	buf := bytes.NewBuffer(nil)

	if err := clientTemplate.Execute(buf, opGroup); err != nil {
		return err
	}
	log.Println("rendered operation group client template:", opGroup.Name+"."+swag.ToGoName(opGroup.Name)+"Client")

	fp := filepath.Join(c.Target, c.ClientPackage, opGroup.Name)
	return writeToFile(fp, swag.ToGoName(opGroup.Name)+"Client", buf.Bytes())
}
Example #6
0
func (a *appGenerator) generateMain(app *GenApp) error {
	pth := filepath.Join(a.Target, "cmd", swag.ToCommandName(swag.ToGoName(app.Name)+"Server"))
	if fileExists(pth, "main") && !a.GenOpts.IncludeMain {
		log.Println("skipped (already exists) main template:", app.Package+".Main")
		return nil
	}
	buf := bytes.NewBuffer(nil)
	if err := mainTemplate.Execute(buf, app); err != nil {
		return err
	}
	log.Println("rendered main template:", "server."+swag.ToGoName(app.Name))
	return writeToFile(pth, "main", buf.Bytes())
}
Example #7
0
func (c *clientGenerator) generateResponses(op *GenOperation) error {
	buf := bytes.NewBuffer(nil)

	if err := clientResponseTemplate.Execute(buf, op); err != nil {
		return err
	}
	log.Println("rendered client responses template:", op.Package+"."+swag.ToGoName(op.Name)+"Responses")

	fp := filepath.Join(c.Target, c.ClientPackage)
	if len(op.Package) > 0 {
		fp = filepath.Join(fp, op.Package)
	}
	return writeToFile(fp, swag.ToGoName(op.Name)+"Responses", buf.Bytes())
}
Example #8
0
func (a *appGenerator) generateConfigureAPI(app *GenApp) error {
	pth := filepath.Join(a.Target, app.APIPackage)
	nm := "Configure" + swag.ToGoName(app.Name)
	if fileExists(pth, nm) {
		log.Println("skipped (already exists) configure api template:", app.Package+".Configure"+swag.ToGoName(app.Name))
		return nil
	}

	buf := bytes.NewBuffer(nil)
	if err := configureAPITemplate.Execute(buf, app); err != nil {
		return err
	}
	log.Println("rendered configure api template:", app.Package+".Configure"+swag.ToGoName(app.Name))
	return writeToFileIfNotExist(pth, nm, buf.Bytes())
}
Example #9
0
func (sg *schemaGenContext) NewAdditionalItems(schema *spec.Schema) *schemaGenContext {
	if Debug {
		log.Printf("new additional items\n")
	}
	pg := sg.shallowClone()
	indexVar := pg.IndexVar
	pg.Name = sg.Name + " items"
	itemsLen := 0
	if sg.Schema.Items != nil {
		itemsLen = sg.Schema.Items.Len()
	}
	var mod string
	if itemsLen > 0 {
		mod = "+" + strconv.Itoa(itemsLen)
	}
	if pg.Path == "" {
		pg.Path = "strconv.Itoa(" + indexVar + mod + ")"
	} else {
		pg.Path = pg.Path + "+ \".\" + strconv.Itoa(" + indexVar + mod + ")"
	}
	pg.IndexVar = indexVar
	pg.ValueExpr = sg.ValueExpr + "." + swag.ToGoName(sg.Name) + "Items[" + indexVar + "]"
	pg.Schema = spec.Schema{}
	if schema != nil {
		pg.Schema = *schema
	}
	pg.Required = false
	return pg
}
func TestSchemaValidation_RequiredProps(t *testing.T) {
	specDoc, err := loads.Spec("../fixtures/codegen/todolist.schemavalidation.yml")
	if assert.NoError(t, err) {
		k := "RequiredProps"
		schema := specDoc.Spec().Definitions[k]

		gm, err := makeGenDefinition(k, "models", schema, specDoc, true, true)
		if assert.NoError(t, err) {
			assert.Len(t, gm.Properties, 6)
			for _, p := range gm.Properties {
				if assert.True(t, p.Required) {
					buf := bytes.NewBuffer(nil)
					err := modelTemplate.Execute(buf, gm)
					if assert.NoError(t, err) {
						formatted, err := formatGoFile("required_props.go", buf.Bytes())
						if assert.NoError(t, err) {
							res := string(formatted)
							assertInCode(t, k+") Validate(formats", res)
							assertInCode(t, "validate"+swag.ToGoName(p.Name), res)
							assertInCode(t, "err := validate.Required", res)
							assertInCode(t, "errors.CompositeValidationError(res...)", res)
						}
					}
				}
			}
		}
	}
}
Example #11
0
func discriminatorInfo(doc *analysis.Spec) *discInfo {
	baseTypes := make(map[string]discor)
	for _, sch := range doc.AllDefinitions() {
		if sch.Schema.Discriminator != "" {
			tpe, _ := sch.Schema.Extensions.GetString("x-go-name")
			if tpe == "" {
				tpe = swag.ToGoName(sch.Name)
			}
			baseTypes[sch.Ref.String()] = discor{
				FieldName: sch.Schema.Discriminator,
				GoType:    tpe,
				JSONName:  sch.Name,
			}
		}
	}

	subTypes := make(map[string]discee)
	for _, sch := range doc.SchemasWithAllOf() {
		for _, ao := range sch.Schema.AllOf {
			if ao.Ref.String() != "" {
				if bt, ok := baseTypes[ao.Ref.String()]; ok {
					name, _ := sch.Schema.Extensions.GetString("x-class")
					if name == "" {
						name = sch.Name
					}
					tpe, _ := sch.Schema.Extensions.GetString("x-go-name")
					if tpe == "" {
						tpe = swag.ToGoName(sch.Name)
					}
					dce := discee{
						FieldName:  bt.FieldName,
						FieldValue: name,
						Ref:        sch.Ref,
						ParentRef:  ao.Ref,
						JSONName:   sch.Name,
						GoType:     tpe,
					}
					subTypes[sch.Ref.String()] = dce
					bt.Children = append(bt.Children, dce)
					baseTypes[ao.Ref.String()] = bt
				}
			}
		}
	}
	return &discInfo{Discriminators: baseTypes, Discriminated: subTypes}
}
Example #12
0
func (a *appGenerator) generateEmbeddedSwaggerJSON(app *GenApp) error {
	buf := bytes.NewBuffer(nil)
	appc := *app
	appc.Package = app.APIPackage
	if err := embeddedSpecTemplate.Execute(buf, &appc); err != nil {
		return err
	}
	log.Println("rendered embedded Swagger JSON template:", app.APIPackage+"."+swag.ToGoName(app.Name))
	return writeToFile(filepath.Join(a.Target, a.ServerPackage), "embedded_spec", buf.Bytes())
}
Example #13
0
func appNameOrDefault(specDoc *loads.Document, name, defaultName string) string {
	if strings.TrimSpace(name) == "" {
		if specDoc.Spec().Info != nil && strings.TrimSpace(specDoc.Spec().Info.Title) != "" {
			name = specDoc.Spec().Info.Title
		} else {
			name = defaultName
		}
	}
	return strings.TrimSuffix(swag.ToGoName(name), "API")
}
Example #14
0
func (sg *schemaGenContext) makeNewStruct(name string, schema spec.Schema) *schemaGenContext {
	if Debug {
		log.Println("making new struct", name, sg.Container)
	}
	sp := sg.TypeResolver.Doc.Spec()
	name = swag.ToGoName(name)
	if sg.TypeResolver.ModelName != sg.Name {
		name = swag.ToGoName(sg.TypeResolver.ModelName + " " + name)
	}
	if sp.Definitions == nil {
		sp.Definitions = make(spec.Definitions)
	}
	sp.Definitions[name] = schema
	pg := schemaGenContext{
		Path:             "",
		Name:             name,
		Receiver:         sg.Receiver,
		IndexVar:         "i",
		ValueExpr:        sg.Receiver,
		Schema:           schema,
		Required:         false,
		Named:            true,
		ExtraSchemas:     make(map[string]GenSchema),
		Discrimination:   sg.Discrimination,
		Container:        sg.Container,
		IncludeValidator: sg.IncludeValidator,
		IncludeModel:     sg.IncludeModel,
	}
	if schema.Ref.String() == "" {
		resolver := newTypeResolver(sg.TypeResolver.ModelsPackage, sg.TypeResolver.Doc)
		resolver.ModelName = name //sg.TypeResolver.ModelName
		pg.TypeResolver = resolver
	}
	pg.GenSchema.IsVirtual = true

	sg.ExtraSchemas[name] = pg.GenSchema
	return &pg
}
Example #15
0
func (o *opGen) generateResponses() error {
	buf := bytes.NewBuffer(nil)

	if err := responsesTemplate.Execute(buf, o.data); err != nil {
		return err
	}
	log.Println("rendered responses template:", o.pkg+"."+o.cname+"Responses")

	fp := filepath.Join(o.Target, o.pkg)
	if o.pkg != o.APIPackage {
		fp = filepath.Join(o.Target, o.APIPackage, o.pkg)
	}
	return writeToFile(fp, swag.ToGoName(o.data.Name)+"Responses", buf.Bytes())
}
Example #16
0
func gatherOperations(specDoc *Spec, operationIDs []string) map[string]opRef {
	var oprefs opRefs

	for method, pathItem := range specDoc.Operations() {
		for pth, operation := range pathItem {
			vv := *operation
			oprefs = append(oprefs, opRef{
				Key:    swag.ToGoName(strings.ToLower(method) + " " + pth),
				Method: method,
				Path:   pth,
				ID:     vv.ID,
				Op:     &vv,
				Ref:    swspec.MustCreateRef("#" + path.Join("/paths", jsonpointer.Escape(pth), method)),
			})
		}
	}

	sort.Sort(oprefs)

	operations := make(map[string]opRef)
	for _, opr := range oprefs {
		nm := opr.ID
		if nm == "" {
			nm = opr.Key
		}

		oo, found := operations[nm]
		if found && oo.Method != opr.Method && oo.Path != opr.Path {
			nm = opr.Key
		}
		if len(operationIDs) == 0 || containsString(operationIDs, opr.ID) || containsString(operationIDs, nm) {
			opr.ID = nm
			opr.Op.ID = nm
			operations[nm] = opr
		}
	}

	return operations
}
Example #17
0
func gatherOperations(specDoc *analysis.Spec, operationIDs []string) map[string]opRef {
	var oprefs opRefs

	for method, pathItem := range specDoc.Operations() {
		for path, operation := range pathItem {
			// nm := ensureUniqueName(operation.ID, method, path, operations)
			vv := *operation
			oprefs = append(oprefs, opRef{
				Key:    swag.ToGoName(strings.ToLower(method) + " " + path),
				Method: method,
				Path:   path,
				ID:     vv.ID,
				Op:     &vv,
			})
		}
	}

	sort.Sort(oprefs)

	operations := make(map[string]opRef)
	for _, opr := range oprefs {
		nm := opr.ID
		if nm == "" {
			nm = opr.Key
		}

		_, found := operations[nm]
		if found {
			nm = opr.Key
		}
		if len(operationIDs) == 0 || containsString(operationIDs, opr.ID) || containsString(operationIDs, nm) {
			opr.ID = nm
			opr.Op.ID = nm
			operations[nm] = opr
		}
	}

	return operations
}
Example #18
0
func (b *codeGenOpBuilder) MakeParameter(receiver string, resolver *typeResolver, param spec.Parameter) (GenParameter, error) {
	if Debug {
		log.Printf("[%s %s] making parameter %q", b.Method, b.Path, param.Name)
	}

	if param.Ref.String() != "" {
		param2, err := spec.ResolveParameter(b.Doc.Spec(), param.Ref)
		if err != nil {
			return GenParameter{}, err
		}
		if param2 == nil {
			return GenParameter{}, fmt.Errorf("could not resolve parameter ref: %s", param.Ref.String())
		}
		param = *param2
	}

	var child *GenItems
	res := GenParameter{
		Name:             param.Name,
		ModelsPackage:    b.ModelsPackage,
		Path:             fmt.Sprintf("%q", param.Name),
		ValueExpression:  fmt.Sprintf("%s.%s", receiver, pascalize(param.Name)),
		IndexVar:         "i",
		BodyParam:        nil,
		Default:          param.Default,
		HasDefault:       param.Default != nil,
		Enum:             param.Enum,
		Description:      param.Description,
		ReceiverName:     receiver,
		CollectionFormat: param.CollectionFormat,
		Child:            child,
		Location:         param.In,
		AllowEmptyValue:  (param.In == "query" || param.In == "formData") && param.AllowEmptyValue,
	}

	if param.In == "body" {
		sc := schemaGenContext{
			Path:             res.Path,
			Name:             res.Name,
			Receiver:         res.ReceiverName,
			ValueExpr:        res.ReceiverName,
			IndexVar:         res.IndexVar,
			Schema:           *param.Schema,
			Required:         param.Required,
			TypeResolver:     resolver,
			Named:            false,
			IncludeModel:     true,
			IncludeValidator: true,
			ExtraSchemas:     make(map[string]GenSchema),
		}
		if err := sc.makeGenSchema(); err != nil {
			return GenParameter{}, err
		}

		schema := sc.GenSchema
		if schema.IsAnonymous {
			schema.Name = swag.ToGoName(b.Operation.ID + " Body")
			nm := schema.Name
			schema.GoType = nm
			schema.IsAnonymous = false
			if len(schema.Properties) > 0 {
				if b.ExtraSchemas == nil {
					b.ExtraSchemas = make(map[string]GenSchema)
				}
				b.ExtraSchemas[nm] = schema
			}
			prevSchema := schema
			schema = GenSchema{}
			schema.IsAnonymous = false
			schema.GoType = nm
			schema.SwaggerType = nm
			if len(prevSchema.Properties) == 0 {
				schema.GoType = "interface{}"
			}
			schema.IsComplexObject = true
			schema.IsInterface = len(schema.Properties) == 0
		}
		res.Schema = &schema
		it := res.Schema.Items

		items := new(GenItems)
		var prev *GenItems
		next := items
		for it != nil {
			next.resolvedType = it.resolvedType
			next.sharedValidations = it.sharedValidations
			next.Formatter = stringFormatters[it.SwaggerFormat]
			_, next.IsCustomFormatter = customFormatters[it.SwaggerFormat]
			it = it.Items
			if prev != nil {
				prev.Child = next
			}
			prev = next
			next = new(GenItems)
		}
		res.Child = items
		res.resolvedType = schema.resolvedType
		res.sharedValidations = schema.sharedValidations
		res.ZeroValue = schema.Zero()

	} else {
		res.resolvedType = simpleResolvedType(param.Type, param.Format, param.Items)
		res.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,
		}

		if param.Items != nil {
			pi, err := b.MakeParameterItem(receiver, param.Name+" "+res.IndexVar, res.IndexVar+"i", "fmt.Sprintf(\"%s.%v\", "+res.Path+", "+res.IndexVar+")", res.Name+"I", param.In, resolver, param.Items, nil)
			if err != nil {
				return GenParameter{}, err
			}
			res.Child = &pi
		}
		res.IsNullable = !param.Required && !param.AllowEmptyValue

	}

	hasNumberValidation := param.Maximum != nil || param.Minimum != nil || param.MultipleOf != nil
	hasStringValidation := param.MaxLength != nil || param.MinLength != nil || param.Pattern != ""
	hasSliceValidations := param.MaxItems != nil || param.MinItems != nil || param.UniqueItems
	hasValidations := hasNumberValidation || hasStringValidation || hasSliceValidations || len(param.Enum) > 0

	res.Converter = stringConverters[res.GoType]
	res.Formatter = stringFormatters[res.GoType]
	res.HasValidations = hasValidations
	res.HasSliceValidations = hasSliceValidations
	return res, nil
}
Example #19
0
	"schemaType":                     true,
	"subTypeBody":                    true,
	"schema":                         true,
	"additionalPropertiesSerializer": true,
	"serverDoc":                      true,
	"structfield":                    true,
	"hasDiscriminatedSerializer":     true,
	"discriminatedSerializer":        true,
}

// FuncMap is a map with default functions for use n the templates.
// These are available in every template
var FuncMap template.FuncMap = map[string]interface{}{
	"pascalize": func(arg string) string {
		if len(arg) == 0 || arg[0] > '9' {
			return swag.ToGoName(arg)
		}

		return swag.ToGoName("Nr " + arg)
	},
	"camelize":  swag.ToJSONName,
	"varname":   swag.ToVarName,
	"humanize":  swag.ToHumanNameLower,
	"snakize":   swag.ToFileName,
	"dasherize": swag.ToCommandName,
	"pluralizeFirstWord": func(arg string) string {
		sentence := strings.Split(arg, " ")
		if len(sentence) == 1 {
			return inflect.Pluralize(arg)
		}
Example #20
0
func fieldNameFromParam(param *spec.Parameter) string {
	if nm, ok := param.Extensions.GetString("go-name"); ok {
		return nm
	}
	return swag.ToGoName(param.Name)
}
Example #21
0
func (ctx *paramTestContext) assertGenParam(t testing.TB, param spec.Parameter, gp GenParameter) bool {
	// went with the verbose option here, easier to debug
	if !assert.Equal(t, param.In, gp.Location) {
		return false
	}
	if !assert.Equal(t, param.Name, gp.Name) {
		return false
	}
	if !assert.Equal(t, fmt.Sprintf("%q", param.Name), gp.Path) {
		return false
	}
	if !assert.Equal(t, "i", gp.IndexVar) {
		return false
	}
	if !assert.Equal(t, "a", gp.ReceiverName) {
		return false
	}
	if !assert.Equal(t, "a."+swag.ToGoName(param.Name), gp.ValueExpression) {
		return false
	}
	if !assert.Equal(t, ctx.Formatter, gp.Formatter) {
		return false
	}
	if !assert.Equal(t, ctx.Converter, gp.Converter) {
		return false
	}
	if !assert.Equal(t, param.Description, gp.Description) {
		return false
	}
	if !assert.Equal(t, param.CollectionFormat, gp.CollectionFormat) {
		return false
	}
	if !assert.Equal(t, param.Required, gp.Required) {
		return false
	}
	if !assert.Equal(t, param.Minimum, gp.Minimum) || !assert.Equal(t, param.ExclusiveMinimum, gp.ExclusiveMinimum) {
		return false
	}
	if !assert.Equal(t, param.Maximum, gp.Maximum) || !assert.Equal(t, param.ExclusiveMaximum, gp.ExclusiveMaximum) {
		return false
	}
	if !assert.Equal(t, param.MinLength, gp.MinLength) {
		return false
	}
	if !assert.Equal(t, param.MaxLength, gp.MaxLength) {
		return false
	}
	if !assert.Equal(t, param.Pattern, gp.Pattern) {
		return false
	}
	if !assert.Equal(t, param.MaxItems, gp.MaxItems) {
		return false
	}
	if !assert.Equal(t, param.MinItems, gp.MinItems) {
		return false
	}
	if !assert.Equal(t, param.UniqueItems, gp.UniqueItems) {
		return false
	}
	if !assert.Equal(t, param.MultipleOf, gp.MultipleOf) {
		return false
	}
	if !assert.EqualValues(t, param.Enum, gp.Enum) {
		return false
	}
	if !assert.Equal(t, param.Type, gp.SwaggerType) {
		return false
	}
	if !assert.Equal(t, param.Format, gp.SwaggerFormat) {
		return false
	}
	if _, ok := primitives[gp.GoType]; ok {
		if !assert.True(t, gp.IsPrimitive) {
			return false
		}
	} else {
		if !assert.False(t, gp.IsPrimitive) {
			return false
		}
	}
	// verify rendered template
	if param.In == "body" {
		if !assertBodyParam(t, param, gp) {
			return false
		}
		return true
	}

	if ctx.Items != nil {
		return ctx.Items.Assert(t, param.Items, gp.Child)
	}

	return true
}
Example #22
0
func (sg *schemaGenContext) buildAdditionalProperties() error {
	if sg.Schema.AdditionalProperties == nil {
		return nil
	}
	addp := *sg.Schema.AdditionalProperties
	wantsAdditional := addp.Allows || addp.Schema != nil
	sg.GenSchema.HasAdditionalProperties = wantsAdditional
	if !wantsAdditional {
		return nil
	}
	// flag swap
	if sg.GenSchema.IsComplexObject {
		sg.GenSchema.IsAdditionalProperties = true
		sg.GenSchema.IsComplexObject = false
		sg.GenSchema.IsMap = false
	}

	if addp.Schema == nil {
		return nil
	}

	if !sg.GenSchema.IsMap && (sg.GenSchema.IsAdditionalProperties && sg.Named) {
		sg.GenSchema.ValueExpression += "." + swag.ToGoName(sg.GenSchema.Name)
		comprop := sg.NewAdditionalProperty(*addp.Schema)
		comprop.Required = true
		if err := comprop.makeGenSchema(); err != nil {
			return err
		}
		sg.MergeResult(comprop, false)
		sg.GenSchema.AdditionalProperties = &comprop.GenSchema
		return nil
	}

	if sg.GenSchema.IsMap && wantsAdditional {
		// find out how deep this rabbit hole goes
		// descend, unwind and rewrite
		// This needs to be depth first, so it first goes as deep as it can and then
		// builds the result in reverse order.
		_, ls, err := newMapStack(sg)
		if err != nil {
			return err
		}
		if err := ls.Build(); err != nil {
			return err
		}

		return nil
	}

	if sg.GenSchema.IsAdditionalProperties && !sg.Named {
		// for an anonoymous object, first build the new object
		// and then replace the current one with a $ref to the
		// new object
		newObj := sg.makeNewStruct(sg.GenSchema.Name+" P"+strconv.Itoa(sg.Index), sg.Schema)
		if err := newObj.makeGenSchema(); err != nil {
			return err
		}

		sg.GenSchema = GenSchema{}
		sg.Schema = *spec.RefProperty("#/definitions/" + newObj.Name)
		if err := sg.makeGenSchema(); err != nil {
			return err
		}
		sg.MergeResult(newObj, false)
		sg.GenSchema.HasValidations = newObj.GenSchema.HasValidations
		sg.ExtraSchemas[newObj.Name] = newObj.GenSchema
		return nil
	}
	return nil
}
Example #23
0
func (sg *schemaGenContext) buildProperties() error {

	if Debug {
		log.Printf("building properties %s (parent: %s)", sg.Name, sg.Container)
	}

	//var discriminatorField string
	//if sg.Discrimination != nil {
	//dis, ok := sg.Discriminated["#/definitions/"+sg.Container]
	//if ok {

	//}
	//}
	for k, v := range sg.Schema.Properties {
		if Debug {
			bbb, _ := json.MarshalIndent(sg.Schema, "", "  ")
			log.Printf("building property %s[%q] (tup: %t) %s\n", sg.Name, k, sg.IsTuple, bbb)
		}

		// check if this requires de-anonymizing, if so lift this as a new struct and extra schema
		tpe, err := sg.TypeResolver.ResolveSchema(&v, true, sg.IsTuple || containsString(sg.Schema.Required, k))
		if sg.Schema.Discriminator == k {
			tpe.IsNullable = false
		}
		if err != nil {
			return err
		}

		vv := v
		var hasValidation bool
		var needsValidation bool
		if tpe.IsComplexObject && tpe.IsAnonymous && len(v.Properties) > 0 {
			pg := sg.makeNewStruct(sg.Name+swag.ToGoName(k), v)
			pg.IsTuple = sg.IsTuple
			if sg.Path != "" {
				pg.Path = sg.Path + "+ \".\"+" + fmt.Sprintf("%q", k)
			} else {
				pg.Path = fmt.Sprintf("%q", k)
			}
			if err := pg.makeGenSchema(); err != nil {
				return err
			}
			if v.Discriminator != "" {
				pg.GenSchema.IsBaseType = true
				pg.GenSchema.IsExported = true
				pg.GenSchema.HasBaseType = true
			}

			vv = *spec.RefProperty("#/definitions/" + pg.Name)
			hasValidation = pg.GenSchema.HasValidations
			needsValidation = pg.GenSchema.NeedsValidation
			sg.MergeResult(pg, false)
			sg.ExtraSchemas[pg.Name] = pg.GenSchema
		}

		emprop := sg.NewStructBranch(k, vv)
		emprop.IsTuple = sg.IsTuple
		if err := emprop.makeGenSchema(); err != nil {
			return err
		}
		if hasValidation || emprop.GenSchema.HasValidations {
			emprop.GenSchema.HasValidations = true
			sg.GenSchema.HasValidations = true
		}
		if needsValidation || emprop.GenSchema.NeedsValidation {
			emprop.GenSchema.NeedsValidation = true
			sg.GenSchema.NeedsValidation = true
		}
		if emprop.Schema.Ref.String() != "" {
			ref := emprop.Schema.Ref
			var sch *spec.Schema
			for ref.String() != "" {
				rsch, err := spec.ResolveRef(sg.TypeResolver.Doc.Spec(), &ref)
				if err != nil {
					return err
				}
				ref = rsch.Ref
				if rsch != nil && rsch.Ref.String() != "" {
					ref = rsch.Ref
					continue
				}
				ref = spec.Ref{}
				sch = rsch
			}
			if emprop.Discrimination != nil {
				if _, ok := emprop.Discrimination.Discriminators[emprop.Schema.Ref.String()]; ok {
					emprop.GenSchema.IsBaseType = true
					emprop.GenSchema.IsNullable = false
					emprop.GenSchema.HasBaseType = true
				}
				if _, ok := emprop.Discrimination.Discriminated[emprop.Schema.Ref.String()]; ok {
					emprop.GenSchema.IsSubType = true
				}
			}
			var nm = filepath.Base(emprop.Schema.Ref.GetURL().Fragment)
			var tn string
			if gn, ok := emprop.Schema.Extensions["x-go-name"]; ok {
				tn = gn.(string)
				nm = tn
			} else {
				tn = swag.ToGoName(nm)
			}

			tr := newTypeResolver(sg.TypeResolver.ModelsPackage, sg.TypeResolver.Doc)
			tr.ModelName = tn
			ttpe, err := tr.ResolveSchema(sch, false, true)
			if err != nil {
				return err
			}
			if ttpe.IsAliased {
				emprop.GenSchema.IsAliased = true
			}
			nv, hv := hasValidations(sch, false)
			if hv {
				emprop.GenSchema.HasValidations = true
			}
			if nv {
				emprop.GenSchema.NeedsValidation = true
			}
		}
		if sg.Schema.Discriminator == k {
			emprop.GenSchema.IsNullable = false
		}
		if emprop.GenSchema.IsBaseType {
			sg.GenSchema.HasBaseType = true
		}
		sg.MergeResult(emprop, false)
		sg.GenSchema.Properties = append(sg.GenSchema.Properties, emprop.GenSchema)
	}
	sort.Sort(sg.GenSchema.Properties)
	return nil
}
Example #24
0
func (a *appGenerator) Generate() error {

	app, err := a.makeCodegenApp()
	if err != nil {
		return err
	}

	if a.DumpData {
		bb, err := json.MarshalIndent(app, "", "  ")
		if err != nil {
			return err
		}
		fmt.Fprintln(os.Stdout, string(bb))
		return nil
	}

	errChan := make(chan error, 100)
	wg := nsync.NewControlWaitGroup(20)

	if a.GenOpts.IncludeModel {
		log.Printf("rendering %d models", len(app.Models))
		for _, mod := range app.Models {
			if len(errChan) > 0 {
				wg.Wait()
				return <-errChan
			}
			modCopy := mod
			wg.Do(func() {
				modCopy.IncludeValidator = true // a.GenOpts.IncludeValidator
				modCopy.IncludeModel = true
				gen := &definitionGenerator{
					Name:             modCopy.Name,
					SpecDoc:          a.SpecDoc,
					Target:           filepath.Join(a.Target, a.ModelsPackage),
					Data:             &modCopy,
					IncludeModel:     true,
					IncludeStruct:    true,
					IncludeValidator: true,
				}
				if err := gen.generateModel(); err != nil {
					errChan <- err
				}
			})
		}
	}
	wg.Wait()

	if a.GenOpts.IncludeHandler {
		for _, opg := range app.OperationGroups {
			opgCopy := opg
			for _, op := range opgCopy.Operations {
				if len(errChan) > 0 {
					wg.Wait()
					return <-errChan
				}
				opCopy := op
				wg.Do(func() {
					gen := &opGen{
						data:              &opCopy,
						pkg:               opgCopy.Name,
						cname:             swag.ToGoName(opCopy.Name),
						IncludeHandler:    a.GenOpts.IncludeHandler,
						IncludeParameters: a.GenOpts.IncludeParameters,
						IncludeResponses:  a.GenOpts.IncludeResponses,
						Doc:               a.SpecDoc,
						Analyzed:          a.Analyzed,
						Target:            filepath.Join(a.Target, a.ServerPackage),
						APIPackage:        a.APIPackage,
					}

					if err := gen.Generate(); err != nil {
						errChan <- err
					}
				})
			}
		}
	}

	if a.GenOpts.IncludeSupport {
		wg.Do(func() {
			if err := a.GenerateSupport(&app); err != nil {
				errChan <- err
			}
		})
	}
	wg.Wait()
	if len(errChan) > 0 {
		return <-errChan
	}
	return nil
}
func TestGenerateModel_Discriminators(t *testing.T) {
	specDoc, err := loads.Spec("../fixtures/codegen/todolist.discriminators.yml")
	if assert.NoError(t, err) {
		definitions := specDoc.Spec().Definitions

		for _, k := range []string{"cat", "Dog"} {
			schema := definitions[k]
			genModel, err := makeGenDefinition(k, "models", schema, specDoc, true, true)
			if assert.NoError(t, err) {
				assert.True(t, genModel.IsComplexObject)
				assert.Equal(t, "petType", genModel.DiscriminatorField)
				assert.Equal(t, k, genModel.DiscriminatorValue)
				buf := bytes.NewBuffer(nil)
				err := modelTemplate.Execute(buf, genModel)
				if assert.NoError(t, err) {
					b, err := formatGoFile("discriminated.go", buf.Bytes())
					if assert.NoError(t, err) {
						res := string(b)
						assertNotInCode(t, "m.Pet.Validate", res)
						assertInCode(t, "if err := m.validateName(formats); err != nil {", res)
						if k == "Dog" {
							assertInCode(t, "func (m *Dog) validatePackSize(formats strfmt.Registry) error {", res)
							assertInCode(t, "if err := m.validatePackSize(formats); err != nil {", res)
							assertInCode(t, "data.PackSize = m.PackSize", res)
							assertInCode(t, "validate.Required(\"packSize\", \"body\", m.PackSize)", res)
						} else {
							assertInCode(t, "func (m *Cat) validateHuntingSkill(formats strfmt.Registry) error {", res)
							assertInCode(t, "if err := m.validateHuntingSkill(formats); err != nil {", res)
							assertInCode(t, "if err := m.validateHuntingSkillEnum(\"huntingSkill\", \"body\", *m.HuntingSkill); err != nil {", res)
							assertInCode(t, "data.HuntingSkill = m.HuntingSkill", res)
						}
						assertInCode(t, "Name *string `json:\"name\"`", res)
						assertInCode(t, "PetType string `json:\"petType\"`", res)

						assertInCode(t, "data.Name = m.nameField", res)
						assertInCode(t, "data.PetType = \""+k+"\"", res)

						kk := swag.ToGoName(k)
						assertInCode(t, "func (m *"+kk+") Name() *string", res)
						assertInCode(t, "func (m *"+kk+") SetName(val *string)", res)
						assertInCode(t, "func (m *"+kk+") PetType() string", res)
						assertInCode(t, "func (m *"+kk+") SetPetType(val string)", res)
						assertInCode(t, "validate.Required(\"name\", \"body\", m.Name())", res)
					}
				}
			}
		}

		k := "Pet"
		schema := definitions[k]
		genModel, err := makeGenDefinition(k, "models", schema, specDoc, true, true)
		if assert.NoError(t, err) {
			assert.True(t, genModel.IsComplexObject)
			assert.Equal(t, "petType", genModel.DiscriminatorField)
			assert.Len(t, genModel.Discriminates, 2)
			assert.Len(t, genModel.ExtraSchemas, 0)
			assert.Equal(t, "Cat", genModel.Discriminates["cat"])
			assert.Equal(t, "Dog", genModel.Discriminates["Dog"])
			buf := bytes.NewBuffer(nil)
			err := modelTemplate.Execute(buf, genModel)
			if assert.NoError(t, err) {
				b, err := formatGoFile("with_discriminator.go", buf.Bytes())
				if assert.NoError(t, err) {
					res := string(b)
					assertInCode(t, "type Pet interface {", res)
					assertInCode(t, "runtime.Validatable", res)
					assertInCode(t, "Name() *string", res)
					assertInCode(t, "SetName(*string)", res)
					assertInCode(t, "PetType() string", res)
					assertInCode(t, "SetPetType(string)", res)
					assertInCode(t, "UnmarshalPet(reader io.Reader, consumer runtime.Consumer) (Pet, error)", res)
					assertInCode(t, "PetType string `json:\"petType\"`", res)
					assertInCode(t, "validate.RequiredString(\"petType\"", res)
					assertInCode(t, "switch getType.PetType {", res)
					assertInCode(t, "var result Cat", res)
					assertInCode(t, "var result Dog", res)
				}
			}
		}

	}
}
Example #26
0
func (b *codeGenOpBuilder) MakeResponse(receiver, name string, isSuccess bool, resolver *typeResolver, code int, resp spec.Response) (GenResponse, error) {
	if Debug {
		log.Printf("[%s %s] making id %q", b.Method, b.Path, b.Operation.ID)
	}

	if resp.Ref.String() != "" {
		resp2, err := spec.ResolveResponse(b.Doc.Spec(), resp.Ref)
		if err != nil {
			return GenResponse{}, err
		}
		if resp2 == nil {
			return GenResponse{}, fmt.Errorf("could not resolve response ref: %s", resp.Ref.String())
		}
		resp = *resp2
	}

	res := GenResponse{
		Package:        b.APIPackage,
		ModelsPackage:  b.ModelsPackage,
		ReceiverName:   receiver,
		Name:           name,
		Description:    resp.Description,
		DefaultImports: nil,
		Imports:        nil,
		IsSuccess:      isSuccess,
		Code:           code,
		Method:         b.Method,
		Path:           b.Path,
	}

	for hName, header := range resp.Headers {
		res.Headers = append(res.Headers, b.MakeHeader(receiver, hName, header))
	}
	sort.Sort(res.Headers)

	if resp.Schema != nil {
		sc := schemaGenContext{
			Path:             fmt.Sprintf("%q", name),
			Name:             name + "Body",
			Receiver:         receiver,
			ValueExpr:        receiver,
			IndexVar:         "i",
			Schema:           *resp.Schema,
			Required:         true,
			TypeResolver:     resolver,
			Named:            false,
			ExtraSchemas:     make(map[string]GenSchema),
			IncludeModel:     true,
			IncludeValidator: true,
		}
		if err := sc.makeGenSchema(); err != nil {
			return GenResponse{}, err
		}

		for k, v := range sc.ExtraSchemas {
			if b.ExtraSchemas == nil {
				b.ExtraSchemas = make(map[string]GenSchema)
			}
			b.ExtraSchemas[k] = v
		}

		schema := sc.GenSchema
		if schema.IsAnonymous {

			schema.Name = swag.ToGoName(sc.Name + " Body")
			nm := schema.Name
			if b.ExtraSchemas == nil {
				b.ExtraSchemas = make(map[string]GenSchema)
			}
			b.ExtraSchemas[schema.Name] = schema
			schema = GenSchema{}
			schema.IsAnonymous = false
			schema.GoType = resolver.goTypeName(nm)
			schema.SwaggerType = nm
		}

		res.Schema = &schema
	}
	return res, nil
}
Example #27
0
func (o *operationGenerator) Generate() error {
	// Build a list of codegen operations based on the tags,
	// the tag decides the actual package for an operation
	// the user specified package serves as root for generating the directory structure
	var operations GenOperations
	authed := len(o.SecurityRequirements) > 0

	var bldr codeGenOpBuilder
	bldr.Name = o.Name
	bldr.Method = o.Method
	bldr.Path = o.Path
	bldr.ModelsPackage = o.ModelsPackage
	bldr.Principal = o.Principal
	bldr.Target = o.Target
	bldr.Operation = o.Operation
	bldr.Authed = authed
	bldr.Doc = o.Doc
	bldr.Analyzed = o.Analyzed
	bldr.DefaultScheme = o.DefaultScheme
	bldr.DefaultProduces = o.DefaultProduces
	bldr.DefaultImports = []string{filepath.ToSlash(filepath.Join(baseImport(o.Base), o.ModelsPackage))}
	bldr.RootAPIPackage = o.APIPackage
	bldr.WithContext = o.WithContext
	bldr.DefaultConsumes = o.DefaultConsumes

	for _, tag := range o.Operation.Tags {
		if len(o.Tags) == 0 {
			bldr.APIPackage = mangleName(swag.ToFileName(tag), o.APIPackage)
			op, err := bldr.MakeOperation()
			if err != nil {
				return err
			}
			operations = append(operations, op)
			continue
		}
		for _, ft := range o.Tags {
			if ft == tag {
				bldr.APIPackage = mangleName(swag.ToFileName(tag), o.APIPackage)
				op, err := bldr.MakeOperation()
				if err != nil {
					return err
				}
				operations = append(operations, op)
				break
			}
		}
	}
	if len(operations) == 0 {
		bldr.APIPackage = o.APIPackage
		op, err := bldr.MakeOperation()
		if err != nil {
			return err
		}
		operations = append(operations, op)
	}
	sort.Sort(operations)

	for _, op := range operations {
		if o.DumpData {
			bb, _ := json.MarshalIndent(swag.ToDynamicJSON(op), "", " ")
			fmt.Fprintln(os.Stdout, string(bb))
			continue
		}
		og := new(opGen)
		og.IncludeHandler = o.IncludeHandler
		og.IncludeParameters = o.IncludeParameters
		og.IncludeResponses = o.IncludeResponses
		og.data = &op
		og.pkg = op.Package
		og.cname = swag.ToGoName(op.Name)
		og.Doc = o.Doc
		og.Analyzed = o.Analyzed
		og.Target = o.Target
		og.APIPackage = o.APIPackage
		og.WithContext = o.WithContext
		return og.Generate()
	}

	return nil
}