Esempio n. 1
0
func (s *SpecValidator) validateSchemaPropertyNames(nm string, sch spec.Schema, knowns map[string]struct{}) []dupProp {
	var dups []dupProp

	schn := nm
	schc := &sch
	for schc.Ref.String() != "" {
		// gather property names
		reso, err := spec.ResolveRef(s.spec.Spec(), &schc.Ref)
		if err != nil {
			panic(err)
		}
		schc = reso
		schn = sch.Ref.String()
	}

	if len(schc.AllOf) > 0 {
		for _, chld := range schc.AllOf {
			dups = append(dups, s.validateSchemaPropertyNames(schn, chld, knowns)...)
		}
		return dups
	}

	for k := range schc.Properties {
		_, ok := knowns[k]
		if ok {
			dups = append(dups, dupProp{Name: k, Definition: schn})
		} else {
			knowns[k] = struct{}{}
		}
	}

	return dups
}
Esempio n. 2
0
func (t *typeResolver) resolveSchemaRef(schema *spec.Schema) (returns bool, result resolvedType, err error) {
	if schema.Ref.String() != "" {
		returns = true
		ref, er := spec.ResolveRef(t.Doc.Spec(), &schema.Ref)
		if er != nil {
			err = er
			return
		}
		var nm = filepath.Base(schema.Ref.GetURL().Fragment)
		var tn string
		if gn, ok := ref.Extensions["x-go-name"]; ok {
			tn = gn.(string)
		} else {
			tn = swag.ToGoName(nm)
		}

		res, er := t.ResolveSchema(ref, false)
		if er != nil {
			err = er
			return
		}
		result = res
		result.GoType = tn
		result.HasDiscriminator = ref.Discriminator != ""
		result.IsNullable = t.isNullable(ref)
		if t.ModelsPackage != "" {
			result.GoType = t.ModelsPackage + "." + tn
		}
		return

	}
	return
}
Esempio n. 3
0
func (s *SpecValidator) validateCircularAncestry(nm string, sch spec.Schema, knowns map[string]struct{}) []string {
	var ancs []string

	schn := nm
	schc := &sch
	if sch.Ref.GetURL() != nil {
		reso, err := spec.ResolveRef(s.spec.Spec(), &sch.Ref)
		if err != nil {
			panic(err)
		}
		schc = reso
		schn = sch.Ref.String()
		knowns[schn] = struct{}{}
	}

	if _, ok := knowns[schn]; ok {
		ancs = append(ancs, schn)
	}
	if len(ancs) > 0 {
		return ancs
	}

	if len(schc.AllOf) > 0 {
		for _, chld := range schc.AllOf {
			ancs = append(ancs, s.validateCircularAncestry(schn, chld, knowns)...)
			if len(ancs) > 0 {
				return ancs
			}
		}
	}

	return ancs
}
Esempio n. 4
0
func (t *typeResolver) resolveSchemaRef(schema *spec.Schema, isRequired bool) (returns bool, result resolvedType, err error) {
	if schema.Ref.String() != "" {
		returns = true
		ref, er := spec.ResolveRef(t.Doc.Spec(), &schema.Ref)
		if er != nil {
			err = er
			return
		}
		var nm = filepath.Base(schema.Ref.GetURL().Fragment)
		var tn string
		if gn, ok := ref.Extensions["x-go-name"]; ok {
			tn = gn.(string)
			nm = tn
		} /*else {
			tn = swag.ToGoName(nm)
		}*/

		res, er := t.ResolveSchema(ref, false, isRequired)
		if er != nil {
			err = er
			return
		}
		result = res

		result.GoType = t.goTypeName(nm)
		result.HasDiscriminator = ref.Discriminator != ""
		result.IsNullable = t.IsNullable(ref)
		//result.IsAliased = true
		return

	}
	return
}
Esempio n. 5
0
func makeGenDefinition(name, pkg string, schema spec.Schema, specDoc *spec.Document) (*GenDefinition, error) {
	receiver := "m"
	resolver := &typeResolver{
		ModelsPackage: "",
		ModelName:     name,
		Doc:           specDoc,
	}

	di := discriminatorInfo(specDoc)

	pg := schemaGenContext{
		Path:           "",
		Name:           name,
		Receiver:       receiver,
		IndexVar:       "i",
		ValueExpr:      receiver,
		Schema:         schema,
		Required:       false,
		TypeResolver:   resolver,
		Named:          true,
		ExtraSchemas:   make(map[string]GenSchema),
		Discrimination: di,
	}
	if err := pg.makeGenSchema(); err != nil {
		return nil, err
	}
	dsi, ok := di.Discriminators["#/definitions/"+name]
	if ok {
		// when these 2 are true then the schema will render as an interface
		pg.GenSchema.IsBaseType = true
		pg.GenSchema.IsExported = true
		pg.GenSchema.DiscriminatorField = dsi.FieldName
		// clone schema and turn into IsExported false
		//tpeImpl := newDiscriminatorImpl(pg.GenSchema)
		//pg.ExtraSchemas[tpeImpl.Name] = tpeImpl

		for _, v := range dsi.Children {
			if pg.GenSchema.Discriminates == nil {
				pg.GenSchema.Discriminates = make(map[string]string)
			}
			pg.GenSchema.Discriminates[v.FieldValue] = v.GoType
		}
	}
	dse, ok := di.Discriminated["#/definitions/"+name]
	if ok {
		pg.GenSchema.DiscriminatorField = dse.FieldName
		pg.GenSchema.DiscriminatorValue = dse.FieldValue
		pg.GenSchema.IsSubType = true

		// find the referenced definitions
		// check if it has a discriminator defined
		// when it has a discriminator get the schema and run makeGenSchema for it.
		// replace the ref with this new genschema
		swsp := specDoc.Spec()
		for i, ss := range schema.AllOf {
			ref := ss.Ref
			for ref.String() != "" {
				rsch, err := spec.ResolveRef(swsp, &ref)
				if err != nil {
					return nil, err
				}
				ref = rsch.Ref
				if rsch != nil && rsch.Ref.String() != "" {
					ref = rsch.Ref
					continue
				}
				ref = spec.Ref{}
				if rsch != nil && rsch.Discriminator != "" {
					gs, err := makeGenDefinition(strings.TrimPrefix(ss.Ref.String(), "#/definitions/"), pkg, *rsch, specDoc)
					if err != nil {
						return nil, err
					}
					gs.GenSchema.IsBaseType = true
					gs.GenSchema.IsExported = true
					pg.GenSchema.AllOf[i] = gs.GenSchema
					schPtr := &(pg.GenSchema.AllOf[i])
					if schPtr.AdditionalItems != nil {
						schPtr.AdditionalItems.IsBaseType = true
					}
					if schPtr.AdditionalProperties != nil {
						schPtr.AdditionalProperties.IsBaseType = true
					}
					for j := range schPtr.Properties {
						schPtr.Properties[j].IsBaseType = true
						schPtr.Properties[j].ValueExpression += "()"
					}
				}
			}
		}
	}

	var defaultImports []string
	if pg.GenSchema.HasValidations {
		defaultImports = []string{
			"github.com/go-swagger/go-swagger/errors",
			"github.com/go-swagger/go-swagger/strfmt",
			"github.com/go-swagger/go-swagger/httpkit/validate",
		}
	}
	var extras []GenSchema
	var extraKeys []string
	for k := range pg.ExtraSchemas {
		extraKeys = append(extraKeys, k)
	}
	sort.Strings(extraKeys)
	for _, k := range extraKeys {
		extras = append(extras, pg.ExtraSchemas[k])
	}

	return &GenDefinition{
		Package:        mangleName(filepath.Base(pkg), "definitions"),
		GenSchema:      pg.GenSchema,
		DependsOn:      pg.Dependencies,
		DefaultImports: defaultImports,
		ExtraSchemas:   extras,
	}, nil
}
Esempio n. 6
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
}