mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-09 12:37:49 +00:00
Working through what changed rabbit hole
Parameter dependencies mean we're back in the ball of yarn stage. Coverage is going to drop for a bit, until all the new hashing and interfaces are in place.
This commit is contained in:
@@ -4,11 +4,14 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Example represents a low-level Example object as defined by OpenAPI 3+
|
||||
@@ -26,6 +29,28 @@ func (ex *Example) FindExtension(ext string) *low.ValueReference[any] {
|
||||
return low.FindItemInMap[any](ext, ex.Extensions)
|
||||
}
|
||||
|
||||
// Hash will return a consistent SHA256 Hash of the Discriminator object
|
||||
func (ex *Example) Hash() [32]byte {
|
||||
var f []string
|
||||
if ex.Summary.Value != "" {
|
||||
f = append(f, ex.Summary.Value)
|
||||
}
|
||||
if ex.Description.Value != "" {
|
||||
f = append(f, ex.Description.Value)
|
||||
}
|
||||
if ex.Value.Value != "" {
|
||||
// this could be anything!
|
||||
f = append(f, fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(ex.Value.Value)))))
|
||||
}
|
||||
if ex.ExternalValue.Value != "" {
|
||||
f = append(f, ex.ExternalValue.Value)
|
||||
}
|
||||
for k := range ex.Extensions {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, sha256.Sum256([]byte(fmt.Sprint(ex.Extensions[k].Value)))))
|
||||
}
|
||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||
}
|
||||
|
||||
// Build extracts extensions and example value
|
||||
func (ex *Example) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
ex.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
@@ -43,8 +43,12 @@ func (x *XML) Hash() [32]byte {
|
||||
x.Name.Value,
|
||||
x.Namespace.Value,
|
||||
x.Prefix.Value,
|
||||
fmt.Sprintf("%v", x.Attribute.Value),
|
||||
fmt.Sprintf("%v", x.Wrapped.Value),
|
||||
fmt.Sprint(x.Attribute.Value),
|
||||
fmt.Sprint(x.Wrapped.Value),
|
||||
}
|
||||
// add extensions to hash
|
||||
for k := range x.Extensions {
|
||||
d = append(d, fmt.Sprintf("%v-%x", k.Value, x.Extensions[k].Value))
|
||||
}
|
||||
return sha256.Sum256([]byte(strings.Join(d, "|")))
|
||||
}
|
||||
|
||||
@@ -548,6 +548,9 @@ func ExtractExtensions(root *yaml.Node) map[KeyReference[string]]ValueReference[
|
||||
|
||||
// AreEqual returns true if two Hashable objects are equal or not.
|
||||
func AreEqual(l, r Hashable) bool {
|
||||
if l == nil || r == nil {
|
||||
return false
|
||||
}
|
||||
return l.Hash() == r.Hash()
|
||||
}
|
||||
|
||||
|
||||
37
datamodel/low/model_interfaces.go
Normal file
37
datamodel/low/model_interfaces.go
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package low
|
||||
|
||||
type IsParameter interface {
|
||||
GetName() *NodeReference[string]
|
||||
GetIn() *NodeReference[string]
|
||||
GetType() *NodeReference[string]
|
||||
GetDescription() *NodeReference[string]
|
||||
GetRequired() *NodeReference[bool]
|
||||
GetDeprecated() *NodeReference[bool]
|
||||
GetAllowEmptyValue() *NodeReference[bool]
|
||||
GetFormat() *NodeReference[string]
|
||||
GetStyle() *NodeReference[string]
|
||||
GetCollectionFormat() *NodeReference[string]
|
||||
GetDefault() *NodeReference[any]
|
||||
GetAllowReserved() *NodeReference[bool]
|
||||
GetExplode() *NodeReference[bool]
|
||||
GetMaximum() *NodeReference[int]
|
||||
GetExclusiveMaximum() *NodeReference[bool]
|
||||
GetMinimum() *NodeReference[int]
|
||||
GetExclusiveMinimum() *NodeReference[bool]
|
||||
GetMaxLength() *NodeReference[int]
|
||||
GetMinLength() *NodeReference[int]
|
||||
GetPattern() *NodeReference[string]
|
||||
GetMaxItems() *NodeReference[int]
|
||||
GetMinItems() *NodeReference[int]
|
||||
GetUniqueItems() *NodeReference[bool]
|
||||
GetEnum() *NodeReference[[]ValueReference[string]]
|
||||
GetMultipleOf() *NodeReference[int]
|
||||
GetExample() *NodeReference[any]
|
||||
GetExamples() *NodeReference[any] // requires cast
|
||||
GetSchema() *NodeReference[any] // requires cast.
|
||||
GetContent() *NodeReference[any] // requires cast.
|
||||
GetItems() *NodeReference[any] // requires cast.
|
||||
}
|
||||
@@ -4,10 +4,13 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Items is a low-level representation of a Swagger / OpenAPI 2 Items object.
|
||||
@@ -35,6 +38,45 @@ type Items struct {
|
||||
MultipleOf low.NodeReference[int]
|
||||
}
|
||||
|
||||
// Hash will return a consistent SHA256 Hash of the Items object
|
||||
func (i *Items) Hash() [32]byte {
|
||||
var f []string
|
||||
if i.Type.Value != "" {
|
||||
f = append(f, i.Type.Value)
|
||||
}
|
||||
if i.Format.Value != "" {
|
||||
f = append(f, i.Format.Value)
|
||||
}
|
||||
if i.CollectionFormat.Value != "" {
|
||||
f = append(f, i.CollectionFormat.Value)
|
||||
}
|
||||
if i.Default.Value != "" {
|
||||
f = append(f, fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(i.Default.Value)))))
|
||||
}
|
||||
f = append(f, fmt.Sprint(i.Maximum.Value))
|
||||
f = append(f, fmt.Sprint(i.Minimum.Value))
|
||||
f = append(f, fmt.Sprint(i.ExclusiveMinimum.Value))
|
||||
f = append(f, fmt.Sprint(i.ExclusiveMaximum.Value))
|
||||
f = append(f, fmt.Sprint(i.MinLength.Value))
|
||||
f = append(f, fmt.Sprint(i.MaxLength.Value))
|
||||
f = append(f, fmt.Sprint(i.MinItems.Value))
|
||||
f = append(f, fmt.Sprint(i.MaxItems.Value))
|
||||
f = append(f, fmt.Sprint(i.MultipleOf.Value))
|
||||
f = append(f, fmt.Sprint(i.UniqueItems.Value))
|
||||
if i.Pattern.Value != "" {
|
||||
f = append(f, fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(i.Pattern.Value)))))
|
||||
}
|
||||
if len(i.Enum.Value) > 0 {
|
||||
for k := range i.Enum.Value {
|
||||
f = append(f, fmt.Sprint(i.Enum.Value[k].Value))
|
||||
}
|
||||
}
|
||||
if i.Items.Value != nil {
|
||||
f = append(f, fmt.Sprintf("%x", i.Items.Value.Hash()))
|
||||
}
|
||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||
}
|
||||
|
||||
// Build will build out items and default value.
|
||||
func (i *Items) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
items, iErr := low.ExtractObject[*Items](ItemsLabel, root, idx)
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Parameter represents a low-level Swagger / OpenAPI 2 Parameter object.
|
||||
@@ -123,3 +126,163 @@ func (p *Parameter) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hash will return a consistent SHA256 Hash of the Parameter object
|
||||
func (p *Parameter) Hash() [32]byte {
|
||||
var f []string
|
||||
if p.Name.Value != "" {
|
||||
f = append(f, p.Name.Value)
|
||||
}
|
||||
if p.In.Value != "" {
|
||||
f = append(f, p.In.Value)
|
||||
}
|
||||
if p.Type.Value != "" {
|
||||
f = append(f, p.Type.Value)
|
||||
}
|
||||
if p.Format.Value != "" {
|
||||
f = append(f, p.Format.Value)
|
||||
}
|
||||
if p.Description.Value != "" {
|
||||
f = append(f, p.Description.Value)
|
||||
}
|
||||
f = append(f, fmt.Sprint(p.Required.Value))
|
||||
f = append(f, fmt.Sprint(p.AllowEmptyValue.Value))
|
||||
if p.Schema.Value != nil {
|
||||
f = append(f, fmt.Sprintf("%x", p.Schema.Value.Schema().Hash()))
|
||||
}
|
||||
if p.CollectionFormat.Value != "" {
|
||||
f = append(f, p.CollectionFormat.Value)
|
||||
}
|
||||
if p.Default.Value != "" {
|
||||
f = append(f, fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(p.Default.Value)))))
|
||||
}
|
||||
f = append(f, fmt.Sprint(p.Maximum.Value))
|
||||
f = append(f, fmt.Sprint(p.Minimum.Value))
|
||||
f = append(f, fmt.Sprint(p.ExclusiveMinimum.Value))
|
||||
f = append(f, fmt.Sprint(p.ExclusiveMaximum.Value))
|
||||
f = append(f, fmt.Sprint(p.MinLength.Value))
|
||||
f = append(f, fmt.Sprint(p.MaxLength.Value))
|
||||
f = append(f, fmt.Sprint(p.MinItems.Value))
|
||||
f = append(f, fmt.Sprint(p.MaxItems.Value))
|
||||
f = append(f, fmt.Sprint(p.MultipleOf.Value))
|
||||
f = append(f, fmt.Sprint(p.UniqueItems.Value))
|
||||
if p.Pattern.Value != "" {
|
||||
f = append(f, fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(p.Pattern.Value)))))
|
||||
}
|
||||
if len(p.Enum.Value) > 0 {
|
||||
for k := range p.Enum.Value {
|
||||
f = append(f, fmt.Sprint(p.Enum.Value[k].Value))
|
||||
}
|
||||
}
|
||||
for k := range p.Extensions {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, sha256.Sum256([]byte(fmt.Sprint(p.Extensions[k].Value)))))
|
||||
}
|
||||
if p.Items.Value != nil {
|
||||
f = append(f, fmt.Sprintf("%x", p.Items.Value.Hash()))
|
||||
}
|
||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||
}
|
||||
|
||||
// IsParameter compliance methods.
|
||||
|
||||
func (p *Parameter) GetName() *low.NodeReference[string] {
|
||||
return &p.Name
|
||||
}
|
||||
func (p *Parameter) GetIn() *low.NodeReference[string] {
|
||||
return &p.In
|
||||
}
|
||||
func (p *Parameter) GetType() *low.NodeReference[string] {
|
||||
return &p.Type
|
||||
}
|
||||
func (p *Parameter) GetDescription() *low.NodeReference[string] {
|
||||
return &p.Description
|
||||
}
|
||||
func (p *Parameter) GetRequired() *low.NodeReference[bool] {
|
||||
return &p.Required
|
||||
}
|
||||
func (p *Parameter) GetDeprecated() *low.NodeReference[bool] {
|
||||
// not implemented.
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetAllowEmptyValue() *low.NodeReference[bool] {
|
||||
return &p.AllowEmptyValue
|
||||
}
|
||||
func (p *Parameter) GetSchema() *low.NodeReference[any] {
|
||||
i := low.NodeReference[any]{
|
||||
KeyNode: p.Schema.KeyNode,
|
||||
ValueNode: p.Schema.ValueNode,
|
||||
Value: p.Schema.KeyNode,
|
||||
}
|
||||
return &i
|
||||
}
|
||||
func (p *Parameter) GetFormat() *low.NodeReference[string] {
|
||||
return &p.Format
|
||||
}
|
||||
func (p *Parameter) GetItems() *low.NodeReference[any] {
|
||||
i := low.NodeReference[any]{
|
||||
KeyNode: p.Items.KeyNode,
|
||||
ValueNode: p.Items.ValueNode,
|
||||
Value: p.Items.KeyNode,
|
||||
}
|
||||
return &i
|
||||
}
|
||||
func (p *Parameter) GetStyle() *low.NodeReference[string] {
|
||||
return nil // not implemented
|
||||
}
|
||||
func (p *Parameter) GetCollectionFormat() *low.NodeReference[string] {
|
||||
return &p.CollectionFormat
|
||||
}
|
||||
func (p *Parameter) GetDefault() *low.NodeReference[any] {
|
||||
return &p.Default
|
||||
}
|
||||
func (p *Parameter) GetAllowReserved() *low.NodeReference[bool] {
|
||||
return nil // not implemented
|
||||
}
|
||||
func (p *Parameter) GetExplode() *low.NodeReference[bool] {
|
||||
return nil // not implemented
|
||||
}
|
||||
func (p *Parameter) GetMaximum() *low.NodeReference[int] {
|
||||
return &p.Maximum
|
||||
}
|
||||
func (p *Parameter) GetExclusiveMaximum() *low.NodeReference[bool] {
|
||||
return &p.ExclusiveMaximum
|
||||
}
|
||||
func (p *Parameter) GetMinimum() *low.NodeReference[int] {
|
||||
return &p.Minimum
|
||||
}
|
||||
func (p *Parameter) GetExclusiveMinimum() *low.NodeReference[bool] {
|
||||
return &p.ExclusiveMinimum
|
||||
}
|
||||
func (p *Parameter) GetMaxLength() *low.NodeReference[int] {
|
||||
return &p.MaxLength
|
||||
}
|
||||
func (p *Parameter) GetMinLength() *low.NodeReference[int] {
|
||||
return &p.MinLength
|
||||
}
|
||||
func (p *Parameter) GetPattern() *low.NodeReference[string] {
|
||||
return &p.Pattern
|
||||
}
|
||||
func (p *Parameter) GetMaxItems() *low.NodeReference[int] {
|
||||
return &p.MaxItems
|
||||
}
|
||||
func (p *Parameter) GetMinItems() *low.NodeReference[int] {
|
||||
return &p.MaxItems
|
||||
}
|
||||
func (p *Parameter) GetUniqueItems() *low.NodeReference[bool] {
|
||||
return &p.UniqueItems
|
||||
}
|
||||
func (p *Parameter) GetEnum() *low.NodeReference[[]low.ValueReference[string]] {
|
||||
return &p.Enum
|
||||
}
|
||||
func (p *Parameter) GetMultipleOf() *low.NodeReference[int] {
|
||||
return &p.MultipleOf
|
||||
}
|
||||
func (p *Parameter) GetExample() *low.NodeReference[any] {
|
||||
return nil // not implemented
|
||||
}
|
||||
func (p *Parameter) GetExamples() *low.NodeReference[any] {
|
||||
return nil // not implemented
|
||||
}
|
||||
func (p *Parameter) GetContent() *low.NodeReference[any] {
|
||||
return nil // not implemented
|
||||
}
|
||||
|
||||
@@ -93,4 +93,10 @@ const (
|
||||
RefLabel = "$ref"
|
||||
DiscriminatorLabel = "discriminator"
|
||||
ExternalDocsLabel = "externalDocs"
|
||||
InLabel = "in"
|
||||
AllowEmptyValueLabel = "allowEmptyValue"
|
||||
StyleLabel = "style"
|
||||
CollectionFormatLabel = "collectionFormat"
|
||||
AllowReservedLabel = "allowReserved"
|
||||
ExplodeLabel = "explode"
|
||||
)
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Encoding represents a low-level OpenAPI 3+ Encoding object
|
||||
@@ -24,6 +27,25 @@ func (en *Encoding) FindHeader(hType string) *low.ValueReference[*Header] {
|
||||
return low.FindItemInMap[*Header](hType, en.Headers.Value)
|
||||
}
|
||||
|
||||
// Hash will return a consistent SHA256 Hash of the Encoding object
|
||||
func (en *Encoding) Hash() [32]byte {
|
||||
var f []string
|
||||
if en.ContentType.Value != "" {
|
||||
f = append(f, en.ContentType.Value)
|
||||
}
|
||||
if len(en.Headers.Value) > 0 {
|
||||
for k := range en.Headers.Value {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, en.Headers.Value[k].Value.Hash()))
|
||||
}
|
||||
}
|
||||
if en.Style.Value != "" {
|
||||
f = append(f, en.Style.Value)
|
||||
}
|
||||
f = append(f, fmt.Sprint(sha256.Sum256([]byte(fmt.Sprint(en.Explode.Value)))))
|
||||
f = append(f, fmt.Sprint(sha256.Sum256([]byte(fmt.Sprint(en.AllowReserved.Value)))))
|
||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||
}
|
||||
|
||||
// Build will extract all Header objects from supplied node.
|
||||
func (en *Encoding) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
headers, hL, hN, err := low.ExtractMap[*Header](HeadersLabel, root, idx)
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Header represents a low-level OpenAPI 3+ Header object.
|
||||
@@ -43,6 +46,42 @@ func (h *Header) FindContent(ext string) *low.ValueReference[*MediaType] {
|
||||
return low.FindItemInMap[*MediaType](ext, h.Content.Value)
|
||||
}
|
||||
|
||||
// Hash will return a consistent SHA256 Hash of the Header object
|
||||
func (h *Header) Hash() [32]byte {
|
||||
var f []string
|
||||
if h.Description.Value != "" {
|
||||
f = append(f, h.Description.Value)
|
||||
}
|
||||
f = append(f, fmt.Sprint(sha256.Sum256([]byte(fmt.Sprint(h.Required.Value)))))
|
||||
f = append(f, fmt.Sprint(sha256.Sum256([]byte(fmt.Sprint(h.Deprecated.Value)))))
|
||||
f = append(f, fmt.Sprint(sha256.Sum256([]byte(fmt.Sprint(h.AllowEmptyValue.Value)))))
|
||||
if h.Style.Value != "" {
|
||||
f = append(f, h.Style.Value)
|
||||
}
|
||||
f = append(f, fmt.Sprint(sha256.Sum256([]byte(fmt.Sprint(h.Explode.Value)))))
|
||||
f = append(f, fmt.Sprint(sha256.Sum256([]byte(fmt.Sprint(h.AllowReserved.Value)))))
|
||||
if h.Schema.Value != nil {
|
||||
f = append(f, fmt.Sprint(h.Schema.Value.Schema().Hash()))
|
||||
}
|
||||
if h.Example.Value != nil {
|
||||
f = append(f, fmt.Sprint(sha256.Sum256([]byte(fmt.Sprint(h.Example.Value)))))
|
||||
}
|
||||
if len(h.Examples.Value) > 0 {
|
||||
for k := range h.Examples.Value {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, h.Examples.Value[k].Value.Hash()))
|
||||
}
|
||||
}
|
||||
if len(h.Content.Value) > 0 {
|
||||
for k := range h.Content.Value {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, h.Content.Value[k].Value.Hash()))
|
||||
}
|
||||
}
|
||||
for k := range h.Extensions {
|
||||
f = append(f, fmt.Sprintf("%s-%v", k.Value, h.Extensions[k].Value))
|
||||
}
|
||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||
}
|
||||
|
||||
// Build will extract extensions, examples, schema and content/media types from node.
|
||||
func (h *Header) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
h.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// MediaType represents a low-level OpenAPI MediaType object.
|
||||
@@ -89,3 +92,28 @@ func (mt *MediaType) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hash will return a consistent SHA256 Hash of the MediaType object
|
||||
func (mt *MediaType) Hash() [32]byte {
|
||||
var f []string
|
||||
if mt.Schema.Value != nil {
|
||||
f = append(f, fmt.Sprintf("%x", mt.Schema.Value.Schema().Hash()))
|
||||
}
|
||||
if mt.Example.Value != nil {
|
||||
f = append(f, fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprint(mt.Example.Value)))))
|
||||
}
|
||||
if len(mt.Examples.Value) > 0 {
|
||||
for k := range mt.Examples.Value {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, mt.Examples.Value[k].Value.Hash()))
|
||||
}
|
||||
}
|
||||
if len(mt.Encoding.Value) > 0 {
|
||||
for k := range mt.Encoding.Value {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, mt.Encoding.Value[k].Value.Hash()))
|
||||
}
|
||||
}
|
||||
for k := range mt.Extensions {
|
||||
f = append(f, fmt.Sprintf("%s-%v", k.Value, mt.Extensions[k].Value))
|
||||
}
|
||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||
}
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Parameter represents a high-level OpenAPI 3+ Parameter object, that is backed by a low-level one.
|
||||
@@ -91,3 +94,155 @@ func (p *Parameter) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hash will return a consistent SHA256 Hash of the Parameter object
|
||||
func (p *Parameter) Hash() [32]byte {
|
||||
var f []string
|
||||
if p.Name.Value != "" {
|
||||
f = append(f, p.Name.Value)
|
||||
}
|
||||
if p.In.Value != "" {
|
||||
f = append(f, p.In.Value)
|
||||
}
|
||||
if p.Description.Value != "" {
|
||||
f = append(f, p.Description.Value)
|
||||
}
|
||||
f = append(f, fmt.Sprint(p.Required.Value))
|
||||
f = append(f, fmt.Sprint(p.Deprecated.Value))
|
||||
f = append(f, fmt.Sprint(p.AllowEmptyValue.Value))
|
||||
if p.Style.Value != "" {
|
||||
f = append(f, fmt.Sprint(p.Style.Value))
|
||||
}
|
||||
f = append(f, fmt.Sprint(p.Explode.Value))
|
||||
f = append(f, fmt.Sprint(p.AllowReserved.Value))
|
||||
if p.Schema.Value != nil {
|
||||
f = append(f, fmt.Sprintf("%x", p.Schema.Value.Schema().Hash()))
|
||||
}
|
||||
if p.Example.Value != nil {
|
||||
f = append(f, fmt.Sprintf("%x", p.Example.Value))
|
||||
}
|
||||
if len(p.Examples.Value) > 0 {
|
||||
for k := range p.Examples.Value {
|
||||
f = append(f, fmt.Sprintf("%s-%x", k.Value, p.Examples.Value[k].Value.Hash()))
|
||||
}
|
||||
}
|
||||
if len(p.Extensions) > 0 {
|
||||
for k := range p.Extensions {
|
||||
f = append(f, fmt.Sprintf("%v-%x", k.Value, p.Extensions[k].Value))
|
||||
}
|
||||
}
|
||||
if len(p.Content.Value) > 0 {
|
||||
for k := range p.Content.Value {
|
||||
f = append(f, fmt.Sprintf("%v-%x", k.Value, p.Content.Value[k].Value.Hash()))
|
||||
}
|
||||
}
|
||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||
}
|
||||
|
||||
// IsParameter compliance methods.
|
||||
|
||||
func (p *Parameter) GetName() *low.NodeReference[string] {
|
||||
return &p.Name
|
||||
}
|
||||
func (p *Parameter) GetIn() *low.NodeReference[string] {
|
||||
return &p.In
|
||||
}
|
||||
func (p *Parameter) GetType() *low.NodeReference[string] {
|
||||
return nil // not implemented
|
||||
}
|
||||
func (p *Parameter) GetDescription() *low.NodeReference[string] {
|
||||
return &p.Description
|
||||
}
|
||||
func (p *Parameter) GetRequired() *low.NodeReference[bool] {
|
||||
return &p.Required
|
||||
}
|
||||
func (p *Parameter) GetDeprecated() *low.NodeReference[bool] {
|
||||
return &p.Deprecated
|
||||
}
|
||||
func (p *Parameter) GetAllowEmptyValue() *low.NodeReference[bool] {
|
||||
return &p.AllowEmptyValue
|
||||
}
|
||||
func (p *Parameter) GetSchema() *low.NodeReference[any] {
|
||||
i := low.NodeReference[any]{
|
||||
KeyNode: p.Schema.KeyNode,
|
||||
ValueNode: p.Schema.ValueNode,
|
||||
Value: p.Schema.KeyNode,
|
||||
}
|
||||
return &i
|
||||
}
|
||||
func (p *Parameter) GetFormat() *low.NodeReference[string] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetItems() *low.NodeReference[any] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetStyle() *low.NodeReference[string] {
|
||||
return &p.Style
|
||||
}
|
||||
func (p *Parameter) GetCollectionFormat() *low.NodeReference[string] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetDefault() *low.NodeReference[any] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetAllowReserved() *low.NodeReference[bool] {
|
||||
return &p.AllowReserved
|
||||
}
|
||||
func (p *Parameter) GetExplode() *low.NodeReference[bool] {
|
||||
return &p.Explode
|
||||
}
|
||||
func (p *Parameter) GetMaximum() *low.NodeReference[int] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetExclusiveMaximum() *low.NodeReference[bool] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetMinimum() *low.NodeReference[int] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetExclusiveMinimum() *low.NodeReference[bool] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetMaxLength() *low.NodeReference[int] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetMinLength() *low.NodeReference[int] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetPattern() *low.NodeReference[string] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetMaxItems() *low.NodeReference[int] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetMinItems() *low.NodeReference[int] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetUniqueItems() *low.NodeReference[bool] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetEnum() *low.NodeReference[[]low.ValueReference[string]] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetMultipleOf() *low.NodeReference[int] {
|
||||
return nil
|
||||
}
|
||||
func (p *Parameter) GetExample() *low.NodeReference[any] {
|
||||
return &p.Example
|
||||
}
|
||||
func (p *Parameter) GetExamples() *low.NodeReference[any] {
|
||||
i := low.NodeReference[any]{
|
||||
KeyNode: p.Examples.KeyNode,
|
||||
ValueNode: p.Examples.ValueNode,
|
||||
Value: p.Examples.KeyNode,
|
||||
}
|
||||
return &i
|
||||
}
|
||||
func (p *Parameter) GetContent() *low.NodeReference[any] {
|
||||
c := low.NodeReference[any]{
|
||||
KeyNode: p.Content.KeyNode,
|
||||
ValueNode: p.Content.ValueNode,
|
||||
Value: p.Content.Value,
|
||||
}
|
||||
return &c
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ import (
|
||||
|
||||
// CreateChange is a generic function that will create a Change of type T, populate all properties if set, and then
|
||||
// add a pointer to Change[T] in the slice of Change pointers provided
|
||||
func CreateChange[T any](changes *[]*Change[T], changeType int, property string, leftValueNode, rightValueNode *yaml.Node,
|
||||
breaking bool, originalObject, newObject any) *[]*Change[T] {
|
||||
func CreateChange(changes *[]*Change, changeType int, property string, leftValueNode, rightValueNode *yaml.Node,
|
||||
breaking bool, originalObject, newObject any) *[]*Change {
|
||||
|
||||
// create a new context for the left and right nodes.
|
||||
ctx := CreateContext(leftValueNode, rightValueNode)
|
||||
c := &Change[T]{
|
||||
c := &Change{
|
||||
Context: ctx,
|
||||
ChangeType: changeType,
|
||||
Property: property,
|
||||
@@ -70,7 +70,7 @@ func FlattenLowLevelMap[T any](
|
||||
}
|
||||
|
||||
// CountBreakingChanges counts the number of changes in a slice that are breaking
|
||||
func CountBreakingChanges[T any](changes []*Change[T]) int {
|
||||
func CountBreakingChanges(changes []*Change) int {
|
||||
b := 0
|
||||
for i := range changes {
|
||||
if changes[i].Breaking {
|
||||
@@ -87,17 +87,17 @@ func CountBreakingChanges[T any](changes []*Change[T]) int {
|
||||
// scenarios that adding things should break anything). Removals are generally breaking, except for non contract
|
||||
// properties like descriptions, summaries and other non-binding values, so a breakingRemove value can be tuned for
|
||||
// these circumstances.
|
||||
func CheckForObjectAdditionOrRemoval[T any](l, r map[string]*low.ValueReference[T], label string, changes *[]*Change[T],
|
||||
func CheckForObjectAdditionOrRemoval[T any](l, r map[string]*low.ValueReference[T], label string, changes *[]*Change,
|
||||
breakingAdd, breakingRemove bool) {
|
||||
var left, right T
|
||||
if CheckSpecificObjectRemoved(l, r, label) {
|
||||
left = l[label].GetValue()
|
||||
CreateChange[T](changes, ObjectRemoved, label, l[label].GetValueNode(), nil,
|
||||
CreateChange(changes, ObjectRemoved, label, l[label].GetValueNode(), nil,
|
||||
breakingRemove, left, right)
|
||||
}
|
||||
if CheckSpecificObjectAdded(l, r, label) {
|
||||
right = r[label].GetValue()
|
||||
CreateChange[T](changes, ObjectAdded, label, nil, r[label].GetValueNode(),
|
||||
CreateChange(changes, ObjectAdded, label, nil, r[label].GetValueNode(),
|
||||
breakingAdd, left, right)
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ func CheckSpecificObjectAdded[T any](l, r map[string]*T, label string) bool {
|
||||
// for running checks on the following methods in order:
|
||||
// CheckPropertyAdditionOrRemoval
|
||||
// CheckForModification
|
||||
func CheckProperties[T any](properties []*PropertyCheck[T]) {
|
||||
func CheckProperties(properties []*PropertyCheck) {
|
||||
for _, n := range properties {
|
||||
CheckPropertyAdditionOrRemoval(n.LeftNode, n.RightNode, n.Label, n.Changes, n.Breaking, n.Original, n.New)
|
||||
CheckForModification(n.LeftNode, n.RightNode, n.Label, n.Changes, n.Breaking, n.Original, n.New)
|
||||
@@ -125,7 +125,7 @@ func CheckProperties[T any](properties []*PropertyCheck[T]) {
|
||||
|
||||
// CheckPropertyAdditionOrRemoval will run both CheckForRemoval (first) and CheckForAddition (second)
|
||||
func CheckPropertyAdditionOrRemoval[T any](l, r *yaml.Node,
|
||||
label string, changes *[]*Change[T], breaking bool, orig, new T) {
|
||||
label string, changes *[]*Change, breaking bool, orig, new T) {
|
||||
CheckForRemoval[T](l, r, label, changes, breaking, orig, new)
|
||||
CheckForAddition[T](l, r, label, changes, breaking, orig, new)
|
||||
}
|
||||
@@ -136,9 +136,9 @@ func CheckPropertyAdditionOrRemoval[T any](l, r *yaml.Node,
|
||||
// PropertyRemoved
|
||||
//
|
||||
// The Change is then added to the slice of []Change[T] instances provided as a pointer.
|
||||
func CheckForRemoval[T any](l, r *yaml.Node, label string, changes *[]*Change[T], breaking bool, orig, new T) {
|
||||
func CheckForRemoval[T any](l, r *yaml.Node, label string, changes *[]*Change, breaking bool, orig, new T) {
|
||||
if l != nil && l.Value != "" && (r == nil || r.Value == "") {
|
||||
CreateChange[T](changes, PropertyRemoved, label, l, r, breaking, orig, new)
|
||||
CreateChange(changes, PropertyRemoved, label, l, r, breaking, orig, new)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,9 +148,9 @@ func CheckForRemoval[T any](l, r *yaml.Node, label string, changes *[]*Change[T]
|
||||
// PropertyAdded
|
||||
//
|
||||
// The Change is then added to the slice of []Change[T] instances provided as a pointer.
|
||||
func CheckForAddition[T any](l, r *yaml.Node, label string, changes *[]*Change[T], breaking bool, orig, new T) {
|
||||
func CheckForAddition[T any](l, r *yaml.Node, label string, changes *[]*Change, breaking bool, orig, new T) {
|
||||
if (l == nil || l.Value == "") && r != nil && r.Value != "" {
|
||||
CreateChange[T](changes, PropertyAdded, label, l, r, breaking, orig, new)
|
||||
CreateChange(changes, PropertyAdded, label, l, r, breaking, orig, new)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,13 +160,13 @@ func CheckForAddition[T any](l, r *yaml.Node, label string, changes *[]*Change[T
|
||||
// If there is a change in value the function adds a change type of Modified.
|
||||
//
|
||||
// The Change is then added to the slice of []Change[T] instances provided as a pointer.
|
||||
func CheckForModification[T any](l, r *yaml.Node, label string, changes *[]*Change[T], breaking bool, orig, new T) {
|
||||
func CheckForModification[T any](l, r *yaml.Node, label string, changes *[]*Change, breaking bool, orig, new T) {
|
||||
if l != nil && l.Value != "" && r != nil && r.Value != "" && r.Value != l.Value && r.Tag == l.Tag {
|
||||
CreateChange[T](changes, Modified, label, l, r, breaking, orig, new)
|
||||
CreateChange(changes, Modified, label, l, r, breaking, orig, new)
|
||||
}
|
||||
// the values may have not changed, but the tag (node type) type may have
|
||||
if l != nil && l.Value != "" && r != nil && r.Value != "" && r.Value != l.Value && r.Tag != l.Tag {
|
||||
CreateChange[T](changes, Modified, label, l, r, breaking, orig, new)
|
||||
CreateChange(changes, Modified, label, l, r, breaking, orig, new)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// ContactChanges Represent changes to a Contact object that is a child of Info, part of an OpenAPI document.
|
||||
type ContactChanges struct {
|
||||
PropertyChanges[*base.Contact]
|
||||
PropertyChanges
|
||||
}
|
||||
|
||||
// TotalChanges represents the total number of changes that have occurred to a Contact object
|
||||
@@ -28,11 +28,11 @@ func (c *ContactChanges) TotalBreakingChanges() int {
|
||||
// returns nil.
|
||||
func CompareContact(l, r *base.Contact) *ContactChanges {
|
||||
|
||||
var changes []*Change[*base.Contact]
|
||||
var props []*PropertyCheck[*base.Contact]
|
||||
var changes []*Change
|
||||
var props []*PropertyCheck
|
||||
|
||||
// check URL
|
||||
props = append(props, &PropertyCheck[*base.Contact]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.URL.ValueNode,
|
||||
RightNode: r.URL.ValueNode,
|
||||
Label: v3.URLLabel,
|
||||
@@ -43,7 +43,7 @@ func CompareContact(l, r *base.Contact) *ContactChanges {
|
||||
})
|
||||
|
||||
// check name
|
||||
props = append(props, &PropertyCheck[*base.Contact]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Name.ValueNode,
|
||||
RightNode: r.Name.ValueNode,
|
||||
Label: v3.NameLabel,
|
||||
@@ -54,7 +54,7 @@ func CompareContact(l, r *base.Contact) *ContactChanges {
|
||||
})
|
||||
|
||||
// check email
|
||||
props = append(props, &PropertyCheck[*base.Contact]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Email.ValueNode,
|
||||
RightNode: r.Email.ValueNode,
|
||||
Label: v3.EmailLabel,
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
|
||||
// DiscriminatorChanges represents changes made to a Discriminator OpenAPI object
|
||||
type DiscriminatorChanges struct {
|
||||
PropertyChanges[*base.Discriminator]
|
||||
MappingChanges []*Change[string]
|
||||
PropertyChanges
|
||||
MappingChanges []*Change
|
||||
}
|
||||
|
||||
// TotalChanges returns a count of everything changed within the Discriminator object
|
||||
@@ -35,12 +35,12 @@ func (d *DiscriminatorChanges) TotalBreakingChanges() int {
|
||||
// and will return a pointer to DiscriminatorChanges
|
||||
func CompareDiscriminator(l, r *base.Discriminator) *DiscriminatorChanges {
|
||||
dc := new(DiscriminatorChanges)
|
||||
var changes []*Change[*base.Discriminator]
|
||||
var props []*PropertyCheck[*base.Discriminator]
|
||||
var mapping []*Change[string]
|
||||
var changes []*Change
|
||||
var props []*PropertyCheck
|
||||
var mapping []*Change
|
||||
|
||||
// Name (breaking change)
|
||||
props = append(props, &PropertyCheck[*base.Discriminator]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.PropertyName.ValueNode,
|
||||
RightNode: r.PropertyName.ValueNode,
|
||||
Label: v3.PropertyNameLabel,
|
||||
@@ -63,7 +63,7 @@ func CompareDiscriminator(l, r *base.Discriminator) *DiscriminatorChanges {
|
||||
// if the existing tag exists, let's check it.
|
||||
if rMap[i] != nil {
|
||||
if lMap[i].Value != rMap[i].Value {
|
||||
CreateChange[string](&mapping, Modified, i, lMap[i].GetValueNode(),
|
||||
CreateChange(&mapping, Modified, i, lMap[i].GetValueNode(),
|
||||
rMap[i].GetValueNode(), true, lMap[i].GetValue(), rMap[i].GetValue())
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ func CompareDiscriminator(l, r *base.Discriminator) *DiscriminatorChanges {
|
||||
|
||||
for i := range rMap {
|
||||
if lMap[i] == nil {
|
||||
CreateChange[string](&mapping, ObjectAdded, i, nil,
|
||||
CreateChange(&mapping, ObjectAdded, i, nil,
|
||||
rMap[i].GetValueNode(), false, nil, rMap[i].GetValue())
|
||||
}
|
||||
}
|
||||
|
||||
9
what-changed/encoding.go
Normal file
9
what-changed/encoding.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package what_changed
|
||||
|
||||
type EncodingChanges struct {
|
||||
ParameterChanges
|
||||
HeaderChanges *HeaderChanges
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// ExampleChanges represent changes to an Example object, part of an OpenAPI specification.
|
||||
type ExampleChanges struct {
|
||||
PropertyChanges[*base.Example]
|
||||
PropertyChanges
|
||||
ExtensionChanges *ExtensionChanges
|
||||
}
|
||||
|
||||
@@ -23,16 +23,25 @@ func (e *ExampleChanges) TotalChanges() int {
|
||||
return l
|
||||
}
|
||||
|
||||
// TotalBreakingChanges returns the total number of breaking changes made to Example
|
||||
func (e *ExampleChanges) TotalBreakingChanges() int {
|
||||
l := e.PropertyChanges.TotalBreakingChanges()
|
||||
if e.ExtensionChanges != nil {
|
||||
l += e.ExtensionChanges.PropertyChanges.TotalBreakingChanges()
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// TotalChanges
|
||||
|
||||
func CompareExamples(l, r *base.Example) *ExampleChanges {
|
||||
|
||||
ec := new(ExampleChanges)
|
||||
var changes []*Change[*base.Example]
|
||||
var props []*PropertyCheck[*base.Example]
|
||||
var changes []*Change
|
||||
var props []*PropertyCheck
|
||||
|
||||
// Summary
|
||||
props = append(props, &PropertyCheck[*base.Example]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Summary.ValueNode,
|
||||
RightNode: r.Summary.ValueNode,
|
||||
Label: v3.SummaryLabel,
|
||||
@@ -43,7 +52,7 @@ func CompareExamples(l, r *base.Example) *ExampleChanges {
|
||||
})
|
||||
|
||||
// Description
|
||||
props = append(props, &PropertyCheck[*base.Example]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Description.ValueNode,
|
||||
RightNode: r.Description.ValueNode,
|
||||
Label: v3.DescriptionLabel,
|
||||
@@ -54,7 +63,7 @@ func CompareExamples(l, r *base.Example) *ExampleChanges {
|
||||
})
|
||||
|
||||
// Value
|
||||
props = append(props, &PropertyCheck[*base.Example]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Value.ValueNode,
|
||||
RightNode: r.Value.ValueNode,
|
||||
Label: v3.ValueLabel,
|
||||
@@ -65,7 +74,7 @@ func CompareExamples(l, r *base.Example) *ExampleChanges {
|
||||
})
|
||||
|
||||
// ExternalValue
|
||||
props = append(props, &PropertyCheck[*base.Example]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.ExternalValue.ValueNode,
|
||||
RightNode: r.ExternalValue.ValueNode,
|
||||
Label: v3.ExternalValue,
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// ExtensionChanges represents any changes to custom extensions defined for an OpenAPI object.
|
||||
type ExtensionChanges struct {
|
||||
PropertyChanges[any]
|
||||
PropertyChanges
|
||||
}
|
||||
|
||||
func (e *ExtensionChanges) TotalChanges() int {
|
||||
@@ -42,15 +42,15 @@ func CompareExtensions(l, r map[low.KeyReference[string]]low.ValueReference[any]
|
||||
seenRight[strings.ToLower(i.Value)] = &h
|
||||
}
|
||||
|
||||
var changes []*Change[any]
|
||||
var changes []*Change
|
||||
for i := range seenLeft {
|
||||
|
||||
CheckForObjectAdditionOrRemoval[any](seenLeft, seenRight, i, &changes, false, true)
|
||||
|
||||
if seenRight[i] != nil {
|
||||
var props []*PropertyCheck[any]
|
||||
var props []*PropertyCheck
|
||||
|
||||
props = append(props, &PropertyCheck[any]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: seenLeft[i].ValueNode,
|
||||
RightNode: seenRight[i].ValueNode,
|
||||
Label: i,
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// ExternalDocChanges represents changes made to any ExternalDoc object from an OpenAPI document.
|
||||
type ExternalDocChanges struct {
|
||||
PropertyChanges[*base.ExternalDoc]
|
||||
PropertyChanges
|
||||
ExtensionChanges *ExtensionChanges
|
||||
}
|
||||
|
||||
@@ -32,11 +32,11 @@ func (e *ExternalDocChanges) TotalBreakingChanges() int {
|
||||
// nodes for any changes between them. If there are changes, then a pointer to ExternalDocChanges
|
||||
// is returned, otherwise if nothing changed - then nil is returned.
|
||||
func CompareExternalDocs(l, r *base.ExternalDoc) *ExternalDocChanges {
|
||||
var changes []*Change[*base.ExternalDoc]
|
||||
var props []*PropertyCheck[*base.ExternalDoc]
|
||||
var changes []*Change
|
||||
var props []*PropertyCheck
|
||||
|
||||
// URL
|
||||
props = append(props, &PropertyCheck[*base.ExternalDoc]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.URL.ValueNode,
|
||||
RightNode: r.URL.ValueNode,
|
||||
Label: v3.URLLabel,
|
||||
@@ -47,7 +47,7 @@ func CompareExternalDocs(l, r *base.ExternalDoc) *ExternalDocChanges {
|
||||
})
|
||||
|
||||
// description.
|
||||
props = append(props, &PropertyCheck[*base.ExternalDoc]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Description.ValueNode,
|
||||
RightNode: r.Description.ValueNode,
|
||||
Label: v3.DescriptionLabel,
|
||||
|
||||
40
what-changed/header_changes.go
Normal file
40
what-changed/header_changes.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package what_changed
|
||||
|
||||
type HeaderChanges struct {
|
||||
PropertyChanges
|
||||
SchemaChanges *SchemaChanges
|
||||
ExampleChanges map[string]*ExampleChanges
|
||||
ContentChanges map[string]*MediaTypeChanges
|
||||
ExtensionChanges *ExtensionChanges
|
||||
}
|
||||
|
||||
func (h *HeaderChanges) TotalChanges() int {
|
||||
c := len(h.Changes)
|
||||
for k := range h.ExampleChanges {
|
||||
c += h.ExampleChanges[k].TotalChanges()
|
||||
}
|
||||
for k := range h.ContentChanges {
|
||||
c += h.ContentChanges[k].TotalChanges()
|
||||
}
|
||||
if h.ExtensionChanges != nil {
|
||||
c += h.ExtensionChanges.TotalChanges()
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (h *HeaderChanges) TotalBreakingChanges() int {
|
||||
c := len(h.Changes)
|
||||
for k := range h.ExampleChanges {
|
||||
c += h.ExampleChanges[k].TotalChanges()
|
||||
}
|
||||
for k := range h.ContentChanges {
|
||||
c += h.ContentChanges[k].TotalChanges()
|
||||
}
|
||||
if h.ExtensionChanges != nil {
|
||||
c += h.ExtensionChanges.TotalChanges()
|
||||
}
|
||||
return c
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// InfoChanges represents the number of changes to an Info object. Part of an OpenAPI document
|
||||
type InfoChanges struct {
|
||||
PropertyChanges[*base.Info]
|
||||
PropertyChanges
|
||||
ContactChanges *ContactChanges
|
||||
LicenseChanges *LicenseChanges
|
||||
}
|
||||
@@ -37,11 +37,11 @@ func (i *InfoChanges) TotalBreakingChanges() int {
|
||||
// returned instead.
|
||||
func CompareInfo(l, r *base.Info) *InfoChanges {
|
||||
|
||||
var changes []*Change[*base.Info]
|
||||
var props []*PropertyCheck[*base.Info]
|
||||
var changes []*Change
|
||||
var props []*PropertyCheck
|
||||
|
||||
// Title
|
||||
props = append(props, &PropertyCheck[*base.Info]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Title.ValueNode,
|
||||
RightNode: r.Title.ValueNode,
|
||||
Label: v3.TitleLabel,
|
||||
@@ -52,7 +52,7 @@ func CompareInfo(l, r *base.Info) *InfoChanges {
|
||||
})
|
||||
|
||||
// Description
|
||||
props = append(props, &PropertyCheck[*base.Info]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Description.ValueNode,
|
||||
RightNode: r.Description.ValueNode,
|
||||
Label: v3.DescriptionLabel,
|
||||
@@ -63,7 +63,7 @@ func CompareInfo(l, r *base.Info) *InfoChanges {
|
||||
})
|
||||
|
||||
// TermsOfService
|
||||
props = append(props, &PropertyCheck[*base.Info]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.TermsOfService.ValueNode,
|
||||
RightNode: r.TermsOfService.ValueNode,
|
||||
Label: v3.TermsOfServiceLabel,
|
||||
@@ -74,7 +74,7 @@ func CompareInfo(l, r *base.Info) *InfoChanges {
|
||||
})
|
||||
|
||||
// Version
|
||||
props = append(props, &PropertyCheck[*base.Info]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Version.ValueNode,
|
||||
RightNode: r.Version.ValueNode,
|
||||
Label: v3.VersionLabel,
|
||||
@@ -94,11 +94,11 @@ func CompareInfo(l, r *base.Info) *InfoChanges {
|
||||
i.ContactChanges = CompareContact(l.Contact.Value, r.Contact.Value)
|
||||
} else {
|
||||
if l.Contact.Value == nil && r.Contact.Value != nil {
|
||||
CreateChange[*base.Info](&changes, ObjectAdded, v3.ContactLabel,
|
||||
CreateChange(&changes, ObjectAdded, v3.ContactLabel,
|
||||
nil, r.Contact.ValueNode, false, nil, r.Contact.Value)
|
||||
}
|
||||
if l.Contact.Value != nil && r.Contact.Value == nil {
|
||||
CreateChange[*base.Info](&changes, ObjectRemoved, v3.ContactLabel,
|
||||
CreateChange(&changes, ObjectRemoved, v3.ContactLabel,
|
||||
l.Contact.ValueNode, nil, false, l.Contact.Value, nil)
|
||||
}
|
||||
}
|
||||
@@ -108,11 +108,11 @@ func CompareInfo(l, r *base.Info) *InfoChanges {
|
||||
i.LicenseChanges = CompareLicense(l.License.Value, r.License.Value)
|
||||
} else {
|
||||
if l.License.Value == nil && r.License.Value != nil {
|
||||
CreateChange[*base.Info](&changes, ObjectAdded, v3.LicenseLabel,
|
||||
CreateChange(&changes, ObjectAdded, v3.LicenseLabel,
|
||||
nil, r.License.ValueNode, false, nil, r.License.Value)
|
||||
}
|
||||
if l.License.Value != nil && r.License.Value == nil {
|
||||
CreateChange[*base.Info](&changes, ObjectRemoved, v3.LicenseLabel,
|
||||
CreateChange(&changes, ObjectRemoved, v3.LicenseLabel,
|
||||
l.License.ValueNode, nil, false, r.License.Value, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// LicenseChanges represent changes to a License object that is a child of Info object. Part of an OpenAPI document
|
||||
type LicenseChanges struct {
|
||||
PropertyChanges[*base.License]
|
||||
PropertyChanges
|
||||
}
|
||||
|
||||
// TotalChanges represents the total number of changes made to a License instance.
|
||||
@@ -28,11 +28,11 @@ func (l *LicenseChanges) TotalBreakingChanges() int {
|
||||
// returns nil.
|
||||
func CompareLicense(l, r *base.License) *LicenseChanges {
|
||||
|
||||
var changes []*Change[*base.License]
|
||||
var props []*PropertyCheck[*base.License]
|
||||
var changes []*Change
|
||||
var props []*PropertyCheck
|
||||
|
||||
// check URL
|
||||
props = append(props, &PropertyCheck[*base.License]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.URL.ValueNode,
|
||||
RightNode: r.URL.ValueNode,
|
||||
Label: v3.URLLabel,
|
||||
@@ -43,7 +43,7 @@ func CompareLicense(l, r *base.License) *LicenseChanges {
|
||||
})
|
||||
|
||||
// check name
|
||||
props = append(props, &PropertyCheck[*base.License]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Name.ValueNode,
|
||||
RightNode: r.Name.ValueNode,
|
||||
Label: v3.NameLabel,
|
||||
|
||||
12
what-changed/media_type.go
Normal file
12
what-changed/media_type.go
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package what_changed
|
||||
|
||||
type MediaTypeChanges struct {
|
||||
PropertyChanges
|
||||
SchemaChanges *SchemaChanges
|
||||
ExtensionChanges *ExtensionChanges
|
||||
ExampleChanges map[string]*ExampleChanges
|
||||
EncodingChanges *EncodingChanges
|
||||
}
|
||||
@@ -54,7 +54,7 @@ func (c *ChangeContext) HasChanged() bool {
|
||||
}
|
||||
|
||||
// Change represents a change between two different elements inside an OpenAPI specification.
|
||||
type Change[T any] struct {
|
||||
type Change struct {
|
||||
|
||||
// Context represents the lines and column numbers of the original and new values
|
||||
// It's worth noting that these values may frequently be different and are not used to calculate
|
||||
@@ -83,18 +83,18 @@ type Change[T any] struct {
|
||||
NewObject any
|
||||
}
|
||||
|
||||
// PropertyChanges holds a slice of Change[T] change pointers
|
||||
type PropertyChanges[T any] struct {
|
||||
Changes []*Change[T]
|
||||
// PropertyChanges holds a slice of Change pointers
|
||||
type PropertyChanges struct {
|
||||
Changes []*Change
|
||||
}
|
||||
|
||||
// TotalChanges returns the total number of property changes made.
|
||||
func (p PropertyChanges[T]) TotalChanges() int {
|
||||
func (p PropertyChanges) TotalChanges() int {
|
||||
return len(p.Changes)
|
||||
}
|
||||
|
||||
// TotalBreakingChanges returns the total number of property breaking changes made.
|
||||
func (p PropertyChanges[T]) TotalBreakingChanges() int {
|
||||
func (p PropertyChanges) TotalBreakingChanges() int {
|
||||
return CountBreakingChanges(p.Changes)
|
||||
}
|
||||
|
||||
@@ -107,13 +107,13 @@ func (p PropertyChanges[T]) TotalBreakingChanges() int {
|
||||
//}
|
||||
|
||||
// PropertyCheck is used by functions to check the state of left and right values.
|
||||
type PropertyCheck[T any] struct {
|
||||
type PropertyCheck struct {
|
||||
|
||||
// Original is the property we're checking on the left
|
||||
Original T
|
||||
Original any
|
||||
|
||||
// New is s the property we're checking on the right
|
||||
New T
|
||||
New any
|
||||
|
||||
// Label is the identifier we're looking for on the left and right hand sides
|
||||
Label string
|
||||
@@ -128,7 +128,7 @@ type PropertyCheck[T any] struct {
|
||||
Breaking bool
|
||||
|
||||
// Changes represents a pointer to the slice to contain all changes found.
|
||||
Changes *[]*Change[T]
|
||||
Changes *[]*Change
|
||||
}
|
||||
|
||||
type Changes struct {
|
||||
|
||||
392
what-changed/parameter.go
Normal file
392
what-changed/parameter.go
Normal file
@@ -0,0 +1,392 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package what_changed
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"gopkg.in/yaml.v3"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type ParameterChanges struct {
|
||||
PropertyChanges
|
||||
SchemaChanges *SchemaChanges
|
||||
ExtensionChanges *ExtensionChanges
|
||||
|
||||
// V2 change types
|
||||
// ItemsChanges
|
||||
|
||||
// v3 change types
|
||||
ExampleChanges map[string]*ExampleChanges
|
||||
}
|
||||
|
||||
// TotalChanges returns a count of everything that changed
|
||||
func (p *ParameterChanges) TotalChanges() int {
|
||||
c := p.PropertyChanges.TotalChanges()
|
||||
if p.SchemaChanges != nil {
|
||||
c += p.SchemaChanges.TotalChanges()
|
||||
}
|
||||
if len(p.ExampleChanges) > 0 {
|
||||
for i := range p.ExampleChanges {
|
||||
c += p.ExampleChanges[i].TotalChanges()
|
||||
}
|
||||
}
|
||||
if p.ExtensionChanges != nil {
|
||||
c += p.ExtensionChanges.TotalChanges()
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
// TotalBreakingChanges always returns 0 for ExternalDoc objects, they are non-binding.
|
||||
func (p *ParameterChanges) TotalBreakingChanges() int {
|
||||
c := p.PropertyChanges.TotalBreakingChanges()
|
||||
if p.SchemaChanges != nil {
|
||||
c += p.SchemaChanges.TotalBreakingChanges()
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func addPropertyCheck(props *[]*PropertyCheck,
|
||||
lvn, rvn *yaml.Node, lv, rv any, changes *[]*Change, label string, breaking bool) {
|
||||
*props = append(*props, &PropertyCheck{
|
||||
LeftNode: lvn,
|
||||
RightNode: rvn,
|
||||
Label: label,
|
||||
Changes: changes,
|
||||
Breaking: breaking,
|
||||
Original: lv,
|
||||
New: rv,
|
||||
})
|
||||
}
|
||||
|
||||
func addOpenAPIParameterProperties(left, right low.IsParameter, changes *[]*Change) []*PropertyCheck {
|
||||
var props []*PropertyCheck
|
||||
|
||||
// style
|
||||
addPropertyCheck(&props, left.GetStyle().ValueNode, right.GetStyle().ValueNode,
|
||||
left.GetStyle(), right.GetStyle(), changes, v3.StyleLabel, false)
|
||||
|
||||
// allow reserved
|
||||
addPropertyCheck(&props, left.GetAllowReserved().ValueNode, right.GetAllowReserved().ValueNode,
|
||||
left.GetAllowReserved(), right.GetAllowReserved(), changes, v3.AllowReservedLabel, true)
|
||||
|
||||
// explode
|
||||
addPropertyCheck(&props, left.GetExplode().ValueNode, right.GetExplode().ValueNode,
|
||||
left.GetExplode(), right.GetExplode(), changes, v3.ExplodeLabel, false)
|
||||
|
||||
// deprecated
|
||||
addPropertyCheck(&props, left.GetDeprecated().ValueNode, right.GetDeprecated().ValueNode,
|
||||
left.GetDeprecated(), right.GetDeprecated(), changes, v3.DeprecatedLabel, false)
|
||||
|
||||
return props
|
||||
}
|
||||
|
||||
func addSwaggerParameterProperties(left, right low.IsParameter, changes *[]*Change) []*PropertyCheck {
|
||||
var props []*PropertyCheck
|
||||
|
||||
// type
|
||||
addPropertyCheck(&props, left.GetType().ValueNode, right.GetType().ValueNode,
|
||||
left.GetType(), right.GetType(), changes, v3.TypeLabel, true)
|
||||
|
||||
// format
|
||||
addPropertyCheck(&props, left.GetFormat().ValueNode, right.GetFormat().ValueNode,
|
||||
left.GetFormat(), right.GetFormat(), changes, v3.FormatLabel, true)
|
||||
|
||||
// collection format
|
||||
addPropertyCheck(&props, left.GetCollectionFormat().ValueNode, right.GetCollectionFormat().ValueNode,
|
||||
left.GetCollectionFormat(), right.GetCollectionFormat(), changes, v3.CollectionFormatLabel, true)
|
||||
|
||||
// maximum
|
||||
addPropertyCheck(&props, left.GetMaximum().ValueNode, right.GetMaximum().ValueNode,
|
||||
left.GetMaximum(), right.GetMaximum(), changes, v3.MaximumLabel, true)
|
||||
|
||||
// minimum
|
||||
addPropertyCheck(&props, left.GetMinimum().ValueNode, right.GetMinimum().ValueNode,
|
||||
left.GetMinimum(), right.GetMinimum(), changes, v3.MinimumLabel, true)
|
||||
|
||||
// exclusive maximum
|
||||
addPropertyCheck(&props, left.GetExclusiveMaximum().ValueNode, right.GetExclusiveMaximum().ValueNode,
|
||||
left.GetExclusiveMaximum(), right.GetExclusiveMaximum(), changes, v3.ExclusiveMaximumLabel, true)
|
||||
|
||||
// exclusive minimum
|
||||
addPropertyCheck(&props, left.GetExclusiveMinimum().ValueNode, right.GetExclusiveMinimum().ValueNode,
|
||||
left.GetExclusiveMinimum(), right.GetExclusiveMinimum(), changes, v3.ExclusiveMinimumLabel, true)
|
||||
|
||||
// max length
|
||||
addPropertyCheck(&props, left.GetMaxLength().ValueNode, right.GetMaxLength().ValueNode,
|
||||
left.GetMaxLength(), right.GetMaxLength(), changes, v3.MaxLengthLabel, true)
|
||||
|
||||
// min length
|
||||
addPropertyCheck(&props, left.GetMinLength().ValueNode, right.GetMinLength().ValueNode,
|
||||
left.GetMinLength(), right.GetMinLength(), changes, v3.MinLengthLabel, true)
|
||||
|
||||
// pattern
|
||||
addPropertyCheck(&props, left.GetPattern().ValueNode, right.GetPattern().ValueNode,
|
||||
left.GetPattern(), right.GetPattern(), changes, v3.PatternLabel, true)
|
||||
|
||||
// max items
|
||||
addPropertyCheck(&props, left.GetMaxItems().ValueNode, right.GetMaxItems().ValueNode,
|
||||
left.GetMaxItems(), right.GetMaxItems(), changes, v3.MaxItemsLabel, true)
|
||||
|
||||
// min items
|
||||
addPropertyCheck(&props, left.GetMinItems().ValueNode, right.GetMinItems().ValueNode,
|
||||
left.GetMinItems(), right.GetMinItems(), changes, v3.MinItemsLabel, true)
|
||||
|
||||
// unique items
|
||||
addPropertyCheck(&props, left.GetUniqueItems().ValueNode, right.GetUniqueItems().ValueNode,
|
||||
left.GetUniqueItems(), right.GetUniqueItems(), changes, v3.UniqueItemsLabel, true)
|
||||
|
||||
// multiple of
|
||||
addPropertyCheck(&props, left.GetMultipleOf().ValueNode, right.GetMultipleOf().ValueNode,
|
||||
left.GetMultipleOf(), right.GetMultipleOf(), changes, v3.MultipleOfLabel, true)
|
||||
|
||||
return props
|
||||
}
|
||||
|
||||
func addCommonParameterProperties(left, right low.IsParameter, changes *[]*Change) []*PropertyCheck {
|
||||
var props []*PropertyCheck
|
||||
|
||||
addPropertyCheck(&props, left.GetName().ValueNode, right.GetName().ValueNode,
|
||||
left.GetName(), right.GetName(), changes, v3.NameLabel, true)
|
||||
|
||||
// in
|
||||
addPropertyCheck(&props, left.GetIn().ValueNode, right.GetIn().ValueNode,
|
||||
left.GetIn(), right.GetIn(), changes, v3.InLabel, true)
|
||||
|
||||
// description
|
||||
addPropertyCheck(&props, left.GetDescription().ValueNode, right.GetDescription().ValueNode,
|
||||
left.GetDescription(), right.GetDescription(), changes, v3.DescriptionLabel, false)
|
||||
|
||||
// required
|
||||
addPropertyCheck(&props, left.GetRequired().ValueNode, right.GetRequired().ValueNode,
|
||||
left.GetRequired(), right.GetRequired(), changes, v3.RequiredLabel, true)
|
||||
|
||||
// allow empty value
|
||||
addPropertyCheck(&props, left.GetAllowEmptyValue().ValueNode, right.GetAllowEmptyValue().ValueNode,
|
||||
left.GetAllowEmptyValue(), right.GetAllowEmptyValue(), changes, v3.AllowEmptyValueLabel, true)
|
||||
|
||||
return props
|
||||
}
|
||||
|
||||
func CompareParameters(l, r any) *ParameterChanges {
|
||||
|
||||
var changes []*Change
|
||||
var props []*PropertyCheck
|
||||
|
||||
pc := new(ParameterChanges)
|
||||
var lSchema *base.SchemaProxy
|
||||
var rSchema *base.SchemaProxy
|
||||
var lext, rext map[low.KeyReference[string]]low.ValueReference[any]
|
||||
|
||||
if reflect.TypeOf(&v2.Parameter{}) == reflect.TypeOf(l) && reflect.TypeOf(&v2.Parameter{}) == reflect.TypeOf(r) {
|
||||
lParam := l.(*v2.Parameter)
|
||||
rParam := r.(*v2.Parameter)
|
||||
|
||||
// perform hash check to avoid further processing
|
||||
if low.AreEqual(lParam, rParam) {
|
||||
return nil
|
||||
}
|
||||
|
||||
props = append(props, addSwaggerParameterProperties(lParam, rParam, &changes)...)
|
||||
props = append(props, addCommonParameterProperties(lParam, rParam, &changes)...)
|
||||
|
||||
// extract schema
|
||||
if lParam != nil {
|
||||
lSchema = lParam.Schema.Value
|
||||
lext = lParam.Extensions
|
||||
}
|
||||
if rParam != nil {
|
||||
rext = rParam.Extensions
|
||||
rSchema = rParam.Schema.Value
|
||||
}
|
||||
|
||||
// todo: items
|
||||
// todo: default
|
||||
// todo: enums
|
||||
|
||||
}
|
||||
|
||||
// OpenAPI
|
||||
if reflect.TypeOf(&v3.Parameter{}) == reflect.TypeOf(l) && reflect.TypeOf(&v3.Parameter{}) == reflect.TypeOf(r) {
|
||||
|
||||
lParam := l.(*v3.Parameter)
|
||||
rParam := r.(*v3.Parameter)
|
||||
|
||||
// perform hash check to avoid further processing
|
||||
if low.AreEqual(lParam, rParam) {
|
||||
return nil
|
||||
}
|
||||
|
||||
props = append(props, addOpenAPIParameterProperties(lParam, rParam, &changes)...)
|
||||
props = append(props, addCommonParameterProperties(lParam, rParam, &changes)...)
|
||||
if lParam != nil {
|
||||
lext = lParam.Extensions
|
||||
lSchema = lParam.Schema.Value
|
||||
}
|
||||
if rParam != nil {
|
||||
rext = rParam.Extensions
|
||||
rSchema = rParam.Schema.Value
|
||||
}
|
||||
|
||||
// example
|
||||
if lParam.Example.Value != nil && rParam.Example.Value != nil {
|
||||
if low.GenerateHashString(lParam.Example.Value) != low.GenerateHashString(rParam.Example.Value) {
|
||||
CreateChange(&changes, Modified, v3.ExampleLabel,
|
||||
lParam.Example.GetValueNode(), rParam.Example.GetValueNode(), false,
|
||||
lParam.Example.GetValue(), rParam.Example.GetValue())
|
||||
}
|
||||
}
|
||||
if lParam.Example.Value == nil && rParam.Example.Value != nil {
|
||||
CreateChange(&changes, PropertyAdded, v3.ExampleLabel,
|
||||
nil, rParam.Example.GetValueNode(), false,
|
||||
nil, rParam.Example.GetValue())
|
||||
|
||||
}
|
||||
if lParam.Example.Value != nil && rParam.Example.Value == nil {
|
||||
CreateChange(&changes, PropertyRemoved, v3.ExampleLabel,
|
||||
lParam.Example.GetValueNode(), nil, false,
|
||||
lParam.Example.GetValue(), nil)
|
||||
|
||||
}
|
||||
|
||||
// examples
|
||||
checkParameterExamples(lParam, rParam, changes, pc)
|
||||
|
||||
// todo: content
|
||||
|
||||
}
|
||||
CheckProperties(props)
|
||||
|
||||
if lSchema != nil && rSchema != nil {
|
||||
pc.SchemaChanges = CompareSchemas(lSchema, rSchema)
|
||||
}
|
||||
if lSchema != nil && rSchema == nil {
|
||||
CreateChange(&changes, ObjectRemoved, v3.SchemaLabel,
|
||||
lSchema.GetValueNode(), nil, true, lSchema,
|
||||
nil)
|
||||
}
|
||||
|
||||
if lSchema == nil && rSchema != nil {
|
||||
CreateChange(&changes, ObjectAdded, v3.SchemaLabel,
|
||||
nil, rSchema.GetValueNode(), true, nil,
|
||||
rSchema)
|
||||
}
|
||||
|
||||
pc.Changes = changes
|
||||
pc.ExtensionChanges = CompareExtensions(lext, rext)
|
||||
|
||||
if pc.TotalChanges() > 0 {
|
||||
return pc
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkParameterExamples(lParam *v3.Parameter, rParam *v3.Parameter, changes []*Change, pc *ParameterChanges) {
|
||||
lExpHashes := make(map[string]string)
|
||||
rExpHashes := make(map[string]string)
|
||||
lExpValues := make(map[string]low.ValueReference[*base.Example])
|
||||
rExpValues := make(map[string]low.ValueReference[*base.Example])
|
||||
if lParam != nil && lParam.Examples.Value != nil {
|
||||
for k := range lParam.Examples.Value {
|
||||
lExpHashes[k.Value] = fmt.Sprintf("%x", lParam.Examples.Value[k].Value.Hash())
|
||||
lExpValues[k.Value] = lParam.Examples.Value[k]
|
||||
}
|
||||
}
|
||||
if rParam != nil && rParam.Examples.Value != nil {
|
||||
for k := range rParam.Examples.Value {
|
||||
rExpHashes[k.Value] = fmt.Sprintf("%x", rParam.Examples.Value[k].Value.Hash())
|
||||
rExpValues[k.Value] = rParam.Examples.Value[k]
|
||||
}
|
||||
}
|
||||
expChanges := make(map[string]*ExampleChanges)
|
||||
|
||||
// check left example hashes
|
||||
for k := range lExpHashes {
|
||||
rhash := rExpHashes[k]
|
||||
if rhash == "" {
|
||||
CreateChange(&changes, ObjectRemoved, v3.ExamplesLabel,
|
||||
lExpValues[k].GetValueNode(), nil, false,
|
||||
lExpValues[k].GetValue(), nil)
|
||||
continue
|
||||
}
|
||||
if lExpHashes[k] == rExpHashes[k] {
|
||||
continue
|
||||
}
|
||||
expChanges[k] = CompareExamples(lExpValues[k].Value, rExpValues[k].Value)
|
||||
}
|
||||
|
||||
//check right example hashes
|
||||
for k := range rExpHashes {
|
||||
lhash := lExpHashes[k]
|
||||
if lhash == "" {
|
||||
CreateChange(&changes, ObjectAdded, v3.ExamplesLabel,
|
||||
nil, lExpValues[k].GetValueNode(), false,
|
||||
nil, lExpValues[k].GetValue())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if len(expChanges) > 0 {
|
||||
pc.ExampleChanges = expChanges
|
||||
}
|
||||
}
|
||||
|
||||
func checkParameterContent(lParam *v3.Parameter, rParam *v3.Parameter, changes []*Change, pc *ParameterChanges) {
|
||||
lConHashes := make(map[string]string)
|
||||
rConHashes := make(map[string]string)
|
||||
lConValues := make(map[string]low.ValueReference[*v3.MediaType])
|
||||
rConValues := make(map[string]low.ValueReference[*v3.MediaType])
|
||||
if lParam != nil && lParam.Content.Value != nil {
|
||||
for k := range lParam.Content.Value {
|
||||
lConHashes[k.Value] = fmt.Sprintf("%x", lParam.Content.Value[k].Value.Hash())
|
||||
lConValues[k.Value] = lParam.Content.Value[k]
|
||||
}
|
||||
}
|
||||
if rParam != nil && rParam.Content.Value != nil {
|
||||
for k := range rParam.Content.Value {
|
||||
rConHashes[k.Value] = fmt.Sprintf("%x", rParam.Content.Value[k].Value.Hash())
|
||||
rConValues[k.Value] = rParam.Content.Value[k]
|
||||
}
|
||||
}
|
||||
expChanges := make(map[string]*ExampleChanges)
|
||||
|
||||
// check left example hashes
|
||||
for k := range lConHashes {
|
||||
rhash := rConHashes[k]
|
||||
if rhash == "" {
|
||||
CreateChange(&changes, ObjectRemoved, v3.ExamplesLabel,
|
||||
lConValues[k].GetValueNode(), nil, false,
|
||||
lConValues[k].GetValue(), nil)
|
||||
continue
|
||||
}
|
||||
if lConHashes[k] == rConHashes[k] {
|
||||
continue
|
||||
}
|
||||
|
||||
// Compare media types.
|
||||
//expChanges[k] = CompareM(lConValues[k].Value, rConValues[k].Value)
|
||||
// todo: start here <--------
|
||||
|
||||
}
|
||||
|
||||
//check right example hashes
|
||||
for k := range rConHashes {
|
||||
lhash := lConHashes[k]
|
||||
if lhash == "" {
|
||||
CreateChange(&changes, ObjectAdded, v3.ExamplesLabel,
|
||||
nil, lConValues[k].GetValueNode(), false,
|
||||
nil, lConValues[k].GetValue())
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if len(expChanges) > 0 {
|
||||
pc.ExampleChanges = expChanges
|
||||
}
|
||||
}
|
||||
286
what-changed/parameter_test.go
Normal file
286
what-changed/parameter_test.go
Normal file
@@ -0,0 +1,286 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package what_changed
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCompareParameters_V3(t *testing.T) {
|
||||
|
||||
left := `name: a param`
|
||||
right := `name: a parama`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Parameter
|
||||
var rDoc v3.Parameter
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare.
|
||||
extChanges := CompareParameters(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
}
|
||||
|
||||
func TestCompareParameters_V3_Schema(t *testing.T) {
|
||||
|
||||
left := `schema:
|
||||
description: something new`
|
||||
right := `schema:
|
||||
description: a changed thing`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Parameter
|
||||
var rDoc v3.Parameter
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare.
|
||||
extChanges := CompareParameters(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, 1, extChanges.SchemaChanges.TotalChanges())
|
||||
|
||||
}
|
||||
|
||||
func TestCompareParameters_V3_SchemaAdd(t *testing.T) {
|
||||
|
||||
left := `description: hello`
|
||||
right := `description: hello
|
||||
schema:
|
||||
description: a changed thing`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Parameter
|
||||
var rDoc v3.Parameter
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare.
|
||||
extChanges := CompareParameters(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectAdded, extChanges.Changes[0].ChangeType)
|
||||
|
||||
}
|
||||
|
||||
func TestCompareParameters_V3_SchemaRemove(t *testing.T) {
|
||||
|
||||
left := `description: hello`
|
||||
right := `description: hello
|
||||
schema:
|
||||
description: a changed thing`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Parameter
|
||||
var rDoc v3.Parameter
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare.
|
||||
extChanges := CompareParameters(&rDoc, &lDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectRemoved, extChanges.Changes[0].ChangeType)
|
||||
|
||||
}
|
||||
|
||||
func TestCompareParameters_V3_Extensions(t *testing.T) {
|
||||
|
||||
left := `x-thing: thang`
|
||||
right := `x-thing: dang`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Parameter
|
||||
var rDoc v3.Parameter
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare.
|
||||
extChanges := CompareParameters(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, 1, extChanges.ExtensionChanges.TotalChanges())
|
||||
|
||||
}
|
||||
|
||||
//func TestCompareParameters_V3_ExampleChange(t *testing.T) {
|
||||
//
|
||||
// left := `example: a string`
|
||||
// right := `example:
|
||||
// now: an object`
|
||||
//
|
||||
// var lNode, rNode yaml.Node
|
||||
// _ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
// _ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
//
|
||||
// // create low level objects
|
||||
// var lDoc v3.Parameter
|
||||
// var rDoc v3.Parameter
|
||||
// _ = low.BuildModel(&lNode, &lDoc)
|
||||
// _ = low.BuildModel(&rNode, &rDoc)
|
||||
// _ = lDoc.Build(lNode.Content[0], nil)
|
||||
// _ = rDoc.Build(rNode.Content[0], nil)
|
||||
//
|
||||
// // compare.
|
||||
// extChanges := CompareParameters(&lDoc, &rDoc)
|
||||
// assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
// assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
// assert.Equal(t, 1, extChanges.ExtensionChanges.TotalChanges())
|
||||
//}
|
||||
|
||||
func TestCompareParameters_V3_ExampleEqual(t *testing.T) {
|
||||
|
||||
left := `example: a string`
|
||||
right := `example: a string`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Parameter
|
||||
var rDoc v3.Parameter
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare.
|
||||
extChanges := CompareParameters(&lDoc, &rDoc)
|
||||
assert.Nil(t, extChanges)
|
||||
}
|
||||
|
||||
func TestCompareParameters_V3_ExampleAdd(t *testing.T) {
|
||||
|
||||
left := `description: something`
|
||||
right := `description: something
|
||||
example: a string`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Parameter
|
||||
var rDoc v3.Parameter
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareParameters(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, PropertyAdded, extChanges.Changes[0].ChangeType)
|
||||
}
|
||||
|
||||
func TestCompareParameters_V3_ExampleRemove(t *testing.T) {
|
||||
|
||||
left := `description: something`
|
||||
right := `description: something
|
||||
example: a string`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.Parameter
|
||||
var rDoc v3.Parameter
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareParameters(&rDoc, &lDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, PropertyRemoved, extChanges.Changes[0].ChangeType)
|
||||
}
|
||||
|
||||
func TestCompareParameters_V2(t *testing.T) {
|
||||
|
||||
left := `name: a param`
|
||||
right := `name: a parama`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.Parameter
|
||||
var rDoc v2.Parameter
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare.
|
||||
extChanges := CompareParameters(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
}
|
||||
|
||||
//func TestCompareParameters_V2_Extensions(t *testing.T) {
|
||||
//
|
||||
// left := `x-thing: thang`
|
||||
// right := `x-thing: dang`
|
||||
//
|
||||
// var lNode, rNode yaml.Node
|
||||
// _ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
// _ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
//
|
||||
// // create low level objects
|
||||
// var lDoc v2.Parameter
|
||||
// var rDoc v2.Parameter
|
||||
// _ = low.BuildModel(&lNode, &lDoc)
|
||||
// _ = low.BuildModel(&rNode, &rDoc)
|
||||
// _ = lDoc.Build(lNode.Content[0], nil)
|
||||
// _ = rDoc.Build(rNode.Content[0], nil)
|
||||
//
|
||||
// // compare.
|
||||
// extChanges := CompareParameters(&lDoc, &rDoc)
|
||||
// assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
// assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
// assert.Equal(t, Modified, extChanges.Changes[0].ChangeType)
|
||||
// assert.Equal(t, 1, extChanges.ExtensionChanges.TotalChanges())
|
||||
//
|
||||
//}
|
||||
@@ -13,8 +13,14 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// SchemaChanges represent all changes to a base.Schema OpenAPI object. These changes are represented
|
||||
// by all versions of OpenAPI.
|
||||
//
|
||||
// Any additions or removals to slice based results will be recorded in the PropertyChanges of the parent
|
||||
// changes, and not the child for example, adding a new schema to `anyOf` will create a new change result in
|
||||
// PropertyChanges.Changes, and not in the AnyOfChanges property.
|
||||
type SchemaChanges struct {
|
||||
PropertyChanges[*base.Schema]
|
||||
PropertyChanges
|
||||
DiscriminatorChanges *DiscriminatorChanges
|
||||
AllOfChanges []*SchemaChanges
|
||||
AnyOfChanges []*SchemaChanges
|
||||
@@ -27,6 +33,7 @@ type SchemaChanges struct {
|
||||
ExtensionChanges *ExtensionChanges
|
||||
}
|
||||
|
||||
// TotalChanges returns a count of the total number of changes made to this schema and all sub-schemas
|
||||
func (s *SchemaChanges) TotalChanges() int {
|
||||
t := s.PropertyChanges.TotalChanges()
|
||||
if s.DiscriminatorChanges != nil {
|
||||
@@ -74,6 +81,7 @@ func (s *SchemaChanges) TotalChanges() int {
|
||||
return t
|
||||
}
|
||||
|
||||
// TotalBreakingChanges returns the total number of breaking changes made to this schema and all sub-schemas.
|
||||
func (s *SchemaChanges) TotalBreakingChanges() int {
|
||||
t := s.PropertyChanges.TotalBreakingChanges()
|
||||
if s.DiscriminatorChanges != nil {
|
||||
@@ -122,18 +130,18 @@ func (s *SchemaChanges) TotalBreakingChanges() int {
|
||||
|
||||
func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
||||
sc := new(SchemaChanges)
|
||||
var changes []*Change[*base.Schema]
|
||||
var changes []*Change
|
||||
|
||||
// Added
|
||||
if l == nil && r != nil {
|
||||
CreateChange[*base.Schema](&changes, ObjectAdded, v3.SchemaLabel,
|
||||
CreateChange(&changes, ObjectAdded, v3.SchemaLabel,
|
||||
nil, nil, true, nil, r)
|
||||
sc.Changes = changes
|
||||
}
|
||||
|
||||
// Removed
|
||||
if l != nil && r == nil {
|
||||
CreateChange[*base.Schema](&changes, ObjectRemoved, v3.SchemaLabel,
|
||||
CreateChange(&changes, ObjectRemoved, v3.SchemaLabel,
|
||||
nil, nil, true, l, nil)
|
||||
sc.Changes = changes
|
||||
}
|
||||
@@ -148,7 +156,7 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
||||
return nil
|
||||
} else {
|
||||
// references are different, that's all we care to know.
|
||||
CreateChange[*base.Schema](&changes, Modified, v3.RefLabel,
|
||||
CreateChange(&changes, Modified, v3.RefLabel,
|
||||
l.GetValueNode().Content[1], r.GetValueNode().Content[1], true, l.GetSchemaReference(),
|
||||
r.GetSchemaReference())
|
||||
sc.Changes = changes
|
||||
@@ -158,7 +166,7 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
||||
|
||||
// changed from inline to ref
|
||||
if !l.IsSchemaReference() && r.IsSchemaReference() {
|
||||
CreateChange[*base.Schema](&changes, Modified, v3.RefLabel,
|
||||
CreateChange(&changes, Modified, v3.RefLabel,
|
||||
l.GetValueNode(), r.GetValueNode().Content[1], true, l, r.GetSchemaReference())
|
||||
sc.Changes = changes
|
||||
return sc // we're done here
|
||||
@@ -166,7 +174,7 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
||||
|
||||
// changed from ref to inline
|
||||
if l.IsSchemaReference() && !r.IsSchemaReference() {
|
||||
CreateChange[*base.Schema](&changes, Modified, v3.RefLabel,
|
||||
CreateChange(&changes, Modified, v3.RefLabel,
|
||||
l.GetValueNode().Content[1], r.GetValueNode(), true, l.GetSchemaReference(), r)
|
||||
sc.Changes = changes
|
||||
return sc // done, nothing else to do.
|
||||
@@ -181,7 +189,7 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
||||
}
|
||||
|
||||
// check XML
|
||||
checkXML(lSchema, rSchema, &changes, sc)
|
||||
checkSchemaXML(lSchema, rSchema, &changes, sc)
|
||||
|
||||
// check examples
|
||||
checkExamples(lSchema, rSchema, &changes)
|
||||
@@ -226,15 +234,15 @@ func CompareSchemas(l, r *base.SchemaProxy) *SchemaChanges {
|
||||
return sc
|
||||
}
|
||||
|
||||
func checkXML(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Change[*base.Schema], sc *SchemaChanges) {
|
||||
func checkSchemaXML(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Change, sc *SchemaChanges) {
|
||||
// XML removed
|
||||
if lSchema.XML.Value != nil && rSchema.XML.Value == nil {
|
||||
CreateChange[*base.Schema](changes, ObjectRemoved, v3.XMLLabel,
|
||||
CreateChange(changes, ObjectRemoved, v3.XMLLabel,
|
||||
lSchema.XML.GetValueNode(), nil, true, lSchema.XML.GetValue(), nil)
|
||||
}
|
||||
// XML added
|
||||
if lSchema.XML.Value == nil && rSchema.XML.Value != nil {
|
||||
CreateChange[*base.Schema](changes, ObjectAdded, v3.XMLLabel,
|
||||
CreateChange(changes, ObjectAdded, v3.XMLLabel,
|
||||
nil, rSchema.XML.GetValueNode(), false, nil, rSchema.XML.GetValue())
|
||||
}
|
||||
|
||||
@@ -249,7 +257,7 @@ func checkXML(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Change[*ba
|
||||
func checkPropertiesPropertyOfASchema(
|
||||
lSchema *base.Schema,
|
||||
rSchema *base.Schema,
|
||||
changes *[]*Change[*base.Schema],
|
||||
changes *[]*Change,
|
||||
sc *SchemaChanges,
|
||||
doneChan chan bool) int {
|
||||
|
||||
@@ -310,10 +318,10 @@ func checkPropertiesPropertyOfASchema(
|
||||
if lProps[w] != rProps[w] {
|
||||
|
||||
// old removed, new added.
|
||||
CreateChange[*base.Schema](changes, ObjectAdded, v3.PropertiesLabel,
|
||||
CreateChange(changes, ObjectAdded, v3.PropertiesLabel,
|
||||
nil, rKeyNodes[rProps[w]], false, nil, rEntities[rProps[w]])
|
||||
|
||||
CreateChange[*base.Schema](changes, ObjectRemoved, v3.PropertiesLabel,
|
||||
CreateChange(changes, ObjectRemoved, v3.PropertiesLabel,
|
||||
lKeyNodes[lProps[w]], nil, true, lEntities[lProps[w]], nil)
|
||||
}
|
||||
|
||||
@@ -328,7 +336,7 @@ func checkPropertiesPropertyOfASchema(
|
||||
go checkProperty(lProps[w], lEntities[lProps[w]], rEntities[rProps[w]], propChanges, doneChan)
|
||||
}
|
||||
if w >= len(rProps) {
|
||||
CreateChange[*base.Schema](changes, ObjectRemoved, v3.PropertiesLabel,
|
||||
CreateChange(changes, ObjectRemoved, v3.PropertiesLabel,
|
||||
lKeyNodes[lProps[w]], nil, true, lEntities[lProps[w]], nil)
|
||||
}
|
||||
}
|
||||
@@ -342,7 +350,7 @@ func checkPropertiesPropertyOfASchema(
|
||||
go checkProperty(rProps[w], lEntities[lProps[w]], rEntities[rProps[w]], propChanges, doneChan)
|
||||
}
|
||||
if w >= len(lProps) {
|
||||
CreateChange[*base.Schema](changes, ObjectAdded, v3.PropertiesLabel,
|
||||
CreateChange(changes, ObjectAdded, v3.PropertiesLabel,
|
||||
nil, rKeyNodes[rProps[w]], false, nil, rEntities[rProps[w]])
|
||||
}
|
||||
}
|
||||
@@ -354,12 +362,12 @@ func checkPropertiesPropertyOfASchema(
|
||||
func checkSchemaPropertyChanges(
|
||||
lSchema *base.Schema,
|
||||
rSchema *base.Schema,
|
||||
changes *[]*Change[*base.Schema], sc *SchemaChanges) {
|
||||
changes *[]*Change, sc *SchemaChanges) {
|
||||
|
||||
var props []*PropertyCheck[*base.Schema]
|
||||
var props []*PropertyCheck
|
||||
|
||||
// $schema (breaking change)
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.SchemaTypeRef.ValueNode,
|
||||
RightNode: rSchema.SchemaTypeRef.ValueNode,
|
||||
Label: v3.SchemaDialectLabel,
|
||||
@@ -370,7 +378,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// ExclusiveMaximum
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.ExclusiveMaximum.ValueNode,
|
||||
RightNode: rSchema.ExclusiveMaximum.ValueNode,
|
||||
Label: v3.ExclusiveMaximumLabel,
|
||||
@@ -381,7 +389,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// ExclusiveMinimum
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.ExclusiveMinimum.ValueNode,
|
||||
RightNode: rSchema.ExclusiveMinimum.ValueNode,
|
||||
Label: v3.ExclusiveMinimumLabel,
|
||||
@@ -392,7 +400,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Type
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Type.ValueNode,
|
||||
RightNode: rSchema.Type.ValueNode,
|
||||
Label: v3.TypeLabel,
|
||||
@@ -403,7 +411,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Title
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Title.ValueNode,
|
||||
RightNode: rSchema.Title.ValueNode,
|
||||
Label: v3.TitleLabel,
|
||||
@@ -414,7 +422,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// MultipleOf
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.MultipleOf.ValueNode,
|
||||
RightNode: rSchema.MultipleOf.ValueNode,
|
||||
Label: v3.MultipleOfLabel,
|
||||
@@ -425,7 +433,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Maximum
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Maximum.ValueNode,
|
||||
RightNode: rSchema.Maximum.ValueNode,
|
||||
Label: v3.MaximumLabel,
|
||||
@@ -436,7 +444,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Minimum
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Minimum.ValueNode,
|
||||
RightNode: rSchema.Minimum.ValueNode,
|
||||
Label: v3.MinimumLabel,
|
||||
@@ -447,7 +455,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// MaxLength
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.MaxLength.ValueNode,
|
||||
RightNode: rSchema.MaxLength.ValueNode,
|
||||
Label: v3.MaxLengthLabel,
|
||||
@@ -458,7 +466,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// MinLength
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.MinLength.ValueNode,
|
||||
RightNode: rSchema.MinLength.ValueNode,
|
||||
Label: v3.MinLengthLabel,
|
||||
@@ -469,7 +477,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Pattern
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Pattern.ValueNode,
|
||||
RightNode: rSchema.Pattern.ValueNode,
|
||||
Label: v3.PatternLabel,
|
||||
@@ -480,7 +488,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Format
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Format.ValueNode,
|
||||
RightNode: rSchema.Format.ValueNode,
|
||||
Label: v3.FormatLabel,
|
||||
@@ -491,7 +499,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// MaxItems
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.MaxItems.ValueNode,
|
||||
RightNode: rSchema.MaxItems.ValueNode,
|
||||
Label: v3.MaxItemsLabel,
|
||||
@@ -502,7 +510,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// MinItems
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.MinItems.ValueNode,
|
||||
RightNode: rSchema.MinItems.ValueNode,
|
||||
Label: v3.MinItemsLabel,
|
||||
@@ -513,7 +521,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// MaxProperties
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.MaxProperties.ValueNode,
|
||||
RightNode: rSchema.MaxProperties.ValueNode,
|
||||
Label: v3.MaxPropertiesLabel,
|
||||
@@ -524,7 +532,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// MinProperties
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.MinProperties.ValueNode,
|
||||
RightNode: rSchema.MinProperties.ValueNode,
|
||||
Label: v3.MinPropertiesLabel,
|
||||
@@ -535,7 +543,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// UniqueItems
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.UniqueItems.ValueNode,
|
||||
RightNode: rSchema.UniqueItems.ValueNode,
|
||||
Label: v3.UniqueItemsLabel,
|
||||
@@ -546,7 +554,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// AdditionalProperties
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.AdditionalProperties.ValueNode,
|
||||
RightNode: rSchema.AdditionalProperties.ValueNode,
|
||||
Label: v3.AdditionalPropertiesLabel,
|
||||
@@ -557,7 +565,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Description
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Description.ValueNode,
|
||||
RightNode: rSchema.Description.ValueNode,
|
||||
Label: v3.DescriptionLabel,
|
||||
@@ -568,7 +576,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// ContentEncoding
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.ContentEncoding.ValueNode,
|
||||
RightNode: rSchema.ContentEncoding.ValueNode,
|
||||
Label: v3.ContentEncodingLabel,
|
||||
@@ -579,7 +587,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// ContentMediaType
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.ContentMediaType.ValueNode,
|
||||
RightNode: rSchema.ContentMediaType.ValueNode,
|
||||
Label: v3.ContentMediaType,
|
||||
@@ -590,7 +598,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Default
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Default.ValueNode,
|
||||
RightNode: rSchema.Default.ValueNode,
|
||||
Label: v3.DefaultLabel,
|
||||
@@ -601,7 +609,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Nullable
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Nullable.ValueNode,
|
||||
RightNode: rSchema.Nullable.ValueNode,
|
||||
Label: v3.NullableLabel,
|
||||
@@ -612,7 +620,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// ReadOnly
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.ReadOnly.ValueNode,
|
||||
RightNode: rSchema.ReadOnly.ValueNode,
|
||||
Label: v3.ReadOnlyLabel,
|
||||
@@ -623,7 +631,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// WriteOnly
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.WriteOnly.ValueNode,
|
||||
RightNode: rSchema.WriteOnly.ValueNode,
|
||||
Label: v3.WriteOnlyLabel,
|
||||
@@ -634,7 +642,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Example
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Example.ValueNode,
|
||||
RightNode: rSchema.Example.ValueNode,
|
||||
Label: v3.ExampleLabel,
|
||||
@@ -645,7 +653,7 @@ func checkSchemaPropertyChanges(
|
||||
})
|
||||
|
||||
// Deprecated
|
||||
props = append(props, &PropertyCheck[*base.Schema]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: lSchema.Deprecated.ValueNode,
|
||||
RightNode: rSchema.Deprecated.ValueNode,
|
||||
Label: v3.DeprecatedLabel,
|
||||
@@ -666,14 +674,14 @@ func checkSchemaPropertyChanges(
|
||||
}
|
||||
for g := range k {
|
||||
if _, ok := j[g]; !ok {
|
||||
CreateChange[*base.Schema](changes, PropertyAdded, v3.RequiredLabel,
|
||||
CreateChange(changes, PropertyAdded, v3.RequiredLabel,
|
||||
nil, rSchema.Required.Value[k[g]].GetValueNode(), true, nil,
|
||||
rSchema.Required.Value[k[g]].GetValue)
|
||||
}
|
||||
}
|
||||
for g := range j {
|
||||
if _, ok := k[g]; !ok {
|
||||
CreateChange[*base.Schema](changes, PropertyRemoved, v3.RequiredLabel,
|
||||
CreateChange(changes, PropertyRemoved, v3.RequiredLabel,
|
||||
lSchema.Required.Value[j[g]].GetValueNode(), nil, true, lSchema.Required.Value[j[g]].GetValue,
|
||||
nil)
|
||||
}
|
||||
@@ -690,14 +698,14 @@ func checkSchemaPropertyChanges(
|
||||
}
|
||||
for g := range k {
|
||||
if _, ok := j[g]; !ok {
|
||||
CreateChange[*base.Schema](changes, PropertyAdded, v3.EnumLabel,
|
||||
CreateChange(changes, PropertyAdded, v3.EnumLabel,
|
||||
nil, rSchema.Enum.Value[k[g]].GetValueNode(), false, nil,
|
||||
rSchema.Enum.Value[k[g]].GetValue)
|
||||
}
|
||||
}
|
||||
for g := range j {
|
||||
if _, ok := k[g]; !ok {
|
||||
CreateChange[*base.Schema](changes, PropertyRemoved, v3.EnumLabel,
|
||||
CreateChange(changes, PropertyRemoved, v3.EnumLabel,
|
||||
lSchema.Enum.Value[j[g]].GetValueNode(), nil, true, lSchema.Enum.Value[j[g]].GetValue,
|
||||
nil)
|
||||
}
|
||||
@@ -712,12 +720,12 @@ func checkSchemaPropertyChanges(
|
||||
}
|
||||
// added Discriminator
|
||||
if lSchema.Discriminator.Value == nil && rSchema.Discriminator.Value != nil {
|
||||
CreateChange[*base.Schema](changes, ObjectAdded, v3.DiscriminatorLabel,
|
||||
CreateChange(changes, ObjectAdded, v3.DiscriminatorLabel,
|
||||
nil, rSchema.Discriminator.ValueNode, true, nil, rSchema.Discriminator.Value)
|
||||
}
|
||||
// removed Discriminator
|
||||
if lSchema.Discriminator.Value != nil && rSchema.Discriminator.Value == nil {
|
||||
CreateChange[*base.Schema](changes, ObjectRemoved, v3.DiscriminatorLabel,
|
||||
CreateChange(changes, ObjectRemoved, v3.DiscriminatorLabel,
|
||||
lSchema.Discriminator.ValueNode, nil, true, lSchema.Discriminator.Value, nil)
|
||||
}
|
||||
|
||||
@@ -730,12 +738,12 @@ func checkSchemaPropertyChanges(
|
||||
}
|
||||
// added ExternalDocs
|
||||
if lSchema.ExternalDocs.Value == nil && rSchema.ExternalDocs.Value != nil {
|
||||
CreateChange[*base.Schema](changes, ObjectAdded, v3.ExternalDocsLabel,
|
||||
CreateChange(changes, ObjectAdded, v3.ExternalDocsLabel,
|
||||
nil, rSchema.ExternalDocs.ValueNode, false, nil, rSchema.ExternalDocs.Value)
|
||||
}
|
||||
// removed ExternalDocs
|
||||
if lSchema.ExternalDocs.Value != nil && rSchema.ExternalDocs.Value == nil {
|
||||
CreateChange[*base.Schema](changes, ObjectRemoved, v3.ExternalDocsLabel,
|
||||
CreateChange(changes, ObjectRemoved, v3.ExternalDocsLabel,
|
||||
lSchema.ExternalDocs.ValueNode, nil, false, lSchema.ExternalDocs.Value, nil)
|
||||
}
|
||||
|
||||
@@ -746,7 +754,7 @@ func checkSchemaPropertyChanges(
|
||||
CheckProperties(props)
|
||||
}
|
||||
|
||||
func checkExamples(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Change[*base.Schema]) {
|
||||
func checkExamples(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Change) {
|
||||
// check examples (3.1+)
|
||||
var lExampKey, rExampKey []string
|
||||
lExampN := make(map[string]*yaml.Node)
|
||||
@@ -777,7 +785,7 @@ func checkExamples(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Chang
|
||||
if len(lExampKey) == len(rExampKey) {
|
||||
for i := range lExampKey {
|
||||
if lExampKey[i] != rExampKey[i] {
|
||||
CreateChange[*base.Schema](changes, Modified, v3.ExamplesLabel,
|
||||
CreateChange(changes, Modified, v3.ExamplesLabel,
|
||||
lExampN[lExampKey[i]], rExampN[rExampKey[i]], false,
|
||||
lExampVal[lExampKey[i]], rExampVal[rExampKey[i]])
|
||||
}
|
||||
@@ -787,12 +795,12 @@ func checkExamples(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Chang
|
||||
if len(lExampKey) > len(rExampKey) {
|
||||
for i := range lExampKey {
|
||||
if i < len(rExampKey) && lExampKey[i] != rExampKey[i] {
|
||||
CreateChange[*base.Schema](changes, Modified, v3.ExamplesLabel,
|
||||
CreateChange(changes, Modified, v3.ExamplesLabel,
|
||||
lExampN[lExampKey[i]], rExampN[rExampKey[i]], false,
|
||||
lExampVal[lExampKey[i]], rExampVal[rExampKey[i]])
|
||||
}
|
||||
if i >= len(rExampKey) {
|
||||
CreateChange[*base.Schema](changes, ObjectRemoved, v3.ExamplesLabel,
|
||||
CreateChange(changes, ObjectRemoved, v3.ExamplesLabel,
|
||||
lExampN[lExampKey[i]], nil, false,
|
||||
lExampVal[lExampKey[i]], nil)
|
||||
}
|
||||
@@ -803,12 +811,12 @@ func checkExamples(lSchema *base.Schema, rSchema *base.Schema, changes *[]*Chang
|
||||
if len(lExampKey) < len(rExampKey) {
|
||||
for i := range rExampKey {
|
||||
if i < len(lExampKey) && lExampKey[i] != rExampKey[i] {
|
||||
CreateChange[*base.Schema](changes, Modified, v3.ExamplesLabel,
|
||||
CreateChange(changes, Modified, v3.ExamplesLabel,
|
||||
lExampN[lExampKey[i]], rExampN[rExampKey[i]], false,
|
||||
lExampVal[lExampKey[i]], rExampVal[rExampKey[i]])
|
||||
}
|
||||
if i >= len(lExampKey) {
|
||||
CreateChange[*base.Schema](changes, ObjectAdded, v3.ExamplesLabel,
|
||||
CreateChange(changes, ObjectAdded, v3.ExamplesLabel,
|
||||
nil, rExampN[rExampKey[i]], false,
|
||||
nil, rExampVal[rExampKey[i]])
|
||||
}
|
||||
@@ -821,7 +829,7 @@ func extractSchemaChanges(
|
||||
rSchema []low.ValueReference[*base.SchemaProxy],
|
||||
label string,
|
||||
sc *[]*SchemaChanges,
|
||||
changes *[]*Change[*base.Schema],
|
||||
changes *[]*Change,
|
||||
done chan bool) {
|
||||
|
||||
// if there is nothing here, there is nothing to do.
|
||||
@@ -876,7 +884,7 @@ func extractSchemaChanges(
|
||||
*sc = append(*sc, CompareSchemas(lEntities[lKeys[w]], rEntities[rKeys[w]]))
|
||||
}
|
||||
if w >= len(rKeys) {
|
||||
CreateChange[*base.Schema](changes, ObjectRemoved, label,
|
||||
CreateChange(changes, ObjectRemoved, label,
|
||||
lEntities[lKeys[w]].GetValueNode(), nil, true, lEntities[lKeys[w]], nil)
|
||||
}
|
||||
}
|
||||
@@ -889,7 +897,7 @@ func extractSchemaChanges(
|
||||
*sc = append(*sc, CompareSchemas(lEntities[lKeys[w]], rEntities[rKeys[w]]))
|
||||
}
|
||||
if w >= len(lKeys) {
|
||||
CreateChange[*base.Schema](changes, ObjectAdded, label,
|
||||
CreateChange(changes, ObjectAdded, label,
|
||||
nil, rEntities[rKeys[w]].GetValueNode(), false, nil, rEntities[rKeys[w]])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
// TagChanges represents changes made to the Tags object of an OpenAPI document.
|
||||
type TagChanges struct {
|
||||
PropertyChanges[*base.Tag]
|
||||
PropertyChanges
|
||||
ExternalDocs *ExternalDocChanges
|
||||
ExtensionChanges *ExtensionChanges
|
||||
}
|
||||
@@ -52,7 +52,7 @@ func CompareTags(l, r []low.ValueReference[*base.Tag]) *TagChanges {
|
||||
seenRight[strings.ToLower(r[i].Value.Name.Value)] = &h
|
||||
}
|
||||
|
||||
var changes []*Change[*base.Tag]
|
||||
var changes []*Change
|
||||
|
||||
// check for removals, modifications and moves
|
||||
for i := range seenLeft {
|
||||
@@ -62,10 +62,10 @@ func CompareTags(l, r []low.ValueReference[*base.Tag]) *TagChanges {
|
||||
// if the existing tag exists, let's check it.
|
||||
if seenRight[i] != nil {
|
||||
|
||||
var props []*PropertyCheck[*base.Tag]
|
||||
var props []*PropertyCheck
|
||||
|
||||
// Name
|
||||
props = append(props, &PropertyCheck[*base.Tag]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: seenLeft[i].Value.Name.ValueNode,
|
||||
RightNode: seenRight[i].Value.Name.ValueNode,
|
||||
Label: v3.NameLabel,
|
||||
@@ -76,7 +76,7 @@ func CompareTags(l, r []low.ValueReference[*base.Tag]) *TagChanges {
|
||||
})
|
||||
|
||||
// Description
|
||||
props = append(props, &PropertyCheck[*base.Tag]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: seenLeft[i].Value.Description.ValueNode,
|
||||
RightNode: seenRight[i].Value.Description.ValueNode,
|
||||
Label: v3.DescriptionLabel,
|
||||
@@ -101,7 +101,7 @@ func CompareTags(l, r []low.ValueReference[*base.Tag]) *TagChanges {
|
||||
|
||||
for i := range seenRight {
|
||||
if seenLeft[i] == nil {
|
||||
CreateChange[*base.Tag](&changes, ObjectAdded, i, nil, seenRight[i].GetValueNode(),
|
||||
CreateChange(&changes, ObjectAdded, i, nil, seenRight[i].GetValueNode(),
|
||||
false, nil, seenRight[i].GetValue())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// XMLChanges represents changes made to the XML object of an OpenAPI document.
|
||||
type XMLChanges struct {
|
||||
PropertyChanges[*base.XML]
|
||||
PropertyChanges
|
||||
ExtensionChanges *ExtensionChanges
|
||||
}
|
||||
|
||||
@@ -33,11 +33,11 @@ func (x *XMLChanges) TotalBreakingChanges() int {
|
||||
// otherwise, if nothing changed - it will return nil
|
||||
func CompareXML(l, r *base.XML) *XMLChanges {
|
||||
xc := new(XMLChanges)
|
||||
var changes []*Change[*base.XML]
|
||||
var props []*PropertyCheck[*base.XML]
|
||||
var changes []*Change
|
||||
var props []*PropertyCheck
|
||||
|
||||
// Name (breaking change)
|
||||
props = append(props, &PropertyCheck[*base.XML]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Name.ValueNode,
|
||||
RightNode: r.Name.ValueNode,
|
||||
Label: v3.NameLabel,
|
||||
@@ -48,7 +48,7 @@ func CompareXML(l, r *base.XML) *XMLChanges {
|
||||
})
|
||||
|
||||
// Namespace (breaking change)
|
||||
props = append(props, &PropertyCheck[*base.XML]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Namespace.ValueNode,
|
||||
RightNode: r.Namespace.ValueNode,
|
||||
Label: v3.NamespaceLabel,
|
||||
@@ -59,7 +59,7 @@ func CompareXML(l, r *base.XML) *XMLChanges {
|
||||
})
|
||||
|
||||
// Prefix (breaking change)
|
||||
props = append(props, &PropertyCheck[*base.XML]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Prefix.ValueNode,
|
||||
RightNode: r.Prefix.ValueNode,
|
||||
Label: v3.PrefixLabel,
|
||||
@@ -70,7 +70,7 @@ func CompareXML(l, r *base.XML) *XMLChanges {
|
||||
})
|
||||
|
||||
// Attribute (breaking change)
|
||||
props = append(props, &PropertyCheck[*base.XML]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Attribute.ValueNode,
|
||||
RightNode: r.Attribute.ValueNode,
|
||||
Label: v3.AttributeLabel,
|
||||
@@ -81,7 +81,7 @@ func CompareXML(l, r *base.XML) *XMLChanges {
|
||||
})
|
||||
|
||||
// Wrapped (breaking change)
|
||||
props = append(props, &PropertyCheck[*base.XML]{
|
||||
props = append(props, &PropertyCheck{
|
||||
LeftNode: l.Wrapped.ValueNode,
|
||||
RightNode: r.Wrapped.ValueNode,
|
||||
Label: v3.WrappedLabel,
|
||||
|
||||
Reference in New Issue
Block a user