Пример #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
}
Пример #2
0
func (s *SpecValidator) validateCircularAncestry(nm string, sch spec.Schema, knowns map[string]struct{}) []string {
	if sch.Ref.String() == "" && len(sch.AllOf) == 0 {
		return nil
	}
	var ancs []string

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

	if schn != nm && schn != "" {
		if _, ok := knowns[schn]; ok {
			ancs = append(ancs, schn)
		}
		knowns[schn] = struct{}{}

		if len(ancs) > 0 {
			return ancs
		}
	}

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

	return ancs
}
Пример #3
0
func (t *typeResolver) resolveSchemaRef(schema *spec.Schema, isRequired bool) (returns bool, result resolvedType, err error) {
	if schema.Ref.String() != "" {
		if Debug {
			_, file, pos, _ := runtime.Caller(1)
			log.Printf("%s:%d: resolving ref (anon: %t, req: %t) %s\n", filepath.Base(file), pos, false, isRequired, 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
}
Пример #4
0
func (s *SpecValidator) resolveRef(ref *spec.Ref) (*spec.Schema, error) {
	if s.spec.SpecFilePath() != "" {
		return spec.ResolveRefWithBase(s.spec.Spec(), ref, &spec.ExpandOptions{RelativeBase: s.spec.SpecFilePath()})
	}
	return spec.ResolveRef(s.spec.Spec(), ref)
}
Пример #5
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
}
Пример #6
0
func makeGenDefinitionHierarchy(name, pkg, container string, schema spec.Schema, specDoc *loads.Document, includeValidator, includeModel bool) (*GenDefinition, error) {
	receiver := "m"
	resolver := newTypeResolver("", specDoc)
	resolver.ModelName = name
	analyzed := analysis.New(specDoc.Spec())

	di := discriminatorInfo(analyzed)

	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,
		Container:        container,
		IncludeValidator: includeValidator,
		IncludeModel:     includeModel,
	}
	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

		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 := makeGenDefinitionHierarchy(strings.TrimPrefix(ss.Ref.String(), "#/definitions/"), pkg, pg.GenSchema.Name, *rsch, specDoc, pg.IncludeValidator, pg.IncludeModel)
					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-openapi/errors",
			"github.com/go-openapi/runtime",
			"github.com/go-openapi/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
}