Vendor Update (#14496)
* update code.gitea.io/sdk/gitea v0.13.1 -> v0.13.2 * update github.com/go-swagger/go-swagger v0.25.0 -> v0.26.0 * update github.com/google/uuid v1.1.2 -> v1.2.0 * update github.com/klauspost/compress v1.11.3 -> v1.11.7 * update github.com/lib/pq 083382b7e6fc -> v1.9.0 * update github.com/markbates/goth v1.65.0 -> v1.66.1 * update github.com/mattn/go-sqlite3 v1.14.4 -> v1.14.6 * update github.com/mgechev/revive 246eac737dc7 -> v1.0.3 * update github.com/minio/minio-go/v7 v7.0.6 -> v7.0.7 * update github.com/niklasfasching/go-org v1.3.2 -> v1.4.0 * update github.com/olivere/elastic/v7 v7.0.21 -> v7.0.22 * update github.com/pquerna/otp v1.2.0 -> v1.3.0 * update github.com/xanzy/go-gitlab v0.39.0 -> v0.42.0 * update github.com/yuin/goldmark v1.2.1 -> v1.3.1
This commit is contained in:
parent
e45bf12a34
commit
d1353e1f7c
403 changed files with 29737 additions and 14357 deletions
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff.go
generated
vendored
|
@ -43,7 +43,7 @@ func (c *DiffCommand) Execute(_ []string) error {
|
|||
output io.WriteCloser
|
||||
err error
|
||||
)
|
||||
if c.Destination != "" {
|
||||
if c.Destination != "stdout" {
|
||||
output, err = os.OpenFile(c.Destination, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0600)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s: %w", c.Destination, err)
|
||||
|
|
266
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/checks.go
generated
vendored
Normal file
266
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/checks.go
generated
vendored
Normal file
|
@ -0,0 +1,266 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// CompareEnums returns added, deleted enum values
|
||||
func CompareEnums(left, right []interface{}) []TypeDiff {
|
||||
diffs := []TypeDiff{}
|
||||
|
||||
leftStrs := []string{}
|
||||
rightStrs := []string{}
|
||||
for _, eachLeft := range left {
|
||||
leftStrs = append(leftStrs, fmt.Sprintf("%v", eachLeft))
|
||||
}
|
||||
for _, eachRight := range right {
|
||||
rightStrs = append(rightStrs, fmt.Sprintf("%v", eachRight))
|
||||
}
|
||||
added, deleted, _ := fromStringArray(leftStrs).DiffsTo(rightStrs)
|
||||
if len(added) > 0 {
|
||||
typeChange := strings.Join(added, ",")
|
||||
diffs = append(diffs, TypeDiff{Change: AddedEnumValue, Description: typeChange})
|
||||
}
|
||||
if len(deleted) > 0 {
|
||||
typeChange := strings.Join(deleted, ",")
|
||||
diffs = append(diffs, TypeDiff{Change: DeletedEnumValue, Description: typeChange})
|
||||
}
|
||||
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CompareProperties recursive property comparison
|
||||
func CompareProperties(location DifferenceLocation, schema1 *spec.Schema, schema2 *spec.Schema, getRefFn1 SchemaFromRefFn, getRefFn2 SchemaFromRefFn, cmp CompareSchemaFn) []SpecDifference {
|
||||
propDiffs := []SpecDifference{}
|
||||
|
||||
if schema1.Properties == nil && schema2.Properties == nil {
|
||||
return propDiffs
|
||||
}
|
||||
|
||||
schema1Props := propertiesFor(schema1, getRefFn1)
|
||||
schema2Props := propertiesFor(schema2, getRefFn2)
|
||||
// find deleted and changed properties
|
||||
|
||||
for eachProp1Name, eachProp1 := range schema1Props {
|
||||
eachProp1 := eachProp1
|
||||
childLoc := addChildDiffNode(location, eachProp1Name, eachProp1.Schema)
|
||||
|
||||
if eachProp2, ok := schema2Props[eachProp1Name]; ok {
|
||||
diffs := CheckToFromRequired(eachProp1.Required, eachProp2.Required)
|
||||
if len(diffs) > 0 {
|
||||
for _, diff := range diffs {
|
||||
propDiffs = append(propDiffs, SpecDifference{DifferenceLocation: childLoc, Code: diff.Change})
|
||||
}
|
||||
}
|
||||
cmp(childLoc, eachProp1.Schema, eachProp2.Schema)
|
||||
} else {
|
||||
propDiffs = append(propDiffs, SpecDifference{DifferenceLocation: childLoc, Code: DeletedProperty})
|
||||
}
|
||||
}
|
||||
|
||||
// find added properties
|
||||
for eachProp2Name, eachProp2 := range schema2.Properties {
|
||||
eachProp2 := eachProp2
|
||||
if _, ok := schema1.Properties[eachProp2Name]; !ok {
|
||||
childLoc := addChildDiffNode(location, eachProp2Name, &eachProp2)
|
||||
propDiffs = append(propDiffs, SpecDifference{DifferenceLocation: childLoc, Code: AddedProperty})
|
||||
}
|
||||
}
|
||||
return propDiffs
|
||||
|
||||
}
|
||||
|
||||
// CompareFloatValues compares a float data item
|
||||
func CompareFloatValues(fieldName string, val1 *float64, val2 *float64, ifGreaterCode SpecChangeCode, ifLessCode SpecChangeCode) []TypeDiff {
|
||||
diffs := []TypeDiff{}
|
||||
if val1 != nil && val2 != nil {
|
||||
if *val2 > *val1 {
|
||||
diffs = append(diffs, TypeDiff{Change: ifGreaterCode, Description: fmt.Sprintf("%s %f->%f", fieldName, *val1, *val2)})
|
||||
} else if *val2 < *val1 {
|
||||
diffs = append(diffs, TypeDiff{Change: ifLessCode, Description: fmt.Sprintf("%s %f->%f", fieldName, *val1, *val2)})
|
||||
}
|
||||
} else {
|
||||
if val1 != val2 {
|
||||
if val1 != nil {
|
||||
diffs = append(diffs, TypeDiff{Change: DeletedConstraint, Description: fmt.Sprintf("%s(%f)", fieldName, *val1)})
|
||||
} else {
|
||||
diffs = append(diffs, TypeDiff{Change: AddedConstraint, Description: fmt.Sprintf("%s(%f)", fieldName, *val2)})
|
||||
}
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CompareIntValues compares to int data items
|
||||
func CompareIntValues(fieldName string, val1 *int64, val2 *int64, ifGreaterCode SpecChangeCode, ifLessCode SpecChangeCode) []TypeDiff {
|
||||
diffs := []TypeDiff{}
|
||||
if val1 != nil && val2 != nil {
|
||||
if *val2 > *val1 {
|
||||
diffs = append(diffs, TypeDiff{Change: ifGreaterCode, Description: fmt.Sprintf("%s %d->%d", fieldName, *val1, *val2)})
|
||||
} else if *val2 < *val1 {
|
||||
diffs = append(diffs, TypeDiff{Change: ifLessCode, Description: fmt.Sprintf("%s %d->%d", fieldName, *val1, *val2)})
|
||||
}
|
||||
} else {
|
||||
if val1 != val2 {
|
||||
if val1 != nil {
|
||||
diffs = append(diffs, TypeDiff{Change: DeletedConstraint, Description: fmt.Sprintf("%s(%d)", fieldName, *val1)})
|
||||
} else {
|
||||
diffs = append(diffs, TypeDiff{Change: AddedConstraint, Description: fmt.Sprintf("%s(%d)", fieldName, *val2)})
|
||||
}
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckToFromPrimitiveType check for diff to or from a primitive
|
||||
func CheckToFromPrimitiveType(diffs []TypeDiff, type1, type2 interface{}) []TypeDiff {
|
||||
|
||||
type1IsPrimitive := isPrimitive(type1)
|
||||
type2IsPrimitive := isPrimitive(type2)
|
||||
|
||||
// Primitive to Obj or Obj to Primitive
|
||||
if type1IsPrimitive != type2IsPrimitive {
|
||||
typeStr1, isarray1 := getSchemaType(type1)
|
||||
typeStr2, isarray2 := getSchemaType(type2)
|
||||
return addTypeDiff(diffs, TypeDiff{Change: ChangedType, FromType: formatTypeString(typeStr1, isarray1), ToType: formatTypeString(typeStr2, isarray2)})
|
||||
}
|
||||
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckRefChange has the property ref changed
|
||||
func CheckRefChange(diffs []TypeDiff, type1, type2 interface{}) (diffReturn []TypeDiff) {
|
||||
|
||||
diffReturn = diffs
|
||||
if isRefType(type1) && isRefType(type2) {
|
||||
// both refs but to different objects (TODO detect renamed object)
|
||||
ref1 := definitionFromRef(getRef(type1))
|
||||
ref2 := definitionFromRef(getRef(type2))
|
||||
if ref1 != ref2 {
|
||||
diffReturn = addTypeDiff(diffReturn, TypeDiff{Change: RefTargetChanged, FromType: getSchemaTypeStr(type1), ToType: getSchemaTypeStr(type2)})
|
||||
}
|
||||
} else if isRefType(type1) != isRefType(type2) {
|
||||
diffReturn = addTypeDiff(diffReturn, TypeDiff{Change: ChangedType, FromType: getSchemaTypeStr(type1), ToType: getSchemaTypeStr(type2)})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// checkNumericTypeChanges checks for changes to or from a numeric type
|
||||
func checkNumericTypeChanges(diffs []TypeDiff, type1, type2 *spec.SchemaProps) []TypeDiff {
|
||||
// Number
|
||||
_, type1IsNumeric := numberWideness[type1.Type[0]]
|
||||
_, type2IsNumeric := numberWideness[type2.Type[0]]
|
||||
|
||||
if type1IsNumeric && type2IsNumeric {
|
||||
foundDiff := false
|
||||
if type1.ExclusiveMaximum && !type2.ExclusiveMaximum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: WidenedType, Description: fmt.Sprintf("Exclusive Maximum Removed:%v->%v", type1.ExclusiveMaximum, type2.ExclusiveMaximum)})
|
||||
foundDiff = true
|
||||
}
|
||||
if !type1.ExclusiveMaximum && type2.ExclusiveMaximum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: NarrowedType, Description: fmt.Sprintf("Exclusive Maximum Added:%v->%v", type1.ExclusiveMaximum, type2.ExclusiveMaximum)})
|
||||
foundDiff = true
|
||||
}
|
||||
if type1.ExclusiveMinimum && !type2.ExclusiveMinimum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: WidenedType, Description: fmt.Sprintf("Exclusive Minimum Removed:%v->%v", type1.ExclusiveMaximum, type2.ExclusiveMaximum)})
|
||||
foundDiff = true
|
||||
}
|
||||
if !type1.ExclusiveMinimum && type2.ExclusiveMinimum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: NarrowedType, Description: fmt.Sprintf("Exclusive Minimum Added:%v->%v", type1.ExclusiveMinimum, type2.ExclusiveMinimum)})
|
||||
foundDiff = true
|
||||
}
|
||||
if !foundDiff {
|
||||
maxDiffs := CompareFloatValues("Maximum", type1.Maximum, type2.Maximum, WidenedType, NarrowedType)
|
||||
diffs = append(diffs, maxDiffs...)
|
||||
minDiffs := CompareFloatValues("Minimum", type1.Minimum, type2.Minimum, NarrowedType, WidenedType)
|
||||
diffs = append(diffs, minDiffs...)
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckStringTypeChanges checks for changes to or from a string type
|
||||
func CheckStringTypeChanges(diffs []TypeDiff, type1, type2 *spec.SchemaProps) []TypeDiff {
|
||||
// string changes
|
||||
if type1.Type[0] == StringType &&
|
||||
type2.Type[0] == StringType {
|
||||
minLengthDiffs := CompareIntValues("MinLength", type1.MinLength, type2.MinLength, NarrowedType, WidenedType)
|
||||
diffs = append(diffs, minLengthDiffs...)
|
||||
maxLengthDiffs := CompareIntValues("MaxLength", type1.MinLength, type2.MinLength, WidenedType, NarrowedType)
|
||||
diffs = append(diffs, maxLengthDiffs...)
|
||||
if type1.Pattern != type2.Pattern {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: ChangedType, Description: fmt.Sprintf("Pattern Changed:%s->%s", type1.Pattern, type2.Pattern)})
|
||||
}
|
||||
if type1.Type[0] == StringType {
|
||||
if len(type1.Enum) > 0 {
|
||||
enumDiffs := CompareEnums(type1.Enum, type2.Enum)
|
||||
diffs = append(diffs, enumDiffs...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckToFromRequired checks for changes to or from a required property
|
||||
func CheckToFromRequired(required1, required2 bool) (diffs []TypeDiff) {
|
||||
if required1 != required2 {
|
||||
code := ChangedOptionalToRequired
|
||||
if required1 {
|
||||
code = ChangedRequiredToOptional
|
||||
}
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: code})
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
const objType = "object"
|
||||
|
||||
func getTypeHierarchyChange(type1, type2 string) TypeDiff {
|
||||
fromType := type1
|
||||
if fromType == "" {
|
||||
fromType = objType
|
||||
}
|
||||
toType := type2
|
||||
if toType == "" {
|
||||
toType = objType
|
||||
}
|
||||
diffDescription := fmt.Sprintf("%s -> %s", fromType, toType)
|
||||
if isStringType(type1) && !isStringType(type2) {
|
||||
return TypeDiff{Change: NarrowedType, Description: diffDescription}
|
||||
}
|
||||
if !isStringType(type1) && isStringType(type2) {
|
||||
return TypeDiff{Change: WidenedType, Description: diffDescription}
|
||||
}
|
||||
type1Wideness, type1IsNumeric := numberWideness[type1]
|
||||
type2Wideness, type2IsNumeric := numberWideness[type2]
|
||||
if type1IsNumeric && type2IsNumeric {
|
||||
if type1Wideness == type2Wideness {
|
||||
return TypeDiff{Change: ChangedToCompatibleType, Description: diffDescription}
|
||||
}
|
||||
if type1Wideness > type2Wideness {
|
||||
return TypeDiff{Change: NarrowedType, Description: diffDescription}
|
||||
}
|
||||
if type1Wideness < type2Wideness {
|
||||
return TypeDiff{Change: WidenedType, Description: diffDescription}
|
||||
}
|
||||
}
|
||||
return TypeDiff{Change: ChangedType, Description: diffDescription}
|
||||
}
|
||||
|
||||
func isRefType(item interface{}) bool {
|
||||
switch s := item.(type) {
|
||||
case spec.Refable:
|
||||
return s.Ref.String() != ""
|
||||
case *spec.Schema:
|
||||
return s.Ref.String() != ""
|
||||
case *spec.SchemaProps:
|
||||
return s.Ref.String() != ""
|
||||
case *spec.SimpleSchema:
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
54
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/compatibility.go
generated
vendored
54
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/compatibility.go
generated
vendored
|
@ -32,29 +32,33 @@ func init() {
|
|||
ChangedTag: NonBreaking,
|
||||
AddedTag: NonBreaking,
|
||||
DeletedTag: NonBreaking,
|
||||
DeletedConstraint: Breaking,
|
||||
AddedConstraint: NonBreaking,
|
||||
},
|
||||
ForRequest: map[SpecChangeCode]Compatibility{
|
||||
AddedRequiredProperty: Breaking,
|
||||
DeletedProperty: Breaking,
|
||||
AddedProperty: Breaking,
|
||||
AddedOptionalParam: NonBreaking,
|
||||
AddedRequiredParam: Breaking,
|
||||
DeletedOptionalParam: NonBreaking,
|
||||
DeletedRequiredParam: NonBreaking,
|
||||
WidenedType: NonBreaking,
|
||||
NarrowedType: Breaking,
|
||||
ChangedType: Breaking,
|
||||
ChangedToCompatibleType: NonBreaking,
|
||||
ChangedOptionalToRequiredParam: Breaking,
|
||||
ChangedRequiredToOptionalParam: NonBreaking,
|
||||
AddedEnumValue: NonBreaking,
|
||||
DeletedEnumValue: Breaking,
|
||||
ChangedDescripton: NonBreaking,
|
||||
AddedDescripton: NonBreaking,
|
||||
DeletedDescripton: NonBreaking,
|
||||
ChangedTag: NonBreaking,
|
||||
AddedTag: NonBreaking,
|
||||
DeletedTag: NonBreaking,
|
||||
AddedRequiredProperty: Breaking,
|
||||
DeletedProperty: Breaking,
|
||||
AddedProperty: Breaking,
|
||||
AddedOptionalParam: NonBreaking,
|
||||
AddedRequiredParam: Breaking,
|
||||
DeletedOptionalParam: NonBreaking,
|
||||
DeletedRequiredParam: NonBreaking,
|
||||
WidenedType: NonBreaking,
|
||||
NarrowedType: Breaking,
|
||||
ChangedType: Breaking,
|
||||
ChangedToCompatibleType: NonBreaking,
|
||||
ChangedOptionalToRequired: Breaking,
|
||||
ChangedRequiredToOptional: NonBreaking,
|
||||
AddedEnumValue: NonBreaking,
|
||||
DeletedEnumValue: Breaking,
|
||||
ChangedDescripton: NonBreaking,
|
||||
AddedDescripton: NonBreaking,
|
||||
DeletedDescripton: NonBreaking,
|
||||
ChangedTag: NonBreaking,
|
||||
AddedTag: NonBreaking,
|
||||
DeletedTag: NonBreaking,
|
||||
DeletedConstraint: NonBreaking,
|
||||
AddedConstraint: Breaking,
|
||||
},
|
||||
ForChange: map[SpecChangeCode]Compatibility{
|
||||
NoChangeDetected: NonBreaking,
|
||||
|
@ -63,8 +67,8 @@ func init() {
|
|||
DeletedDeprecatedEndpoint: NonBreaking,
|
||||
AddedConsumesFormat: NonBreaking,
|
||||
DeletedConsumesFormat: Breaking,
|
||||
AddedProducesFormat: Breaking,
|
||||
DeletedProducesFormat: NonBreaking,
|
||||
AddedProducesFormat: NonBreaking,
|
||||
DeletedProducesFormat: Breaking,
|
||||
AddedSchemes: NonBreaking,
|
||||
DeletedSchemes: Breaking,
|
||||
ChangedHostURL: Breaking,
|
||||
|
@ -75,6 +79,10 @@ func init() {
|
|||
ChangedTag: NonBreaking,
|
||||
AddedTag: NonBreaking,
|
||||
DeletedTag: NonBreaking,
|
||||
RefTargetChanged: Breaking,
|
||||
RefTargetRenamed: NonBreaking,
|
||||
AddedDefinition: NonBreaking,
|
||||
DeletedDefinition: NonBreaking,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
187
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/difftypes.go
generated
vendored
187
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/difftypes.go
generated
vendored
|
@ -43,8 +43,6 @@ const (
|
|||
AddedRequiredParam
|
||||
// DeletedRequiredParam - A required parameter has been deleted in the new spec
|
||||
DeletedRequiredParam
|
||||
// ChangedRequiredToOptional - A required parameter has been made optional in the new spec
|
||||
ChangedRequiredToOptional
|
||||
// AddedEndpoint - An endpoint has been added in the new spec
|
||||
AddedEndpoint
|
||||
// WidenedType - An type has been changed to a more permissive type eg int->string
|
||||
|
@ -61,10 +59,10 @@ const (
|
|||
DeletedEnumValue
|
||||
// AddedOptionalParam - A new optional parameter has been added to the new spec
|
||||
AddedOptionalParam
|
||||
// ChangedOptionalToRequiredParam - An optional parameter is now required in the new spec
|
||||
ChangedOptionalToRequiredParam
|
||||
// ChangedRequiredToOptionalParam - An required parameter is now optional in the new spec
|
||||
ChangedRequiredToOptionalParam
|
||||
// ChangedOptionalToRequired - An optional parameter is now required in the new spec
|
||||
ChangedOptionalToRequired
|
||||
// ChangedRequiredToOptional - An required parameter is now optional in the new spec
|
||||
ChangedRequiredToOptional
|
||||
// AddedResponse An endpoint has new response code in the new spec
|
||||
AddedResponse
|
||||
// AddedConsumesFormat - a new consumes format (json/xml/yaml etc) has been added in the new spec
|
||||
|
@ -89,88 +87,112 @@ const (
|
|||
ChangedResponseHeader
|
||||
// DeletedResponseHeader Added a header Item
|
||||
DeletedResponseHeader
|
||||
// RefTargetChanged Changed a ref to point to a different object
|
||||
RefTargetChanged
|
||||
// RefTargetRenamed Renamed a ref to point to the same object
|
||||
RefTargetRenamed
|
||||
// DeletedConstraint Deleted a schema constraint
|
||||
DeletedConstraint
|
||||
// AddedConstraint Added a schema constraint
|
||||
AddedConstraint
|
||||
// DeletedDefinition removed one of the definitions
|
||||
DeletedDefinition
|
||||
// AddedDefinition removed one of the definitions
|
||||
AddedDefinition
|
||||
)
|
||||
|
||||
var toLongStringSpecChangeCode = map[SpecChangeCode]string{
|
||||
NoChangeDetected: "No Change detected",
|
||||
AddedEndpoint: "Added endpoint",
|
||||
DeletedEndpoint: "Deleted endpoint",
|
||||
DeletedDeprecatedEndpoint: "Deleted a deprecated endpoint",
|
||||
AddedRequiredProperty: "Added required property",
|
||||
DeletedProperty: "Deleted property",
|
||||
ChangedDescripton: "Changed a description",
|
||||
AddedDescripton: "Added a description",
|
||||
DeletedDescripton: "Deleted a description",
|
||||
ChangedTag: "Changed a tag",
|
||||
AddedTag: "Added a tag",
|
||||
DeletedTag: "Deleted a tag",
|
||||
AddedProperty: "Added property",
|
||||
AddedOptionalParam: "Added optional param",
|
||||
AddedRequiredParam: "Added required param",
|
||||
DeletedOptionalParam: "Deleted optional param",
|
||||
DeletedRequiredParam: "Deleted required param",
|
||||
DeletedResponse: "Deleted response",
|
||||
AddedResponse: "Added response",
|
||||
WidenedType: "Widened type",
|
||||
NarrowedType: "Narrowed type",
|
||||
ChangedType: "Changed type",
|
||||
ChangedToCompatibleType: "Changed type to equivalent type",
|
||||
ChangedOptionalToRequiredParam: "Changed optional param to required",
|
||||
ChangedRequiredToOptionalParam: "Changed required param to optional",
|
||||
AddedEnumValue: "Added possible enumeration(s)",
|
||||
DeletedEnumValue: "Deleted possible enumeration(s)",
|
||||
AddedConsumesFormat: "Added a consumes format",
|
||||
DeletedConsumesFormat: "Deleted a consumes format",
|
||||
AddedProducesFormat: "Added produces format",
|
||||
DeletedProducesFormat: "Deleted produces format",
|
||||
AddedSchemes: "Added schemes",
|
||||
DeletedSchemes: "Deleted schemes",
|
||||
ChangedHostURL: "Changed host URL",
|
||||
ChangedBasePath: "Changed base path",
|
||||
AddedResponseHeader: "Added response header",
|
||||
ChangedResponseHeader: "Changed response header",
|
||||
DeletedResponseHeader: "Deleted response header",
|
||||
NoChangeDetected: "No Change detected",
|
||||
AddedEndpoint: "Added endpoint",
|
||||
DeletedEndpoint: "Deleted endpoint",
|
||||
DeletedDeprecatedEndpoint: "Deleted a deprecated endpoint",
|
||||
AddedRequiredProperty: "Added required property",
|
||||
DeletedProperty: "Deleted property",
|
||||
ChangedDescripton: "Changed a description",
|
||||
AddedDescripton: "Added a description",
|
||||
DeletedDescripton: "Deleted a description",
|
||||
ChangedTag: "Changed a tag",
|
||||
AddedTag: "Added a tag",
|
||||
DeletedTag: "Deleted a tag",
|
||||
AddedProperty: "Added property",
|
||||
AddedOptionalParam: "Added optional param",
|
||||
AddedRequiredParam: "Added required param",
|
||||
DeletedOptionalParam: "Deleted optional param",
|
||||
DeletedRequiredParam: "Deleted required param",
|
||||
DeletedResponse: "Deleted response",
|
||||
AddedResponse: "Added response",
|
||||
WidenedType: "Widened type",
|
||||
NarrowedType: "Narrowed type",
|
||||
ChangedType: "Changed type",
|
||||
ChangedToCompatibleType: "Changed type to equivalent type",
|
||||
ChangedOptionalToRequired: "Changed optional param to required",
|
||||
ChangedRequiredToOptional: "Changed required param to optional",
|
||||
AddedEnumValue: "Added possible enumeration(s)",
|
||||
DeletedEnumValue: "Deleted possible enumeration(s)",
|
||||
AddedConsumesFormat: "Added a consumes format",
|
||||
DeletedConsumesFormat: "Deleted a consumes format",
|
||||
AddedProducesFormat: "Added produces format",
|
||||
DeletedProducesFormat: "Deleted produces format",
|
||||
AddedSchemes: "Added schemes",
|
||||
DeletedSchemes: "Deleted schemes",
|
||||
ChangedHostURL: "Changed host URL",
|
||||
ChangedBasePath: "Changed base path",
|
||||
AddedResponseHeader: "Added response header",
|
||||
ChangedResponseHeader: "Changed response header",
|
||||
DeletedResponseHeader: "Deleted response header",
|
||||
RefTargetChanged: "Changed ref to different object",
|
||||
RefTargetRenamed: "Changed ref to renamed object",
|
||||
DeletedConstraint: "Deleted a schema constraint",
|
||||
AddedConstraint: "Added a schema constraint",
|
||||
DeletedDefinition: "Deleted a schema definition",
|
||||
AddedDefinition: "Added a schema definition",
|
||||
}
|
||||
|
||||
var toStringSpecChangeCode = map[SpecChangeCode]string{
|
||||
AddedEndpoint: "AddedEndpoint",
|
||||
NoChangeDetected: "NoChangeDetected",
|
||||
DeletedEndpoint: "DeletedEndpoint",
|
||||
DeletedDeprecatedEndpoint: "DeletedDeprecatedEndpoint",
|
||||
AddedRequiredProperty: "AddedRequiredProperty",
|
||||
DeletedProperty: "DeletedProperty",
|
||||
AddedProperty: "AddedProperty",
|
||||
ChangedDescripton: "ChangedDescription",
|
||||
AddedDescripton: "AddedDescription",
|
||||
DeletedDescripton: "DeletedDescription",
|
||||
ChangedTag: "ChangedTag",
|
||||
AddedTag: "AddedTag",
|
||||
DeletedTag: "DeletedTag",
|
||||
AddedOptionalParam: "AddedOptionalParam",
|
||||
AddedRequiredParam: "AddedRequiredParam",
|
||||
DeletedOptionalParam: "DeletedRequiredParam",
|
||||
DeletedRequiredParam: "Deleted required param",
|
||||
DeletedResponse: "DeletedResponse",
|
||||
AddedResponse: "AddedResponse",
|
||||
WidenedType: "WidenedType",
|
||||
NarrowedType: "NarrowedType",
|
||||
ChangedType: "ChangedType",
|
||||
ChangedToCompatibleType: "ChangedToCompatibleType",
|
||||
ChangedOptionalToRequiredParam: "ChangedOptionalToRequiredParam",
|
||||
ChangedRequiredToOptionalParam: "ChangedRequiredToOptionalParam",
|
||||
AddedEnumValue: "AddedEnumValue",
|
||||
DeletedEnumValue: "DeletedEnumValue",
|
||||
AddedConsumesFormat: "AddedConsumesFormat",
|
||||
DeletedConsumesFormat: "DeletedConsumesFormat",
|
||||
AddedProducesFormat: "AddedProducesFormat",
|
||||
DeletedProducesFormat: "DeletedProducesFormat",
|
||||
AddedSchemes: "AddedSchemes",
|
||||
DeletedSchemes: "DeletedSchemes",
|
||||
ChangedHostURL: "ChangedHostURL",
|
||||
ChangedBasePath: "ChangedBasePath",
|
||||
AddedResponseHeader: "AddedResponseHeader",
|
||||
ChangedResponseHeader: "ChangedResponseHeader",
|
||||
DeletedResponseHeader: "DeletedResponseHeader",
|
||||
AddedEndpoint: "AddedEndpoint",
|
||||
NoChangeDetected: "NoChangeDetected",
|
||||
DeletedEndpoint: "DeletedEndpoint",
|
||||
DeletedDeprecatedEndpoint: "DeletedDeprecatedEndpoint",
|
||||
AddedRequiredProperty: "AddedRequiredProperty",
|
||||
DeletedProperty: "DeletedProperty",
|
||||
AddedProperty: "AddedProperty",
|
||||
ChangedDescripton: "ChangedDescription",
|
||||
AddedDescripton: "AddedDescription",
|
||||
DeletedDescripton: "DeletedDescription",
|
||||
ChangedTag: "ChangedTag",
|
||||
AddedTag: "AddedTag",
|
||||
DeletedTag: "DeletedTag",
|
||||
AddedOptionalParam: "AddedOptionalParam",
|
||||
AddedRequiredParam: "AddedRequiredParam",
|
||||
DeletedOptionalParam: "DeletedRequiredParam",
|
||||
DeletedRequiredParam: "Deleted required param",
|
||||
DeletedResponse: "DeletedResponse",
|
||||
AddedResponse: "AddedResponse",
|
||||
WidenedType: "WidenedType",
|
||||
NarrowedType: "NarrowedType",
|
||||
ChangedType: "ChangedType",
|
||||
ChangedToCompatibleType: "ChangedToCompatibleType",
|
||||
ChangedOptionalToRequired: "ChangedOptionalToRequiredParam",
|
||||
ChangedRequiredToOptional: "ChangedRequiredToOptionalParam",
|
||||
AddedEnumValue: "AddedEnumValue",
|
||||
DeletedEnumValue: "DeletedEnumValue",
|
||||
AddedConsumesFormat: "AddedConsumesFormat",
|
||||
DeletedConsumesFormat: "DeletedConsumesFormat",
|
||||
AddedProducesFormat: "AddedProducesFormat",
|
||||
DeletedProducesFormat: "DeletedProducesFormat",
|
||||
AddedSchemes: "AddedSchemes",
|
||||
DeletedSchemes: "DeletedSchemes",
|
||||
ChangedHostURL: "ChangedHostURL",
|
||||
ChangedBasePath: "ChangedBasePath",
|
||||
AddedResponseHeader: "AddedResponseHeader",
|
||||
ChangedResponseHeader: "ChangedResponseHeader",
|
||||
DeletedResponseHeader: "DeletedResponseHeader",
|
||||
RefTargetChanged: "RefTargetChanged",
|
||||
RefTargetRenamed: "RefTargetRenamed",
|
||||
DeletedConstraint: "DeletedConstraint",
|
||||
AddedConstraint: "AddedConstraint",
|
||||
DeletedDefinition: "DeletedDefinition",
|
||||
AddedDefinition: "AddedDefinition",
|
||||
}
|
||||
|
||||
var toIDSpecChangeCode = map[string]SpecChangeCode{}
|
||||
|
@ -273,5 +295,4 @@ func init() {
|
|||
for key, val := range toStringCompatibility {
|
||||
toIDCompatibility[val] = key
|
||||
}
|
||||
|
||||
}
|
||||
|
|
57
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/node.go
generated
vendored
57
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/node.go
generated
vendored
|
@ -1,5 +1,11 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// Node is the position od a diff in a spec
|
||||
type Node struct {
|
||||
Field string `json:"name,omitempty"`
|
||||
|
@ -12,14 +18,12 @@ type Node struct {
|
|||
func (n *Node) String() string {
|
||||
name := n.Field
|
||||
if n.IsArray {
|
||||
name = "array[" + n.TypeName + "]"
|
||||
name = fmt.Sprintf("%s<array[%s]>", name, n.TypeName)
|
||||
} else if len(n.TypeName) > 0 {
|
||||
name = fmt.Sprintf("%s<%s>", name, n.TypeName)
|
||||
}
|
||||
|
||||
if n.ChildNode != nil {
|
||||
return name + "." + n.ChildNode.String()
|
||||
}
|
||||
if len(n.TypeName) > 0 {
|
||||
return name + " : " + n.TypeName
|
||||
return fmt.Sprintf("%s.%s", name, n.ChildNode.String())
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
@ -36,12 +40,43 @@ func (n *Node) AddLeafNode(toAdd *Node) *Node {
|
|||
return n
|
||||
}
|
||||
|
||||
//Copy deep copy of this node and children
|
||||
// Copy deep copy of this node and children
|
||||
func (n Node) Copy() *Node {
|
||||
newNode := n
|
||||
|
||||
if newNode.ChildNode != nil {
|
||||
n.ChildNode = newNode.ChildNode.Copy()
|
||||
newChild := n.ChildNode
|
||||
if newChild != nil {
|
||||
newChild = newChild.Copy()
|
||||
}
|
||||
newNode := Node{
|
||||
Field: n.Field,
|
||||
TypeName: n.TypeName,
|
||||
IsArray: n.IsArray,
|
||||
ChildNode: newChild,
|
||||
}
|
||||
|
||||
return &newNode
|
||||
}
|
||||
|
||||
func getSchemaDiffNode(name string, schema interface{}) *Node {
|
||||
node := Node{
|
||||
Field: name,
|
||||
}
|
||||
if schema != nil {
|
||||
switch s := schema.(type) {
|
||||
case spec.Refable:
|
||||
node.TypeName, node.IsArray = getSchemaType(s)
|
||||
case *spec.Schema:
|
||||
node.TypeName, node.IsArray = getSchemaType(s.SchemaProps)
|
||||
case spec.SimpleSchema:
|
||||
node.TypeName, node.IsArray = getSchemaType(s)
|
||||
case *spec.SimpleSchema:
|
||||
node.TypeName, node.IsArray = getSchemaType(s)
|
||||
case *spec.SchemaProps:
|
||||
node.TypeName, node.IsArray = getSchemaType(s)
|
||||
case spec.SchemaProps:
|
||||
node.TypeName, node.IsArray = getSchemaType(&s)
|
||||
default:
|
||||
node.TypeName = fmt.Sprintf("Unknown type %v", schema)
|
||||
}
|
||||
}
|
||||
return &node
|
||||
}
|
||||
|
|
59
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/reporting.go
generated
vendored
59
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/reporting.go
generated
vendored
|
@ -5,8 +5,6 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
@ -14,6 +12,9 @@ import (
|
|||
// ArrayType const for array
|
||||
var ArrayType = "array"
|
||||
|
||||
// ObjectType const for object
|
||||
var ObjectType = "object"
|
||||
|
||||
// Compare returns the result of analysing breaking and non breaking changes
|
||||
// between to Swagger specs
|
||||
func Compare(spec1, spec2 *spec.Swagger) (diffs SpecDifferences, err error) {
|
||||
|
@ -72,60 +73,6 @@ func getNameOnlyDiffNode(forLocation string) *Node {
|
|||
return &node
|
||||
}
|
||||
|
||||
func getSimpleSchemaDiffNode(name string, schema *spec.SimpleSchema) *Node {
|
||||
node := Node{
|
||||
Field: name,
|
||||
}
|
||||
if schema != nil {
|
||||
node.TypeName, node.IsArray = getSimpleSchemaType(schema)
|
||||
}
|
||||
return &node
|
||||
}
|
||||
|
||||
func getSchemaDiffNode(name string, schema *spec.Schema) *Node {
|
||||
node := Node{
|
||||
Field: name,
|
||||
}
|
||||
if schema != nil {
|
||||
node.TypeName, node.IsArray = getSchemaType(&schema.SchemaProps)
|
||||
}
|
||||
return &node
|
||||
}
|
||||
|
||||
func definitonFromURL(url *url.URL) string {
|
||||
if url == nil {
|
||||
return ""
|
||||
}
|
||||
fragmentParts := strings.Split(url.Fragment, "/")
|
||||
numParts := len(fragmentParts)
|
||||
if numParts == 0 {
|
||||
return ""
|
||||
}
|
||||
return fragmentParts[numParts-1]
|
||||
}
|
||||
|
||||
func getSimpleSchemaType(schema *spec.SimpleSchema) (typeName string, isArray bool) {
|
||||
typeName = schema.Type
|
||||
if typeName == ArrayType {
|
||||
typeName, _ = getSimpleSchemaType(&schema.Items.SimpleSchema)
|
||||
return typeName, true
|
||||
}
|
||||
return typeName, false
|
||||
}
|
||||
|
||||
func getSchemaType(schema *spec.SchemaProps) (typeName string, isArray bool) {
|
||||
refStr := definitonFromURL(schema.Ref.GetURL())
|
||||
if len(refStr) > 0 {
|
||||
return refStr, false
|
||||
}
|
||||
typeName = schema.Type[0]
|
||||
if typeName == ArrayType {
|
||||
typeName, _ = getSchemaType(&schema.Items.Schema.SchemaProps)
|
||||
return typeName, true
|
||||
}
|
||||
return typeName, false
|
||||
}
|
||||
|
||||
func primitiveTypeString(typeName, typeFormat string) string {
|
||||
if typeFormat != "" {
|
||||
return fmt.Sprintf("%s.%s", typeName, typeFormat)
|
||||
|
|
126
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/schema.go
generated
vendored
Normal file
126
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/schema.go
generated
vendored
Normal file
|
@ -0,0 +1,126 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
func getTypeFromSchema(schema *spec.Schema) (typeName string, isArray bool) {
|
||||
refStr := definitionFromRef(schema.Ref)
|
||||
if len(refStr) > 0 {
|
||||
return refStr, false
|
||||
}
|
||||
typeName = schema.Type[0]
|
||||
if typeName == ArrayType {
|
||||
typeName, _ = getSchemaType(&schema.Items.Schema.SchemaProps)
|
||||
return typeName, true
|
||||
}
|
||||
return typeName, false
|
||||
|
||||
}
|
||||
|
||||
func getTypeFromSimpleSchema(schema *spec.SimpleSchema) (typeName string, isArray bool) {
|
||||
typeName = schema.Type
|
||||
format := schema.Format
|
||||
if len(format) > 0 {
|
||||
typeName = fmt.Sprintf("%s.%s", typeName, format)
|
||||
}
|
||||
if typeName == ArrayType {
|
||||
typeName, _ = getSchemaType(&schema.Items.SimpleSchema)
|
||||
return typeName, true
|
||||
}
|
||||
return typeName, false
|
||||
|
||||
}
|
||||
|
||||
func getTypeFromSchemaProps(schema *spec.SchemaProps) (typeName string, isArray bool) {
|
||||
refStr := definitionFromRef(schema.Ref)
|
||||
if len(refStr) > 0 {
|
||||
return refStr, false
|
||||
}
|
||||
if len(schema.Type) > 0 {
|
||||
typeName = schema.Type[0]
|
||||
format := schema.Format
|
||||
if len(format) > 0 {
|
||||
typeName = fmt.Sprintf("%s.%s", typeName, format)
|
||||
}
|
||||
if typeName == ArrayType {
|
||||
typeName, _ = getSchemaType(&schema.Items.Schema.SchemaProps)
|
||||
return typeName, true
|
||||
}
|
||||
}
|
||||
return typeName, false
|
||||
|
||||
}
|
||||
|
||||
func getSchemaTypeStr(item interface{}) string {
|
||||
typeStr, isArray := getSchemaType(item)
|
||||
return formatTypeString(typeStr, isArray)
|
||||
}
|
||||
|
||||
func getSchemaType(item interface{}) (typeName string, isArray bool) {
|
||||
|
||||
switch s := item.(type) {
|
||||
case *spec.Schema:
|
||||
typeName, isArray = getTypeFromSchema(s)
|
||||
case *spec.SchemaProps:
|
||||
typeName, isArray = getTypeFromSchemaProps(s)
|
||||
case spec.SchemaProps:
|
||||
typeName, isArray = getTypeFromSchemaProps(&s)
|
||||
case spec.SimpleSchema:
|
||||
typeName, isArray = getTypeFromSimpleSchema(&s)
|
||||
case *spec.SimpleSchema:
|
||||
typeName, isArray = getTypeFromSimpleSchema(s)
|
||||
default:
|
||||
typeName = "unknown"
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func formatTypeString(typ string, isarray bool) string {
|
||||
if isarray {
|
||||
return fmt.Sprintf("<array[%s]>", typ)
|
||||
}
|
||||
return fmt.Sprintf("<%s>", typ)
|
||||
}
|
||||
|
||||
func definitionFromRef(ref spec.Ref) string {
|
||||
url := ref.GetURL()
|
||||
if url == nil {
|
||||
return ""
|
||||
}
|
||||
fragmentParts := strings.Split(url.Fragment, "/")
|
||||
numParts := len(fragmentParts)
|
||||
|
||||
return fragmentParts[numParts-1]
|
||||
}
|
||||
|
||||
func isArray(item interface{}) bool {
|
||||
switch s := item.(type) {
|
||||
case *spec.Schema:
|
||||
return isArrayType(s.Type)
|
||||
case *spec.SchemaProps:
|
||||
return isArrayType(s.Type)
|
||||
case *spec.SimpleSchema:
|
||||
return isArrayType(spec.StringOrArray{s.Type})
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func isPrimitive(item interface{}) bool {
|
||||
switch s := item.(type) {
|
||||
case *spec.Schema:
|
||||
return isPrimitiveType(s.Type)
|
||||
case *spec.SchemaProps:
|
||||
return isPrimitiveType(s.Type)
|
||||
case spec.StringOrArray:
|
||||
return isPrimitiveType(s)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
500
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_analyser.go
generated
vendored
500
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_analyser.go
generated
vendored
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
// StringType For identifying string types
|
||||
const StringType = "string"
|
||||
|
||||
// URLMethodResponse encapsulates these three elements to act as a map key
|
||||
|
@ -26,18 +27,19 @@ type URLMethods map[URLMethod]*PathItemOp
|
|||
|
||||
// SpecAnalyser contains all the differences for a Spec
|
||||
type SpecAnalyser struct {
|
||||
Diffs SpecDifferences
|
||||
urlMethods1 URLMethods
|
||||
urlMethods2 URLMethods
|
||||
Definitions1 spec.Definitions
|
||||
Definitions2 spec.Definitions
|
||||
AlreadyComparedDefinitions map[string]bool
|
||||
Diffs SpecDifferences
|
||||
urlMethods1 URLMethods
|
||||
urlMethods2 URLMethods
|
||||
Definitions1 spec.Definitions
|
||||
Definitions2 spec.Definitions
|
||||
ReferencedDefinitions map[string]bool
|
||||
}
|
||||
|
||||
// NewSpecAnalyser returns an empty SpecDiffs
|
||||
func NewSpecAnalyser() *SpecAnalyser {
|
||||
return &SpecAnalyser{
|
||||
Diffs: SpecDifferences{},
|
||||
Diffs: SpecDifferences{},
|
||||
ReferencedDefinitions: map[string]bool{},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,9 +52,10 @@ func (sd *SpecAnalyser) Analyse(spec1, spec2 *spec.Swagger) error {
|
|||
|
||||
sd.analyseSpecMetadata(spec1, spec2)
|
||||
sd.analyseEndpoints()
|
||||
sd.analyseParams()
|
||||
sd.analyseRequestParams()
|
||||
sd.analyseEndpointData()
|
||||
sd.analyseResponseParams()
|
||||
sd.AnalyseDefinitions()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -94,7 +97,7 @@ func (sd *SpecAnalyser) analyseSpecMetadata(spec1, spec2 *spec.Swagger) {
|
|||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: schemesLocation, Code: DeletedSchemes, Compatibility: Breaking, DiffInfo: eachDeleted})
|
||||
}
|
||||
|
||||
// // host should be able to change without any issues?
|
||||
// host should be able to change without any issues?
|
||||
sd.analyseMetaDataProperty(spec1.Info.Description, spec2.Info.Description, ChangedDescripton, NonBreaking)
|
||||
|
||||
// // host should be able to change without any issues?
|
||||
|
@ -116,6 +119,32 @@ func (sd *SpecAnalyser) analyseEndpoints() {
|
|||
sd.findAddedEndpoints()
|
||||
}
|
||||
|
||||
// AnalyseDefinitions check for changes to defintion objects not referenced in any endpoint
|
||||
func (sd *SpecAnalyser) AnalyseDefinitions() {
|
||||
alreadyReferenced := map[string]bool{}
|
||||
for k := range sd.ReferencedDefinitions {
|
||||
alreadyReferenced[k] = true
|
||||
}
|
||||
location := DifferenceLocation{Node: &Node{Field: "Spec Definitions"}}
|
||||
for name1, sch := range sd.Definitions1 {
|
||||
schema1 := sch
|
||||
if _, ok := alreadyReferenced[name1]; !ok {
|
||||
childLocation := location.AddNode(&Node{Field: name1})
|
||||
if schema2, ok := sd.Definitions2[name1]; ok {
|
||||
sd.compareSchema(childLocation, &schema1, &schema2)
|
||||
} else {
|
||||
sd.addDiffs(childLocation, []TypeDiff{{Change: DeletedDefinition}})
|
||||
}
|
||||
}
|
||||
}
|
||||
for name2 := range sd.Definitions2 {
|
||||
if _, ok := sd.Definitions1[name2]; !ok {
|
||||
childLocation := location.AddNode(&Node{Field: name2})
|
||||
sd.addDiffs(childLocation, []TypeDiff{{Change: AddedDefinition}})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyseEndpointData() {
|
||||
|
||||
for URLMethod, op2 := range sd.urlMethods2 {
|
||||
|
@ -124,20 +153,19 @@ func (sd *SpecAnalyser) analyseEndpointData() {
|
|||
location := DifferenceLocation{URL: URLMethod.Path, Method: URLMethod.Method}
|
||||
|
||||
for _, eachAddedTag := range addedTags {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: AddedTag, DiffInfo: eachAddedTag})
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: AddedTag, DiffInfo: fmt.Sprintf(`"%s"`, eachAddedTag)})
|
||||
}
|
||||
for _, eachDeletedTag := range deletedTags {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: DeletedTag, DiffInfo: eachDeletedTag})
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: DeletedTag, DiffInfo: fmt.Sprintf(`"%s"`, eachDeletedTag)})
|
||||
}
|
||||
|
||||
sd.compareDescripton(location, op1.Operation.Description, op2.Operation.Description)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) analyseParams() {
|
||||
func (sd *SpecAnalyser) analyseRequestParams() {
|
||||
locations := []string{"query", "path", "body", "header"}
|
||||
|
||||
for _, paramLocation := range locations {
|
||||
|
@ -153,7 +181,7 @@ func (sd *SpecAnalyser) analyseParams() {
|
|||
// detect deleted params
|
||||
for paramName1, param1 := range params1 {
|
||||
if _, ok := params2[paramName1]; !ok {
|
||||
childLocation := location.AddNode(getSchemaDiffNode(paramName1, param1.Schema))
|
||||
childLocation := location.AddNode(getSchemaDiffNode(paramName1, ¶m1.SimpleSchema))
|
||||
code := DeletedOptionalParam
|
||||
if param1.Required {
|
||||
code = DeletedRequiredParam
|
||||
|
@ -163,12 +191,12 @@ func (sd *SpecAnalyser) analyseParams() {
|
|||
}
|
||||
// detect added changed params
|
||||
for paramName2, param2 := range params2 {
|
||||
//changed?
|
||||
// changed?
|
||||
if param1, ok := params1[paramName2]; ok {
|
||||
sd.compareParams(URLMethod, paramLocation, paramName2, param1, param2)
|
||||
} else {
|
||||
// Added
|
||||
childLocation := location.AddNode(getSchemaDiffNode(paramName2, param2.Schema))
|
||||
childLocation := location.AddNode(getSchemaDiffNode(paramName2, ¶m2.SimpleSchema))
|
||||
code := AddedOptionalParam
|
||||
if param2.Required {
|
||||
code = AddedRequiredParam
|
||||
|
@ -183,8 +211,10 @@ func (sd *SpecAnalyser) analyseParams() {
|
|||
|
||||
func (sd *SpecAnalyser) analyseResponseParams() {
|
||||
// Loop through url+methods in spec 2 - check deleted and changed
|
||||
for URLMethod2, op2 := range sd.urlMethods2 {
|
||||
if op1, ok := sd.urlMethods1[URLMethod2]; ok {
|
||||
for eachURLMethodFrom2, op2 := range sd.urlMethods2 {
|
||||
|
||||
// present in both specs? Use key from spec 2 to lookup in spec 1
|
||||
if op1, ok := sd.urlMethods1[eachURLMethodFrom2]; ok {
|
||||
// compare responses for url and method
|
||||
op1Responses := op1.Operation.Responses.StatusCodeResponses
|
||||
op2Responses := op2.Operation.Responses.StatusCodeResponses
|
||||
|
@ -192,7 +222,7 @@ func (sd *SpecAnalyser) analyseResponseParams() {
|
|||
// deleted responses
|
||||
for code1 := range op1Responses {
|
||||
if _, ok := op2Responses[code1]; !ok {
|
||||
location := DifferenceLocation{URL: URLMethod2.Path, Method: URLMethod2.Method, Response: code1}
|
||||
location := DifferenceLocation{URL: eachURLMethodFrom2.Path, Method: eachURLMethodFrom2.Method, Response: code1, Node: getSchemaDiffNode("Body", op1Responses[code1].Schema)}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: DeletedResponse})
|
||||
}
|
||||
}
|
||||
|
@ -202,39 +232,48 @@ func (sd *SpecAnalyser) analyseResponseParams() {
|
|||
if op1Response, ok := op1Responses[code2]; ok {
|
||||
op1Headers := op1Response.ResponseProps.Headers
|
||||
headerRootNode := getNameOnlyDiffNode("Headers")
|
||||
location := DifferenceLocation{URL: URLMethod2.Path, Method: URLMethod2.Method, Response: code2, Node: headerRootNode}
|
||||
|
||||
// Iterate Spec2 Headers looking for added and updated
|
||||
location := DifferenceLocation{URL: eachURLMethodFrom2.Path, Method: eachURLMethodFrom2.Method, Response: code2, Node: headerRootNode}
|
||||
for op2HeaderName, op2Header := range op2Response.ResponseProps.Headers {
|
||||
if op1Header, ok := op1Headers[op2HeaderName]; ok {
|
||||
sd.compareSimpleSchema(location.AddNode(getNameOnlyDiffNode(op2HeaderName)),
|
||||
&op1Header.SimpleSchema,
|
||||
&op2Header.SimpleSchema, false, false)
|
||||
diffs := sd.CompareProps(forHeader(op1Header), forHeader(op2Header))
|
||||
sd.addDiffs(location, diffs)
|
||||
} else {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: location.AddNode(getNameOnlyDiffNode(op2HeaderName)),
|
||||
DifferenceLocation: location.AddNode(getSchemaDiffNode(op2HeaderName, &op2Header.SimpleSchema)),
|
||||
Code: AddedResponseHeader})
|
||||
}
|
||||
}
|
||||
for op1HeaderName := range op1Response.ResponseProps.Headers {
|
||||
if _, ok := op2Response.ResponseProps.Headers[op1HeaderName]; !ok {
|
||||
op1Header := op1Response.ResponseProps.Headers[op1HeaderName]
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: location.AddNode(getNameOnlyDiffNode(op1HeaderName)),
|
||||
DifferenceLocation: location.AddNode(getSchemaDiffNode(op1HeaderName, &op1Header.SimpleSchema)),
|
||||
Code: DeletedResponseHeader})
|
||||
}
|
||||
}
|
||||
responseLocation := DifferenceLocation{URL: URLMethod2.Path, Method: URLMethod2.Method, Response: code2}
|
||||
schem := op1Response.Schema
|
||||
node := getNameOnlyDiffNode("NoContent")
|
||||
if schem != nil {
|
||||
node = getSchemaDiffNode("Body", &schem.SchemaProps)
|
||||
}
|
||||
responseLocation := DifferenceLocation{URL: eachURLMethodFrom2.Path,
|
||||
Method: eachURLMethodFrom2.Method,
|
||||
Response: code2,
|
||||
Node: node}
|
||||
sd.compareDescripton(responseLocation, op1Response.Description, op2Response.Description)
|
||||
|
||||
if op1Response.Schema != nil {
|
||||
sd.compareSchema(
|
||||
DifferenceLocation{URL: URLMethod2.Path, Method: URLMethod2.Method, Response: code2},
|
||||
DifferenceLocation{URL: eachURLMethodFrom2.Path, Method: eachURLMethodFrom2.Method, Response: code2, Node: getSchemaDiffNode("Body", op1Response.Schema)},
|
||||
op1Response.Schema,
|
||||
op2Response.Schema, true, true)
|
||||
op2Response.Schema)
|
||||
}
|
||||
} else {
|
||||
// op2Response
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: DifferenceLocation{URL: URLMethod2.Path, Method: URLMethod2.Method, Response: code2},
|
||||
DifferenceLocation: DifferenceLocation{URL: eachURLMethodFrom2.Path, Method: eachURLMethodFrom2.Method, Response: code2, Node: getSchemaDiffNode("Body", op2Response.Schema)},
|
||||
Code: AddedResponse})
|
||||
}
|
||||
}
|
||||
|
@ -249,126 +288,51 @@ func addTypeDiff(diffs []TypeDiff, diff TypeDiff) []TypeDiff {
|
|||
return diffs
|
||||
}
|
||||
|
||||
// CheckToFromPrimitiveType check for diff to or from a primitive
|
||||
func (sd *SpecAnalyser) CheckToFromPrimitiveType(diffs []TypeDiff, type1, type2 spec.SchemaProps) []TypeDiff {
|
||||
|
||||
type1IsPrimitive := len(type1.Type) > 0
|
||||
type2IsPrimitive := len(type2.Type) > 0
|
||||
|
||||
// Primitive to Obj or Obj to Primitive
|
||||
if type1IsPrimitive && !type2IsPrimitive {
|
||||
return addTypeDiff(diffs, TypeDiff{Change: ChangedType, FromType: type1.Type[0], ToType: "obj"})
|
||||
}
|
||||
|
||||
if !type1IsPrimitive && type2IsPrimitive {
|
||||
return addTypeDiff(diffs, TypeDiff{Change: ChangedType, FromType: type2.Type[0], ToType: "obj"})
|
||||
}
|
||||
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckToFromArrayType check for changes to or from an Array type
|
||||
func (sd *SpecAnalyser) CheckToFromArrayType(diffs []TypeDiff, type1, type2 spec.SchemaProps) []TypeDiff {
|
||||
// Single to Array or Array to Single
|
||||
type1Array := type1.Type[0] == ArrayType
|
||||
type2Array := type2.Type[0] == ArrayType
|
||||
|
||||
if type1Array && !type2Array {
|
||||
return addTypeDiff(diffs, TypeDiff{Change: ChangedType, FromType: "obj", ToType: type2.Type[0]})
|
||||
}
|
||||
|
||||
if !type1Array && type2Array {
|
||||
return addTypeDiff(diffs, TypeDiff{Change: ChangedType, FromType: type1.Type[0], ToType: ArrayType})
|
||||
}
|
||||
|
||||
if type1Array && type2Array {
|
||||
// array
|
||||
// TODO: Items??
|
||||
diffs = addTypeDiff(diffs, compareIntValues("MaxItems", type1.MaxItems, type2.MaxItems, WidenedType, NarrowedType))
|
||||
diffs = addTypeDiff(diffs, compareIntValues("MinItems", type1.MinItems, type2.MinItems, NarrowedType, WidenedType))
|
||||
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckStringTypeChanges checks for changes to or from a string type
|
||||
func (sd *SpecAnalyser) CheckStringTypeChanges(diffs []TypeDiff, type1, type2 spec.SchemaProps) []TypeDiff {
|
||||
// string changes
|
||||
if type1.Type[0] == StringType &&
|
||||
type2.Type[0] == StringType {
|
||||
diffs = addTypeDiff(diffs, compareIntValues("MinLength", type1.MinLength, type2.MinLength, NarrowedType, WidenedType))
|
||||
diffs = addTypeDiff(diffs, compareIntValues("MaxLength", type1.MinLength, type2.MinLength, WidenedType, NarrowedType))
|
||||
if type1.Pattern != type2.Pattern {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: ChangedType, Description: fmt.Sprintf("Pattern Changed:%s->%s", type1.Pattern, type2.Pattern)})
|
||||
}
|
||||
if type1.Type[0] == StringType {
|
||||
if len(type1.Enum) > 0 {
|
||||
enumDiffs := sd.compareEnums(type1.Enum, type2.Enum)
|
||||
diffs = append(diffs, enumDiffs...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CheckNumericTypeChanges checks for changes to or from a numeric type
|
||||
func (sd *SpecAnalyser) CheckNumericTypeChanges(diffs []TypeDiff, type1, type2 spec.SchemaProps) []TypeDiff {
|
||||
// Number
|
||||
_, type1IsNumeric := numberWideness[type1.Type[0]]
|
||||
_, type2IsNumeric := numberWideness[type2.Type[0]]
|
||||
|
||||
if type1IsNumeric && type2IsNumeric {
|
||||
diffs = addTypeDiff(diffs, compareFloatValues("Maximum", type1.Maximum, type2.Maximum, WidenedType, NarrowedType))
|
||||
diffs = addTypeDiff(diffs, compareFloatValues("Minimum", type1.Minimum, type2.Minimum, NarrowedType, WidenedType))
|
||||
if type1.ExclusiveMaximum && !type2.ExclusiveMaximum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: WidenedType, Description: fmt.Sprintf("Exclusive Maximum Removed:%v->%v", type1.ExclusiveMaximum, type2.ExclusiveMaximum)})
|
||||
}
|
||||
if !type1.ExclusiveMaximum && type2.ExclusiveMaximum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: NarrowedType, Description: fmt.Sprintf("Exclusive Maximum Added:%v->%v", type1.ExclusiveMaximum, type2.ExclusiveMaximum)})
|
||||
}
|
||||
if type1.ExclusiveMinimum && !type2.ExclusiveMinimum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: WidenedType, Description: fmt.Sprintf("Exclusive Minimum Removed:%v->%v", type1.ExclusiveMaximum, type2.ExclusiveMaximum)})
|
||||
}
|
||||
if !type1.ExclusiveMinimum && type2.ExclusiveMinimum {
|
||||
diffs = addTypeDiff(diffs, TypeDiff{Change: NarrowedType, Description: fmt.Sprintf("Exclusive Minimum Added:%v->%v", type1.ExclusiveMinimum, type2.ExclusiveMinimum)})
|
||||
}
|
||||
}
|
||||
return diffs
|
||||
}
|
||||
|
||||
// CompareTypes computes type specific property diffs
|
||||
func (sd *SpecAnalyser) CompareTypes(type1, type2 spec.SchemaProps) []TypeDiff {
|
||||
// CompareProps computes type specific property diffs
|
||||
func (sd *SpecAnalyser) CompareProps(type1, type2 *spec.SchemaProps) []TypeDiff {
|
||||
|
||||
diffs := []TypeDiff{}
|
||||
|
||||
diffs = sd.CheckToFromPrimitiveType(diffs, type1, type2)
|
||||
diffs = CheckToFromPrimitiveType(diffs, type1, type2)
|
||||
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
}
|
||||
|
||||
diffs = sd.CheckToFromArrayType(diffs, type1, type2)
|
||||
if isArray(type1) {
|
||||
maxItemDiffs := CompareIntValues("MaxItems", type1.MaxItems, type2.MaxItems, WidenedType, NarrowedType)
|
||||
diffs = append(diffs, maxItemDiffs...)
|
||||
minItemsDiff := CompareIntValues("MinItems", type1.MinItems, type2.MinItems, NarrowedType, WidenedType)
|
||||
diffs = append(diffs, minItemsDiff...)
|
||||
}
|
||||
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
}
|
||||
|
||||
// check type hierarchy change eg string -> integer = NarrowedChange
|
||||
//Type
|
||||
//Format
|
||||
diffs = CheckRefChange(diffs, type1, type2)
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
}
|
||||
|
||||
if !(isPrimitiveType(type1.Type) && isPrimitiveType(type2.Type)) {
|
||||
return diffs
|
||||
}
|
||||
|
||||
// check primitive type hierarchy change eg string -> integer = NarrowedChange
|
||||
if type1.Type[0] != type2.Type[0] ||
|
||||
type1.Format != type2.Format {
|
||||
diff := getTypeHierarchyChange(primitiveTypeString(type1.Type[0], type1.Format), primitiveTypeString(type2.Type[0], type2.Format))
|
||||
diffs = addTypeDiff(diffs, diff)
|
||||
}
|
||||
|
||||
diffs = sd.CheckStringTypeChanges(diffs, type1, type2)
|
||||
diffs = CheckStringTypeChanges(diffs, type1, type2)
|
||||
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
}
|
||||
|
||||
diffs = sd.CheckNumericTypeChanges(diffs, type1, type2)
|
||||
diffs = checkNumericTypeChanges(diffs, type1, type2)
|
||||
|
||||
if len(diffs) > 0 {
|
||||
return diffs
|
||||
|
@ -385,49 +349,37 @@ func (sd *SpecAnalyser) compareParams(urlMethod URLMethod, location string, name
|
|||
sd.compareDescripton(paramLocation, param1.Description, param2.Description)
|
||||
|
||||
if param1.Schema != nil && param2.Schema != nil {
|
||||
childLocation = childLocation.AddNode(getSchemaDiffNode(name, param2.Schema))
|
||||
sd.compareSchema(childLocation, param1.Schema, param2.Schema, param1.Required, param2.Required)
|
||||
}
|
||||
diffs := sd.CompareTypes(forParam(param1), forParam(param2))
|
||||
|
||||
childLocation = childLocation.AddNode(getSchemaDiffNode(name, param2.Schema))
|
||||
for _, eachDiff := range diffs {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: childLocation,
|
||||
Code: eachDiff.Change,
|
||||
DiffInfo: eachDiff.Description})
|
||||
}
|
||||
if param1.Required != param2.Required {
|
||||
code := ChangedRequiredToOptionalParam
|
||||
if param2.Required {
|
||||
code = ChangedOptionalToRequiredParam
|
||||
if len(name) > 0 {
|
||||
childLocation = childLocation.AddNode(getSchemaDiffNode(name, param2.Schema))
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: childLocation, Code: code})
|
||||
|
||||
sd.compareSchema(childLocation, param1.Schema, param2.Schema)
|
||||
}
|
||||
diffs := sd.CompareProps(forParam(param1), forParam(param2))
|
||||
|
||||
childLocation = childLocation.AddNode(getSchemaDiffNode(name, ¶m2.SimpleSchema))
|
||||
if len(diffs) > 0 {
|
||||
sd.addDiffs(childLocation, diffs)
|
||||
}
|
||||
|
||||
diffs = CheckToFromRequired(param1.Required, param2.Required)
|
||||
if len(diffs) > 0 {
|
||||
sd.addDiffs(childLocation, diffs)
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) compareSimpleSchema(location DifferenceLocation, schema1, schema2 *spec.SimpleSchema, required1, required2 bool) {
|
||||
if schema1 == nil || schema2 == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if schema1.Type == ArrayType {
|
||||
refSchema1 := schema1.Items.SimpleSchema
|
||||
refSchema2 := schema2.Items.SimpleSchema
|
||||
|
||||
childLocation := location.AddNode(getSimpleSchemaDiffNode("", schema1))
|
||||
sd.compareSimpleSchema(childLocation, &refSchema1, &refSchema2, required1, required2)
|
||||
return
|
||||
}
|
||||
if required1 != required2 {
|
||||
code := AddedRequiredProperty
|
||||
if required1 {
|
||||
code = ChangedRequiredToOptional
|
||||
|
||||
func (sd *SpecAnalyser) addTypeDiff(location DifferenceLocation, diff *TypeDiff) {
|
||||
diffCopy := diff
|
||||
desc := diffCopy.Description
|
||||
if len(desc) == 0 {
|
||||
if diffCopy.FromType != diffCopy.ToType {
|
||||
desc = fmt.Sprintf("%s -> %s", diffCopy.FromType, diffCopy.ToType)
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: code})
|
||||
}
|
||||
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{
|
||||
DifferenceLocation: location,
|
||||
Code: diffCopy.Change,
|
||||
DiffInfo: desc})
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) compareDescripton(location DifferenceLocation, desc1, desc2 string) {
|
||||
|
@ -440,145 +392,96 @@ func (sd *SpecAnalyser) compareDescripton(location DifferenceLocation, desc1, de
|
|||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: code})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) compareSchema(location DifferenceLocation, schema1, schema2 *spec.Schema, required1, required2 bool) {
|
||||
func isPrimitiveType(item spec.StringOrArray) bool {
|
||||
return len(item) > 0 && item[0] != ArrayType && item[0] != ObjectType
|
||||
}
|
||||
|
||||
if schema1 == nil || schema2 == nil {
|
||||
func isArrayType(item spec.StringOrArray) bool {
|
||||
return len(item) > 0 && item[0] == ArrayType
|
||||
}
|
||||
func (sd *SpecAnalyser) getRefSchemaFromSpec1(ref spec.Ref) (*spec.Schema, string) {
|
||||
return sd.schemaFromRef(ref, &sd.Definitions1)
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) getRefSchemaFromSpec2(ref spec.Ref) (*spec.Schema, string) {
|
||||
return sd.schemaFromRef(ref, &sd.Definitions2)
|
||||
}
|
||||
|
||||
// CompareSchemaFn Fn spec for comparing schemas
|
||||
type CompareSchemaFn func(location DifferenceLocation, schema1, schema2 *spec.Schema)
|
||||
|
||||
func (sd *SpecAnalyser) compareSchema(location DifferenceLocation, schema1, schema2 *spec.Schema) {
|
||||
|
||||
refDiffs := []TypeDiff{}
|
||||
refDiffs = CheckRefChange(refDiffs, schema1, schema2)
|
||||
if len(refDiffs) > 0 {
|
||||
for _, d := range refDiffs {
|
||||
diff := d
|
||||
sd.addTypeDiff(location, &diff)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if isRefType(schema1) {
|
||||
schema1, _ = sd.schemaFromRef(getRef(schema1), &sd.Definitions1)
|
||||
}
|
||||
if isRefType(schema2) {
|
||||
schema2, _ = sd.schemaFromRef(getRef(schema2), &sd.Definitions2)
|
||||
}
|
||||
|
||||
sd.compareDescripton(location, schema1.Description, schema2.Description)
|
||||
|
||||
if len(schema1.Type) == 0 {
|
||||
refSchema1, definition1 := sd.schemaFromRef(schema1, &sd.Definitions1)
|
||||
refSchema2, definition2 := sd.schemaFromRef(schema2, &sd.Definitions2)
|
||||
|
||||
if len(definition1) > 0 {
|
||||
info := fmt.Sprintf("[%s -> %s]", definition1, definition2)
|
||||
|
||||
if definition1 != definition2 {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location,
|
||||
Code: ChangedType,
|
||||
DiffInfo: info,
|
||||
})
|
||||
}
|
||||
sd.compareSchema(location, refSchema1, refSchema2, required1, required2)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if schema1.Type[0] == ArrayType {
|
||||
refSchema1, definition1 := sd.schemaFromRef(schema1.Items.Schema, &sd.Definitions1)
|
||||
refSchema2, _ := sd.schemaFromRef(schema2.Items.Schema, &sd.Definitions2)
|
||||
|
||||
if len(definition1) > 0 {
|
||||
childLocation := location.AddNode(getSchemaDiffNode("", schema1))
|
||||
sd.compareSchema(childLocation, refSchema1, refSchema2, required1, required2)
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
diffs := sd.CompareTypes(schema1.SchemaProps, schema2.SchemaProps)
|
||||
|
||||
for _, eachTypeDiff := range diffs {
|
||||
if eachTypeDiff.Change != NoChangeDetected {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: eachTypeDiff.Change, DiffInfo: eachTypeDiff.Description})
|
||||
}
|
||||
}
|
||||
typeDiffs := sd.CompareProps(&schema1.SchemaProps, &schema2.SchemaProps)
|
||||
if len(typeDiffs) > 0 {
|
||||
sd.addDiffs(location, typeDiffs)
|
||||
return
|
||||
}
|
||||
|
||||
if required1 != required2 {
|
||||
code := AddedRequiredProperty
|
||||
if required1 {
|
||||
code = ChangedRequiredToOptional
|
||||
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: location, Code: code})
|
||||
}
|
||||
requiredProps2 := sliceToStrMap(schema2.Required)
|
||||
requiredProps1 := sliceToStrMap(schema1.Required)
|
||||
schema1Props := sd.propertiesFor(schema1, &sd.Definitions1)
|
||||
schema2Props := sd.propertiesFor(schema2, &sd.Definitions2)
|
||||
// find deleted and changed properties
|
||||
for eachProp1Name, eachProp1 := range schema1Props {
|
||||
eachProp1 := eachProp1
|
||||
_, required1 := requiredProps1[eachProp1Name]
|
||||
_, required2 := requiredProps2[eachProp1Name]
|
||||
childLoc := sd.addChildDiffNode(location, eachProp1Name, &eachProp1)
|
||||
|
||||
if eachProp2, ok := schema2Props[eachProp1Name]; ok {
|
||||
sd.compareSchema(childLoc, &eachProp1, &eachProp2, required1, required2)
|
||||
sd.compareDescripton(childLoc, eachProp1.Description, eachProp2.Description)
|
||||
} else {
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: childLoc, Code: DeletedProperty})
|
||||
}
|
||||
if isArray(schema1) {
|
||||
sd.compareSchema(location, schema1.Items.Schema, schema2.Items.Schema)
|
||||
}
|
||||
|
||||
// find added properties
|
||||
for eachProp2Name, eachProp2 := range schema2.Properties {
|
||||
eachProp2 := eachProp2
|
||||
if _, ok := schema1.Properties[eachProp2Name]; !ok {
|
||||
childLoc := sd.addChildDiffNode(location, eachProp2Name, &eachProp2)
|
||||
_, required2 := requiredProps2[eachProp2Name]
|
||||
code := AddedProperty
|
||||
if required2 {
|
||||
code = AddedRequiredProperty
|
||||
}
|
||||
sd.Diffs = sd.Diffs.addDiff(SpecDifference{DifferenceLocation: childLoc, Code: code})
|
||||
diffs := CompareProperties(location, schema1, schema2, sd.getRefSchemaFromSpec1, sd.getRefSchemaFromSpec2, sd.compareSchema)
|
||||
for _, diff := range diffs {
|
||||
sd.Diffs = sd.Diffs.addDiff(diff)
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) addDiffs(location DifferenceLocation, diffs []TypeDiff) {
|
||||
for _, e := range diffs {
|
||||
eachTypeDiff := e
|
||||
if eachTypeDiff.Change != NoChangeDetected {
|
||||
sd.addTypeDiff(location, &eachTypeDiff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) addChildDiffNode(location DifferenceLocation, propName string, propSchema *spec.Schema) DifferenceLocation {
|
||||
newLoc := location
|
||||
if newLoc.Node != nil {
|
||||
newLoc.Node = newLoc.Node.Copy()
|
||||
}
|
||||
|
||||
childNode := sd.fromSchemaProps(propName, &propSchema.SchemaProps)
|
||||
if newLoc.Node != nil {
|
||||
newLoc.Node.AddLeafNode(&childNode)
|
||||
func addChildDiffNode(location DifferenceLocation, propName string, propSchema *spec.Schema) DifferenceLocation {
|
||||
newNode := location.Node
|
||||
childNode := fromSchemaProps(propName, &propSchema.SchemaProps)
|
||||
if newNode != nil {
|
||||
newNode = newNode.Copy()
|
||||
newNode.AddLeafNode(&childNode)
|
||||
} else {
|
||||
newLoc.Node = &childNode
|
||||
newNode = &childNode
|
||||
}
|
||||
return DifferenceLocation{
|
||||
URL: location.URL,
|
||||
Method: location.Method,
|
||||
Response: location.Response,
|
||||
Node: newNode,
|
||||
}
|
||||
return newLoc
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) fromSchemaProps(fieldName string, props *spec.SchemaProps) Node {
|
||||
func fromSchemaProps(fieldName string, props *spec.SchemaProps) Node {
|
||||
node := Node{}
|
||||
node.IsArray = props.Type[0] == ArrayType
|
||||
if !node.IsArray {
|
||||
node.TypeName = props.Type[0]
|
||||
}
|
||||
node.TypeName, node.IsArray = getSchemaType(props)
|
||||
node.Field = fieldName
|
||||
return node
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) compareEnums(left, right []interface{}) []TypeDiff {
|
||||
diffs := []TypeDiff{}
|
||||
|
||||
leftStrs := []string{}
|
||||
rightStrs := []string{}
|
||||
for _, eachLeft := range left {
|
||||
leftStrs = append(leftStrs, fmt.Sprintf("%v", eachLeft))
|
||||
}
|
||||
for _, eachRight := range right {
|
||||
rightStrs = append(rightStrs, fmt.Sprintf("%v", eachRight))
|
||||
}
|
||||
added, deleted, _ := fromStringArray(leftStrs).DiffsTo(rightStrs)
|
||||
if len(added) > 0 {
|
||||
typeChange := strings.Join(added, ",")
|
||||
diffs = append(diffs, TypeDiff{Change: AddedEnumValue, Description: typeChange})
|
||||
}
|
||||
if len(deleted) > 0 {
|
||||
typeChange := strings.Join(deleted, ",")
|
||||
diffs = append(diffs, TypeDiff{Change: DeletedEnumValue, Description: typeChange})
|
||||
}
|
||||
|
||||
return diffs
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) findAddedEndpoints() {
|
||||
for URLMethod := range sd.urlMethods2 {
|
||||
if _, ok := sd.urlMethods1[URLMethod]; !ok {
|
||||
|
@ -607,48 +510,23 @@ func (sd *SpecAnalyser) analyseMetaDataProperty(item1, item2 string, codeIfDiff
|
|||
}
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) schemaFromRef(schema *spec.Schema, defns *spec.Definitions) (actualSchema *spec.Schema, definitionName string) {
|
||||
ref := schema.Ref
|
||||
url := ref.GetURL()
|
||||
if url == nil {
|
||||
return schema, ""
|
||||
}
|
||||
fragmentParts := strings.Split(url.Fragment, "/")
|
||||
numParts := len(fragmentParts)
|
||||
if numParts == 0 {
|
||||
return schema, ""
|
||||
}
|
||||
|
||||
definitionName = fragmentParts[numParts-1]
|
||||
func (sd *SpecAnalyser) schemaFromRef(ref spec.Ref, defns *spec.Definitions) (actualSchema *spec.Schema, definitionName string) {
|
||||
definitionName = definitionFromRef(ref)
|
||||
foundSchema, ok := (*defns)[definitionName]
|
||||
if !ok {
|
||||
return nil, definitionName
|
||||
}
|
||||
sd.ReferencedDefinitions[definitionName] = true
|
||||
actualSchema = &foundSchema
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func (sd *SpecAnalyser) propertiesFor(schema *spec.Schema, defns *spec.Definitions) map[string]spec.Schema {
|
||||
schemaFromRef, _ := sd.schemaFromRef(schema, defns)
|
||||
schema = schemaFromRef
|
||||
props := map[string]spec.Schema{}
|
||||
|
||||
if schema.Properties != nil {
|
||||
for name, prop := range schema.Properties {
|
||||
prop := prop
|
||||
eachProp, _ := sd.schemaFromRef(&prop, defns)
|
||||
props[name] = *eachProp
|
||||
}
|
||||
}
|
||||
for _, eachAllOf := range schema.AllOf {
|
||||
eachAllOf := eachAllOf
|
||||
eachAllOfActual, _ := sd.schemaFromRef(&eachAllOf, defns)
|
||||
for name, prop := range eachAllOfActual.Properties {
|
||||
prop := prop
|
||||
eachProp, _ := sd.schemaFromRef(&prop, defns)
|
||||
props[name] = *eachProp
|
||||
}
|
||||
}
|
||||
return props
|
||||
// PropertyDefn combines a property with its required-ness
|
||||
type PropertyDefn struct {
|
||||
Schema *spec.Schema
|
||||
Required bool
|
||||
}
|
||||
|
||||
// PropertyMap a unified map including all AllOf fields
|
||||
type PropertyMap map[string]PropertyDefn
|
||||
|
|
41
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_difference.go
generated
vendored
41
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/spec_difference.go
generated
vendored
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SpecDifference encapsulates the details of an individual diff in part of a spec
|
||||
|
@ -89,37 +90,37 @@ func (sd SpecDifference) String() string {
|
|||
prefix := ""
|
||||
direction := ""
|
||||
|
||||
if isResponse {
|
||||
direction = " Response"
|
||||
if hasMethod {
|
||||
if hasURL {
|
||||
if hasMethod {
|
||||
prefix = fmt.Sprintf("%s:%s -> %d", sd.DifferenceLocation.URL, sd.DifferenceLocation.Method, sd.DifferenceLocation.Response)
|
||||
} else {
|
||||
prefix = fmt.Sprintf("%s ", sd.DifferenceLocation.URL)
|
||||
}
|
||||
prefix = fmt.Sprintf("%s:%s", sd.DifferenceLocation.URL, sd.DifferenceLocation.Method)
|
||||
}
|
||||
if isResponse {
|
||||
prefix += fmt.Sprintf(" -> %d", sd.DifferenceLocation.Response)
|
||||
direction = "Response"
|
||||
} else {
|
||||
direction = "Request"
|
||||
}
|
||||
} else {
|
||||
if hasURL {
|
||||
if hasMethod {
|
||||
direction = " Request"
|
||||
prefix = fmt.Sprintf("%s:%s", sd.DifferenceLocation.URL, sd.DifferenceLocation.Method)
|
||||
} else {
|
||||
prefix = fmt.Sprintf("%s ", sd.DifferenceLocation.URL)
|
||||
}
|
||||
} else {
|
||||
prefix = " Metadata"
|
||||
}
|
||||
prefix = sd.DifferenceLocation.URL
|
||||
}
|
||||
|
||||
paramOrPropertyLocation := ""
|
||||
if sd.DifferenceLocation.Node != nil {
|
||||
paramOrPropertyLocation = " - " + sd.DifferenceLocation.Node.String() + " "
|
||||
paramOrPropertyLocation = sd.DifferenceLocation.Node.String()
|
||||
}
|
||||
optionalInfo := ""
|
||||
if sd.DiffInfo != "" {
|
||||
optionalInfo = fmt.Sprintf(" <%s>", sd.DiffInfo)
|
||||
optionalInfo = sd.DiffInfo
|
||||
}
|
||||
return fmt.Sprintf("%s%s%s- %s%s", prefix, direction, paramOrPropertyLocation, sd.Code.Description(), optionalInfo)
|
||||
|
||||
items := []string{}
|
||||
for _, item := range []string{prefix, direction, paramOrPropertyLocation, sd.Code.Description(), optionalInfo} {
|
||||
if item != "" {
|
||||
items = append(items, item)
|
||||
}
|
||||
}
|
||||
return strings.Join(items, " - ")
|
||||
// return fmt.Sprintf("%s%s%s - %s%s", prefix, direction, paramOrPropertyLocation, sd.Code.Description(), optionalInfo)
|
||||
}
|
||||
|
||||
func (sd SpecDifferences) addDiff(diff SpecDifference) SpecDifferences {
|
||||
|
|
121
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/type_adapters.go
generated
vendored
121
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/diff/type_adapters.go
generated
vendored
|
@ -1,8 +1,6 @@
|
|||
package diff
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
|
@ -32,8 +30,28 @@ func forItems(items *spec.Items) *spec.Schema {
|
|||
return &schema
|
||||
}
|
||||
|
||||
func forParam(param spec.Parameter) spec.SchemaProps {
|
||||
return spec.SchemaProps{
|
||||
func forHeader(header spec.Header) *spec.SchemaProps {
|
||||
return &spec.SchemaProps{
|
||||
Type: []string{header.Type},
|
||||
Format: header.Format,
|
||||
Items: &spec.SchemaOrArray{Schema: forItems(header.Items)},
|
||||
Maximum: header.Maximum,
|
||||
ExclusiveMaximum: header.ExclusiveMaximum,
|
||||
Minimum: header.Minimum,
|
||||
ExclusiveMinimum: header.ExclusiveMinimum,
|
||||
MaxLength: header.MaxLength,
|
||||
MinLength: header.MinLength,
|
||||
Pattern: header.Pattern,
|
||||
MaxItems: header.MaxItems,
|
||||
MinItems: header.MinItems,
|
||||
UniqueItems: header.UniqueItems,
|
||||
MultipleOf: header.MultipleOf,
|
||||
Enum: header.Enum,
|
||||
}
|
||||
}
|
||||
|
||||
func forParam(param spec.Parameter) *spec.SchemaProps {
|
||||
return &spec.SchemaProps{
|
||||
Type: []string{param.Type},
|
||||
Format: param.Format,
|
||||
Items: &spec.SchemaOrArray{Schema: forItems(param.Items)},
|
||||
|
@ -95,76 +113,51 @@ func getURLMethodsFor(spec *spec.Swagger) URLMethods {
|
|||
return returnURLMethods
|
||||
}
|
||||
|
||||
func sliceToStrMap(elements []string) map[string]bool {
|
||||
elementMap := make(map[string]bool)
|
||||
for _, s := range elements {
|
||||
elementMap[s] = true
|
||||
}
|
||||
return elementMap
|
||||
}
|
||||
|
||||
func isStringType(typeName string) bool {
|
||||
return typeName == "string" || typeName == "password"
|
||||
}
|
||||
|
||||
const objType = "obj"
|
||||
// SchemaFromRefFn define this to get a schema for a ref
|
||||
type SchemaFromRefFn func(spec.Ref) (*spec.Schema, string)
|
||||
|
||||
func getTypeHierarchyChange(type1, type2 string) TypeDiff {
|
||||
if type1 == type2 {
|
||||
return TypeDiff{Change: NoChangeDetected, Description: ""}
|
||||
func propertiesFor(schema *spec.Schema, getRefFn SchemaFromRefFn) PropertyMap {
|
||||
if isRefType(schema) {
|
||||
schema, _ = getRefFn(schema.Ref)
|
||||
}
|
||||
fromType := type1
|
||||
if fromType == "" {
|
||||
fromType = objType
|
||||
props := PropertyMap{}
|
||||
|
||||
requiredProps := schema.Required
|
||||
requiredMap := map[string]bool{}
|
||||
for _, prop := range requiredProps {
|
||||
requiredMap[prop] = true
|
||||
}
|
||||
toType := type2
|
||||
if toType == "" {
|
||||
toType = objType
|
||||
}
|
||||
diffDescription := fmt.Sprintf("%s -> %s", fromType, toType)
|
||||
if isStringType(type1) && !isStringType(type2) {
|
||||
return TypeDiff{Change: NarrowedType, Description: diffDescription}
|
||||
}
|
||||
if !isStringType(type1) && isStringType(type2) {
|
||||
return TypeDiff{Change: WidenedType, Description: diffDescription}
|
||||
}
|
||||
type1Wideness, type1IsNumeric := numberWideness[type1]
|
||||
type2Wideness, type2IsNumeric := numberWideness[type2]
|
||||
if type1IsNumeric && type2IsNumeric {
|
||||
if type1Wideness == type2Wideness {
|
||||
return TypeDiff{Change: ChangedToCompatibleType, Description: diffDescription}
|
||||
}
|
||||
if type1Wideness > type2Wideness {
|
||||
return TypeDiff{Change: NarrowedType, Description: diffDescription}
|
||||
}
|
||||
if type1Wideness < type2Wideness {
|
||||
return TypeDiff{Change: WidenedType, Description: diffDescription}
|
||||
|
||||
if schema.Properties != nil {
|
||||
for name, prop := range schema.Properties {
|
||||
prop := prop
|
||||
required := requiredMap[name]
|
||||
props[name] = PropertyDefn{Schema: &prop, Required: required}
|
||||
}
|
||||
}
|
||||
return TypeDiff{Change: ChangedType, Description: diffDescription}
|
||||
for _, e := range schema.AllOf {
|
||||
eachAllOf := e
|
||||
allOfMap := propertiesFor(&eachAllOf, getRefFn)
|
||||
for name, prop := range allOfMap {
|
||||
props[name] = prop
|
||||
}
|
||||
}
|
||||
return props
|
||||
}
|
||||
|
||||
func compareFloatValues(fieldName string, val1 *float64, val2 *float64, ifGreaterCode SpecChangeCode, ifLessCode SpecChangeCode) TypeDiff {
|
||||
if val1 != nil && val2 != nil {
|
||||
if *val2 > *val1 {
|
||||
return TypeDiff{Change: ifGreaterCode, Description: fmt.Sprintf("%s %f->%f", fieldName, *val1, *val2)}
|
||||
}
|
||||
if *val2 < *val1 {
|
||||
return TypeDiff{Change: ifLessCode, Description: fmt.Sprintf("%s %f->%f", fieldName, *val1, *val2)}
|
||||
}
|
||||
func getRef(item interface{}) spec.Ref {
|
||||
switch s := item.(type) {
|
||||
case *spec.Refable:
|
||||
return s.Ref
|
||||
case *spec.Schema:
|
||||
return s.Ref
|
||||
case *spec.SchemaProps:
|
||||
return s.Ref
|
||||
default:
|
||||
return spec.Ref{}
|
||||
}
|
||||
return TypeDiff{Change: NoChangeDetected, Description: ""}
|
||||
}
|
||||
|
||||
func compareIntValues(fieldName string, val1 *int64, val2 *int64, ifGreaterCode SpecChangeCode, ifLessCode SpecChangeCode) TypeDiff {
|
||||
if val1 != nil && val2 != nil {
|
||||
if *val2 > *val1 {
|
||||
return TypeDiff{Change: ifGreaterCode, Description: fmt.Sprintf("%s %d->%d", fieldName, *val1, *val2)}
|
||||
}
|
||||
if *val2 < *val1 {
|
||||
return TypeDiff{Change: ifLessCode, Description: fmt.Sprintf("%s %d->%d", fieldName, *val1, *val2)}
|
||||
}
|
||||
|
||||
}
|
||||
return TypeDiff{Change: NoChangeDetected, Description: ""}
|
||||
}
|
||||
|
|
10
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/expand.go
generated
vendored
10
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/expand.go
generated
vendored
|
@ -47,11 +47,12 @@ func writeToFile(swspec *spec.Swagger, pretty bool, format string, output string
|
|||
var err error
|
||||
asJSON := format == "json"
|
||||
|
||||
if pretty && asJSON {
|
||||
switch {
|
||||
case pretty && asJSON:
|
||||
b, err = json.MarshalIndent(swspec, "", " ")
|
||||
} else if asJSON {
|
||||
case asJSON:
|
||||
b, err = json.Marshal(swspec)
|
||||
} else {
|
||||
default:
|
||||
// marshals as YAML
|
||||
b, err = json.Marshal(swspec)
|
||||
if err == nil {
|
||||
|
@ -62,12 +63,15 @@ func writeToFile(swspec *spec.Swagger, pretty bool, format string, output string
|
|||
b, err = yaml.Marshal(d)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if output == "" {
|
||||
fmt.Println(string(b))
|
||||
return nil
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(output, b, 0644) // #nosec
|
||||
}
|
||||
|
|
1
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate.go
generated
vendored
1
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate.go
generated
vendored
|
@ -24,4 +24,5 @@ type Generate struct {
|
|||
Server *generate.Server `command:"server"`
|
||||
Spec *generate.SpecFile `command:"spec"`
|
||||
Client *generate.Client `command:"client"`
|
||||
Markdown *generate.Markdown `command:"markdown"`
|
||||
}
|
||||
|
|
33
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/markdown.go
generated
vendored
Normal file
33
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/markdown.go
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
package generate
|
||||
|
||||
import (
|
||||
"github.com/go-swagger/go-swagger/generator"
|
||||
"github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
// Markdown generates a markdown representation of the spec
|
||||
type Markdown struct {
|
||||
WithShared
|
||||
WithModels
|
||||
WithOperations
|
||||
|
||||
Output flags.Filename `long:"output" short:"" description:"the file to write the generated markdown." default:"markdown.md"`
|
||||
}
|
||||
|
||||
func (m Markdown) apply(opts *generator.GenOpts) {
|
||||
m.Shared.apply(opts)
|
||||
m.Models.apply(opts)
|
||||
m.Operations.apply(opts)
|
||||
}
|
||||
|
||||
func (m *Markdown) generate(opts *generator.GenOpts) error {
|
||||
return generator.GenerateMarkdown(string(m.Output), m.Models.Models, m.Operations.Operations, opts)
|
||||
}
|
||||
|
||||
func (m Markdown) log(rp string) {
|
||||
}
|
||||
|
||||
// Execute runs this command
|
||||
func (m *Markdown) Execute(args []string) error {
|
||||
return createSwagger(m)
|
||||
}
|
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/server.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/server.go
generated
vendored
|
@ -52,7 +52,7 @@ type Server struct {
|
|||
Name string `long:"name" short:"A" description:"the name of the application, defaults to a mangled value of info.title"`
|
||||
// TODO(fredbi): CmdName string `long:"cmd-name" short:"A" description:"the name of the server command, when main is generated (defaults to {name}-server)"`
|
||||
|
||||
//deprecated flags
|
||||
// deprecated flags
|
||||
WithContext bool `long:"with-context" description:"handlers get a context as first arg (deprecated)"`
|
||||
}
|
||||
|
||||
|
|
3
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/shared.go
generated
vendored
3
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/generate/shared.go
generated
vendored
|
@ -80,10 +80,13 @@ type sharedCommand interface {
|
|||
type schemeOptions struct {
|
||||
Principal string `short:"P" long:"principal" description:"the model to use for the security principal"`
|
||||
DefaultScheme string `long:"default-scheme" description:"the default scheme for this API" default:"http"`
|
||||
|
||||
PrincipalIface bool `long:"principal-is-interface" description:"the security principal provided is an interface, not a struct"`
|
||||
}
|
||||
|
||||
func (so schemeOptions) apply(opts *generator.GenOpts) {
|
||||
opts.Principal = so.Principal
|
||||
opts.PrincipalCustomIface = so.PrincipalIface
|
||||
opts.DefaultScheme = so.DefaultScheme
|
||||
}
|
||||
|
||||
|
|
10
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/mixin.go
generated
vendored
10
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/mixin.go
generated
vendored
|
@ -16,7 +16,8 @@ import (
|
|||
|
||||
const (
|
||||
// Output messages
|
||||
nothingToDo = "nothing to do. Need some swagger files to merge.\nUSAGE: swagger mixin [-c <expected#Collisions>] <primary-swagger-file> <mixin-swagger-file...>"
|
||||
nothingToDo = "nothing to do. Need some swagger files to merge.\nUSAGE: swagger mixin [-c <expected#Collisions>] <primary-swagger-file> <mixin-swagger-file...>"
|
||||
ignoreConflictsAndCollisionsSpecified = "both the flags ignore conflicts and collisions were specified. These have conflicting meaning so please only specify one"
|
||||
)
|
||||
|
||||
// MixinSpec holds command line flag definitions specific to the mixin
|
||||
|
@ -28,6 +29,7 @@ type MixinSpec struct {
|
|||
Output flags.Filename `long:"output" short:"o" description:"the file to write to"`
|
||||
KeepSpecOrder bool `long:"keep-spec-order" description:"Keep schema properties order identical to spec file"`
|
||||
Format string `long:"format" description:"the format for the spec document" default:"json" choice:"yaml" choice:"json"`
|
||||
IgnoreConflicts bool `long:"ignore-conflicts" description:"Ignore conflict"`
|
||||
}
|
||||
|
||||
// Execute runs the mixin command which merges Swagger 2.0 specs into
|
||||
|
@ -52,6 +54,9 @@ func (c *MixinSpec) Execute(args []string) error {
|
|||
if len(args) < 2 {
|
||||
return errors.New(nothingToDo)
|
||||
}
|
||||
if c.IgnoreConflicts && c.ExpectedCollisionCount != 0 {
|
||||
return errors.New(ignoreConflictsAndCollisionsSpecified)
|
||||
}
|
||||
|
||||
log.Printf("args[0] = %v\n", args[0])
|
||||
log.Printf("args[1:] = %v\n", args[1:])
|
||||
|
@ -65,6 +70,9 @@ func (c *MixinSpec) Execute(args []string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if c.IgnoreConflicts {
|
||||
return nil
|
||||
}
|
||||
if len(collisions) != int(c.ExpectedCollisionCount) {
|
||||
if len(collisions) != 0 {
|
||||
// use bash $? to get actual # collisions
|
||||
|
|
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/serve.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/serve.go
generated
vendored
|
@ -27,7 +27,7 @@ type ServeCmd struct {
|
|||
NoUI bool `long:"no-ui" description:"when present, only the swagger spec will be served"`
|
||||
Flatten bool `long:"flatten" description:"when present, flatten the swagger spec before serving it"`
|
||||
Port int `long:"port" short:"p" description:"the port to serve this site" env:"PORT"`
|
||||
Host string `long:"host" description:"the interface to serve this site, defaults to 0.0.0.0" env:"HOST"`
|
||||
Host string `long:"host" description:"the interface to serve this site, defaults to 0.0.0.0" default:"0.0.0.0" env:"HOST"`
|
||||
}
|
||||
|
||||
// Execute the serve command
|
||||
|
|
13
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/version.go
generated
vendored
13
vendor/github.com/go-swagger/go-swagger/cmd/swagger/commands/version.go
generated
vendored
|
@ -1,6 +1,9 @@
|
|||
package commands
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
)
|
||||
|
||||
var (
|
||||
// Version for the swagger command
|
||||
|
@ -16,9 +19,17 @@ type PrintVersion struct {
|
|||
// Execute this command
|
||||
func (p *PrintVersion) Execute(args []string) error {
|
||||
if Version == "" {
|
||||
if info, available := debug.ReadBuildInfo(); available && info.Main.Version != "(devel)" {
|
||||
// built from source, with module (e.g. go get)
|
||||
fmt.Println("version:", info.Main.Version)
|
||||
fmt.Println("commit:", fmt.Sprintf("(unknown, mod sum: %q)", info.Main.Sum))
|
||||
return nil
|
||||
}
|
||||
// built from source, local repo
|
||||
fmt.Println("dev")
|
||||
return nil
|
||||
}
|
||||
// released version
|
||||
fmt.Println("version:", Version)
|
||||
fmt.Println("commit:", Commit)
|
||||
|
||||
|
|
7
vendor/github.com/go-swagger/go-swagger/cmd/swagger/swagger.go
generated
vendored
7
vendor/github.com/go-swagger/go-swagger/cmd/swagger/swagger.go
generated
vendored
|
@ -41,7 +41,7 @@ func main() {
|
|||
// Recovering from internal panics
|
||||
// Stack may be printed in Debug mode
|
||||
// Need import "runtime/debug".
|
||||
//defer func() {
|
||||
// defer func() {
|
||||
// r := recover()
|
||||
// if r != nil {
|
||||
// log.Printf("Fatal error:", r)
|
||||
|
@ -50,7 +50,7 @@ func main() {
|
|||
// }
|
||||
// os.Exit(1)
|
||||
// }
|
||||
//}()
|
||||
// }()
|
||||
|
||||
parser := flags.NewParser(&opts, flags.Default)
|
||||
parser.ShortDescription = "helps you keep your API well described"
|
||||
|
@ -123,6 +123,9 @@ It aims to represent the contract of your API with a language agnostic descripti
|
|||
case "operation":
|
||||
cmd.ShortDescription = "generate one or more server operations from the swagger spec"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
case "markdown":
|
||||
cmd.ShortDescription = "generate a markdown representation from the swagger spec"
|
||||
cmd.LongDescription = cmd.ShortDescription
|
||||
}
|
||||
}
|
||||
|
||||
|
|
3
vendor/github.com/go-swagger/go-swagger/codescan/README.md
generated
vendored
Normal file
3
vendor/github.com/go-swagger/go-swagger/codescan/README.md
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# codescan
|
||||
|
||||
Version of the go source parser with support for go modules, from go1.11 onwards.
|
6
vendor/github.com/go-swagger/go-swagger/codescan/application.go
generated
vendored
6
vendor/github.com/go-swagger/go-swagger/codescan/application.go
generated
vendored
|
@ -595,7 +595,7 @@ func (a *typeIndex) detectNodes(file *ast.File) (node, error) {
|
|||
if seenStruct == "" || seenStruct == matches[1] {
|
||||
seenStruct = matches[1]
|
||||
} else {
|
||||
return 0, fmt.Errorf("classifier: already annotated as %s, can't also be %q", seenStruct, matches[1])
|
||||
return 0, fmt.Errorf("classifier: already annotated as %s, can't also be %q - %s", seenStruct, matches[1], cline.Text)
|
||||
}
|
||||
case "meta":
|
||||
n |= metaNode
|
||||
|
@ -604,14 +604,14 @@ func (a *typeIndex) detectNodes(file *ast.File) (node, error) {
|
|||
if seenStruct == "" || seenStruct == matches[1] {
|
||||
seenStruct = matches[1]
|
||||
} else {
|
||||
return 0, fmt.Errorf("classifier: already annotated as %s, can't also be %q", seenStruct, matches[1])
|
||||
return 0, fmt.Errorf("classifier: already annotated as %s, can't also be %q - %s", seenStruct, matches[1], cline.Text)
|
||||
}
|
||||
case "response":
|
||||
n |= responseNode
|
||||
if seenStruct == "" || seenStruct == matches[1] {
|
||||
seenStruct = matches[1]
|
||||
} else {
|
||||
return 0, fmt.Errorf("classifier: already annotated as %s, can't also be %q", seenStruct, matches[1])
|
||||
return 0, fmt.Errorf("classifier: already annotated as %s, can't also be %q - %s", seenStruct, matches[1], cline.Text)
|
||||
}
|
||||
case "strfmt", "name", "discriminated", "file", "enum", "default", "alias", "type":
|
||||
// TODO: perhaps collect these and pass along to avoid lookups later on
|
||||
|
|
5
vendor/github.com/go-swagger/go-swagger/codescan/doc.go
generated
vendored
Normal file
5
vendor/github.com/go-swagger/go-swagger/codescan/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
/*Package codescan provides a scanner for go files that produces a swagger spec document.
|
||||
|
||||
This package is intendnd for go1.11 onwards, and does support go modules.
|
||||
*/
|
||||
package codescan
|
3
vendor/github.com/go-swagger/go-swagger/codescan/meta.go
generated
vendored
3
vendor/github.com/go-swagger/go-swagger/codescan/meta.go
generated
vendored
|
@ -204,7 +204,8 @@ func parseContactInfo(line string) (*spec.ContactInfo, error) {
|
|||
ContactInfoProps: spec.ContactInfoProps{
|
||||
URL: url,
|
||||
Name: name,
|
||||
Email: email,},
|
||||
Email: email,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
3
vendor/github.com/go-swagger/go-swagger/codescan/parameters.go
generated
vendored
3
vendor/github.com/go-swagger/go-swagger/codescan/parameters.go
generated
vendored
|
@ -260,9 +260,6 @@ func (p *parameterBuilder) buildFromField(fld *types.Var, tpe types.Type, typabl
|
|||
typable.Typed("string", sfnm)
|
||||
return nil
|
||||
}
|
||||
//if err := r.makeRef(decl, typable); err != nil {
|
||||
// return err
|
||||
//}
|
||||
sb := &schemaBuilder{ctx: p.ctx, decl: decl}
|
||||
sb.inferNames()
|
||||
if err := sb.buildFromType(decl.Type, typable); err != nil {
|
||||
|
|
27
vendor/github.com/go-swagger/go-swagger/codescan/parser.go
generated
vendored
27
vendor/github.com/go-swagger/go-swagger/codescan/parser.go
generated
vendored
|
@ -626,7 +626,8 @@ COMMENTS:
|
|||
}
|
||||
|
||||
var matched bool
|
||||
for _, tagger := range st.taggers {
|
||||
for _, tg := range st.taggers {
|
||||
tagger := tg
|
||||
if tagger.Matches(line) {
|
||||
st.seenTag = true
|
||||
st.currentTagger = &tagger
|
||||
|
@ -1311,13 +1312,13 @@ func (ss *setOpResponses) Matches(line string) bool {
|
|||
return ss.rx.MatchString(line)
|
||||
}
|
||||
|
||||
//ResponseTag used when specifying a response to point to a defined swagger:response
|
||||
// ResponseTag used when specifying a response to point to a defined swagger:response
|
||||
const ResponseTag = "response"
|
||||
|
||||
//BodyTag used when specifying a response to point to a model/schema
|
||||
// BodyTag used when specifying a response to point to a model/schema
|
||||
const BodyTag = "body"
|
||||
|
||||
//DescriptionTag used when specifying a response that gives a description of the response
|
||||
// DescriptionTag used when specifying a response that gives a description of the response
|
||||
const DescriptionTag = "description"
|
||||
|
||||
func parseTags(line string) (modelOrResponse string, arrays int, isDefinitionRef bool, description string, err error) {
|
||||
|
@ -1331,8 +1332,8 @@ func parseTags(line string) (modelOrResponse string, arrays int, isDefinitionRef
|
|||
tag = tagValList[0]
|
||||
value = tagValList[1]
|
||||
} else {
|
||||
//TODO: Print a warning, and in the long term, do not support not tagged values
|
||||
//Add a default tag if none is supplied
|
||||
// TODO: Print a warning, and in the long term, do not support not tagged values
|
||||
// Add a default tag if none is supplied
|
||||
if i == 0 {
|
||||
tag = ResponseTag
|
||||
} else {
|
||||
|
@ -1353,15 +1354,15 @@ func parseTags(line string) (modelOrResponse string, arrays int, isDefinitionRef
|
|||
}
|
||||
}
|
||||
if foundModelOrResponse {
|
||||
//Read the model or response tag
|
||||
// Read the model or response tag
|
||||
parsedModelOrResponse = true
|
||||
//Check for nested arrays
|
||||
// Check for nested arrays
|
||||
arrays = 0
|
||||
for strings.HasPrefix(value, "[]") {
|
||||
arrays++
|
||||
value = value[2:]
|
||||
}
|
||||
//What's left over is the model name
|
||||
// What's left over is the model name
|
||||
modelOrResponse = value
|
||||
} else {
|
||||
foundDescription := false
|
||||
|
@ -1369,7 +1370,7 @@ func parseTags(line string) (modelOrResponse string, arrays int, isDefinitionRef
|
|||
foundDescription = true
|
||||
}
|
||||
if foundDescription {
|
||||
//Descriptions are special, they make they read the rest of the line
|
||||
// Descriptions are special, they make they read the rest of the line
|
||||
descriptionWords := []string{value}
|
||||
if i < len(tags)-1 {
|
||||
descriptionWords = append(descriptionWords, tags[i+1:]...)
|
||||
|
@ -1382,13 +1383,13 @@ func parseTags(line string) (modelOrResponse string, arrays int, isDefinitionRef
|
|||
} else {
|
||||
err = fmt.Errorf("invalid tag: %s", tag)
|
||||
}
|
||||
//return error
|
||||
// return error
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Maybe do, if !parsedModelOrResponse {return some error}
|
||||
// TODO: Maybe do, if !parsedModelOrResponse {return some error}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1431,7 +1432,7 @@ func (ss *setOpResponses) Parse(lines []string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//A possible exception for having a definition
|
||||
// A possible exception for having a definition
|
||||
if _, ok := ss.responses[refTarget]; !ok {
|
||||
if _, ok := ss.definitions[refTarget]; ok {
|
||||
isDefinitionRef = true
|
||||
|
|
6
vendor/github.com/go-swagger/go-swagger/codescan/responses.go
generated
vendored
6
vendor/github.com/go-swagger/go-swagger/codescan/responses.go
generated
vendored
|
@ -402,6 +402,12 @@ func (r *responseBuilder) buildFromStruct(decl *entityDecl, tpe *types.Struct, r
|
|||
return nil, err
|
||||
}
|
||||
return append(taggers, otherTaggers...), nil
|
||||
case *ast.SelectorExpr:
|
||||
otherTaggers, err := parseArrayTypes(iftpe.Sel, items.Items, level+1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return otherTaggers, nil
|
||||
case *ast.StarExpr:
|
||||
otherTaggers, err := parseArrayTypes(iftpe.X, items, level)
|
||||
if err != nil {
|
||||
|
|
11
vendor/github.com/go-swagger/go-swagger/codescan/schema.go
generated
vendored
11
vendor/github.com/go-swagger/go-swagger/codescan/schema.go
generated
vendored
|
@ -238,7 +238,7 @@ func (s *schemaBuilder) buildFromType(tpe types.Type, tgt swaggerTypable) error
|
|||
case *types.Array:
|
||||
return s.buildFromType(titpe.Elem(), tgt.Items())
|
||||
case *types.Map:
|
||||
//debugLog("map: %v -> [%v]%v", fld.Name(), ftpe.Key().String(), ftpe.Elem().String())
|
||||
// debugLog("map: %v -> [%v]%v", fld.Name(), ftpe.Key().String(), ftpe.Elem().String())
|
||||
// check if key is a string type, if not print a message
|
||||
// and skip the map property. Only maps with string keys can go into additional properties
|
||||
sch := tgt.Schema()
|
||||
|
@ -387,7 +387,6 @@ func (s *schemaBuilder) buildFromType(tpe types.Type, tgt swaggerTypable) error
|
|||
return nil
|
||||
}
|
||||
default:
|
||||
//log.Printf("WARNING: can't determine refined type %s (%T)", titpe.String(), titpe)
|
||||
panic(fmt.Sprintf("WARNING: can't determine refined type %s (%T)", titpe.String(), titpe))
|
||||
}
|
||||
|
||||
|
@ -429,7 +428,7 @@ func (s *schemaBuilder) buildFromInterface(decl *entityDecl, it *types.Interface
|
|||
continue
|
||||
}
|
||||
|
||||
//decl.
|
||||
// decl.
|
||||
debugLog("maybe interface field %s: %s(%T)", o.Name(), o.Type().String(), o.Type())
|
||||
afld = an
|
||||
break
|
||||
|
@ -514,7 +513,7 @@ func (s *schemaBuilder) buildFromInterface(decl *entityDecl, it *types.Interface
|
|||
|
||||
var afld *ast.Field
|
||||
ans, _ := astutil.PathEnclosingInterval(decl.File, fld.Pos(), fld.Pos())
|
||||
//debugLog("got %d nodes (exact: %t)", len(ans), isExact)
|
||||
// debugLog("got %d nodes (exact: %t)", len(ans), isExact)
|
||||
for _, an := range ans {
|
||||
at, valid := an.(*ast.Field)
|
||||
if !valid {
|
||||
|
@ -600,7 +599,7 @@ func (s *schemaBuilder) buildFromStruct(decl *entityDecl, st *types.Struct, sche
|
|||
debugLog("maybe allof field(%t) %s: %s (%T) [%q](anon: %t, embedded: %t)", fld.IsField(), fld.Name(), fld.Type().String(), fld.Type(), tg, fld.Anonymous(), fld.Embedded())
|
||||
var afld *ast.Field
|
||||
ans, _ := astutil.PathEnclosingInterval(decl.File, fld.Pos(), fld.Pos())
|
||||
//debugLog("got %d nodes (exact: %t)", len(ans), isExact)
|
||||
// debugLog("got %d nodes (exact: %t)", len(ans), isExact)
|
||||
for _, an := range ans {
|
||||
at, valid := an.(*ast.Field)
|
||||
if !valid {
|
||||
|
@ -696,7 +695,7 @@ func (s *schemaBuilder) buildFromStruct(decl *entityDecl, st *types.Struct, sche
|
|||
|
||||
var afld *ast.Field
|
||||
ans, _ := astutil.PathEnclosingInterval(decl.File, fld.Pos(), fld.Pos())
|
||||
//debugLog("got %d nodes (exact: %t)", len(ans), isExact)
|
||||
// debugLog("got %d nodes (exact: %t)", len(ans), isExact)
|
||||
for _, an := range ans {
|
||||
at, valid := an.(*ast.Field)
|
||||
if !valid {
|
||||
|
|
1
vendor/github.com/go-swagger/go-swagger/generator/.gitignore
generated
vendored
Normal file
1
vendor/github.com/go-swagger/go-swagger/generator/.gitignore
generated
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
generated/
|
306
vendor/github.com/go-swagger/go-swagger/generator/bindata.go
generated
vendored
306
vendor/github.com/go-swagger/go-swagger/generator/bindata.go
generated
vendored
File diff suppressed because one or more lines are too long
11
vendor/github.com/go-swagger/go-swagger/generator/client.go
generated
vendored
11
vendor/github.com/go-swagger/go-swagger/generator/client.go
generated
vendored
|
@ -84,10 +84,11 @@ func (c *clientGenerator) Generate() error {
|
|||
}
|
||||
|
||||
if c.GenOpts.IncludeModel {
|
||||
for _, mod := range app.Models {
|
||||
if mod.IsStream {
|
||||
for _, m := range app.Models {
|
||||
if m.IsStream {
|
||||
continue
|
||||
}
|
||||
mod := m
|
||||
if err := c.GenOpts.renderDefinition(&mod); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -95,8 +96,10 @@ func (c *clientGenerator) Generate() error {
|
|||
}
|
||||
|
||||
if c.GenOpts.IncludeHandler {
|
||||
for _, opg := range app.OperationGroups {
|
||||
for _, op := range opg.Operations {
|
||||
for _, g := range app.OperationGroups {
|
||||
opg := g
|
||||
for _, o := range opg.Operations {
|
||||
op := o
|
||||
if err := c.GenOpts.renderOperation(&op); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
2
vendor/github.com/go-swagger/go-swagger/generator/formats.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/generator/formats.go
generated
vendored
|
@ -57,7 +57,7 @@ var zeroes = map[string]string{
|
|||
"strfmt.UUID3": "strfmt.UUID3(\"\")",
|
||||
"strfmt.UUID4": "strfmt.UUID4(\"\")",
|
||||
"strfmt.UUID5": "strfmt.UUID5(\"\")",
|
||||
//"file": "runtime.File",
|
||||
// "file": "runtime.File",
|
||||
}
|
||||
|
||||
// conversion functions from string representation to a numerical or boolean
|
||||
|
|
2
vendor/github.com/go-swagger/go-swagger/generator/language.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/generator/language.go
generated
vendored
|
@ -262,7 +262,7 @@ func GoLangOpts() *LanguageOpts {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.Replace(strings.Replace(strings.Replace(string(b), "}", ",}", -1), "[", "{", -1), "]", ",}", -1), nil
|
||||
return strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(string(b), "}", ",}"), "[", "{"), "]", ",}"), nil
|
||||
}
|
||||
|
||||
opts.BaseImportFunc = func(tgt string) string {
|
||||
|
|
220
vendor/github.com/go-swagger/go-swagger/generator/model.go
generated
vendored
220
vendor/github.com/go-swagger/go-swagger/generator/model.go
generated
vendored
|
@ -186,7 +186,7 @@ func shallowValidationLookup(sch GenSchema) bool {
|
|||
if sch.Required || hasFormatValidation(sch.resolvedType) {
|
||||
return true
|
||||
}
|
||||
if sch.MaxLength != nil || sch.MinLength != nil || sch.Pattern != "" || sch.MultipleOf != nil || sch.Minimum != nil || sch.Maximum != nil || len(sch.Enum) > 0 || len(sch.ItemsEnum) > 0 {
|
||||
if sch.HasStringValidations() || sch.HasNumberValidations() || sch.HasEnum() || len(sch.ItemsEnum) > 0 || sch.HasObjectValidations() {
|
||||
return true
|
||||
}
|
||||
for _, a := range sch.AllOf {
|
||||
|
@ -230,7 +230,7 @@ func makeGenDefinitionHierarchy(name, pkg, container string, schema spec.Schema,
|
|||
// Check if model is imported from external package using x-go-type
|
||||
receiver := "m"
|
||||
// models are resolved in the current package
|
||||
resolver := newTypeResolver("", specDoc)
|
||||
resolver := newTypeResolver("", "", specDoc)
|
||||
resolver.ModelName = name
|
||||
analyzed := analysis.New(specDoc.Spec())
|
||||
|
||||
|
@ -375,7 +375,7 @@ func makeGenDefinitionHierarchy(name, pkg, container string, schema spec.Schema,
|
|||
}
|
||||
|
||||
func findImports(sch *GenSchema) map[string]string {
|
||||
imp := map[string]string{}
|
||||
imp := make(map[string]string, 20)
|
||||
t := sch.resolvedType
|
||||
if t.Pkg != "" && t.PkgAlias != "" {
|
||||
imp[t.PkgAlias] = t.Pkg
|
||||
|
@ -404,7 +404,8 @@ func findImports(sch *GenSchema) map[string]string {
|
|||
}
|
||||
}
|
||||
if sch.Properties != nil {
|
||||
for _, p := range sch.Properties {
|
||||
for _, props := range sch.Properties {
|
||||
p := props
|
||||
sub := findImports(&p)
|
||||
for k, v := range sub {
|
||||
imp[k] = v
|
||||
|
@ -418,7 +419,8 @@ func findImports(sch *GenSchema) map[string]string {
|
|||
}
|
||||
}
|
||||
if sch.AllOf != nil {
|
||||
for _, p := range sch.AllOf {
|
||||
for _, props := range sch.AllOf {
|
||||
p := props
|
||||
sub := findImports(&p)
|
||||
for k, v := range sub {
|
||||
imp[k] = v
|
||||
|
@ -426,8 +428,11 @@ func findImports(sch *GenSchema) map[string]string {
|
|||
}
|
||||
}
|
||||
for k, v := range sch.ExtraImports {
|
||||
imp[k] = v
|
||||
if k != "" && v != "" {
|
||||
imp[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return imp
|
||||
}
|
||||
|
||||
|
@ -621,33 +626,39 @@ func (sg *schemaGenContext) NewAdditionalProperty(schema spec.Schema) *schemaGen
|
|||
return pg
|
||||
}
|
||||
|
||||
func hasSliceValidations(model *spec.Schema) (hasSliceValidations bool) {
|
||||
hasSliceValidations = model.MaxItems != nil || model.MinItems != nil || model.UniqueItems || len(model.Enum) > 0
|
||||
return
|
||||
func hasContextValidations(model *spec.Schema) bool {
|
||||
// always assume ref needs context validate
|
||||
// TODO: find away to determine ref needs context validate or not
|
||||
if model.ReadOnly || model.Ref.String() != "" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasValidations(model *spec.Schema, isRequired bool) (hasValidation bool) {
|
||||
// NOTE: needsValidation has gone deprecated and is replaced by top-level's shallowValidationLookup()
|
||||
hasNumberValidation := model.Maximum != nil || model.Minimum != nil || model.MultipleOf != nil
|
||||
hasStringValidation := model.MaxLength != nil || model.MinLength != nil || model.Pattern != ""
|
||||
hasEnum := len(model.Enum) > 0
|
||||
func hasValidations(model *spec.Schema, isRequired bool) bool {
|
||||
if isRequired {
|
||||
return true
|
||||
}
|
||||
|
||||
v := model.Validations()
|
||||
if v.HasNumberValidations() || v.HasStringValidations() || v.HasArrayValidations() || v.HasEnum() || v.HasObjectValidations() {
|
||||
return true
|
||||
}
|
||||
|
||||
// since this was added to deal with discriminator, we'll fix this when testing discriminated types
|
||||
simpleObject := len(model.Properties) > 0 && model.Discriminator == ""
|
||||
if len(model.Properties) > 0 && model.Discriminator == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
// lift validations from allOf branches
|
||||
hasAllOfValidation := false
|
||||
for _, s := range model.AllOf {
|
||||
hasAllOfValidation = hasValidations(&s, false)
|
||||
hasAllOfValidation = s.Ref.String() != "" || hasAllOfValidation
|
||||
if hasAllOfValidation {
|
||||
break
|
||||
schema := s
|
||||
if s.Ref.String() != "" || hasValidations(&schema, false) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
hasValidation = hasNumberValidation || hasStringValidation || hasSliceValidations(model) || hasEnum || simpleObject || hasAllOfValidation || isRequired
|
||||
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
func hasFormatValidation(tpe resolvedType) bool {
|
||||
|
@ -660,34 +671,25 @@ func hasFormatValidation(tpe resolvedType) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// handleFormatConflicts handles all conflicting model properties when a format is set
|
||||
func handleFormatConflicts(model *spec.Schema) {
|
||||
switch model.Format {
|
||||
case "date", "datetime", "uuid", "bsonobjectid", "base64", "duration":
|
||||
model.MinLength = nil
|
||||
model.MaxLength = nil
|
||||
model.Pattern = ""
|
||||
// more cases should be inserted here if they arise
|
||||
}
|
||||
}
|
||||
|
||||
func (sg *schemaGenContext) schemaValidations() sharedValidations {
|
||||
model := sg.Schema
|
||||
// resolve any conflicting properties if the model has a format
|
||||
handleFormatConflicts(&model)
|
||||
|
||||
isRequired := sg.Required
|
||||
if model.Default != nil || model.ReadOnly {
|
||||
// when readOnly or default is specified, this disables Required validation (Swagger-specific)
|
||||
isRequired = false
|
||||
if sg.Required {
|
||||
log.Printf("warn: properties with a default value or readOnly should not be required [%s]", sg.Name)
|
||||
}
|
||||
}
|
||||
hasSliceValidations := model.MaxItems != nil || model.MinItems != nil || model.UniqueItems || len(model.Enum) > 0
|
||||
hasValidations := hasValidations(&model, isRequired)
|
||||
|
||||
s := sharedValidationsFromSchema(model, sg.Required)
|
||||
s.HasValidations = hasValidations
|
||||
s.HasSliceValidations = hasSliceValidations
|
||||
return s
|
||||
v := model.Validations()
|
||||
return sharedValidations{
|
||||
Required: sg.Required, /* TODO(fred): guard for cases with discriminator field, default and readOnly*/
|
||||
SchemaValidations: v,
|
||||
HasSliceValidations: v.HasArrayValidations() || v.HasEnum(),
|
||||
HasValidations: hasValidations(&model, isRequired),
|
||||
}
|
||||
}
|
||||
|
||||
func mergeValidation(other *schemaGenContext) bool {
|
||||
|
@ -708,6 +710,7 @@ func mergeValidation(other *schemaGenContext) bool {
|
|||
|
||||
func (sg *schemaGenContext) MergeResult(other *schemaGenContext, liftsRequired bool) {
|
||||
sg.GenSchema.HasValidations = sg.GenSchema.HasValidations || mergeValidation(other)
|
||||
sg.GenSchema.HasContextValidations = sg.GenSchema.HasContextValidations || other.GenSchema.HasContextValidations
|
||||
|
||||
if liftsRequired && other.GenSchema.AdditionalProperties != nil && other.GenSchema.AdditionalProperties.Required {
|
||||
sg.GenSchema.Required = true
|
||||
|
@ -743,21 +746,20 @@ func (sg *schemaGenContext) buildProperties() error {
|
|||
debugLog("building properties %s (parent: %s)", sg.Name, sg.Container)
|
||||
|
||||
for k, v := range sg.Schema.Properties {
|
||||
debugLogAsJSON("building property %s[%q] (tup: %t) (BaseType: %t)",
|
||||
sg.Name, k, sg.IsTuple, sg.GenSchema.IsBaseType, sg.Schema)
|
||||
debugLog("property %s[%q] (tup: %t) HasValidations: %t)",
|
||||
sg.Name, k, sg.IsTuple, sg.GenSchema.HasValidations)
|
||||
debugLogAsJSON("building property %s[%q] (IsTuple: %t) (IsBaseType: %t) (HasValidations: %t)",
|
||||
sg.Name, k, sg.IsTuple, sg.GenSchema.IsBaseType, sg.GenSchema.HasValidations, v)
|
||||
|
||||
vv := v
|
||||
|
||||
// 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 || swag.ContainsStrings(sg.Schema.Required, k))
|
||||
if sg.Schema.Discriminator == k {
|
||||
tpe.IsNullable = false
|
||||
}
|
||||
tpe, err := sg.TypeResolver.ResolveSchema(&vv, true, sg.IsTuple || swag.ContainsStrings(sg.Schema.Required, k))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sg.Schema.Discriminator == k {
|
||||
tpe.IsNullable = false
|
||||
}
|
||||
|
||||
vv := v
|
||||
var hasValidation bool
|
||||
if tpe.IsComplexObject && tpe.IsAnonymous && len(v.Properties) > 0 {
|
||||
// this is an anonymous complex construct: build a new new type for it
|
||||
|
@ -904,8 +906,13 @@ func (sg *schemaGenContext) buildProperties() error {
|
|||
emprop.GenSchema.Extensions = emprop.Schema.Extensions
|
||||
|
||||
// set custom serializer tag
|
||||
if customTag, found := emprop.Schema.Extensions[xGoCustomTag]; found {
|
||||
emprop.GenSchema.CustomTag = customTag.(string)
|
||||
if customTag, found := tpe.Extensions[xGoCustomTag]; found {
|
||||
tagAsStr, ok := customTag.(string)
|
||||
if ok {
|
||||
emprop.GenSchema.CustomTag = tagAsStr
|
||||
} else {
|
||||
log.Printf("warning: expect %s extension to be a string, got: %v. Skipped", xGoCustomTag, customTag)
|
||||
}
|
||||
}
|
||||
sg.GenSchema.Properties = append(sg.GenSchema.Properties, emprop.GenSchema)
|
||||
}
|
||||
|
@ -926,7 +933,8 @@ func (sg *schemaGenContext) buildAllOf() error {
|
|||
sg.Container = sg.Name
|
||||
}
|
||||
debugLogAsJSON("building all of for %d entries", len(sg.Schema.AllOf), sg.Schema)
|
||||
for i, sch := range sg.Schema.AllOf {
|
||||
for i, schema := range sg.Schema.AllOf {
|
||||
sch := schema
|
||||
tpe, ert := sg.TypeResolver.ResolveSchema(&sch, sch.Ref.String() == "", false)
|
||||
if ert != nil {
|
||||
return ert
|
||||
|
@ -1006,7 +1014,12 @@ func (sg *schemaGenContext) buildAllOf() error {
|
|||
log.Printf("warning: cannot generate serializable allOf with conflicting array definitions in %s", sg.Container)
|
||||
}
|
||||
|
||||
sg.GenSchema.IsNullable = true
|
||||
// AllOf types are always considered nullable, except when an extension says otherwise
|
||||
if override, ok := sg.TypeResolver.isNullableOverride(&sg.Schema); ok {
|
||||
sg.GenSchema.IsNullable = override
|
||||
} else {
|
||||
sg.GenSchema.IsNullable = true
|
||||
}
|
||||
|
||||
// prevent IsAliased to bubble up (e.g. when a single branch is itself aliased)
|
||||
sg.GenSchema.IsAliased = sg.GenSchema.IsAliased && len(sg.GenSchema.AllOf) < 2
|
||||
|
@ -1037,7 +1050,7 @@ func newMapStack(context *schemaGenContext) (first, last *mapStack, err error) {
|
|||
}
|
||||
|
||||
if !tpe.IsMap {
|
||||
//reached the end of the rabbit hole
|
||||
// reached the end of the rabbit hole
|
||||
if tpe.IsComplexObject && tpe.IsAnonymous {
|
||||
// found an anonymous object: create the struct from a newly created definition
|
||||
nw := l.Context.makeNewStruct(l.Context.makeRefName()+" Anon", *l.Type.AdditionalProperties.Schema)
|
||||
|
@ -1047,6 +1060,7 @@ func newMapStack(context *schemaGenContext) (first, last *mapStack, err error) {
|
|||
l.Type.AdditionalProperties.Schema = sch
|
||||
l.ValueRef = l.Context.NewAdditionalProperty(*sch)
|
||||
}
|
||||
|
||||
// other cases where to stop are: a $ref or a simple object
|
||||
break
|
||||
}
|
||||
|
@ -1060,7 +1074,7 @@ func newMapStack(context *schemaGenContext) (first, last *mapStack, err error) {
|
|||
l = l.Next
|
||||
}
|
||||
|
||||
//return top and bottom entries of this stack of AdditionalProperties
|
||||
// return top and bottom entries of this stack of AdditionalProperties
|
||||
return ms, l, nil
|
||||
}
|
||||
|
||||
|
@ -1442,7 +1456,7 @@ func (sg *schemaGenContext) buildArray() error {
|
|||
// items from maps of aliased or nullable type remain required
|
||||
|
||||
// NOTE(fredbi): since this is reset below, this Required = true serves the obscure purpose
|
||||
// of indirectly lifting validations from the slice. This is carried on differently now.
|
||||
// of indirectly lifting validations from the slice. This is carried out differently now.
|
||||
// elProp.Required = true
|
||||
|
||||
if err := elProp.makeGenSchema(); err != nil {
|
||||
|
@ -1484,7 +1498,7 @@ func (sg *schemaGenContext) buildArray() error {
|
|||
|
||||
// lift validations
|
||||
sg.GenSchema.HasValidations = sg.GenSchema.HasValidations || schemaCopy.HasValidations
|
||||
sg.GenSchema.HasSliceValidations = hasSliceValidations(&sg.Schema)
|
||||
sg.GenSchema.HasSliceValidations = sg.Schema.Validations().HasArrayValidations() || sg.Schema.Validations().HasEnum()
|
||||
|
||||
// prevents bubbling custom formatter flag
|
||||
sg.GenSchema.IsCustomFormatter = false
|
||||
|
@ -1516,7 +1530,8 @@ func (sg *schemaGenContext) buildItems() error {
|
|||
if sg.Named {
|
||||
sg.GenSchema.Name = sg.Name
|
||||
sg.GenSchema.GoType = sg.TypeResolver.goTypeName(sg.Name)
|
||||
for i, s := range sg.Schema.Items.Schemas {
|
||||
for i, sch := range sg.Schema.Items.Schemas {
|
||||
s := sch
|
||||
elProp := sg.NewTupleElement(&s, i)
|
||||
|
||||
if s.Ref.String() == "" {
|
||||
|
@ -1630,7 +1645,11 @@ func (sg *schemaGenContext) buildAdditionalItems() error {
|
|||
}
|
||||
|
||||
func (sg *schemaGenContext) buildXMLNameWithTags() error {
|
||||
if sg.WithXML || sg.Schema.XML != nil {
|
||||
// render some "xml" struct tag under one the following conditions:
|
||||
// - consumes/produces in spec contains xml
|
||||
// - struct tags CLI option contains xml
|
||||
// - XML object present in spec for this schema
|
||||
if sg.WithXML || swag.ContainsStrings(sg.StructTags, "xml") || sg.Schema.XML != nil {
|
||||
sg.GenSchema.XMLName = sg.Name
|
||||
|
||||
if sg.Schema.XML != nil {
|
||||
|
@ -1641,10 +1660,6 @@ func (sg *schemaGenContext) buildXMLNameWithTags() error {
|
|||
sg.GenSchema.XMLName += ",attr"
|
||||
}
|
||||
}
|
||||
|
||||
if !sg.GenSchema.Required && sg.GenSchema.IsEmptyOmitted {
|
||||
sg.GenSchema.XMLName += ",omitempty"
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -1730,7 +1745,7 @@ func (sg *schemaGenContext) shortCircuitNamedRef() (bool, error) {
|
|||
tpe.IsMap = false
|
||||
tpe.IsArray = false
|
||||
tpe.IsAnonymous = false
|
||||
tpe.IsNullable = sg.TypeResolver.IsNullable(&sg.Schema)
|
||||
tpe.IsNullable = sg.TypeResolver.isNullable(&sg.Schema)
|
||||
|
||||
item := sg.NewCompositionBranch(sg.Schema, 0)
|
||||
if err := item.makeGenSchema(); err != nil {
|
||||
|
@ -1759,13 +1774,13 @@ func (sg *schemaGenContext) liftSpecialAllOf() error {
|
|||
var seenNullable bool
|
||||
var schemaToLift spec.Schema
|
||||
|
||||
for _, sch := range sg.Schema.AllOf {
|
||||
|
||||
for _, schema := range sg.Schema.AllOf {
|
||||
sch := schema
|
||||
tpe, err := sg.TypeResolver.ResolveSchema(&sch, true, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sg.TypeResolver.IsNullable(&sch) {
|
||||
if sg.TypeResolver.isNullable(&sch) {
|
||||
seenNullable = true
|
||||
}
|
||||
if len(sch.Type) > 0 || len(sch.Properties) > 0 || sch.Ref.GetURL() != nil || len(sch.AllOf) > 0 {
|
||||
|
@ -1839,6 +1854,21 @@ func goName(sch *spec.Schema, orig string) string {
|
|||
return orig
|
||||
}
|
||||
|
||||
func (sg *schemaGenContext) derefMapElement(outer *GenSchema, sch *GenSchema, elem *GenSchema) {
|
||||
derefType := strings.TrimPrefix(elem.GoType, "*")
|
||||
|
||||
if outer.IsAliased {
|
||||
nesting := strings.TrimSuffix(strings.TrimSuffix(outer.AliasedType, elem.GoType), "*")
|
||||
outer.AliasedType = nesting + derefType
|
||||
outer.GoType = derefType
|
||||
} else {
|
||||
nesting := strings.TrimSuffix(strings.TrimSuffix(outer.GoType, elem.GoType), "*")
|
||||
outer.GoType = nesting + derefType
|
||||
}
|
||||
|
||||
elem.GoType = derefType
|
||||
}
|
||||
|
||||
func (sg *schemaGenContext) checkNeedsPointer(outer *GenSchema, sch *GenSchema, elem *GenSchema) {
|
||||
derefType := strings.TrimPrefix(elem.GoType, "*")
|
||||
switch {
|
||||
|
@ -1876,10 +1906,21 @@ func (sg *schemaGenContext) buildMapOfNullable(sch *GenSchema) {
|
|||
// render element of aliased or anonyous map as a pointer
|
||||
it := elem.Items
|
||||
for it != nil {
|
||||
if it.IsPrimitive && it.IsNullable {
|
||||
switch {
|
||||
case it.IsPrimitive && it.IsNullable:
|
||||
sg.checkNeedsPointer(outer, sch, it)
|
||||
} else if it.IsMap {
|
||||
case it.IsMap:
|
||||
sg.buildMapOfNullable(it)
|
||||
case !it.IsPrimitive && !it.IsArray && it.IsComplexObject && it.IsNullable:
|
||||
// structs in map are not rendered as pointer by default
|
||||
// unless some x-nullable overrides says so
|
||||
_, forced := it.Extensions[xNullable]
|
||||
if !forced {
|
||||
_, forced = it.Extensions[xIsNullable]
|
||||
}
|
||||
if !forced {
|
||||
sg.derefMapElement(outer, sch, it)
|
||||
}
|
||||
}
|
||||
it = it.Items
|
||||
}
|
||||
|
@ -1893,12 +1934,18 @@ func (sg *schemaGenContext) makeGenSchema() error {
|
|||
debugLogAsJSON("making gen schema (anon: %t, req: %t, tuple: %t) %s\n",
|
||||
!sg.Named, sg.Required, sg.IsTuple, sg.Name, sg.Schema)
|
||||
|
||||
ex := ""
|
||||
sg.GenSchema.Example = ""
|
||||
if sg.Schema.Example != nil {
|
||||
ex = fmt.Sprintf("%#v", sg.Schema.Example)
|
||||
data, err := asJSON(sg.Schema.Example)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Deleting the unnecessary double quotes for string types
|
||||
// otherwise the generate spec will generate as "\"foo\""
|
||||
sg.GenSchema.Example = strings.Trim(data, "\"")
|
||||
}
|
||||
sg.GenSchema.ExternalDocs = trimExternalDoc(sg.Schema.ExternalDocs)
|
||||
sg.GenSchema.IsExported = true
|
||||
sg.GenSchema.Example = ex
|
||||
sg.GenSchema.Path = sg.Path
|
||||
sg.GenSchema.IndexVar = sg.IndexVar
|
||||
sg.GenSchema.Location = body
|
||||
|
@ -1960,12 +2007,37 @@ func (sg *schemaGenContext) makeGenSchema() error {
|
|||
// include format validations, excluding binary
|
||||
sg.GenSchema.HasValidations = sg.GenSchema.HasValidations || hasFormatValidation(tpe)
|
||||
|
||||
// include context validations
|
||||
sg.GenSchema.HasContextValidations = sg.GenSchema.HasContextValidations || hasContextValidations(&sg.Schema) && !tpe.IsInterface && !tpe.IsStream && !tpe.SkipExternalValidation
|
||||
|
||||
// usage of a polymorphic base type is rendered with getter funcs on private properties.
|
||||
// In the case of aliased types, the value expression remains unchanged to the receiver.
|
||||
if tpe.IsArray && tpe.ElemType != nil && tpe.ElemType.IsBaseType && sg.GenSchema.ValueExpression != sg.GenSchema.ReceiverName {
|
||||
sg.GenSchema.ValueExpression += asMethod
|
||||
}
|
||||
|
||||
if tpe.IsExternal { // anonymous external types
|
||||
extType, pkg, alias := sg.TypeResolver.knownDefGoType(sg.GenSchema.Name, sg.Schema, sg.TypeResolver.goTypeName)
|
||||
if pkg != "" && alias != "" {
|
||||
sg.GenSchema.ExtraImports[alias] = pkg
|
||||
}
|
||||
|
||||
if !tpe.IsEmbedded {
|
||||
sg.GenSchema.resolvedType = tpe
|
||||
sg.GenSchema.Required = sg.Required
|
||||
// assume we validate everything but interface and io.Reader - validation may be disabled by using the noValidation hint
|
||||
sg.GenSchema.HasValidations = !(tpe.IsInterface || tpe.IsStream || tpe.SkipExternalValidation)
|
||||
sg.GenSchema.IsAliased = sg.GenSchema.HasValidations
|
||||
|
||||
log.Printf("INFO: type %s is external, with inferred spec type %s, referred to as %s", sg.GenSchema.Name, sg.GenSchema.GoType, extType)
|
||||
sg.GenSchema.GoType = extType
|
||||
sg.GenSchema.AliasedType = extType
|
||||
return nil
|
||||
}
|
||||
// TODO: case for embedded types as anonymous definitions
|
||||
return fmt.Errorf("ERROR: inline definitions embedded types are not supported")
|
||||
}
|
||||
|
||||
debugLog("gschema nullable: %t", sg.GenSchema.IsNullable)
|
||||
if e := sg.buildAdditionalProperties(); e != nil {
|
||||
return e
|
||||
|
|
184
vendor/github.com/go-swagger/go-swagger/generator/operation.go
generated
vendored
184
vendor/github.com/go-swagger/go-swagger/generator/operation.go
generated
vendored
|
@ -193,7 +193,8 @@ func (o *operationGenerator) Generate() error {
|
|||
operations = append(operations, op)
|
||||
sort.Sort(operations)
|
||||
|
||||
for _, op := range operations {
|
||||
for _, pp := range operations {
|
||||
op := pp
|
||||
if o.GenOpts.DumpData {
|
||||
_ = dumpData(swag.ToDynamicJSON(op))
|
||||
continue
|
||||
|
@ -312,7 +313,7 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
//
|
||||
// In all cases, resetting definitions to the _original_ (untransformed) spec is not an option:
|
||||
// we take from there the spec possibly already transformed by the GenDefinitions stage.
|
||||
resolver := newTypeResolver(b.GenOpts.LanguageOpts.ManglePackageName(b.ModelsPackage, defaultModelsTarget), b.Doc)
|
||||
resolver := newTypeResolver(b.GenOpts.LanguageOpts.ManglePackageName(b.ModelsPackage, defaultModelsTarget), b.DefaultImports[b.ModelsPackage], b.Doc)
|
||||
receiver := "o"
|
||||
|
||||
operation := b.Operation
|
||||
|
@ -399,6 +400,7 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
defaultResponse = &gr
|
||||
}
|
||||
}
|
||||
|
||||
// Always render a default response, even when no responses were defined
|
||||
if operation.Responses == nil || (operation.Responses.Default == nil && len(srs) == 0) {
|
||||
gr, err := b.MakeResponse(receiver, b.Name+" default", false, resolver, -1, spec.Response{})
|
||||
|
@ -408,44 +410,41 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
defaultResponse = &gr
|
||||
}
|
||||
|
||||
if b.Principal == "" {
|
||||
b.Principal = iface
|
||||
}
|
||||
|
||||
swsp := resolver.Doc.Spec()
|
||||
var extraSchemes []string
|
||||
if ess, ok := operation.Extensions.GetStringSlice(xSchemes); ok {
|
||||
extraSchemes = append(extraSchemes, ess...)
|
||||
}
|
||||
|
||||
if ess1, ok := swsp.Extensions.GetStringSlice(xSchemes); ok {
|
||||
extraSchemes = concatUnique(ess1, extraSchemes)
|
||||
}
|
||||
sort.Strings(extraSchemes)
|
||||
schemes := concatUnique(swsp.Schemes, operation.Schemes)
|
||||
sort.Strings(schemes)
|
||||
schemes, extraSchemes := gatherURISchemes(swsp, operation)
|
||||
originalSchemes := operation.Schemes
|
||||
originalExtraSchemes := getExtraSchemes(operation.Extensions)
|
||||
|
||||
produces := producesOrDefault(operation.Produces, swsp.Produces, b.DefaultProduces)
|
||||
sort.Strings(produces)
|
||||
|
||||
consumes := producesOrDefault(operation.Consumes, swsp.Consumes, b.DefaultConsumes)
|
||||
sort.Strings(consumes)
|
||||
|
||||
var hasStreamingResponse bool
|
||||
if defaultResponse != nil && defaultResponse.Schema != nil && defaultResponse.Schema.IsStream {
|
||||
hasStreamingResponse = true
|
||||
}
|
||||
var successResponse *GenResponse
|
||||
for _, sr := range successResponses {
|
||||
for _, resp := range successResponses {
|
||||
sr := resp
|
||||
if sr.IsSuccess {
|
||||
successResponse = &sr
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, sr := range successResponses {
|
||||
if !hasStreamingResponse && sr.Schema != nil && sr.Schema.IsStream {
|
||||
hasStreamingResponse = true
|
||||
break
|
||||
|
||||
var hasStreamingResponse bool
|
||||
if defaultResponse != nil && defaultResponse.Schema != nil && defaultResponse.Schema.IsStream {
|
||||
hasStreamingResponse = true
|
||||
}
|
||||
|
||||
if !hasStreamingResponse {
|
||||
for _, sr := range successResponses {
|
||||
if !hasStreamingResponse && sr.Schema != nil && sr.Schema.IsStream {
|
||||
hasStreamingResponse = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !hasStreamingResponse {
|
||||
for _, r := range responses {
|
||||
if r.Schema != nil && r.Schema.IsStream {
|
||||
|
@ -488,8 +487,9 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
HasBodyParams: hasBodyParams,
|
||||
HasStreamingResponse: hasStreamingResponse,
|
||||
Authorized: b.Authed,
|
||||
Security: b.makeSecurityRequirements(receiver),
|
||||
Security: b.makeSecurityRequirements(receiver), // resolved security requirements, for codegen
|
||||
SecurityDefinitions: b.makeSecuritySchemes(receiver),
|
||||
SecurityRequirements: securityRequirements(operation.Security), // raw security requirements, for doc
|
||||
Principal: b.Principal,
|
||||
Responses: responses,
|
||||
DefaultResponse: defaultResponse,
|
||||
|
@ -497,12 +497,19 @@ func (b *codeGenOpBuilder) MakeOperation() (GenOperation, error) {
|
|||
SuccessResponses: successResponses,
|
||||
ExtraSchemas: gatherExtraSchemas(b.ExtraSchemas),
|
||||
Schemes: schemeOrDefault(schemes, b.DefaultScheme),
|
||||
ProducesMediaTypes: produces,
|
||||
ConsumesMediaTypes: consumes,
|
||||
ExtraSchemes: extraSchemes,
|
||||
SchemeOverrides: originalSchemes, // raw operation schemes, for doc
|
||||
ProducesMediaTypes: produces, // resolved produces, for codegen
|
||||
ConsumesMediaTypes: consumes, // resolved consumes, for codegen
|
||||
Produces: operation.Produces, // for doc
|
||||
Consumes: operation.Consumes, // for doc
|
||||
ExtraSchemes: extraSchemes, // resolved schemes, for codegen
|
||||
ExtraSchemeOverrides: originalExtraSchemes, // raw operation extra schemes, for doc
|
||||
TimeoutName: timeoutName,
|
||||
Extensions: operation.Extensions,
|
||||
StrictResponders: b.GenOpts.StrictResponders,
|
||||
|
||||
PrincipalIsNullable: b.GenOpts.PrincipalIsNullable(),
|
||||
ExternalDocs: trimExternalDoc(operation.ExternalDocs),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -523,26 +530,15 @@ func schemeOrDefault(schemes []string, defaultScheme string) []string {
|
|||
return schemes
|
||||
}
|
||||
|
||||
func concatUnique(collections ...[]string) []string {
|
||||
resultSet := make(map[string]struct{})
|
||||
for _, c := range collections {
|
||||
for _, i := range c {
|
||||
if _, ok := resultSet[i]; !ok {
|
||||
resultSet[i] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
var result []string
|
||||
for k := range resultSet {
|
||||
result = append(result, k)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (b *codeGenOpBuilder) MakeResponse(receiver, name string, isSuccess bool, resolver *typeResolver, code int, resp spec.Response) (GenResponse, error) {
|
||||
debugLog("[%s %s] making id %q", b.Method, b.Path, b.Operation.ID)
|
||||
|
||||
// assume minimal flattening has been carried on, so there is not $ref in response (but some may remain in response schema)
|
||||
examples := make(GenResponseExamples, 0, len(resp.Examples))
|
||||
for k, v := range resp.Examples {
|
||||
examples = append(examples, GenResponseExample{MediaType: k, Example: v})
|
||||
}
|
||||
sort.Sort(examples)
|
||||
|
||||
res := GenResponse{
|
||||
Package: b.GenOpts.LanguageOpts.ManglePackageName(b.APIPackage, defaultOperationsTarget),
|
||||
|
@ -559,6 +555,7 @@ func (b *codeGenOpBuilder) MakeResponse(receiver, name string, isSuccess bool, r
|
|||
Extensions: resp.Extensions,
|
||||
StrictResponders: b.GenOpts.StrictResponders,
|
||||
OperationName: b.Name,
|
||||
Examples: examples,
|
||||
}
|
||||
|
||||
// prepare response headers
|
||||
|
@ -583,26 +580,29 @@ func (b *codeGenOpBuilder) MakeResponse(receiver, name string, isSuccess bool, r
|
|||
}
|
||||
|
||||
func (b *codeGenOpBuilder) MakeHeader(receiver, name string, hdr spec.Header) (GenHeader, error) {
|
||||
tpe := typeForHeader(hdr) //simpleResolvedType(hdr.Type, hdr.Format, hdr.Items)
|
||||
tpe := simpleResolvedType(hdr.Type, hdr.Format, hdr.Items, &hdr.CommonValidations)
|
||||
|
||||
id := swag.ToGoName(name)
|
||||
res := GenHeader{
|
||||
sharedValidations: sharedValidationsFromSimple(hdr.CommonValidations, true), // NOTE: Required is not defined by the Swagger schema for header. Set arbitrarily to true for convenience in templates.
|
||||
resolvedType: tpe,
|
||||
Package: b.GenOpts.LanguageOpts.ManglePackageName(b.APIPackage, defaultOperationsTarget),
|
||||
ReceiverName: receiver,
|
||||
ID: id,
|
||||
Name: name,
|
||||
Path: fmt.Sprintf("%q", name),
|
||||
ValueExpression: fmt.Sprintf("%s.%s", receiver, id),
|
||||
Description: trimBOM(hdr.Description),
|
||||
Default: hdr.Default,
|
||||
HasDefault: hdr.Default != nil,
|
||||
Converter: stringConverters[tpe.GoType],
|
||||
Formatter: stringFormatters[tpe.GoType],
|
||||
ZeroValue: tpe.Zero(),
|
||||
CollectionFormat: hdr.CollectionFormat,
|
||||
IndexVar: "i",
|
||||
sharedValidations: sharedValidations{
|
||||
Required: true,
|
||||
SchemaValidations: hdr.Validations(), // NOTE: Required is not defined by the Swagger schema for header. Set arbitrarily to true for convenience in templates.
|
||||
},
|
||||
resolvedType: tpe,
|
||||
Package: b.GenOpts.LanguageOpts.ManglePackageName(b.APIPackage, defaultOperationsTarget),
|
||||
ReceiverName: receiver,
|
||||
ID: id,
|
||||
Name: name,
|
||||
Path: fmt.Sprintf("%q", name),
|
||||
ValueExpression: fmt.Sprintf("%s.%s", receiver, id),
|
||||
Description: trimBOM(hdr.Description),
|
||||
Default: hdr.Default,
|
||||
HasDefault: hdr.Default != nil,
|
||||
Converter: stringConverters[tpe.GoType],
|
||||
Formatter: stringFormatters[tpe.GoType],
|
||||
ZeroValue: tpe.Zero(),
|
||||
CollectionFormat: hdr.CollectionFormat,
|
||||
IndexVar: "i",
|
||||
}
|
||||
res.HasValidations, res.HasSliceValidations = b.HasValidations(hdr.CommonValidations, res.resolvedType)
|
||||
|
||||
|
@ -625,8 +625,12 @@ func (b *codeGenOpBuilder) MakeHeader(receiver, name string, hdr spec.Header) (G
|
|||
|
||||
func (b *codeGenOpBuilder) MakeHeaderItem(receiver, paramName, indexVar, path, valueExpression string, items, parent *spec.Items) (GenItems, error) {
|
||||
var res GenItems
|
||||
res.resolvedType = simpleResolvedType(items.Type, items.Format, items.Items)
|
||||
res.sharedValidations = sharedValidationsFromSimple(items.CommonValidations, false)
|
||||
res.resolvedType = simpleResolvedType(items.Type, items.Format, items.Items, &items.CommonValidations)
|
||||
|
||||
res.sharedValidations = sharedValidations{
|
||||
Required: false,
|
||||
SchemaValidations: items.Validations(),
|
||||
}
|
||||
res.Name = paramName
|
||||
res.Path = path
|
||||
res.Location = "header"
|
||||
|
@ -656,18 +660,20 @@ func (b *codeGenOpBuilder) MakeHeaderItem(receiver, paramName, indexVar, path, v
|
|||
|
||||
// HasValidations resolves the validation status for simple schema objects
|
||||
func (b *codeGenOpBuilder) HasValidations(sh spec.CommonValidations, rt resolvedType) (hasValidations bool, hasSliceValidations bool) {
|
||||
hasNumberValidation := sh.Maximum != nil || sh.Minimum != nil || sh.MultipleOf != nil
|
||||
hasStringValidation := sh.MaxLength != nil || sh.MinLength != nil || sh.Pattern != ""
|
||||
hasSliceValidations = sh.MaxItems != nil || sh.MinItems != nil || sh.UniqueItems || len(sh.Enum) > 0
|
||||
hasValidations = hasNumberValidation || hasStringValidation || hasSliceValidations || hasFormatValidation(rt)
|
||||
hasSliceValidations = sh.HasArrayValidations() || sh.HasEnum()
|
||||
hasValidations = sh.HasNumberValidations() || sh.HasStringValidations() || hasSliceValidations || hasFormatValidation(rt)
|
||||
return
|
||||
}
|
||||
|
||||
func (b *codeGenOpBuilder) MakeParameterItem(receiver, paramName, indexVar, path, valueExpression, location string, resolver *typeResolver, items, parent *spec.Items) (GenItems, error) {
|
||||
debugLog("making parameter item recv=%s param=%s index=%s valueExpr=%s path=%s location=%s", receiver, paramName, indexVar, valueExpression, path, location)
|
||||
var res GenItems
|
||||
res.resolvedType = simpleResolvedType(items.Type, items.Format, items.Items)
|
||||
res.sharedValidations = sharedValidationsFromSimple(items.CommonValidations, false)
|
||||
res.resolvedType = simpleResolvedType(items.Type, items.Format, items.Items, &items.CommonValidations)
|
||||
|
||||
res.sharedValidations = sharedValidations{
|
||||
Required: false,
|
||||
SchemaValidations: items.Validations(),
|
||||
}
|
||||
res.Name = paramName
|
||||
res.Path = path
|
||||
res.Location = location
|
||||
|
@ -741,8 +747,11 @@ func (b *codeGenOpBuilder) MakeParameter(receiver string, resolver *typeResolver
|
|||
}
|
||||
} else {
|
||||
// Process parameters declared in other inputs: path, query, header (SimpleSchema)
|
||||
res.resolvedType = simpleResolvedType(param.Type, param.Format, param.Items)
|
||||
res.sharedValidations = sharedValidationsFromSimple(param.CommonValidations, param.Required)
|
||||
res.resolvedType = simpleResolvedType(param.Type, param.Format, param.Items, ¶m.CommonValidations)
|
||||
res.sharedValidations = sharedValidations{
|
||||
Required: param.Required,
|
||||
SchemaValidations: param.Validations(),
|
||||
}
|
||||
|
||||
res.ZeroValue = res.resolvedType.Zero()
|
||||
|
||||
|
@ -960,7 +969,7 @@ func (b *codeGenOpBuilder) setBodyParamValidation(p *GenParameter) {
|
|||
|
||||
// makeSecuritySchemes produces a sorted list of security schemes for this operation
|
||||
func (b *codeGenOpBuilder) makeSecuritySchemes(receiver string) GenSecuritySchemes {
|
||||
return gatherSecuritySchemes(b.SecurityDefinitions, b.Name, b.Principal, receiver)
|
||||
return gatherSecuritySchemes(b.SecurityDefinitions, b.Name, b.Principal, receiver, b.GenOpts.PrincipalIsNullable())
|
||||
}
|
||||
|
||||
// makeSecurityRequirements produces a sorted list of security requirements for this operation.
|
||||
|
@ -1006,7 +1015,7 @@ func (b *codeGenOpBuilder) saveResolveContext(resolver *typeResolver, schema *sp
|
|||
if b.PristineDoc == nil {
|
||||
b.PristineDoc = b.Doc.Pristine()
|
||||
}
|
||||
rslv := newTypeResolver(b.GenOpts.LanguageOpts.ManglePackageName(resolver.ModelsPackage, defaultModelsTarget), b.PristineDoc)
|
||||
rslv := newTypeResolver(b.GenOpts.LanguageOpts.ManglePackageName(resolver.ModelsPackage, defaultModelsTarget), b.DefaultImports[b.ModelsPackage], b.PristineDoc)
|
||||
|
||||
return rslv, b.cloneSchema(schema)
|
||||
}
|
||||
|
@ -1026,7 +1035,7 @@ func (b *codeGenOpBuilder) liftExtraSchemas(resolver, rslv *typeResolver, bs *sp
|
|||
pkg := b.GenOpts.LanguageOpts.ManglePackageName(resolver.ModelsPackage, defaultModelsTarget)
|
||||
|
||||
// make a resolver for current package (i.e. operations)
|
||||
pg.TypeResolver = newTypeResolver("", rslv.Doc).withKeepDefinitionsPackage(pkg)
|
||||
pg.TypeResolver = newTypeResolver("", b.DefaultImports[b.APIPackage], rslv.Doc).withKeepDefinitionsPackage(pkg)
|
||||
pg.ExtraSchemas = make(map[string]GenSchema, len(sc.ExtraSchemas))
|
||||
pg.UseContainerInName = true
|
||||
|
||||
|
@ -1062,7 +1071,10 @@ func (b *codeGenOpBuilder) buildOperationSchema(schemaPath, containerName, schem
|
|||
if sch == nil {
|
||||
sch = &spec.Schema{}
|
||||
}
|
||||
rslv := resolver
|
||||
shallowClonedResolver := *resolver
|
||||
shallowClonedResolver.ModelsFullPkg = b.DefaultImports[b.ModelsPackage]
|
||||
rslv := &shallowClonedResolver
|
||||
|
||||
sc := schemaGenContext{
|
||||
Path: schemaPath,
|
||||
Name: containerName,
|
||||
|
@ -1203,7 +1215,7 @@ func (b *codeGenOpBuilder) analyzeTags() (string, []string, bool) {
|
|||
}
|
||||
}
|
||||
if tag == b.APIPackage {
|
||||
// confict with "operations" package is handled separately
|
||||
// conflict with "operations" package is handled separately
|
||||
tag = renameOperationPackage(intersected, tag)
|
||||
}
|
||||
b.APIPackage = b.GenOpts.LanguageOpts.ManglePackageName(tag, b.APIPackage) // actual package name
|
||||
|
@ -1238,11 +1250,14 @@ func deconflictPrincipal(pkg string) string {
|
|||
// deconflictPkg renames package names which conflict with standard imports
|
||||
func deconflictPkg(pkg string, renamer func(string) string) string {
|
||||
switch pkg {
|
||||
case "api", "httptransport", "formats":
|
||||
// package conflict with variables
|
||||
case "api", "httptransport", "formats", "server":
|
||||
fallthrough
|
||||
// package conflict with go-openapi imports
|
||||
case "errors", "runtime", "middleware", "security", "spec", "strfmt", "loads", "swag", "validate":
|
||||
fallthrough
|
||||
case "tls", "http", "fmt", "strings", "log":
|
||||
// package conflict with stdlib/other lib imports
|
||||
case "tls", "http", "fmt", "strings", "log", "flags", "pflag", "json", "time":
|
||||
return renamer(pkg)
|
||||
}
|
||||
return pkg
|
||||
|
@ -1260,5 +1275,16 @@ func renameOperationPackage(seenTags []string, pkg string) string {
|
|||
}
|
||||
|
||||
func renamePrincipalPackage(pkg string) string {
|
||||
// favors readability over perfect deconfliction
|
||||
return "auth"
|
||||
}
|
||||
|
||||
func renameServerPackage(pkg string) string {
|
||||
// favors readability over perfect deconfliction
|
||||
return "swagger" + pkg + "srv"
|
||||
}
|
||||
|
||||
func renameAPIPackage(pkg string) string {
|
||||
// favors readability over perfect deconfliction
|
||||
return "swagger" + pkg
|
||||
}
|
||||
|
|
187
vendor/github.com/go-swagger/go-swagger/generator/shared.go
generated
vendored
187
vendor/github.com/go-swagger/go-swagger/generator/shared.go
generated
vendored
|
@ -197,6 +197,29 @@ func DefaultSectionOpts(gen *GenOpts) {
|
|||
|
||||
}
|
||||
|
||||
// MarkdownOpts for rendering a spec as markdown
|
||||
func MarkdownOpts() *LanguageOpts {
|
||||
opts := &LanguageOpts{}
|
||||
opts.Init()
|
||||
return opts
|
||||
}
|
||||
|
||||
// MarkdownSectionOpts for a given opts and output file.
|
||||
func MarkdownSectionOpts(gen *GenOpts, output string) {
|
||||
gen.Sections.Models = nil
|
||||
gen.Sections.OperationGroups = nil
|
||||
gen.Sections.Operations = nil
|
||||
gen.LanguageOpts = MarkdownOpts()
|
||||
gen.Sections.Application = []TemplateOpts{
|
||||
{
|
||||
Name: "markdowndocs",
|
||||
Source: "asset:markdownDocs",
|
||||
Target: filepath.Dir(output),
|
||||
FileName: filepath.Base(output),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TemplateOpts allows for codegen customization
|
||||
type TemplateOpts struct {
|
||||
Name string `mapstructure:"name"`
|
||||
|
@ -241,6 +264,7 @@ type GenOpts struct {
|
|||
ServerPackage string
|
||||
ClientPackage string
|
||||
Principal string
|
||||
PrincipalCustomIface bool // user-provided interface for Principal (non-nullable)
|
||||
Target string
|
||||
Sections SectionOpts
|
||||
LanguageOpts *LanguageOpts
|
||||
|
@ -268,6 +292,8 @@ type GenOpts struct {
|
|||
AllowEnumCI bool
|
||||
StrictResponders bool
|
||||
AcceptDefinitionsOnly bool
|
||||
|
||||
templates *Repository // a shallow clone of the global template repository
|
||||
}
|
||||
|
||||
// CheckOpts carries out some global consistency checks on options.
|
||||
|
@ -362,12 +388,23 @@ func (g *GenOpts) SpecPath() string {
|
|||
return specRel
|
||||
}
|
||||
|
||||
// PrincipalIsNullable indicates whether the principal type used for authentication
|
||||
// may be used as a pointer
|
||||
func (g *GenOpts) PrincipalIsNullable() bool {
|
||||
debugLog("Principal: %s, %t, isnullable: %t", g.Principal, g.PrincipalCustomIface, g.Principal != iface && !g.PrincipalCustomIface)
|
||||
return g.Principal != iface && !g.PrincipalCustomIface
|
||||
}
|
||||
|
||||
// EnsureDefaults for these gen opts
|
||||
func (g *GenOpts) EnsureDefaults() error {
|
||||
if g.defaultsEnsured {
|
||||
return nil
|
||||
}
|
||||
|
||||
g.templates = templates.ShallowClone()
|
||||
|
||||
g.templates.LoadDefaults()
|
||||
|
||||
if g.LanguageOpts == nil {
|
||||
g.LanguageOpts = DefaultLanguageFunc()
|
||||
}
|
||||
|
@ -401,6 +438,7 @@ func (g *GenOpts) EnsureDefaults() error {
|
|||
|
||||
if g.Principal == "" {
|
||||
g.Principal = iface
|
||||
g.PrincipalCustomIface = false
|
||||
}
|
||||
|
||||
g.defaultsEnsured = true
|
||||
|
@ -426,7 +464,9 @@ func (g *GenOpts) location(t *TemplateOpts, data interface{}) (string, string, e
|
|||
var tags []string
|
||||
tagsF := v.FieldByName("Tags")
|
||||
if tagsF.IsValid() {
|
||||
tags = tagsF.Interface().([]string)
|
||||
if tt, ok := tagsF.Interface().([]string); ok {
|
||||
tags = tt
|
||||
}
|
||||
}
|
||||
|
||||
var useTags bool
|
||||
|
@ -482,7 +522,7 @@ func (g *GenOpts) render(t *TemplateOpts, data interface{}) ([]byte, error) {
|
|||
var templ *template.Template
|
||||
|
||||
if strings.HasPrefix(strings.ToLower(t.Source), "asset:") {
|
||||
tt, err := templates.Get(strings.TrimPrefix(t.Source, "asset:"))
|
||||
tt, err := g.templates.Get(strings.TrimPrefix(t.Source, "asset:"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -492,7 +532,7 @@ func (g *GenOpts) render(t *TemplateOpts, data interface{}) ([]byte, error) {
|
|||
if templ == nil {
|
||||
// try to load from repository (and enable dependencies)
|
||||
name := swag.ToJSONName(strings.TrimSuffix(t.Source, ".gotmpl"))
|
||||
tt, err := templates.Get(name)
|
||||
tt, err := g.templates.Get(name)
|
||||
if err == nil {
|
||||
templ = tt
|
||||
}
|
||||
|
@ -611,7 +651,8 @@ func (g *GenOpts) shouldRenderOperations() bool {
|
|||
|
||||
func (g *GenOpts) renderApplication(app *GenApp) error {
|
||||
log.Printf("rendering %d templates for application %s", len(g.Sections.Application), app.Name)
|
||||
for _, templ := range g.Sections.Application {
|
||||
for _, tp := range g.Sections.Application {
|
||||
templ := tp
|
||||
if !g.shouldRenderApp(&templ, app) {
|
||||
continue
|
||||
}
|
||||
|
@ -624,7 +665,8 @@ func (g *GenOpts) renderApplication(app *GenApp) error {
|
|||
|
||||
func (g *GenOpts) renderOperationGroup(gg *GenOperationGroup) error {
|
||||
log.Printf("rendering %d templates for operation group %s", len(g.Sections.OperationGroups), g.Name)
|
||||
for _, templ := range g.Sections.OperationGroups {
|
||||
for _, tp := range g.Sections.OperationGroups {
|
||||
templ := tp
|
||||
if !g.shouldRenderOperations() {
|
||||
continue
|
||||
}
|
||||
|
@ -638,7 +680,8 @@ func (g *GenOpts) renderOperationGroup(gg *GenOperationGroup) error {
|
|||
|
||||
func (g *GenOpts) renderOperation(gg *GenOperation) error {
|
||||
log.Printf("rendering %d templates for operation %s", len(g.Sections.Operations), g.Name)
|
||||
for _, templ := range g.Sections.Operations {
|
||||
for _, tp := range g.Sections.Operations {
|
||||
templ := tp
|
||||
if !g.shouldRenderOperations() {
|
||||
continue
|
||||
}
|
||||
|
@ -652,7 +695,8 @@ func (g *GenOpts) renderOperation(gg *GenOperation) error {
|
|||
|
||||
func (g *GenOpts) renderDefinition(gg *GenDefinition) error {
|
||||
log.Printf("rendering %d templates for model %s", len(g.Sections.Models), gg.Name)
|
||||
for _, templ := range g.Sections.Models {
|
||||
for _, tp := range g.Sections.Models {
|
||||
templ := tp
|
||||
if !g.IncludeModel {
|
||||
continue
|
||||
}
|
||||
|
@ -665,20 +709,18 @@ func (g *GenOpts) renderDefinition(gg *GenDefinition) error {
|
|||
}
|
||||
|
||||
func (g *GenOpts) setTemplates() error {
|
||||
templates.LoadDefaults()
|
||||
|
||||
if g.Template != "" {
|
||||
// set contrib templates
|
||||
if err := templates.LoadContrib(g.Template); err != nil {
|
||||
if err := g.templates.LoadContrib(g.Template); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
templates.SetAllowOverride(g.AllowTemplateOverride)
|
||||
g.templates.SetAllowOverride(g.AllowTemplateOverride)
|
||||
|
||||
if g.TemplateDir != "" {
|
||||
// set custom templates
|
||||
if err := templates.LoadDir(g.TemplateDir); err != nil {
|
||||
if err := g.templates.LoadDir(g.TemplateDir); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -690,27 +732,33 @@ func (g *GenOpts) defaultImports() map[string]string {
|
|||
baseImport := g.LanguageOpts.baseImport(g.Target)
|
||||
defaultImports := make(map[string]string, 50)
|
||||
|
||||
var modelsAlias, importPath string
|
||||
if g.ExistingModels == "" {
|
||||
// generated models
|
||||
importPath := path.Join(
|
||||
importPath = path.Join(
|
||||
baseImport,
|
||||
g.LanguageOpts.ManglePackagePath(g.ModelPackage, defaultModelsTarget))
|
||||
defaultImports[g.LanguageOpts.ManglePackageName(g.ModelPackage, defaultModelsTarget)] = importPath
|
||||
modelsAlias = g.LanguageOpts.ManglePackageName(g.ModelPackage, defaultModelsTarget)
|
||||
} else {
|
||||
// external models
|
||||
importPath := g.LanguageOpts.ManglePackagePath(g.ExistingModels, "")
|
||||
defaultImports["models"] = importPath
|
||||
importPath = g.LanguageOpts.ManglePackagePath(g.ExistingModels, "")
|
||||
modelsAlias = path.Base(defaultModelsTarget)
|
||||
}
|
||||
defaultImports[modelsAlias] = importPath
|
||||
|
||||
// resolve model representing an authenticated principal
|
||||
alias, _, target := g.resolvePrincipal()
|
||||
if alias == "" || target == g.ModelPackage || path.Base(target) == modelsAlias {
|
||||
// if principal is specified with the models generation package, do not import any extra package
|
||||
return defaultImports
|
||||
}
|
||||
|
||||
alias, _, target := g.resolvePrincipal()
|
||||
if alias != "" {
|
||||
if pth, _ := path.Split(target); pth != "" {
|
||||
// if principal is specified with an path, generate this import
|
||||
defaultImports[alias] = target
|
||||
} else {
|
||||
// if principal is specified with a relative path, assume it is located in generated target
|
||||
defaultImports[alias] = path.Join(baseImport, target)
|
||||
}
|
||||
if pth, _ := path.Split(target); pth != "" {
|
||||
// if principal is specified with a path, assume this is a fully qualified package and generate this import
|
||||
defaultImports[alias] = target
|
||||
} else {
|
||||
// if principal is specified with a relative path (no "/", e.g. internal.Principal), assume it is located in generated target
|
||||
defaultImports[alias] = path.Join(baseImport, target)
|
||||
}
|
||||
return defaultImports
|
||||
}
|
||||
|
@ -873,16 +921,18 @@ func trimBOM(in string) string {
|
|||
}
|
||||
|
||||
// gatherSecuritySchemes produces a sorted representation from a map of spec security schemes
|
||||
func gatherSecuritySchemes(securitySchemes map[string]spec.SecurityScheme, appName, principal, receiver string) (security GenSecuritySchemes) {
|
||||
func gatherSecuritySchemes(securitySchemes map[string]spec.SecurityScheme, appName, principal, receiver string, nullable bool) (security GenSecuritySchemes) {
|
||||
for scheme, req := range securitySchemes {
|
||||
isOAuth2 := strings.ToLower(req.Type) == "oauth2"
|
||||
var scopes []string
|
||||
scopes := make([]string, 0, len(req.Scopes))
|
||||
genScopes := make([]GenSecurityScope, 0, len(req.Scopes))
|
||||
if isOAuth2 {
|
||||
for k := range req.Scopes {
|
||||
for k, v := range req.Scopes {
|
||||
scopes = append(scopes, k)
|
||||
genScopes = append(genScopes, GenSecurityScope{Name: k, Description: v})
|
||||
}
|
||||
sort.Strings(scopes)
|
||||
}
|
||||
sort.Strings(scopes)
|
||||
|
||||
security = append(security, GenSecurityScheme{
|
||||
AppName: appName,
|
||||
|
@ -893,6 +943,7 @@ func gatherSecuritySchemes(securitySchemes map[string]spec.SecurityScheme, appNa
|
|||
IsAPIKeyAuth: strings.ToLower(req.Type) == "apikey",
|
||||
IsOAuth2: isOAuth2,
|
||||
Scopes: scopes,
|
||||
ScopesDesc: genScopes,
|
||||
Principal: principal,
|
||||
Source: req.In,
|
||||
// from original spec
|
||||
|
@ -903,12 +954,26 @@ func gatherSecuritySchemes(securitySchemes map[string]spec.SecurityScheme, appNa
|
|||
AuthorizationURL: req.AuthorizationURL,
|
||||
TokenURL: req.TokenURL,
|
||||
Extensions: req.Extensions,
|
||||
|
||||
PrincipalIsNullable: nullable,
|
||||
})
|
||||
}
|
||||
sort.Sort(security)
|
||||
return
|
||||
}
|
||||
|
||||
// securityRequirements just clones the original SecurityRequirements from either the spec
|
||||
// or an operation, without any modification. This is used to generate documentation.
|
||||
func securityRequirements(orig []map[string][]string) (result []analysis.SecurityRequirement) {
|
||||
for _, r := range orig {
|
||||
for k, v := range r {
|
||||
result = append(result, analysis.SecurityRequirement{Name: k, Scopes: v})
|
||||
}
|
||||
}
|
||||
// TODO(fred): sort this for stable generation
|
||||
return
|
||||
}
|
||||
|
||||
// gatherExtraSchemas produces a sorted list of extra schemas.
|
||||
//
|
||||
// ExtraSchemas are inlined types rendered in the same model file.
|
||||
|
@ -927,42 +992,23 @@ func gatherExtraSchemas(extraMap map[string]GenSchema) (extras GenSchemaList) {
|
|||
return
|
||||
}
|
||||
|
||||
func sharedValidationsFromSimple(v spec.CommonValidations, isRequired bool) (sh sharedValidations) {
|
||||
sh = sharedValidations{
|
||||
Required: isRequired,
|
||||
Maximum: v.Maximum,
|
||||
ExclusiveMaximum: v.ExclusiveMaximum,
|
||||
Minimum: v.Minimum,
|
||||
ExclusiveMinimum: v.ExclusiveMinimum,
|
||||
MaxLength: v.MaxLength,
|
||||
MinLength: v.MinLength,
|
||||
Pattern: v.Pattern,
|
||||
MaxItems: v.MaxItems,
|
||||
MinItems: v.MinItems,
|
||||
UniqueItems: v.UniqueItems,
|
||||
MultipleOf: v.MultipleOf,
|
||||
Enum: v.Enum,
|
||||
func getExtraSchemes(ext spec.Extensions) []string {
|
||||
if ess, ok := ext.GetStringSlice(xSchemes); ok {
|
||||
return ess
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
func sharedValidationsFromSchema(v spec.Schema, isRequired bool) (sh sharedValidations) {
|
||||
sh = sharedValidations{
|
||||
Required: isRequired,
|
||||
Maximum: v.Maximum,
|
||||
ExclusiveMaximum: v.ExclusiveMaximum,
|
||||
Minimum: v.Minimum,
|
||||
ExclusiveMinimum: v.ExclusiveMinimum,
|
||||
MaxLength: v.MaxLength,
|
||||
MinLength: v.MinLength,
|
||||
Pattern: v.Pattern,
|
||||
MaxItems: v.MaxItems,
|
||||
MinItems: v.MinItems,
|
||||
UniqueItems: v.UniqueItems,
|
||||
MultipleOf: v.MultipleOf,
|
||||
Enum: v.Enum,
|
||||
}
|
||||
return
|
||||
func gatherURISchemes(swsp *spec.Swagger, operation spec.Operation) ([]string, []string) {
|
||||
var extraSchemes []string
|
||||
extraSchemes = append(extraSchemes, getExtraSchemes(operation.Extensions)...)
|
||||
extraSchemes = concatUnique(getExtraSchemes(swsp.Extensions), extraSchemes)
|
||||
sort.Strings(extraSchemes)
|
||||
|
||||
schemes := concatUnique(swsp.Schemes, operation.Schemes)
|
||||
sort.Strings(schemes)
|
||||
|
||||
return schemes, extraSchemes
|
||||
}
|
||||
|
||||
func dumpData(data interface{}) error {
|
||||
|
@ -978,3 +1024,20 @@ func importAlias(pkg string) string {
|
|||
_, k := path.Split(pkg)
|
||||
return k
|
||||
}
|
||||
|
||||
// concatUnique concatenate collections of strings with deduplication
|
||||
func concatUnique(collections ...[]string) []string {
|
||||
resultSet := make(map[string]struct{})
|
||||
for _, c := range collections {
|
||||
for _, i := range c {
|
||||
if _, ok := resultSet[i]; !ok {
|
||||
resultSet[i] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
result := make([]string, 0, len(resultSet))
|
||||
for k := range resultSet {
|
||||
result = append(result, k)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
6
vendor/github.com/go-swagger/go-swagger/generator/spec.go
generated
vendored
6
vendor/github.com/go-swagger/go-swagger/generator/spec.go
generated
vendored
|
@ -119,7 +119,7 @@ func (g *GenOpts) printFlattenOpts() {
|
|||
log.Printf("preprocessing spec with option: %s", preprocessingOption)
|
||||
}
|
||||
|
||||
//findSwaggerSpec fetches a default swagger spec if none is provided
|
||||
// findSwaggerSpec fetches a default swagger spec if none is provided
|
||||
func findSwaggerSpec(nm string) (string, error) {
|
||||
specs := []string{"swagger.json", "swagger.yml", "swagger.yaml"}
|
||||
if nm != "" {
|
||||
|
@ -168,7 +168,7 @@ func WithAutoXOrder(specPath string) string {
|
|||
for i, prop := range props {
|
||||
if pSlice, ok := prop.Value.(yaml.MapSlice); ok {
|
||||
isObject := false
|
||||
xOrderIndex := -1 //Find if x-order already exists
|
||||
xOrderIndex := -1 // find if x-order already exists
|
||||
|
||||
for i, v := range pSlice {
|
||||
if v.Key == "type" && v.Value == object {
|
||||
|
@ -180,7 +180,7 @@ func WithAutoXOrder(specPath string) string {
|
|||
}
|
||||
}
|
||||
|
||||
if xOrderIndex > -1 { //Override existing x-order
|
||||
if xOrderIndex > -1 { // override existing x-order
|
||||
pSlice[xOrderIndex] = yaml.MapItem{Key: xOrder, Value: i}
|
||||
} else { // append new x-order
|
||||
pSlice = append(pSlice, yaml.MapItem{Key: xOrder, Value: i})
|
||||
|
|
280
vendor/github.com/go-swagger/go-swagger/generator/structs.go
generated
vendored
280
vendor/github.com/go-swagger/go-swagger/generator/structs.go
generated
vendored
|
@ -8,6 +8,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/analysis"
|
||||
"github.com/go-openapi/spec"
|
||||
)
|
||||
|
||||
|
@ -94,6 +95,106 @@ type GenSchema struct {
|
|||
WantsMarshalBinary bool // do we generate MarshalBinary interface?
|
||||
StructTags []string
|
||||
ExtraImports map[string]string // non-standard imports detected when using external types
|
||||
ExternalDocs *spec.ExternalDocumentation
|
||||
}
|
||||
|
||||
func (g GenSchema) renderMarshalTag() string {
|
||||
if g.HasBaseType {
|
||||
return "-"
|
||||
}
|
||||
|
||||
var result strings.Builder
|
||||
|
||||
result.WriteString(g.OriginalName)
|
||||
|
||||
if !g.Required && g.IsEmptyOmitted {
|
||||
result.WriteString(",omitempty")
|
||||
}
|
||||
|
||||
if g.IsJSONString {
|
||||
result.WriteString(",string")
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// PrintTags takes care of rendering tags for a struct field
|
||||
func (g GenSchema) PrintTags() string {
|
||||
tags := make(map[string]string, 3)
|
||||
orderedTags := make([]string, 0, 3)
|
||||
|
||||
tags["json"] = g.renderMarshalTag()
|
||||
orderedTags = append(orderedTags, "json")
|
||||
|
||||
if len(g.XMLName) > 0 {
|
||||
if !g.Required && g.IsEmptyOmitted {
|
||||
tags["xml"] = g.XMLName + ",omitempty"
|
||||
} else {
|
||||
tags["xml"] = g.XMLName
|
||||
}
|
||||
orderedTags = append(orderedTags, "xml")
|
||||
}
|
||||
|
||||
// Add extra struct tags, only if the tag hasn't already been set, i.e. example.
|
||||
// Extra struct tags have the same value has the `json` tag.
|
||||
for _, tag := range g.StructTags {
|
||||
if _, exists := tags[tag]; exists {
|
||||
// dedupe
|
||||
continue
|
||||
}
|
||||
|
||||
if tag == "example" && len(g.Example) > 0 {
|
||||
// only add example tag if it's contained in the struct tags
|
||||
tags["example"] = g.Example // json representation of the example object
|
||||
} else {
|
||||
tags[tag] = tags["json"]
|
||||
}
|
||||
|
||||
orderedTags = append(orderedTags, tag)
|
||||
}
|
||||
|
||||
// Assemble the tags in key value pairs with the value properly quoted.
|
||||
kvPairs := make([]string, 0, len(orderedTags)+1)
|
||||
for _, key := range orderedTags {
|
||||
kvPairs = append(kvPairs, fmt.Sprintf("%s:%s", key, strconv.Quote(tags[key])))
|
||||
}
|
||||
|
||||
if len(g.CustomTag) > 0 {
|
||||
kvPairs = append(kvPairs, g.CustomTag)
|
||||
}
|
||||
|
||||
// Join the key value pairs by a space.
|
||||
completeTag := strings.Join(kvPairs, " ")
|
||||
|
||||
// If the values contain a backtick, we cannot render the tag using backticks because Go does not support
|
||||
// escaping backticks in raw string literals.
|
||||
valuesHaveBacktick := false
|
||||
for _, value := range tags {
|
||||
if !strconv.CanBackquote(value) {
|
||||
valuesHaveBacktick = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !valuesHaveBacktick {
|
||||
return fmt.Sprintf("`%s`", completeTag)
|
||||
}
|
||||
|
||||
// We have to escape the tag again to put it in a literal with double quotes as the tag format uses double quotes.
|
||||
return strconv.Quote(completeTag)
|
||||
}
|
||||
|
||||
// UnderlyingType tells the go type or the aliased go type
|
||||
func (g GenSchema) UnderlyingType() string {
|
||||
if g.IsAliased {
|
||||
return g.AliasedType
|
||||
}
|
||||
return g.GoType
|
||||
}
|
||||
|
||||
// ToString returns a string conversion expression for the schema
|
||||
func (g GenSchema) ToString() string {
|
||||
return g.resolvedType.ToString(g.ValueExpression)
|
||||
}
|
||||
|
||||
func (g GenSchemaList) Len() int { return len(g) }
|
||||
|
@ -122,32 +223,13 @@ func (g GenSchemaList) Less(i, j int) bool {
|
|||
}
|
||||
|
||||
type sharedValidations struct {
|
||||
HasValidations bool
|
||||
Required bool
|
||||
spec.SchemaValidations
|
||||
|
||||
// String validations
|
||||
MaxLength *int64
|
||||
MinLength *int64
|
||||
Pattern string
|
||||
|
||||
// Number validations
|
||||
MultipleOf *float64
|
||||
Minimum *float64
|
||||
Maximum *float64
|
||||
ExclusiveMinimum bool
|
||||
ExclusiveMaximum bool
|
||||
|
||||
Enum []interface{}
|
||||
ItemsEnum []interface{}
|
||||
|
||||
// Slice validations
|
||||
MinItems *int64
|
||||
MaxItems *int64
|
||||
UniqueItems bool
|
||||
HasSliceValidations bool
|
||||
|
||||
// Not used yet (perhaps intended for maxProperties, minProperties validations?)
|
||||
NeedsSize bool
|
||||
HasValidations bool
|
||||
HasContextValidations bool
|
||||
Required bool
|
||||
HasSliceValidations bool
|
||||
ItemsEnum []interface{}
|
||||
|
||||
// NOTE: "patternProperties" and "dependencies" not supported by Swagger 2.0
|
||||
}
|
||||
|
@ -176,6 +258,20 @@ type GenResponse struct {
|
|||
|
||||
StrictResponders bool
|
||||
OperationName string
|
||||
Examples GenResponseExamples
|
||||
}
|
||||
|
||||
// GenResponseExamples is a sortable collection []GenResponseExample
|
||||
type GenResponseExamples []GenResponseExample
|
||||
|
||||
func (g GenResponseExamples) Len() int { return len(g) }
|
||||
func (g GenResponseExamples) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
||||
func (g GenResponseExamples) Less(i, j int) bool { return g[i].MediaType < g[j].MediaType }
|
||||
|
||||
// GenResponseExample captures an example provided for a response for some mime type
|
||||
type GenResponseExample struct {
|
||||
MediaType string
|
||||
Example interface{}
|
||||
}
|
||||
|
||||
// GenHeader represents a header on a response for code generation
|
||||
|
@ -210,11 +306,16 @@ type GenHeader struct {
|
|||
|
||||
// ItemsDepth returns a string "items.items..." with as many items as the level of nesting of the array.
|
||||
// For a header objects it always returns "".
|
||||
func (g *GenHeader) ItemsDepth() string {
|
||||
func (h *GenHeader) ItemsDepth() string {
|
||||
// NOTE: this is currently used by templates to generate explicit comments in nested structures
|
||||
return ""
|
||||
}
|
||||
|
||||
// ToString returns a string conversion expression for the header
|
||||
func (h GenHeader) ToString() string {
|
||||
return h.resolvedType.ToString(h.ValueExpression)
|
||||
}
|
||||
|
||||
// GenHeaders is a sorted collection of headers for codegen
|
||||
type GenHeaders []GenHeader
|
||||
|
||||
|
@ -260,8 +361,8 @@ type GenParameter struct {
|
|||
Child *GenItems
|
||||
Parent *GenItems
|
||||
|
||||
/// Unused
|
||||
//BodyParam *GenParameter
|
||||
// Unused
|
||||
// BodyParam *GenParameter
|
||||
|
||||
Default interface{}
|
||||
HasDefault bool
|
||||
|
@ -323,6 +424,16 @@ func (g *GenParameter) ItemsDepth() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// UnderlyingType tells the go type or the aliased go type
|
||||
func (g GenParameter) UnderlyingType() string {
|
||||
return g.GoType
|
||||
}
|
||||
|
||||
// ToString returns a string conversion expression for the parameter
|
||||
func (g GenParameter) ToString() string {
|
||||
return g.resolvedType.ToString(g.ValueExpression)
|
||||
}
|
||||
|
||||
// GenParameters represents a sorted parameter collection
|
||||
type GenParameters []GenParameter
|
||||
|
||||
|
@ -377,6 +488,16 @@ func (g *GenItems) ItemsDepth() string {
|
|||
return strings.Repeat("items.", i)
|
||||
}
|
||||
|
||||
// UnderlyingType tells the go type or the aliased go type
|
||||
func (g GenItems) UnderlyingType() string {
|
||||
return g.GoType
|
||||
}
|
||||
|
||||
// ToString returns a string conversion expression for the item
|
||||
func (g GenItems) ToString() string {
|
||||
return g.resolvedType.ToString(g.ValueExpression)
|
||||
}
|
||||
|
||||
// GenOperationGroup represents a named (tagged) group of operations
|
||||
type GenOperationGroup struct {
|
||||
GenCommon
|
||||
|
@ -470,10 +591,12 @@ type GenOperation struct {
|
|||
ExtraSchemas GenSchemaList
|
||||
PackageAlias string
|
||||
|
||||
Authorized bool
|
||||
Security []GenSecurityRequirements
|
||||
SecurityDefinitions GenSecuritySchemes
|
||||
Principal string
|
||||
Authorized bool
|
||||
Security []GenSecurityRequirements // resolved security requirements for the operation
|
||||
SecurityDefinitions GenSecuritySchemes
|
||||
SecurityRequirements []analysis.SecurityRequirement // original security requirements as per the spec (for doc)
|
||||
Principal string
|
||||
PrincipalIsNullable bool
|
||||
|
||||
SuccessResponse *GenResponse
|
||||
SuccessResponses []GenResponse
|
||||
|
@ -494,15 +617,20 @@ type GenOperation struct {
|
|||
HasBodyParams bool
|
||||
HasStreamingResponse bool
|
||||
|
||||
Schemes []string
|
||||
ExtraSchemes []string
|
||||
ProducesMediaTypes []string
|
||||
ConsumesMediaTypes []string
|
||||
TimeoutName string
|
||||
Schemes []string
|
||||
ExtraSchemes []string
|
||||
SchemeOverrides []string // original scheme overrides for operation, as per spec (for doc)
|
||||
ExtraSchemeOverrides []string // original extra scheme overrides for operation, as per spec (for doc)
|
||||
ProducesMediaTypes []string
|
||||
ConsumesMediaTypes []string
|
||||
TimeoutName string
|
||||
|
||||
Extensions map[string]interface{}
|
||||
|
||||
StrictResponders bool
|
||||
ExternalDocs *spec.ExternalDocumentation
|
||||
Produces []string // original produces for operation (for doc)
|
||||
Consumes []string // original consumes for operation (for doc)
|
||||
}
|
||||
|
||||
// GenOperations represents a list of operations to generate
|
||||
|
@ -517,28 +645,33 @@ func (g GenOperations) Swap(i, j int) { g[i], g[j] = g[j], g[i] }
|
|||
// from a swagger spec
|
||||
type GenApp struct {
|
||||
GenCommon
|
||||
APIPackage string
|
||||
Package string
|
||||
ReceiverName string
|
||||
Name string
|
||||
Principal string
|
||||
DefaultConsumes string
|
||||
DefaultProduces string
|
||||
Host string
|
||||
BasePath string
|
||||
Info *spec.Info
|
||||
ExternalDocs *spec.ExternalDocumentation
|
||||
Imports map[string]string
|
||||
DefaultImports map[string]string
|
||||
Schemes []string
|
||||
ExtraSchemes []string
|
||||
Consumes GenSerGroups
|
||||
Produces GenSerGroups
|
||||
SecurityDefinitions GenSecuritySchemes
|
||||
Models []GenDefinition
|
||||
Operations GenOperations
|
||||
OperationGroups GenOperationGroups
|
||||
SwaggerJSON string
|
||||
APIPackage string
|
||||
ServerPackageAlias string
|
||||
APIPackageAlias string
|
||||
Package string
|
||||
ReceiverName string
|
||||
Name string
|
||||
Principal string
|
||||
PrincipalIsNullable bool
|
||||
DefaultConsumes string
|
||||
DefaultProduces string
|
||||
Host string
|
||||
BasePath string
|
||||
Info *spec.Info
|
||||
ExternalDocs *spec.ExternalDocumentation
|
||||
Tags []spec.Tag
|
||||
Imports map[string]string
|
||||
DefaultImports map[string]string
|
||||
Schemes []string
|
||||
ExtraSchemes []string
|
||||
Consumes GenSerGroups
|
||||
Produces GenSerGroups
|
||||
SecurityDefinitions GenSecuritySchemes
|
||||
SecurityRequirements []analysis.SecurityRequirement // original security requirements as per the spec (for doc)
|
||||
Models []GenDefinition
|
||||
Operations GenOperations
|
||||
OperationGroups GenOperationGroups
|
||||
SwaggerJSON string
|
||||
// Embedded specs: this is important for when the generated server adds routes.
|
||||
// NOTE: there is a distinct advantage to having this in runtime rather than generated code.
|
||||
// We are not ever going to generate the router.
|
||||
|
@ -613,16 +746,18 @@ type GenSerializer struct {
|
|||
|
||||
// GenSecurityScheme represents a security scheme for code generation
|
||||
type GenSecurityScheme struct {
|
||||
AppName string
|
||||
ID string
|
||||
Name string
|
||||
ReceiverName string
|
||||
IsBasicAuth bool
|
||||
IsAPIKeyAuth bool
|
||||
IsOAuth2 bool
|
||||
Scopes []string
|
||||
Source string
|
||||
Principal string
|
||||
AppName string
|
||||
ID string
|
||||
Name string
|
||||
ReceiverName string
|
||||
IsBasicAuth bool
|
||||
IsAPIKeyAuth bool
|
||||
IsOAuth2 bool
|
||||
Scopes []string
|
||||
Source string
|
||||
Principal string
|
||||
PrincipalIsNullable bool
|
||||
|
||||
// from spec.SecurityScheme
|
||||
Description string
|
||||
Type string
|
||||
|
@ -631,6 +766,7 @@ type GenSecurityScheme struct {
|
|||
AuthorizationURL string
|
||||
TokenURL string
|
||||
Extensions map[string]interface{}
|
||||
ScopesDesc []GenSecurityScope
|
||||
}
|
||||
|
||||
// GenSecuritySchemes sorted representation of serializers
|
||||
|
@ -646,6 +782,12 @@ type GenSecurityRequirement struct {
|
|||
Scopes []string
|
||||
}
|
||||
|
||||
// GenSecurityScope represents a scope descriptor for an OAuth2 security scheme
|
||||
type GenSecurityScope struct {
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
// GenSecurityRequirements represents a compounded security requirement specification.
|
||||
// In a []GenSecurityRequirements complete requirements specification,
|
||||
// outer elements are interpreted as optional requirements (OR), and
|
||||
|
|
167
vendor/github.com/go-swagger/go-swagger/generator/support.go
generated
vendored
167
vendor/github.com/go-swagger/go-swagger/generator/support.go
generated
vendored
|
@ -49,6 +49,25 @@ func GenerateSupport(name string, modelNames, operationIDs []string, opts *GenOp
|
|||
return generator.GenerateSupport(nil)
|
||||
}
|
||||
|
||||
// GenerateMarkdown documentation for a swagger specification
|
||||
func GenerateMarkdown(output string, modelNames, operationIDs []string, opts *GenOpts) error {
|
||||
if output == "." || output == "" {
|
||||
output = "markdown.md"
|
||||
}
|
||||
|
||||
if err := opts.EnsureDefaults(); err != nil {
|
||||
return err
|
||||
}
|
||||
MarkdownSectionOpts(opts, output)
|
||||
|
||||
generator, err := newAppGenerator("", modelNames, operationIDs, opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return generator.GenerateMarkdown()
|
||||
}
|
||||
|
||||
func newAppGenerator(name string, modelNames, operationIDs []string, opts *GenOpts) (*appGenerator, error) {
|
||||
if err := opts.CheckOpts(); err != nil {
|
||||
return nil, err
|
||||
|
@ -142,7 +161,8 @@ func (a *appGenerator) Generate() error {
|
|||
// templates are now lazy loaded so there is concurrent map access I can't guard
|
||||
if a.GenOpts.IncludeModel {
|
||||
log.Printf("rendering %d models", len(app.Models))
|
||||
for _, mod := range app.Models {
|
||||
for _, md := range app.Models {
|
||||
mod := md
|
||||
mod.IncludeModel = true
|
||||
mod.IncludeValidator = a.GenOpts.IncludeValidator
|
||||
if err := a.GenOpts.renderDefinition(&mod); err != nil {
|
||||
|
@ -153,9 +173,11 @@ func (a *appGenerator) Generate() error {
|
|||
|
||||
if a.GenOpts.IncludeHandler {
|
||||
log.Printf("rendering %d operation groups (tags)", app.OperationGroups.Len())
|
||||
for _, opg := range app.OperationGroups {
|
||||
for _, g := range app.OperationGroups {
|
||||
opg := g
|
||||
log.Printf("rendering %d operations for %s", opg.Operations.Len(), opg.Name)
|
||||
for _, op := range opg.Operations {
|
||||
for _, p := range opg.Operations {
|
||||
op := p
|
||||
if err := a.GenOpts.renderOperation(&op); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -190,11 +212,23 @@ func (a *appGenerator) GenerateSupport(ap *GenApp) error {
|
|||
baseImport := a.GenOpts.LanguageOpts.baseImport(a.Target)
|
||||
serverPath := path.Join(baseImport,
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.ServerPackage, defaultServerTarget))
|
||||
app.DefaultImports[importAlias(serverPath)] = serverPath
|
||||
|
||||
pkgAlias := deconflictPkg(importAlias(serverPath), renameServerPackage)
|
||||
app.DefaultImports[pkgAlias] = serverPath
|
||||
app.ServerPackageAlias = pkgAlias
|
||||
|
||||
return a.GenOpts.renderApplication(app)
|
||||
}
|
||||
|
||||
func (a *appGenerator) GenerateMarkdown() error {
|
||||
app, err := a.makeCodegenApp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return a.GenOpts.renderApplication(&app)
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeSecuritySchemes() GenSecuritySchemes {
|
||||
requiredSecuritySchemes := make(map[string]spec.SecurityScheme, len(a.Analyzed.RequiredSecuritySchemes()))
|
||||
for _, scheme := range a.Analyzed.RequiredSecuritySchemes() {
|
||||
|
@ -202,7 +236,7 @@ func (a *appGenerator) makeSecuritySchemes() GenSecuritySchemes {
|
|||
requiredSecuritySchemes[scheme] = *req
|
||||
}
|
||||
}
|
||||
return gatherSecuritySchemes(requiredSecuritySchemes, a.Name, a.Principal, a.Receiver)
|
||||
return gatherSecuritySchemes(requiredSecuritySchemes, a.Name, a.Principal, a.Receiver, a.GenOpts.PrincipalIsNullable())
|
||||
}
|
||||
|
||||
func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
||||
|
@ -219,9 +253,14 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
|
||||
baseImport := a.GenOpts.LanguageOpts.baseImport(a.Target)
|
||||
defaultImports := a.GenOpts.defaultImports()
|
||||
imports := a.GenOpts.initImports(a.OperationsPackage)
|
||||
|
||||
log.Println("planning definitions")
|
||||
imports := make(map[string]string, 50)
|
||||
alias := deconflictPkg(a.GenOpts.LanguageOpts.ManglePackageName(a.OperationsPackage, defaultOperationsTarget), renameAPIPackage)
|
||||
imports[alias] = path.Join(
|
||||
baseImport,
|
||||
a.GenOpts.LanguageOpts.ManglePackagePath(a.OperationsPackage, defaultOperationsTarget))
|
||||
|
||||
log.Printf("planning definitions (found: %d)", len(a.Models))
|
||||
|
||||
genModels := make(GenDefinitions, 0, len(a.Models))
|
||||
for mn, m := range a.Models {
|
||||
|
@ -250,7 +289,7 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
}
|
||||
sort.Sort(genModels)
|
||||
|
||||
log.Println("planning operations")
|
||||
log.Printf("planning operations (found: %d)", len(a.Operations))
|
||||
|
||||
genOps := make(GenOperations, 0, len(a.Operations))
|
||||
for operationName, opp := range a.Operations {
|
||||
|
@ -318,15 +357,16 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
}
|
||||
sort.Sort(genOps)
|
||||
|
||||
log.Println("grouping operations into packages")
|
||||
|
||||
opsGroupedByPackage := make(map[string]GenOperations, len(genOps))
|
||||
for _, operation := range genOps {
|
||||
opsGroupedByPackage[operation.PackageAlias] = append(opsGroupedByPackage[operation.PackageAlias], operation)
|
||||
}
|
||||
|
||||
log.Printf("grouping operations into packages (packages: %d)", len(opsGroupedByPackage))
|
||||
|
||||
opGroups := make(GenOperationGroups, 0, len(opsGroupedByPackage))
|
||||
for k, v := range opsGroupedByPackage {
|
||||
log.Printf("operations for package packages %q (found: %d)", k, len(v))
|
||||
sort.Sort(v)
|
||||
// trim duplicate extra schemas within the same package
|
||||
vv := make(GenOperations, 0, len(v))
|
||||
|
@ -368,8 +408,7 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
|
||||
log.Println("planning meta data and facades")
|
||||
|
||||
var collectedSchemes []string
|
||||
var extraSchemes []string
|
||||
var collectedSchemes, extraSchemes []string
|
||||
for _, op := range genOps {
|
||||
collectedSchemes = concatUnique(collectedSchemes, op.Schemes)
|
||||
extraSchemes = concatUnique(extraSchemes, op.ExtraSchemes)
|
||||
|
@ -395,31 +434,36 @@ func (a *appGenerator) makeCodegenApp() (GenApp, error) {
|
|||
Copyright: a.GenOpts.Copyright,
|
||||
TargetImportPath: baseImport,
|
||||
},
|
||||
APIPackage: a.GenOpts.LanguageOpts.ManglePackageName(a.ServerPackage, defaultServerTarget),
|
||||
Package: a.Package,
|
||||
ReceiverName: receiver,
|
||||
Name: a.Name,
|
||||
Host: host,
|
||||
BasePath: basePath,
|
||||
Schemes: schemeOrDefault(collectedSchemes, a.DefaultScheme),
|
||||
ExtraSchemes: extraSchemes,
|
||||
ExternalDocs: sw.ExternalDocs,
|
||||
Info: sw.Info,
|
||||
Consumes: consumes,
|
||||
Produces: produces,
|
||||
DefaultConsumes: a.DefaultConsumes,
|
||||
DefaultProduces: a.DefaultProduces,
|
||||
DefaultImports: defaultImports,
|
||||
Imports: imports,
|
||||
SecurityDefinitions: security,
|
||||
Models: genModels,
|
||||
Operations: genOps,
|
||||
OperationGroups: opGroups,
|
||||
Principal: a.GenOpts.PrincipalAlias(),
|
||||
SwaggerJSON: generateReadableSpec(jsonb),
|
||||
FlatSwaggerJSON: generateReadableSpec(flatjsonb),
|
||||
ExcludeSpec: a.GenOpts.ExcludeSpec,
|
||||
GenOpts: a.GenOpts,
|
||||
APIPackage: a.GenOpts.LanguageOpts.ManglePackageName(a.ServerPackage, defaultServerTarget),
|
||||
APIPackageAlias: alias,
|
||||
Package: a.Package,
|
||||
ReceiverName: receiver,
|
||||
Name: a.Name,
|
||||
Host: host,
|
||||
BasePath: basePath,
|
||||
Schemes: schemeOrDefault(collectedSchemes, a.DefaultScheme),
|
||||
ExtraSchemes: extraSchemes,
|
||||
ExternalDocs: trimExternalDoc(sw.ExternalDocs),
|
||||
Tags: trimTags(sw.Tags),
|
||||
Info: trimInfo(sw.Info),
|
||||
Consumes: consumes,
|
||||
Produces: produces,
|
||||
DefaultConsumes: a.DefaultConsumes,
|
||||
DefaultProduces: a.DefaultProduces,
|
||||
DefaultImports: defaultImports,
|
||||
Imports: imports,
|
||||
SecurityDefinitions: security,
|
||||
SecurityRequirements: securityRequirements(a.SpecDoc.Spec().Security), // top level securityRequirements
|
||||
Models: genModels,
|
||||
Operations: genOps,
|
||||
OperationGroups: opGroups,
|
||||
Principal: a.GenOpts.PrincipalAlias(),
|
||||
SwaggerJSON: generateReadableSpec(jsonb),
|
||||
FlatSwaggerJSON: generateReadableSpec(flatjsonb),
|
||||
ExcludeSpec: a.GenOpts.ExcludeSpec,
|
||||
GenOpts: a.GenOpts,
|
||||
|
||||
PrincipalIsNullable: a.GenOpts.PrincipalIsNullable(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -438,3 +482,52 @@ func generateReadableSpec(spec []byte) string {
|
|||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func trimExternalDoc(in *spec.ExternalDocumentation) *spec.ExternalDocumentation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &spec.ExternalDocumentation{
|
||||
URL: in.URL,
|
||||
Description: trimBOM(in.Description),
|
||||
}
|
||||
}
|
||||
|
||||
func trimInfo(in *spec.Info) *spec.Info {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Contact: in.Contact,
|
||||
Title: trimBOM(in.Title),
|
||||
Description: trimBOM(in.Description),
|
||||
TermsOfService: trimBOM(in.TermsOfService),
|
||||
License: in.License,
|
||||
Version: in.Version,
|
||||
},
|
||||
VendorExtensible: in.VendorExtensible,
|
||||
}
|
||||
}
|
||||
|
||||
func trimTags(in []spec.Tag) []spec.Tag {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
tags := make([]spec.Tag, 0, len(in))
|
||||
|
||||
for _, tag := range in {
|
||||
tags = append(tags, spec.Tag{
|
||||
TagProps: spec.TagProps{
|
||||
Name: tag.Name,
|
||||
Description: trimBOM(tag.Description),
|
||||
ExternalDocs: trimExternalDoc(tag.ExternalDocs),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return tags
|
||||
}
|
||||
|
|
258
vendor/github.com/go-swagger/go-swagger/generator/template_repo.go
generated
vendored
258
vendor/github.com/go-swagger/go-swagger/generator/template_repo.go
generated
vendored
|
@ -5,10 +5,14 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"text/template"
|
||||
"text/template/parse"
|
||||
"unicode"
|
||||
|
@ -16,6 +20,7 @@ import (
|
|||
"log"
|
||||
|
||||
"github.com/go-openapi/inflect"
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/swag"
|
||||
"github.com/kr/pretty"
|
||||
)
|
||||
|
@ -28,6 +33,8 @@ var (
|
|||
FuncMapFunc func(*LanguageOpts) template.FuncMap
|
||||
|
||||
templates *Repository
|
||||
|
||||
docFormat map[string]string
|
||||
)
|
||||
|
||||
func initTemplateRepo() {
|
||||
|
@ -40,6 +47,11 @@ func initTemplateRepo() {
|
|||
assets = defaultAssets()
|
||||
protectedTemplates = defaultProtectedTemplates()
|
||||
templates = NewRepository(FuncMapFunc(DefaultLanguageFunc()))
|
||||
|
||||
docFormat = map[string]string{
|
||||
"binary": "binary (byte stream)",
|
||||
"byte": "byte (base64 string)",
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultFuncMap yields a map with default functions for use n the templates.
|
||||
|
@ -72,9 +84,11 @@ func DefaultFuncMap(lang *LanguageOpts) template.FuncMap {
|
|||
},
|
||||
"dropPackage": dropPackage,
|
||||
"upper": strings.ToUpper,
|
||||
"lower": strings.ToLower,
|
||||
"contains": swag.ContainsStrings,
|
||||
"padSurround": padSurround,
|
||||
"joinFilePath": filepath.Join,
|
||||
"joinPath": path.Join,
|
||||
"comment": padComment,
|
||||
"blockcomment": blockComment,
|
||||
"inspect": pretty.Sprint,
|
||||
|
@ -85,6 +99,44 @@ func DefaultFuncMap(lang *LanguageOpts) template.FuncMap {
|
|||
"stringContains": strings.Contains,
|
||||
"imports": lang.imports,
|
||||
"dict": dict,
|
||||
"isInteger": isInteger,
|
||||
"escapeBackticks": func(arg string) string {
|
||||
return strings.ReplaceAll(arg, "`", "`+\"`\"+`")
|
||||
},
|
||||
"paramDocType": func(param GenParameter) string {
|
||||
return resolvedDocType(param.SwaggerType, param.SwaggerFormat, param.Child)
|
||||
},
|
||||
"headerDocType": func(header GenHeader) string {
|
||||
return resolvedDocType(header.SwaggerType, header.SwaggerFormat, header.Child)
|
||||
},
|
||||
"schemaDocType": func(in interface{}) string {
|
||||
switch schema := in.(type) {
|
||||
case GenSchema:
|
||||
return resolvedDocSchemaType(schema.SwaggerType, schema.SwaggerFormat, schema.Items)
|
||||
case *GenSchema:
|
||||
if schema == nil {
|
||||
return ""
|
||||
}
|
||||
return resolvedDocSchemaType(schema.SwaggerType, schema.SwaggerFormat, schema.Items)
|
||||
case GenDefinition:
|
||||
return resolvedDocSchemaType(schema.SwaggerType, schema.SwaggerFormat, schema.Items)
|
||||
case *GenDefinition:
|
||||
if schema == nil {
|
||||
return ""
|
||||
}
|
||||
return resolvedDocSchemaType(schema.SwaggerType, schema.SwaggerFormat, schema.Items)
|
||||
default:
|
||||
panic("dev error: schemaDocType should be called with GenSchema or GenDefinition")
|
||||
}
|
||||
},
|
||||
"schemaDocMapType": func(schema GenSchema) string {
|
||||
return resolvedDocElemType("object", schema.SwaggerFormat, &schema.resolvedType)
|
||||
},
|
||||
"docCollectionFormat": resolvedDocCollectionFormat,
|
||||
"trimSpace": strings.TrimSpace,
|
||||
"httpStatus": httpStatus,
|
||||
"cleanupEnumVariant": cleanupEnumVariant,
|
||||
"gt0": gt0,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -98,6 +150,9 @@ func defaultAssets() map[string][]byte {
|
|||
"schemavalidator.gotmpl": MustAsset("templates/schemavalidator.gotmpl"),
|
||||
"schemapolymorphic.gotmpl": MustAsset("templates/schemapolymorphic.gotmpl"),
|
||||
"schemaembedded.gotmpl": MustAsset("templates/schemaembedded.gotmpl"),
|
||||
"validation/minimum.gotmpl": MustAsset("templates/validation/minimum.gotmpl"),
|
||||
"validation/maximum.gotmpl": MustAsset("templates/validation/maximum.gotmpl"),
|
||||
"validation/multipleOf.gotmpl": MustAsset("templates/validation/multipleOf.gotmpl"),
|
||||
|
||||
// schema serialization templates
|
||||
"additionalpropertiesserializer.gotmpl": MustAsset("templates/serializers/additionalpropertiesserializer.gotmpl"),
|
||||
|
@ -117,6 +172,10 @@ func defaultAssets() map[string][]byte {
|
|||
"model.gotmpl": MustAsset("templates/model.gotmpl"),
|
||||
"header.gotmpl": MustAsset("templates/header.gotmpl"),
|
||||
|
||||
// simple schema generation helpers templates
|
||||
"simpleschema/defaultsvar.gotmpl": MustAsset("templates/simpleschema/defaultsvar.gotmpl"),
|
||||
"simpleschema/defaultsinit.gotmpl": MustAsset("templates/simpleschema/defaultsinit.gotmpl"),
|
||||
|
||||
"swagger_json_embed.gotmpl": MustAsset("templates/swagger_json_embed.gotmpl"),
|
||||
|
||||
// server templates
|
||||
|
@ -135,6 +194,8 @@ func defaultAssets() map[string][]byte {
|
|||
"client/response.gotmpl": MustAsset("templates/client/response.gotmpl"),
|
||||
"client/client.gotmpl": MustAsset("templates/client/client.gotmpl"),
|
||||
"client/facade.gotmpl": MustAsset("templates/client/facade.gotmpl"),
|
||||
|
||||
"markdown/docs.gotmpl": MustAsset("templates/markdown/docs.gotmpl"),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,13 +228,20 @@ func defaultProtectedTemplates() map[string]bool {
|
|||
"tuplefield": true,
|
||||
"tuplefieldIface": true,
|
||||
"typeSchemaType": true,
|
||||
"validationCustomformat": true,
|
||||
"validationPrimitive": true,
|
||||
"validationStructfield": true,
|
||||
"withBaseTypeBody": true,
|
||||
"withoutBaseTypeBody": true,
|
||||
"simpleschemaDefaultsvar": true,
|
||||
"simpleschemaDefaultsinit": true,
|
||||
|
||||
// all serializers TODO(fred)
|
||||
// validation helpers
|
||||
"validationCustomformat": true,
|
||||
"validationPrimitive": true,
|
||||
"validationStructfield": true,
|
||||
"withBaseTypeBody": true,
|
||||
"withoutBaseTypeBody": true,
|
||||
"validationMinimum": true,
|
||||
"validationMaximum": true,
|
||||
"validationMultipleOf": true,
|
||||
|
||||
// all serializers
|
||||
"additionalPropertiesSerializer": true,
|
||||
"tupleSerializer": true,
|
||||
"schemaSerializer": true,
|
||||
|
@ -213,6 +281,31 @@ type Repository struct {
|
|||
templates map[string]*template.Template
|
||||
funcs template.FuncMap
|
||||
allowOverride bool
|
||||
mux sync.Mutex
|
||||
}
|
||||
|
||||
// ShallowClone a repository.
|
||||
//
|
||||
// Clones the maps of files and templates, so as to be able to use
|
||||
// the cloned repo concurrently.
|
||||
func (t *Repository) ShallowClone() *Repository {
|
||||
clone := &Repository{
|
||||
files: make(map[string]string, len(t.files)),
|
||||
templates: make(map[string]*template.Template, len(t.templates)),
|
||||
funcs: t.funcs,
|
||||
allowOverride: t.allowOverride,
|
||||
}
|
||||
|
||||
t.mux.Lock()
|
||||
defer t.mux.Unlock()
|
||||
|
||||
for k, file := range t.files {
|
||||
clone.files[k] = file
|
||||
}
|
||||
for k, tpl := range t.templates {
|
||||
clone.templates[k] = tpl
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
// LoadDefaults will load the embedded templates
|
||||
|
@ -532,7 +625,7 @@ func padComment(str string, pads ...string) string {
|
|||
}
|
||||
|
||||
func blockComment(str string) string {
|
||||
return strings.Replace(str, "*/", "[*]/", -1)
|
||||
return strings.ReplaceAll(str, "*/", "[*]/")
|
||||
}
|
||||
|
||||
func pascalize(arg string) string {
|
||||
|
@ -566,6 +659,28 @@ func prefixForName(arg string) string {
|
|||
return "Nr"
|
||||
}
|
||||
|
||||
func replaceSpecialChar(in rune) string {
|
||||
switch in {
|
||||
case '.':
|
||||
return "-Dot-"
|
||||
case '+':
|
||||
return "-Plus-"
|
||||
case '-':
|
||||
return "-Dash-"
|
||||
case '#':
|
||||
return "-Hashtag-"
|
||||
}
|
||||
return string(in)
|
||||
}
|
||||
|
||||
func cleanupEnumVariant(in string) string {
|
||||
replaced := ""
|
||||
for _, char := range in {
|
||||
replaced += replaceSpecialChar(char)
|
||||
}
|
||||
return replaced
|
||||
}
|
||||
|
||||
func dict(values ...interface{}) (map[string]interface{}, error) {
|
||||
if len(values)%2 != 0 {
|
||||
return nil, fmt.Errorf("expected even number of arguments, got %d", len(values))
|
||||
|
@ -580,3 +695,132 @@ func dict(values ...interface{}) (map[string]interface{}, error) {
|
|||
}
|
||||
return dict, nil
|
||||
}
|
||||
|
||||
func isInteger(arg interface{}) bool {
|
||||
// is integer determines if a value may be represented by an integer
|
||||
switch val := arg.(type) {
|
||||
case int8, int16, int32, int, int64, uint8, uint16, uint32, uint, uint64:
|
||||
return true
|
||||
case *int8, *int16, *int32, *int, *int64, *uint8, *uint16, *uint32, *uint, *uint64:
|
||||
v := reflect.ValueOf(arg)
|
||||
return !v.IsNil()
|
||||
case float64:
|
||||
return math.Round(val) == val
|
||||
case *float64:
|
||||
return val != nil && math.Round(*val) == *val
|
||||
case float32:
|
||||
return math.Round(float64(val)) == float64(val)
|
||||
case *float32:
|
||||
return val != nil && math.Round(float64(*val)) == float64(*val)
|
||||
case string:
|
||||
_, err := strconv.ParseInt(val, 10, 64)
|
||||
return err == nil
|
||||
case *string:
|
||||
if val == nil {
|
||||
return false
|
||||
}
|
||||
_, err := strconv.ParseInt(*val, 10, 64)
|
||||
return err == nil
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func resolvedDocCollectionFormat(cf string, child *GenItems) string {
|
||||
if child == nil {
|
||||
return cf
|
||||
}
|
||||
ccf := cf
|
||||
if ccf == "" {
|
||||
ccf = "csv"
|
||||
}
|
||||
rcf := resolvedDocCollectionFormat(child.CollectionFormat, child.Child)
|
||||
if rcf == "" {
|
||||
return ccf
|
||||
}
|
||||
return ccf + "|" + rcf
|
||||
}
|
||||
|
||||
func resolvedDocType(tn, ft string, child *GenItems) string {
|
||||
if tn == "array" {
|
||||
if child == nil {
|
||||
return "[]any"
|
||||
}
|
||||
return "[]" + resolvedDocType(child.SwaggerType, child.SwaggerFormat, child.Child)
|
||||
}
|
||||
|
||||
if ft != "" {
|
||||
if doc, ok := docFormat[ft]; ok {
|
||||
return doc
|
||||
}
|
||||
return fmt.Sprintf("%s (formatted %s)", ft, tn)
|
||||
}
|
||||
|
||||
return tn
|
||||
}
|
||||
|
||||
func resolvedDocSchemaType(tn, ft string, child *GenSchema) string {
|
||||
if tn == "array" {
|
||||
if child == nil {
|
||||
return "[]any"
|
||||
}
|
||||
return "[]" + resolvedDocSchemaType(child.SwaggerType, child.SwaggerFormat, child.Items)
|
||||
}
|
||||
|
||||
if tn == "object" {
|
||||
if child == nil || child.ElemType == nil {
|
||||
return "map of any"
|
||||
}
|
||||
if child.IsMap {
|
||||
return "map of " + resolvedDocElemType(child.SwaggerType, child.SwaggerFormat, &child.resolvedType)
|
||||
}
|
||||
|
||||
return child.GoType
|
||||
}
|
||||
|
||||
if ft != "" {
|
||||
if doc, ok := docFormat[ft]; ok {
|
||||
return doc
|
||||
}
|
||||
return fmt.Sprintf("%s (formatted %s)", ft, tn)
|
||||
}
|
||||
|
||||
return tn
|
||||
}
|
||||
|
||||
func resolvedDocElemType(tn, ft string, schema *resolvedType) string {
|
||||
if schema == nil {
|
||||
return ""
|
||||
}
|
||||
if schema.IsMap {
|
||||
return "map of " + resolvedDocElemType(schema.ElemType.SwaggerType, schema.ElemType.SwaggerFormat, schema.ElemType)
|
||||
}
|
||||
|
||||
if schema.IsArray {
|
||||
return "[]" + resolvedDocElemType(schema.ElemType.SwaggerType, schema.ElemType.SwaggerFormat, schema.ElemType)
|
||||
}
|
||||
|
||||
if ft != "" {
|
||||
if doc, ok := docFormat[ft]; ok {
|
||||
return doc
|
||||
}
|
||||
return fmt.Sprintf("%s (formatted %s)", ft, tn)
|
||||
}
|
||||
|
||||
return tn
|
||||
}
|
||||
|
||||
func httpStatus(code int) string {
|
||||
if name, ok := runtime.Statuses[code]; ok {
|
||||
return name
|
||||
}
|
||||
// non-standard codes deserve some name
|
||||
return fmt.Sprintf("Status %d", code)
|
||||
}
|
||||
|
||||
func gt0(in *int64) bool {
|
||||
// gt0 returns true if the *int64 points to a value > 0
|
||||
// NOTE: plain {{ gt .MinProperties 0 }} just refuses to work normally
|
||||
// with a pointer
|
||||
return in != nil && *in > 0
|
||||
}
|
||||
|
|
421
vendor/github.com/go-swagger/go-swagger/generator/types.go
generated
vendored
421
vendor/github.com/go-swagger/go-swagger/generator/types.go
generated
vendored
|
@ -17,8 +17,8 @@ package generator
|
|||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/loads"
|
||||
|
@ -69,10 +69,14 @@ func initTypes() {
|
|||
}
|
||||
}
|
||||
|
||||
func simpleResolvedType(tn, fmt string, items *spec.Items) (result resolvedType) {
|
||||
func simpleResolvedType(tn, fmt string, items *spec.Items, v *spec.CommonValidations) (result resolvedType) {
|
||||
result.SwaggerType = tn
|
||||
result.SwaggerFormat = fmt
|
||||
|
||||
defer func() {
|
||||
guardValidations(result.SwaggerType, v)
|
||||
}()
|
||||
|
||||
if tn == file {
|
||||
// special case of swagger type "file", rendered as io.ReadCloser interface
|
||||
result.IsPrimitive = true
|
||||
|
@ -82,7 +86,11 @@ func simpleResolvedType(tn, fmt string, items *spec.Items) (result resolvedType)
|
|||
}
|
||||
|
||||
if fmt != "" {
|
||||
fmtn := strings.Replace(fmt, "-", "", -1)
|
||||
defer func() {
|
||||
guardFormatConflicts(result.SwaggerFormat, v)
|
||||
}()
|
||||
|
||||
fmtn := strings.ReplaceAll(fmt, "-", "")
|
||||
if fmm, ok := formatMapping[tn]; ok {
|
||||
if tpe, ok := fmm[fmtn]; ok {
|
||||
result.GoType = tpe
|
||||
|
@ -114,7 +122,7 @@ func simpleResolvedType(tn, fmt string, items *spec.Items) (result resolvedType)
|
|||
result.GoType = "[]" + iface
|
||||
return
|
||||
}
|
||||
res := simpleResolvedType(items.Type, items.Format, items.Items)
|
||||
res := simpleResolvedType(items.Type, items.Format, items.Items, &items.CommonValidations)
|
||||
result.GoType = "[]" + res.GoType
|
||||
return
|
||||
}
|
||||
|
@ -123,22 +131,18 @@ func simpleResolvedType(tn, fmt string, items *spec.Items) (result resolvedType)
|
|||
return
|
||||
}
|
||||
|
||||
func typeForHeader(header spec.Header) resolvedType {
|
||||
return simpleResolvedType(header.Type, header.Format, header.Items)
|
||||
}
|
||||
|
||||
func newTypeResolver(pkg string, doc *loads.Document) *typeResolver {
|
||||
func newTypeResolver(pkg, fullPkg string, doc *loads.Document) *typeResolver {
|
||||
resolver := typeResolver{ModelsPackage: pkg, Doc: doc}
|
||||
resolver.KnownDefs = make(map[string]struct{}, len(doc.Spec().Definitions))
|
||||
for k, sch := range doc.Spec().Definitions {
|
||||
tpe, _, _ := knownDefGoType(k, sch, nil)
|
||||
tpe, _, _ := resolver.knownDefGoType(k, sch, nil)
|
||||
resolver.KnownDefs[tpe] = struct{}{}
|
||||
}
|
||||
return &resolver
|
||||
}
|
||||
|
||||
// knownDefGoType returns go type, package and package alias for definition
|
||||
func knownDefGoType(def string, schema spec.Schema, clear func(string) string) (string, string, string) {
|
||||
func (t typeResolver) knownDefGoType(def string, schema spec.Schema, clear func(string) string) (string, string, string) {
|
||||
debugLog("known def type: %q", def)
|
||||
ext := schema.Extensions
|
||||
nm, hasGoName := ext.GetString(xGoName)
|
||||
|
@ -147,8 +151,7 @@ func knownDefGoType(def string, schema spec.Schema, clear func(string) string) (
|
|||
debugLog("known def type %s named from %s as %q", def, xGoName, nm)
|
||||
def = nm
|
||||
}
|
||||
extType, isExternalType := hasExternalType(ext)
|
||||
|
||||
extType, isExternalType := t.resolveExternalType(ext)
|
||||
if !isExternalType || extType.Embedded {
|
||||
if clear == nil {
|
||||
debugLog("known def type no clear: %q", def)
|
||||
|
@ -159,7 +162,11 @@ func knownDefGoType(def string, schema spec.Schema, clear func(string) string) (
|
|||
}
|
||||
|
||||
// external type definition trumps regular type resolution
|
||||
log.Printf("type %s imported as external type %s.%s", def, extType.Import.Package, extType.Type)
|
||||
if extType.Import.Alias == "" {
|
||||
debugLog("type %s imported as external type %s, assumed in current package", def, extType.Type)
|
||||
return extType.Type, extType.Import.Package, extType.Import.Alias
|
||||
}
|
||||
debugLog("type %s imported as external type from %s as %s.%s", def, extType.Import.Package, extType.Import.Alias, extType.Type)
|
||||
return extType.Import.Alias + "." + extType.Type, extType.Import.Package, extType.Import.Alias
|
||||
}
|
||||
|
||||
|
@ -179,8 +186,9 @@ type externalTypeDefinition struct {
|
|||
Alias string
|
||||
}
|
||||
Hints struct {
|
||||
Kind string
|
||||
Nullable bool
|
||||
Kind string
|
||||
Nullable *bool
|
||||
NoValidation *bool
|
||||
}
|
||||
Embedded bool
|
||||
}
|
||||
|
@ -190,23 +198,57 @@ func hasExternalType(ext spec.Extensions) (*externalTypeDefinition, bool) {
|
|||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
var extType externalTypeDefinition
|
||||
err := mapstructure.Decode(v, &extType)
|
||||
if err != nil {
|
||||
log.Printf("warning: x-go-type extension could not be decoded (%v). Skipped", v)
|
||||
return nil, false
|
||||
}
|
||||
if extType.Import.Package != "" && extType.Import.Alias == "" {
|
||||
// NOTE(fred): possible name conflict here (TODO(fred): deconflict this default alias)
|
||||
extType.Import.Alias = path.Base(extType.Import.Package)
|
||||
}
|
||||
debugLogAsJSON("known def external %s type", xGoType, extType)
|
||||
|
||||
return &extType, true
|
||||
}
|
||||
|
||||
func (t typeResolver) resolveExternalType(ext spec.Extensions) (*externalTypeDefinition, bool) {
|
||||
extType, hasExt := hasExternalType(ext)
|
||||
if !hasExt {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// NOTE:
|
||||
// * basic deconfliction of the default alias
|
||||
// * if no package is specified, defaults to models (as provided from CLI or defaut generation location for models)
|
||||
toAlias := func(pkg string) string {
|
||||
mangled := GoLangOpts().ManglePackageName(pkg, "")
|
||||
return deconflictPkg(mangled, func(in string) string {
|
||||
return in + "ext"
|
||||
})
|
||||
}
|
||||
|
||||
switch {
|
||||
case extType.Import.Package != "" && extType.Import.Alias == "":
|
||||
extType.Import.Alias = toAlias(extType.Import.Package)
|
||||
case extType.Import.Package == "" && extType.Import.Alias != "":
|
||||
extType.Import.Package = t.ModelsFullPkg
|
||||
case extType.Import.Package == "" && extType.Import.Alias == "":
|
||||
// in this case, the external type is assumed to be present in the current package.
|
||||
// For completion, whenever this type is used in anonymous types declared by operations,
|
||||
// we assume this is the package where models are expected to be found.
|
||||
extType.Import.Package = t.ModelsFullPkg
|
||||
if extType.Import.Package != "" {
|
||||
extType.Import.Alias = toAlias(extType.Import.Package)
|
||||
}
|
||||
}
|
||||
|
||||
debugLogAsJSON("known def external %s type", xGoType, extType)
|
||||
|
||||
return extType, true
|
||||
}
|
||||
|
||||
type typeResolver struct {
|
||||
Doc *loads.Document
|
||||
ModelsPackage string
|
||||
ModelsPackage string // package alias (e.g. "models")
|
||||
ModelsFullPkg string // fully qualified package (e.g. "github.com/example/models")
|
||||
ModelName string
|
||||
KnownDefs map[string]struct{}
|
||||
// unexported fields
|
||||
|
@ -216,7 +258,7 @@ type typeResolver struct {
|
|||
|
||||
// NewWithModelName clones a type resolver and specifies a new model name
|
||||
func (t *typeResolver) NewWithModelName(name string) *typeResolver {
|
||||
tt := newTypeResolver(t.ModelsPackage, t.Doc)
|
||||
tt := newTypeResolver(t.ModelsPackage, t.ModelsFullPkg, t.Doc)
|
||||
tt.ModelName = name
|
||||
|
||||
// propagates kept definitions
|
||||
|
@ -236,24 +278,12 @@ func (t *typeResolver) withKeepDefinitionsPackage(definitionsPackage string) *ty
|
|||
return t
|
||||
}
|
||||
|
||||
// IsNullable hints the generator as to render the type with a pointer or not.
|
||||
//
|
||||
// A schema is deemed nullable (i.e. rendered by a pointer) when:
|
||||
// - a custom extension says it has to be so
|
||||
// - it is an object with properties
|
||||
// - it is a composed object (allOf)
|
||||
//
|
||||
// The interpretation of Required as a mean to make a type nullable is carried on elsewhere.
|
||||
func (t *typeResolver) IsNullable(schema *spec.Schema) bool {
|
||||
nullable := t.isNullable(schema)
|
||||
return nullable || len(schema.AllOf) > 0
|
||||
}
|
||||
|
||||
func (t *typeResolver) resolveSchemaRef(schema *spec.Schema, isRequired bool) (returns bool, result resolvedType, err error) {
|
||||
if schema.Ref.String() == "" {
|
||||
return
|
||||
}
|
||||
debugLog("resolving ref (anon: %t, req: %t) %s", false, isRequired, schema.Ref.String())
|
||||
|
||||
returns = true
|
||||
var ref *spec.Schema
|
||||
var er error
|
||||
|
@ -264,6 +294,13 @@ func (t *typeResolver) resolveSchemaRef(schema *spec.Schema, isRequired bool) (r
|
|||
err = er
|
||||
return
|
||||
}
|
||||
|
||||
extType, isExternalType := t.resolveExternalType(schema.Extensions)
|
||||
if isExternalType {
|
||||
// deal with validations for an aliased external type
|
||||
result.SkipExternalValidation = swag.BoolValue(extType.Hints.NoValidation)
|
||||
}
|
||||
|
||||
res, er := t.ResolveSchema(ref, false, isRequired)
|
||||
if er != nil {
|
||||
err = er
|
||||
|
@ -272,7 +309,7 @@ func (t *typeResolver) resolveSchemaRef(schema *spec.Schema, isRequired bool) (r
|
|||
result = res
|
||||
|
||||
tn := filepath.Base(schema.Ref.GetURL().Fragment)
|
||||
tpe, pkg, alias := knownDefGoType(tn, *ref, t.goTypeName)
|
||||
tpe, pkg, alias := t.knownDefGoType(tn, *ref, t.goTypeName)
|
||||
debugLog("type name %s, package %s, alias %s", tpe, pkg, alias)
|
||||
if tpe != "" {
|
||||
result.GoType = tpe
|
||||
|
@ -281,7 +318,7 @@ func (t *typeResolver) resolveSchemaRef(schema *spec.Schema, isRequired bool) (r
|
|||
}
|
||||
result.HasDiscriminator = res.HasDiscriminator
|
||||
result.IsBaseType = result.HasDiscriminator
|
||||
result.IsNullable = t.IsNullable(ref)
|
||||
result.IsNullable = result.IsNullable || t.isNullable(ref) // this has to be overriden for slices and maps
|
||||
result.IsEnumCI = false
|
||||
return
|
||||
}
|
||||
|
@ -304,7 +341,7 @@ func (t *typeResolver) resolveFormat(schema *spec.Schema, isAnonymous bool, isRe
|
|||
}
|
||||
|
||||
debugLog("resolving format (anon: %t, req: %t)", isAnonymous, isRequired)
|
||||
schFmt := strings.Replace(schema.Format, "-", "", -1)
|
||||
schFmt := strings.ReplaceAll(schema.Format, "-", "")
|
||||
if fmm, ok := formatMapping[result.SwaggerType]; ok {
|
||||
if tpe, ok := fmm[schFmt]; ok {
|
||||
returns = true
|
||||
|
@ -334,13 +371,33 @@ func (t *typeResolver) resolveFormat(schema *spec.Schema, isAnonymous bool, isRe
|
|||
case number, integer:
|
||||
result.IsNullable = nullableNumber(schema, isRequired)
|
||||
default:
|
||||
result.IsNullable = t.IsNullable(schema)
|
||||
result.IsNullable = t.isNullable(schema)
|
||||
}
|
||||
}
|
||||
|
||||
guardFormatConflicts(schema.Format, schema)
|
||||
return
|
||||
}
|
||||
|
||||
// isNullable hints the generator as to render the type with a pointer or not.
|
||||
//
|
||||
// A schema is deemed nullable (i.e. rendered by a pointer) when:
|
||||
// - a custom extension says it has to be so
|
||||
// - it is an object with properties
|
||||
// - it is a composed object (allOf)
|
||||
//
|
||||
// The interpretation of Required as a mean to make a type nullable is carried out elsewhere.
|
||||
func (t *typeResolver) isNullable(schema *spec.Schema) bool {
|
||||
|
||||
if nullable, ok := t.isNullableOverride(schema); ok {
|
||||
return nullable
|
||||
}
|
||||
|
||||
return len(schema.Properties) > 0 || len(schema.AllOf) > 0
|
||||
}
|
||||
|
||||
// isNullableOverride determines a nullable flag forced by an extension
|
||||
func (t *typeResolver) isNullableOverride(schema *spec.Schema) (bool, bool) {
|
||||
check := func(extension string) (bool, bool) {
|
||||
v, found := schema.Extensions[extension]
|
||||
nullable, cast := v.(bool)
|
||||
|
@ -348,12 +405,14 @@ func (t *typeResolver) isNullable(schema *spec.Schema) bool {
|
|||
}
|
||||
|
||||
if nullable, ok := check(xIsNullable); ok {
|
||||
return nullable
|
||||
return nullable, ok
|
||||
}
|
||||
|
||||
if nullable, ok := check(xNullable); ok {
|
||||
return nullable
|
||||
return nullable, ok
|
||||
}
|
||||
return len(schema.Properties) > 0
|
||||
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (t *typeResolver) firstType(schema *spec.Schema) string {
|
||||
|
@ -402,9 +461,30 @@ func (t *typeResolver) resolveArray(schema *spec.Schema, isAnonymous, isRequired
|
|||
err = er
|
||||
return
|
||||
}
|
||||
// override the general nullability rule from ResolveSchema():
|
||||
// only complex items are nullable (when not discriminated, not forced by x-nullable)
|
||||
rt.IsNullable = t.IsNullable(schema.Items.Schema) && !rt.HasDiscriminator
|
||||
|
||||
// Override the general nullability rule from ResolveSchema() in array elements:
|
||||
// - only complex items are nullable (when not discriminated, not forced by x-nullable)
|
||||
// - arrays of allOf have non nullable elements when not forced by x-nullable
|
||||
elem := schema.Items.Schema
|
||||
if elem.Ref.String() != "" {
|
||||
// drill into $ref to figure out whether we want the element type to nullable or not
|
||||
resolved, erf := spec.ResolveRef(t.Doc.Spec(), &elem.Ref)
|
||||
if erf != nil {
|
||||
debugLog("error resolving ref %s: %v", schema.Ref.String(), erf)
|
||||
}
|
||||
elem = resolved
|
||||
}
|
||||
|
||||
debugLogAsJSON("resolved item for %s", rt.GoType, elem)
|
||||
if nullable, ok := t.isNullableOverride(elem); ok {
|
||||
debugLog("found nullable override in element %s: %t", rt.GoType, nullable)
|
||||
rt.IsNullable = nullable
|
||||
} else {
|
||||
// this differs from isNullable for elements with AllOf
|
||||
debugLog("no nullable override in element %s: Properties: %t, HasDiscriminator: %t", rt.GoType, len(elem.Properties) > 0, rt.HasDiscriminator)
|
||||
rt.IsNullable = len(elem.Properties) > 0 && !rt.HasDiscriminator
|
||||
}
|
||||
|
||||
result.GoType = "[]" + rt.GoType
|
||||
if rt.IsNullable && !strings.HasPrefix(rt.GoType, "*") {
|
||||
result.GoType = "[]*" + rt.GoType
|
||||
|
@ -448,7 +528,7 @@ func (t *typeResolver) resolveObject(schema *spec.Schema, isAnonymous bool) (res
|
|||
result.IsBaseType = schema.Discriminator != ""
|
||||
if !isAnonymous {
|
||||
result.SwaggerType = object
|
||||
tpe, pkg, alias := knownDefGoType(t.ModelName, *schema, t.goTypeName)
|
||||
tpe, pkg, alias := t.knownDefGoType(t.ModelName, *schema, t.goTypeName)
|
||||
result.GoType = tpe
|
||||
result.Pkg = pkg
|
||||
result.PkgAlias = alias
|
||||
|
@ -457,12 +537,18 @@ func (t *typeResolver) resolveObject(schema *spec.Schema, isAnonymous bool) (res
|
|||
result.GoType = t.goTypeName(t.ModelName)
|
||||
result.IsComplexObject = true
|
||||
var isNullable bool
|
||||
for _, p := range schema.AllOf {
|
||||
if t.IsNullable(&p) {
|
||||
for _, sch := range schema.AllOf {
|
||||
p := sch
|
||||
if t.isNullable(&p) {
|
||||
isNullable = true
|
||||
}
|
||||
}
|
||||
result.IsNullable = isNullable
|
||||
if override, ok := t.isNullableOverride(schema); ok {
|
||||
// prioritize x-nullable extensions
|
||||
result.IsNullable = override
|
||||
} else {
|
||||
result.IsNullable = isNullable
|
||||
}
|
||||
result.SwaggerType = object
|
||||
return
|
||||
}
|
||||
|
@ -471,7 +557,7 @@ func (t *typeResolver) resolveObject(schema *spec.Schema, isAnonymous bool) (res
|
|||
// resolved type, this should also flag the object as anonymous,
|
||||
// when a ref is found, the anonymous flag will be reset
|
||||
if len(schema.Properties) > 0 {
|
||||
result.IsNullable = t.IsNullable(schema)
|
||||
result.IsNullable = t.isNullable(schema)
|
||||
result.IsComplexObject = true
|
||||
// no return here, still need to check for additional properties
|
||||
}
|
||||
|
@ -489,6 +575,12 @@ func (t *typeResolver) resolveObject(schema *spec.Schema, isAnonymous bool) (res
|
|||
|
||||
result.SwaggerType = object
|
||||
|
||||
if et.IsExternal {
|
||||
// external AdditionalProperties are a special case because we look ahead into schemas
|
||||
extType, _, _ := t.knownDefGoType(t.ModelName, *sch, t.goTypeName)
|
||||
et.GoType = extType
|
||||
}
|
||||
|
||||
// only complex map elements are nullable (when not forced by x-nullable)
|
||||
// TODO: figure out if required to check when not discriminated like arrays?
|
||||
et.IsNullable = t.isNullable(schema.AdditionalProperties.Schema)
|
||||
|
@ -544,11 +636,16 @@ func (t *typeResolver) resolveObject(schema *spec.Schema, isAnonymous bool) (res
|
|||
}
|
||||
|
||||
// an object without property and without AdditionalProperties schema is rendered as interface{}
|
||||
result.GoType = iface
|
||||
result.IsMap = true
|
||||
result.SwaggerType = object
|
||||
result.IsNullable = false
|
||||
result.IsInterface = len(schema.Properties) == 0
|
||||
// an object without properties but with MinProperties or MaxProperties is rendered as map[string]interface{}
|
||||
result.IsInterface = len(schema.Properties) == 0 && !schema.Validations().HasObjectValidations()
|
||||
if result.IsInterface {
|
||||
result.GoType = iface
|
||||
} else {
|
||||
result.GoType = "map[string]interface{}"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -656,21 +753,38 @@ func hasEnumCI(ve spec.Extensions) bool {
|
|||
return ok && isEnumCI
|
||||
}
|
||||
|
||||
func (t *typeResolver) shortCircuitResolveExternal(tpe, pkg, alias string, extType *externalTypeDefinition, schema *spec.Schema) resolvedType {
|
||||
func (t *typeResolver) shortCircuitResolveExternal(tpe, pkg, alias string, extType *externalTypeDefinition, schema *spec.Schema, isRequired bool) resolvedType {
|
||||
// short circuit type resolution for external types
|
||||
debugLogAsJSON("shortCircuitResolveExternal", extType)
|
||||
|
||||
var result resolvedType
|
||||
result.Extensions = schema.Extensions
|
||||
result.GoType = tpe
|
||||
result.Pkg = pkg
|
||||
result.PkgAlias = alias
|
||||
result.IsInterface = false
|
||||
// by default consider that we have a type with validations. Use hint "interface" or "noValidation" to disable validations
|
||||
result.SkipExternalValidation = swag.BoolValue(extType.Hints.NoValidation)
|
||||
result.IsNullable = isRequired
|
||||
|
||||
result.setKind(extType.Hints.Kind)
|
||||
result.IsNullable = t.IsNullable(schema)
|
||||
if result.IsInterface || result.IsStream {
|
||||
result.IsNullable = false
|
||||
}
|
||||
if extType.Hints.Nullable != nil {
|
||||
result.IsNullable = swag.BoolValue(extType.Hints.Nullable)
|
||||
}
|
||||
|
||||
if nullable, ok := t.isNullableOverride(schema); ok {
|
||||
result.IsNullable = nullable // x-nullable directive rules them all
|
||||
}
|
||||
|
||||
// other extensions
|
||||
if result.IsArray {
|
||||
result.IsEmptyOmitted = false
|
||||
tpe = "array"
|
||||
}
|
||||
|
||||
result.setExtensions(schema, tpe)
|
||||
return result
|
||||
}
|
||||
|
@ -687,32 +801,73 @@ func (t *typeResolver) ResolveSchema(schema *spec.Schema, isAnonymous, isRequire
|
|||
return
|
||||
}
|
||||
|
||||
extType, isExternalType := hasExternalType(schema.Extensions)
|
||||
extType, isExternalType := t.resolveExternalType(schema.Extensions)
|
||||
if isExternalType {
|
||||
tpe, pkg, alias := knownDefGoType(t.ModelName, *schema, t.goTypeName)
|
||||
debugLog("found type declared as external, imported from %s as %s. Has type hints? %t, rendered has embedded? %t",
|
||||
pkg, tpe, extType.Hints.Kind != "", extType.Embedded)
|
||||
tpe, pkg, alias := t.knownDefGoType(t.ModelName, *schema, t.goTypeName)
|
||||
debugLog("found type %s declared as external, imported from %s as %s. Has type hints? %t, rendered has embedded? %t",
|
||||
t.ModelName, pkg, tpe, extType.Hints.Kind != "", extType.Embedded)
|
||||
|
||||
if extType.Hints.Kind != "" && !extType.Embedded {
|
||||
// use hint to qualify type
|
||||
debugLog("short circuits external type resolution with hint for %s", tpe)
|
||||
result = t.shortCircuitResolveExternal(tpe, pkg, alias, extType, schema)
|
||||
result = t.shortCircuitResolveExternal(tpe, pkg, alias, extType, schema, isRequired)
|
||||
result.IsExternal = isAnonymous // mark anonymous external types only, not definitions
|
||||
return
|
||||
}
|
||||
|
||||
// use spec to qualify type
|
||||
debugLog("marking type %s as external embedded: %t", tpe, extType.Embedded)
|
||||
// mark this type as an embedded external definition if requested
|
||||
defer func() {
|
||||
defer func() { // enforce bubbling up decisions taken about being an external type
|
||||
// mark this type as an embedded external definition if requested
|
||||
result.IsEmbedded = extType.Embedded
|
||||
result.IsExternal = isAnonymous // for non-embedded, mark anonymous external types only, not definitions
|
||||
|
||||
result.IsAnonymous = false
|
||||
result.IsAliased = true
|
||||
result.IsNullable = isRequired
|
||||
if extType.Hints.Nullable != nil {
|
||||
result.IsNullable = swag.BoolValue(extType.Hints.Nullable)
|
||||
}
|
||||
|
||||
result.IsMap = false
|
||||
result.AliasedType = result.GoType
|
||||
result.IsInterface = false
|
||||
|
||||
if result.IsEmbedded {
|
||||
result.ElemType = &resolvedType{
|
||||
GoType: extType.Import.Alias + "." + extType.Type,
|
||||
Pkg: extType.Import.Package,
|
||||
PkgAlias: extType.Import.Alias,
|
||||
IsNullable: extType.Hints.Nullable,
|
||||
IsExternal: isAnonymous, // mark anonymous external types only, not definitions
|
||||
IsInterface: false,
|
||||
Pkg: extType.Import.Package,
|
||||
PkgAlias: extType.Import.Alias,
|
||||
SkipExternalValidation: swag.BoolValue(extType.Hints.NoValidation),
|
||||
}
|
||||
result.setKind(extType.Hints.Kind)
|
||||
if extType.Import.Alias != "" {
|
||||
result.ElemType.GoType = extType.Import.Alias + "." + extType.Type
|
||||
} else {
|
||||
result.ElemType.GoType = extType.Type
|
||||
}
|
||||
result.ElemType.setKind(extType.Hints.Kind)
|
||||
if result.IsInterface || result.IsStream {
|
||||
result.ElemType.IsNullable = false
|
||||
}
|
||||
if extType.Hints.Nullable != nil {
|
||||
result.ElemType.IsNullable = swag.BoolValue(extType.Hints.Nullable)
|
||||
}
|
||||
// embedded external: by default consider validation is skipped for the external type
|
||||
//
|
||||
// NOTE: at this moment the template generates a type assertion, so this setting does not really matter
|
||||
// for embedded types.
|
||||
if extType.Hints.NoValidation != nil {
|
||||
result.ElemType.SkipExternalValidation = swag.BoolValue(extType.Hints.NoValidation)
|
||||
} else {
|
||||
result.ElemType.SkipExternalValidation = true
|
||||
}
|
||||
} else {
|
||||
// non-embedded external type: by default consider that validation is enabled (SkipExternalValidation: false)
|
||||
result.SkipExternalValidation = swag.BoolValue(extType.Hints.NoValidation)
|
||||
}
|
||||
if nullable, ok := t.isNullableOverride(schema); ok {
|
||||
result.IsNullable = nullable
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
@ -720,15 +875,16 @@ func (t *typeResolver) ResolveSchema(schema *spec.Schema, isAnonymous, isRequire
|
|||
tpe := t.firstType(schema)
|
||||
var returns bool
|
||||
|
||||
guardValidations(tpe, schema, schema.Type...)
|
||||
|
||||
returns, result, err = t.resolveSchemaRef(schema, isRequired)
|
||||
|
||||
if returns {
|
||||
if !isAnonymous {
|
||||
result.IsMap = false
|
||||
result.IsComplexObject = true
|
||||
debugLog("not anonymous ref")
|
||||
}
|
||||
debugLog("anonymous after ref")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -793,6 +949,18 @@ func (t *typeResolver) ResolveSchema(schema *spec.Schema, isAnonymous, isRequire
|
|||
result.HasDiscriminator = schema.Discriminator != ""
|
||||
|
||||
case "null":
|
||||
if schema.Validations().HasObjectValidations() {
|
||||
// no explicit object type, but inferred from object validations:
|
||||
// this makes the type a map[string]interface{} instead of interface{}
|
||||
result, err = t.resolveObject(schema, isAnonymous)
|
||||
if err != nil {
|
||||
result = resolvedType{}
|
||||
break
|
||||
}
|
||||
result.HasDiscriminator = schema.Discriminator != ""
|
||||
break
|
||||
}
|
||||
|
||||
result.GoType = iface
|
||||
result.SwaggerType = object
|
||||
result.IsNullable = false
|
||||
|
@ -801,9 +969,89 @@ func (t *typeResolver) ResolveSchema(schema *spec.Schema, isAnonymous, isRequire
|
|||
default:
|
||||
err = fmt.Errorf("unresolvable: %v (format %q)", schema.Type, schema.Format)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func warnSkipValidation(types interface{}) func(string, interface{}) {
|
||||
return func(validation string, value interface{}) {
|
||||
value = reflect.Indirect(reflect.ValueOf(value)).Interface()
|
||||
log.Printf("warning: validation %s (value: %v) not compatible with type %v. Skipped", validation, value, types)
|
||||
}
|
||||
}
|
||||
|
||||
// guardValidations removes (with a warning) validations that don't fit with the schema type.
|
||||
//
|
||||
// Notice that the "enum" validation is allowed on any type but file.
|
||||
func guardValidations(tpe string, schema interface {
|
||||
Validations() spec.SchemaValidations
|
||||
SetValidations(spec.SchemaValidations)
|
||||
}, types ...string) {
|
||||
|
||||
v := schema.Validations()
|
||||
if len(types) == 0 {
|
||||
types = []string{tpe}
|
||||
}
|
||||
defer func() {
|
||||
schema.SetValidations(v)
|
||||
}()
|
||||
|
||||
if tpe != array {
|
||||
v.ClearArrayValidations(warnSkipValidation(types))
|
||||
}
|
||||
|
||||
if tpe != str && tpe != file {
|
||||
v.ClearStringValidations(warnSkipValidation(types))
|
||||
}
|
||||
|
||||
if tpe != object {
|
||||
v.ClearObjectValidations(warnSkipValidation(types))
|
||||
}
|
||||
|
||||
if tpe != number && tpe != integer {
|
||||
v.ClearNumberValidations(warnSkipValidation(types))
|
||||
}
|
||||
|
||||
if tpe == file {
|
||||
// keep MinLength/MaxLength on file
|
||||
if v.Pattern != "" {
|
||||
warnSkipValidation(types)("pattern", v.Pattern)
|
||||
v.Pattern = ""
|
||||
}
|
||||
if v.HasEnum() {
|
||||
warnSkipValidation(types)("enum", v.Enum)
|
||||
v.Enum = nil
|
||||
}
|
||||
}
|
||||
|
||||
// other cases: mapped as interface{}: no validations allowed but Enum
|
||||
}
|
||||
|
||||
// guardFormatConflicts handles all conflicting properties
|
||||
// (for schema model or simple schema) when a format is set.
|
||||
//
|
||||
// At this moment, validation guards already handle all known conflicts, but for the
|
||||
// special case of binary (i.e. io.Reader).
|
||||
func guardFormatConflicts(format string, schema interface {
|
||||
Validations() spec.SchemaValidations
|
||||
SetValidations(spec.SchemaValidations)
|
||||
}) {
|
||||
v := schema.Validations()
|
||||
msg := fmt.Sprintf("for format %q", format)
|
||||
|
||||
// for this format, no additional validations are supported
|
||||
if format == "binary" {
|
||||
// no validations supported on binary fields at this moment (io.Reader)
|
||||
v.ClearStringValidations(warnSkipValidation(msg))
|
||||
if v.HasEnum() {
|
||||
warnSkipValidation(msg)
|
||||
v.Enum = nil
|
||||
}
|
||||
schema.SetValidations(v)
|
||||
}
|
||||
// more cases should be inserted here if they arise
|
||||
}
|
||||
|
||||
// resolvedType is a swagger type that has been resolved and analyzed for usage
|
||||
// in a template
|
||||
type resolvedType struct {
|
||||
|
@ -820,6 +1068,7 @@ type resolvedType struct {
|
|||
IsJSONString bool
|
||||
IsEnumCI bool
|
||||
IsBase64 bool
|
||||
IsExternal bool
|
||||
|
||||
// A tuple gets rendered as an anonymous struct with P{index} as property name
|
||||
IsTuple bool
|
||||
|
@ -855,9 +1104,12 @@ type resolvedType struct {
|
|||
// is generated in models that embeds the external type, with the Validate
|
||||
// method.
|
||||
IsEmbedded bool
|
||||
|
||||
SkipExternalValidation bool
|
||||
}
|
||||
|
||||
func (rt *resolvedType) Zero() string {
|
||||
// Zero returns an initializer for the type
|
||||
func (rt resolvedType) Zero() string {
|
||||
// if type is aliased, provide zero from the aliased type
|
||||
if rt.IsAliased {
|
||||
if zr, ok := zeroes[rt.AliasedType]; ok {
|
||||
|
@ -889,10 +1141,39 @@ func (rt *resolvedType) Zero() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
// ToString returns a string conversion for a type akin to a string
|
||||
func (rt resolvedType) ToString(value string) string {
|
||||
if !rt.IsPrimitive || rt.SwaggerType != "string" || rt.IsStream {
|
||||
return ""
|
||||
}
|
||||
if rt.IsCustomFormatter {
|
||||
if rt.IsAliased {
|
||||
return fmt.Sprintf("%s(%s).String()", rt.AliasedType, value)
|
||||
}
|
||||
return fmt.Sprintf("%s.String()", value)
|
||||
}
|
||||
var deref string
|
||||
if rt.IsNullable {
|
||||
deref = "*"
|
||||
}
|
||||
if rt.GoType == "string" || rt.GoType == "*string" {
|
||||
return fmt.Sprintf("%s%s", deref, value)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("string(%s%s)", deref, value)
|
||||
}
|
||||
|
||||
func (rt *resolvedType) setExtensions(schema *spec.Schema, origType string) {
|
||||
rt.IsEnumCI = hasEnumCI(schema.Extensions)
|
||||
rt.setIsEmptyOmitted(schema, origType)
|
||||
rt.setIsJSONString(schema, origType)
|
||||
|
||||
if customTag, found := schema.Extensions[xGoCustomTag]; found {
|
||||
if rt.Extensions == nil {
|
||||
rt.Extensions = make(spec.Extensions)
|
||||
}
|
||||
rt.Extensions[xGoCustomTag] = customTag
|
||||
}
|
||||
}
|
||||
|
||||
func (rt *resolvedType) setIsEmptyOmitted(schema *spec.Schema, tpe string) {
|
||||
|
|
3
vendor/github.com/go-swagger/go-swagger/scan/README.md
generated
vendored
Normal file
3
vendor/github.com/go-swagger/go-swagger/scan/README.md
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
# scan
|
||||
|
||||
Pre go1.11 version of the go source parser, without support for go modules.
|
6
vendor/github.com/go-swagger/go-swagger/scan/classifier.go
generated
vendored
6
vendor/github.com/go-swagger/go-swagger/scan/classifier.go
generated
vendored
|
@ -119,7 +119,7 @@ func (pc *programClassifier) Classify(prog *loader.Program) (*classifiedProgram,
|
|||
if seenStruct == "" || seenStruct == matches[1] {
|
||||
seenStruct = matches[1]
|
||||
} else {
|
||||
return nil, fmt.Errorf("classifier: already annotated as %s, can't also be %q", seenStruct, matches[1])
|
||||
return nil, fmt.Errorf("classifier: already annotated as %s, can't also be %q - %s", seenStruct, matches[1], cline.Text)
|
||||
}
|
||||
case "meta":
|
||||
if !mt {
|
||||
|
@ -134,7 +134,7 @@ func (pc *programClassifier) Classify(prog *loader.Program) (*classifiedProgram,
|
|||
if seenStruct == "" || seenStruct == matches[1] {
|
||||
seenStruct = matches[1]
|
||||
} else {
|
||||
return nil, fmt.Errorf("classifier: already annotated as %s, can't also be %q", seenStruct, matches[1])
|
||||
return nil, fmt.Errorf("classifier: already annotated as %s, can't also be %q - %s", seenStruct, matches[1], cline.Text)
|
||||
}
|
||||
case "response":
|
||||
if !rs {
|
||||
|
@ -144,7 +144,7 @@ func (pc *programClassifier) Classify(prog *loader.Program) (*classifiedProgram,
|
|||
if seenStruct == "" || seenStruct == matches[1] {
|
||||
seenStruct = matches[1]
|
||||
} else {
|
||||
return nil, fmt.Errorf("classifier: already annotated as %s, can't also be %q", seenStruct, matches[1])
|
||||
return nil, fmt.Errorf("classifier: already annotated as %s, can't also be %q - %s", seenStruct, matches[1], cline.Text)
|
||||
}
|
||||
case "strfmt", "name", "discriminated", "file", "enum", "default", "alias", "type":
|
||||
// TODO: perhaps collect these and pass along to avoid lookups later on
|
||||
|
|
2
vendor/github.com/go-swagger/go-swagger/scan/doc.go
generated
vendored
2
vendor/github.com/go-swagger/go-swagger/scan/doc.go
generated
vendored
|
@ -16,6 +16,8 @@
|
|||
|
||||
/*Package scan provides a scanner for go files that produces a swagger spec document.
|
||||
|
||||
This package is intended for pre-go1.11 versions, and does not support go modules.
|
||||
|
||||
You give it a main file and it will parse all the files that are required by that main
|
||||
package to produce a swagger specification.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue