mirror of
				https://github.com/go-gitea/gitea
				synced 2025-11-04 05:18:25 +00:00 
			
		
		
		
	* Use vendored go-swagger * vendor go-swagger * revert un wanteed change * remove un-needed GO111MODULE * Update Makefile Co-Authored-By: techknowlogick <matti@mdranta.net>
		
			
				
	
	
		
			235 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package analysis
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
 | 
						|
	"github.com/go-openapi/spec"
 | 
						|
	"github.com/go-openapi/strfmt"
 | 
						|
)
 | 
						|
 | 
						|
// SchemaOpts configures the schema analyzer
 | 
						|
type SchemaOpts struct {
 | 
						|
	Schema   *spec.Schema
 | 
						|
	Root     interface{}
 | 
						|
	BasePath string
 | 
						|
	_        struct{}
 | 
						|
}
 | 
						|
 | 
						|
// Schema analysis, will classify the schema according to known
 | 
						|
// patterns.
 | 
						|
func Schema(opts SchemaOpts) (*AnalyzedSchema, error) {
 | 
						|
	if opts.Schema == nil {
 | 
						|
		return nil, fmt.Errorf("no schema to analyze")
 | 
						|
	}
 | 
						|
 | 
						|
	a := &AnalyzedSchema{
 | 
						|
		schema:   opts.Schema,
 | 
						|
		root:     opts.Root,
 | 
						|
		basePath: opts.BasePath,
 | 
						|
	}
 | 
						|
 | 
						|
	a.initializeFlags()
 | 
						|
	a.inferKnownType()
 | 
						|
	a.inferEnum()
 | 
						|
	a.inferBaseType()
 | 
						|
 | 
						|
	if err := a.inferMap(); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
	if err := a.inferArray(); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	a.inferTuple()
 | 
						|
 | 
						|
	if err := a.inferFromRef(); err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	a.inferSimpleSchema()
 | 
						|
	return a, nil
 | 
						|
}
 | 
						|
 | 
						|
// AnalyzedSchema indicates what the schema represents
 | 
						|
type AnalyzedSchema struct {
 | 
						|
	schema   *spec.Schema
 | 
						|
	root     interface{}
 | 
						|
	basePath string
 | 
						|
 | 
						|
	hasProps           bool
 | 
						|
	hasAllOf           bool
 | 
						|
	hasItems           bool
 | 
						|
	hasAdditionalProps bool
 | 
						|
	hasAdditionalItems bool
 | 
						|
	hasRef             bool
 | 
						|
 | 
						|
	IsKnownType      bool
 | 
						|
	IsSimpleSchema   bool
 | 
						|
	IsArray          bool
 | 
						|
	IsSimpleArray    bool
 | 
						|
	IsMap            bool
 | 
						|
	IsSimpleMap      bool
 | 
						|
	IsExtendedObject bool
 | 
						|
	IsTuple          bool
 | 
						|
	IsTupleWithExtra bool
 | 
						|
	IsBaseType       bool
 | 
						|
	IsEnum           bool
 | 
						|
}
 | 
						|
 | 
						|
// Inherits copies value fields from other onto this schema
 | 
						|
func (a *AnalyzedSchema) inherits(other *AnalyzedSchema) {
 | 
						|
	if other == nil {
 | 
						|
		return
 | 
						|
	}
 | 
						|
	a.hasProps = other.hasProps
 | 
						|
	a.hasAllOf = other.hasAllOf
 | 
						|
	a.hasItems = other.hasItems
 | 
						|
	a.hasAdditionalItems = other.hasAdditionalItems
 | 
						|
	a.hasAdditionalProps = other.hasAdditionalProps
 | 
						|
	a.hasRef = other.hasRef
 | 
						|
 | 
						|
	a.IsKnownType = other.IsKnownType
 | 
						|
	a.IsSimpleSchema = other.IsSimpleSchema
 | 
						|
	a.IsArray = other.IsArray
 | 
						|
	a.IsSimpleArray = other.IsSimpleArray
 | 
						|
	a.IsMap = other.IsMap
 | 
						|
	a.IsSimpleMap = other.IsSimpleMap
 | 
						|
	a.IsExtendedObject = other.IsExtendedObject
 | 
						|
	a.IsTuple = other.IsTuple
 | 
						|
	a.IsTupleWithExtra = other.IsTupleWithExtra
 | 
						|
	a.IsBaseType = other.IsBaseType
 | 
						|
	a.IsEnum = other.IsEnum
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) inferFromRef() error {
 | 
						|
	if a.hasRef {
 | 
						|
		sch := new(spec.Schema)
 | 
						|
		sch.Ref = a.schema.Ref
 | 
						|
		err := spec.ExpandSchema(sch, a.root, nil)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		rsch, err := Schema(SchemaOpts{
 | 
						|
			Schema:   sch,
 | 
						|
			Root:     a.root,
 | 
						|
			BasePath: a.basePath,
 | 
						|
		})
 | 
						|
		if err != nil {
 | 
						|
			// NOTE(fredbi): currently the only cause for errors is
 | 
						|
			// unresolved ref. Since spec.ExpandSchema() expands the
 | 
						|
			// schema recursively, there is no chance to get there,
 | 
						|
			// until we add more causes for error in this schema analysis.
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		a.inherits(rsch)
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) inferSimpleSchema() {
 | 
						|
	a.IsSimpleSchema = a.IsKnownType || a.IsSimpleArray || a.IsSimpleMap
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) inferKnownType() {
 | 
						|
	tpe := a.schema.Type
 | 
						|
	format := a.schema.Format
 | 
						|
	a.IsKnownType = tpe.Contains("boolean") ||
 | 
						|
		tpe.Contains("integer") ||
 | 
						|
		tpe.Contains("number") ||
 | 
						|
		tpe.Contains("string") ||
 | 
						|
		(format != "" && strfmt.Default.ContainsName(format)) ||
 | 
						|
		(a.isObjectType() && !a.hasProps && !a.hasAllOf && !a.hasAdditionalProps && !a.hasAdditionalItems)
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) inferMap() error {
 | 
						|
	if a.isObjectType() {
 | 
						|
		hasExtra := a.hasProps || a.hasAllOf
 | 
						|
		a.IsMap = a.hasAdditionalProps && !hasExtra
 | 
						|
		a.IsExtendedObject = a.hasAdditionalProps && hasExtra
 | 
						|
		if a.IsMap {
 | 
						|
			if a.schema.AdditionalProperties.Schema != nil {
 | 
						|
				msch, err := Schema(SchemaOpts{
 | 
						|
					Schema:   a.schema.AdditionalProperties.Schema,
 | 
						|
					Root:     a.root,
 | 
						|
					BasePath: a.basePath,
 | 
						|
				})
 | 
						|
				if err != nil {
 | 
						|
					return err
 | 
						|
				}
 | 
						|
				a.IsSimpleMap = msch.IsSimpleSchema
 | 
						|
			} else if a.schema.AdditionalProperties.Allows {
 | 
						|
				a.IsSimpleMap = true
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) inferArray() error {
 | 
						|
	// an array has Items defined as an object schema, otherwise we qualify this JSON array as a tuple
 | 
						|
	// (yes, even if the Items array contains only one element).
 | 
						|
	// arrays in JSON schema may be unrestricted (i.e no Items specified).
 | 
						|
	// Note that arrays in Swagger MUST have Items. Nonetheless, we analyze unrestricted arrays.
 | 
						|
	//
 | 
						|
	// NOTE: the spec package misses the distinction between:
 | 
						|
	// items: [] and items: {}, so we consider both arrays here.
 | 
						|
	a.IsArray = a.isArrayType() && (a.schema.Items == nil || a.schema.Items.Schemas == nil)
 | 
						|
	if a.IsArray && a.hasItems {
 | 
						|
		if a.schema.Items.Schema != nil {
 | 
						|
			itsch, err := Schema(SchemaOpts{
 | 
						|
				Schema:   a.schema.Items.Schema,
 | 
						|
				Root:     a.root,
 | 
						|
				BasePath: a.basePath,
 | 
						|
			})
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
			a.IsSimpleArray = itsch.IsSimpleSchema
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if a.IsArray && !a.hasItems {
 | 
						|
		a.IsSimpleArray = true
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) inferTuple() {
 | 
						|
	tuple := a.hasItems && a.schema.Items.Schemas != nil
 | 
						|
	a.IsTuple = tuple && !a.hasAdditionalItems
 | 
						|
	a.IsTupleWithExtra = tuple && a.hasAdditionalItems
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) inferBaseType() {
 | 
						|
	if a.isObjectType() {
 | 
						|
		a.IsBaseType = a.schema.Discriminator != ""
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) inferEnum() {
 | 
						|
	a.IsEnum = len(a.schema.Enum) > 0
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) initializeFlags() {
 | 
						|
	a.hasProps = len(a.schema.Properties) > 0
 | 
						|
	a.hasAllOf = len(a.schema.AllOf) > 0
 | 
						|
	a.hasRef = a.schema.Ref.String() != ""
 | 
						|
 | 
						|
	a.hasItems = a.schema.Items != nil &&
 | 
						|
		(a.schema.Items.Schema != nil || len(a.schema.Items.Schemas) > 0)
 | 
						|
 | 
						|
	a.hasAdditionalProps = a.schema.AdditionalProperties != nil &&
 | 
						|
		(a.schema.AdditionalProperties != nil || a.schema.AdditionalProperties.Allows)
 | 
						|
 | 
						|
	a.hasAdditionalItems = a.schema.AdditionalItems != nil &&
 | 
						|
		(a.schema.AdditionalItems.Schema != nil || a.schema.AdditionalItems.Allows)
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) isObjectType() bool {
 | 
						|
	return !a.hasRef && (a.schema.Type == nil || a.schema.Type.Contains("") || a.schema.Type.Contains("object"))
 | 
						|
}
 | 
						|
 | 
						|
func (a *AnalyzedSchema) isArrayType() bool {
 | 
						|
	return !a.hasRef && (a.schema.Type != nil && a.schema.Type.Contains("array"))
 | 
						|
}
 |