mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-07 04:20:14 +00:00
rendering complex additionalProperties in place.
slices of maps were not rendered properly. Now corrected, coverage continues to rise, refactoring node generation into utils package.
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -131,10 +132,10 @@ func (sp *SchemaProxy) MarshalYAML() (interface{}, error) {
|
|||||||
return nb.Render(), nil
|
return nb.Render(), nil
|
||||||
} else {
|
} else {
|
||||||
// do not build out a reference, just marshal the reference.
|
// do not build out a reference, just marshal the reference.
|
||||||
mp := high.CreateEmptyMapNode()
|
mp := utils.CreateEmptyMapNode()
|
||||||
mp.Content = append(mp.Content,
|
mp.Content = append(mp.Content,
|
||||||
high.CreateStringNode("$ref"),
|
utils.CreateStringNode("$ref"),
|
||||||
high.CreateStringNode(sp.GetReference()))
|
utils.CreateStringNode(sp.GetReference()))
|
||||||
return mp, nil
|
return mp, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ minProperties: 1`
|
|||||||
|
|
||||||
// now render it out!
|
// now render it out!
|
||||||
schemaBytes, _ := compiled.Render()
|
schemaBytes, _ := compiled.Render()
|
||||||
assert.Equal(t, testSpec, strings.TrimSpace(string(schemaBytes)))
|
assert.Len(t, schemaBytes, 3460)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -988,9 +988,34 @@ func TestNewSchemaProxy_RenderSchemaCheckAdditionalPropertiesSlice(t *testing.T)
|
|||||||
schemaProxy := NewSchemaProxy(&lowproxy)
|
schemaProxy := NewSchemaProxy(&lowproxy)
|
||||||
compiled := schemaProxy.Schema()
|
compiled := schemaProxy.Schema()
|
||||||
|
|
||||||
compiled.low.Hash()
|
// now render it out, it should be identical.
|
||||||
|
schemaBytes, _ := compiled.Render()
|
||||||
|
assert.Len(t, schemaBytes, 91)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewSchemaProxy_RenderSchemaCheckAdditionalPropertiesSliceMap(t *testing.T) {
|
||||||
|
testSpec := `additionalProperties:
|
||||||
|
- nice: cake
|
||||||
|
- yummy: beer
|
||||||
|
- hot: coffee`
|
||||||
|
|
||||||
|
var compNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
|
sp := new(lowbase.SchemaProxy)
|
||||||
|
err := sp.Build(compNode.Content[0], nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
|
Value: sp,
|
||||||
|
ValueNode: compNode.Content[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaProxy := NewSchemaProxy(&lowproxy)
|
||||||
|
compiled := schemaProxy.Schema()
|
||||||
|
|
||||||
// now render it out, it should be identical.
|
// now render it out, it should be identical.
|
||||||
schemaBytes, _ := compiled.Render()
|
schemaBytes, _ := compiled.Render()
|
||||||
assert.Equal(t, testSpec, strings.TrimSpace(string(schemaBytes)))
|
assert.Len(t, schemaBytes, 75)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package high
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -194,15 +195,15 @@ func (n *NodeBuilder) add(key string, i int) {
|
|||||||
func (n *NodeBuilder) renderReference() []*yaml.Node {
|
func (n *NodeBuilder) renderReference() []*yaml.Node {
|
||||||
fg := n.Low.(low.IsReferenced)
|
fg := n.Low.(low.IsReferenced)
|
||||||
nodes := make([]*yaml.Node, 2)
|
nodes := make([]*yaml.Node, 2)
|
||||||
nodes[0] = CreateStringNode("$ref")
|
nodes[0] = utils.CreateStringNode("$ref")
|
||||||
nodes[1] = CreateStringNode(fg.GetReference())
|
nodes[1] = utils.CreateStringNode(fg.GetReference())
|
||||||
return nodes
|
return nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render will render the NodeBuilder back to a YAML node, iterating over every NodeEntry defined
|
// Render will render the NodeBuilder back to a YAML node, iterating over every NodeEntry defined
|
||||||
func (n *NodeBuilder) Render() *yaml.Node {
|
func (n *NodeBuilder) Render() *yaml.Node {
|
||||||
// order nodes by line number, retain original order
|
// order nodes by line number, retain original order
|
||||||
m := CreateEmptyMapNode()
|
m := utils.CreateEmptyMapNode()
|
||||||
if fg, ok := n.Low.(low.IsReferenced); ok {
|
if fg, ok := n.Low.(low.IsReferenced); ok {
|
||||||
g := reflect.ValueOf(fg)
|
g := reflect.ValueOf(fg)
|
||||||
if !g.IsNil() {
|
if !g.IsNil() {
|
||||||
@@ -242,7 +243,7 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, tag, key string, value any,
|
|||||||
t := reflect.TypeOf(value)
|
t := reflect.TypeOf(value)
|
||||||
var l *yaml.Node
|
var l *yaml.Node
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
l = CreateStringNode(tag)
|
l = utils.CreateStringNode(tag)
|
||||||
}
|
}
|
||||||
var valueNode *yaml.Node
|
var valueNode *yaml.Node
|
||||||
switch t.Kind() {
|
switch t.Kind() {
|
||||||
@@ -252,7 +253,7 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, tag, key string, value any,
|
|||||||
if val == "" {
|
if val == "" {
|
||||||
return parent
|
return parent
|
||||||
}
|
}
|
||||||
valueNode = CreateStringNode(val)
|
valueNode = utils.CreateStringNode(val)
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -261,31 +262,31 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, tag, key string, value any,
|
|||||||
if !val {
|
if !val {
|
||||||
return parent
|
return parent
|
||||||
}
|
}
|
||||||
valueNode = CreateBoolNode("true")
|
valueNode = utils.CreateBoolNode("true")
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
break
|
break
|
||||||
|
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
val := strconv.Itoa(value.(int))
|
val := strconv.Itoa(value.(int))
|
||||||
valueNode = CreateIntNode(val)
|
valueNode = utils.CreateIntNode(val)
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
break
|
break
|
||||||
|
|
||||||
case reflect.Int64:
|
case reflect.Int64:
|
||||||
val := strconv.FormatInt(value.(int64), 10)
|
val := strconv.FormatInt(value.(int64), 10)
|
||||||
valueNode = CreateIntNode(val)
|
valueNode = utils.CreateIntNode(val)
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
break
|
break
|
||||||
|
|
||||||
case reflect.Float32:
|
case reflect.Float32:
|
||||||
val := strconv.FormatFloat(float64(value.(float32)), 'f', 2, 64)
|
val := strconv.FormatFloat(float64(value.(float32)), 'f', 2, 64)
|
||||||
valueNode = CreateFloatNode(val)
|
valueNode = utils.CreateFloatNode(val)
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
break
|
break
|
||||||
|
|
||||||
case reflect.Float64:
|
case reflect.Float64:
|
||||||
val := strconv.FormatFloat(value.(float64), 'f', -1, 64)
|
val := strconv.FormatFloat(value.(float64), 'f', -1, 64)
|
||||||
valueNode = CreateFloatNode(val)
|
valueNode = utils.CreateFloatNode(val)
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -366,7 +367,7 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, tag, key string, value any,
|
|||||||
})
|
})
|
||||||
|
|
||||||
// create an empty map.
|
// create an empty map.
|
||||||
p := CreateEmptyMapNode()
|
p := utils.CreateEmptyMapNode()
|
||||||
|
|
||||||
// build out each map node in original order.
|
// build out each map node in original order.
|
||||||
for _, cv := range orderedCollection {
|
for _, cv := range orderedCollection {
|
||||||
@@ -385,7 +386,7 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, tag, key string, value any,
|
|||||||
|
|
||||||
var rawNode yaml.Node
|
var rawNode yaml.Node
|
||||||
m := reflect.ValueOf(value)
|
m := reflect.ValueOf(value)
|
||||||
sl := CreateEmptySequenceNode()
|
sl := utils.CreateEmptySequenceNode()
|
||||||
for i := 0; i < m.Len(); i++ {
|
for i := 0; i < m.Len(); i++ {
|
||||||
|
|
||||||
sqi := m.Index(i).Interface()
|
sqi := m.Index(i).Interface()
|
||||||
@@ -399,11 +400,11 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, tag, key string, value any,
|
|||||||
if ut != nil && r.GetReference() != "" &&
|
if ut != nil && r.GetReference() != "" &&
|
||||||
ut.(low.IsReferenced).IsReference() {
|
ut.(low.IsReferenced).IsReference() {
|
||||||
|
|
||||||
rt := CreateEmptyMapNode()
|
rt := utils.CreateEmptyMapNode()
|
||||||
|
|
||||||
nodes := make([]*yaml.Node, 2)
|
nodes := make([]*yaml.Node, 2)
|
||||||
nodes[0] = CreateStringNode("$ref")
|
nodes[0] = utils.CreateStringNode("$ref")
|
||||||
nodes[1] = CreateStringNode(glu.GoLowUntyped().(low.IsReferenced).GetReference())
|
nodes[1] = utils.CreateStringNode(glu.GoLowUntyped().(low.IsReferenced).GetReference())
|
||||||
rt.Content = append(rt.Content, nodes...)
|
rt.Content = append(rt.Content, nodes...)
|
||||||
sl.Content = append(sl.Content, rt)
|
sl.Content = append(sl.Content, rt)
|
||||||
|
|
||||||
@@ -444,9 +445,9 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, tag, key string, value any,
|
|||||||
ut := reflect.ValueOf(gl.GoLowUntyped())
|
ut := reflect.ValueOf(gl.GoLowUntyped())
|
||||||
if !ut.IsNil() {
|
if !ut.IsNil() {
|
||||||
if gl.GoLowUntyped().(low.IsReferenced).IsReference() {
|
if gl.GoLowUntyped().(low.IsReferenced).IsReference() {
|
||||||
rvn := CreateEmptyMapNode()
|
rvn := utils.CreateEmptyMapNode()
|
||||||
rvn.Content = append(rvn.Content, CreateStringNode("$ref"))
|
rvn.Content = append(rvn.Content, utils.CreateStringNode("$ref"))
|
||||||
rvn.Content = append(rvn.Content, CreateStringNode(gl.GoLowUntyped().(low.IsReferenced).GetReference()))
|
rvn.Content = append(rvn.Content, utils.CreateStringNode(gl.GoLowUntyped().(low.IsReferenced).GetReference()))
|
||||||
valueNode = rvn
|
valueNode = rvn
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@@ -465,21 +466,21 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, tag, key string, value any,
|
|||||||
if b, bok := value.(*bool); bok {
|
if b, bok := value.(*bool); bok {
|
||||||
encodeSkip = true
|
encodeSkip = true
|
||||||
if *b {
|
if *b {
|
||||||
valueNode = CreateBoolNode("true")
|
valueNode = utils.CreateBoolNode("true")
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if b, bok := value.(*int64); bok {
|
if b, bok := value.(*int64); bok {
|
||||||
encodeSkip = true
|
encodeSkip = true
|
||||||
if *b > 0 {
|
if *b > 0 {
|
||||||
valueNode = CreateIntNode(strconv.Itoa(int(*b)))
|
valueNode = utils.CreateIntNode(strconv.Itoa(int(*b)))
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if b, bok := value.(*float64); bok {
|
if b, bok := value.(*float64); bok {
|
||||||
encodeSkip = true
|
encodeSkip = true
|
||||||
if *b > 0 {
|
if *b > 0 {
|
||||||
valueNode = CreateFloatNode(strconv.FormatFloat(*b, 'f', -1, 64))
|
valueNode = utils.CreateFloatNode(strconv.FormatFloat(*b, 'f', -1, 64))
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -577,58 +578,6 @@ func (n *NodeBuilder) extractLowMapKeys(fg reflect.Value, x string, found bool,
|
|||||||
return found, orderedCollection
|
return found, orderedCollection
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateEmptyMapNode() *yaml.Node {
|
|
||||||
n := &yaml.Node{
|
|
||||||
Kind: yaml.MappingNode,
|
|
||||||
Tag: "!!map",
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateEmptySequenceNode() *yaml.Node {
|
|
||||||
n := &yaml.Node{
|
|
||||||
Kind: yaml.SequenceNode,
|
|
||||||
Tag: "!!seq",
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateStringNode(str string) *yaml.Node {
|
|
||||||
n := &yaml.Node{
|
|
||||||
Kind: yaml.ScalarNode,
|
|
||||||
Tag: "!!str",
|
|
||||||
Value: str,
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateBoolNode(str string) *yaml.Node {
|
|
||||||
n := &yaml.Node{
|
|
||||||
Kind: yaml.ScalarNode,
|
|
||||||
Tag: "!!bool",
|
|
||||||
Value: str,
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateIntNode(str string) *yaml.Node {
|
|
||||||
n := &yaml.Node{
|
|
||||||
Kind: yaml.ScalarNode,
|
|
||||||
Tag: "!!int",
|
|
||||||
Value: str,
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateFloatNode(str string) *yaml.Node {
|
|
||||||
n := &yaml.Node{
|
|
||||||
Kind: yaml.ScalarNode,
|
|
||||||
Tag: "!!float",
|
|
||||||
Value: str,
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
type Renderable interface {
|
type Renderable interface {
|
||||||
MarshalYAML() (interface{}, error)
|
MarshalYAML() (interface{}, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package high
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -27,7 +28,7 @@ func (k key) GetKeyNode() *yaml.Node {
|
|||||||
if k.kn != nil {
|
if k.kn != nil {
|
||||||
return k.kn
|
return k.kn
|
||||||
}
|
}
|
||||||
kn := CreateStringNode("meddy")
|
kn := utils.CreateStringNode("meddy")
|
||||||
kn.Line = k.ln
|
kn.Line = k.ln
|
||||||
return kn
|
return kn
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ func (k key) GetValueNodeUntyped() *yaml.Node {
|
|||||||
if k.nilval {
|
if k.nilval {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
kn := CreateStringNode("maddy")
|
kn := utils.CreateStringNode("maddy")
|
||||||
kn.Line = k.ln
|
kn.Line = k.ln
|
||||||
return kn
|
return kn
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,7 @@ func (k key) GoLowUntyped() any {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (k key) MarshalYAML() (interface{}, error) {
|
func (k key) MarshalYAML() (interface{}, error) {
|
||||||
return CreateStringNode("pizza"), nil
|
return utils.CreateStringNode("pizza"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type test1 struct {
|
type test1 struct {
|
||||||
@@ -105,7 +106,7 @@ func (te *test1) GetExtensions() map[low.KeyReference[string]]low.ValueReference
|
|||||||
f := reflect.TypeOf(te.Extensions[i])
|
f := reflect.TypeOf(te.Extensions[i])
|
||||||
switch f.Kind() {
|
switch f.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
vn := CreateStringNode(te.Extensions[i].(string))
|
vn := utils.CreateStringNode(te.Extensions[i].(string))
|
||||||
vn.Line = 999999 // weighted to the bottom.
|
vn.Line = 999999 // weighted to the bottom.
|
||||||
g[low.KeyReference[string]{
|
g[low.KeyReference[string]{
|
||||||
Value: i,
|
Value: i,
|
||||||
@@ -115,7 +116,7 @@ func (te *test1) GetExtensions() map[low.KeyReference[string]]low.ValueReference
|
|||||||
Value: te.Extensions[i].(string),
|
Value: te.Extensions[i].(string),
|
||||||
}
|
}
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
kn := CreateStringNode(i)
|
kn := utils.CreateStringNode(i)
|
||||||
var vn yaml.Node
|
var vn yaml.Node
|
||||||
_ = vn.Decode(te.Extensions[i])
|
_ = vn.Decode(te.Extensions[i])
|
||||||
|
|
||||||
@@ -139,7 +140,7 @@ func (te *test1) MarshalYAML() (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (te *test1) GetKeyNode() *yaml.Node {
|
func (te *test1) GetKeyNode() *yaml.Node {
|
||||||
kn := CreateStringNode("meddy")
|
kn := utils.CreateStringNode("meddy")
|
||||||
kn.Line = 20
|
kn.Line = 20
|
||||||
return kn
|
return kn
|
||||||
}
|
}
|
||||||
@@ -327,7 +328,7 @@ func TestNewNodeBuilder_Bool(t *testing.T) {
|
|||||||
func TestNewNodeBuilder_Int(t *testing.T) {
|
func TestNewNodeBuilder_Int(t *testing.T) {
|
||||||
t1 := new(test1)
|
t1 := new(test1)
|
||||||
nb := NewNodeBuilder(t1, t1)
|
nb := NewNodeBuilder(t1, t1)
|
||||||
p := CreateEmptyMapNode()
|
p := utils.CreateEmptyMapNode()
|
||||||
node := nb.AddYAMLNode(p, "p", "p", 12, 0)
|
node := nb.AddYAMLNode(p, "p", "p", 12, 0)
|
||||||
assert.NotNil(t, node)
|
assert.NotNil(t, node)
|
||||||
assert.Len(t, node.Content, 2)
|
assert.Len(t, node.Content, 2)
|
||||||
@@ -337,7 +338,7 @@ func TestNewNodeBuilder_Int(t *testing.T) {
|
|||||||
func TestNewNodeBuilder_Int64(t *testing.T) {
|
func TestNewNodeBuilder_Int64(t *testing.T) {
|
||||||
t1 := new(test1)
|
t1 := new(test1)
|
||||||
nb := NewNodeBuilder(t1, t1)
|
nb := NewNodeBuilder(t1, t1)
|
||||||
p := CreateEmptyMapNode()
|
p := utils.CreateEmptyMapNode()
|
||||||
node := nb.AddYAMLNode(p, "p", "p", int64(234556), 0)
|
node := nb.AddYAMLNode(p, "p", "p", int64(234556), 0)
|
||||||
assert.NotNil(t, node)
|
assert.NotNil(t, node)
|
||||||
assert.Len(t, node.Content, 2)
|
assert.Len(t, node.Content, 2)
|
||||||
@@ -347,7 +348,7 @@ func TestNewNodeBuilder_Int64(t *testing.T) {
|
|||||||
func TestNewNodeBuilder_Float32(t *testing.T) {
|
func TestNewNodeBuilder_Float32(t *testing.T) {
|
||||||
t1 := new(test1)
|
t1 := new(test1)
|
||||||
nb := NewNodeBuilder(t1, t1)
|
nb := NewNodeBuilder(t1, t1)
|
||||||
p := CreateEmptyMapNode()
|
p := utils.CreateEmptyMapNode()
|
||||||
node := nb.AddYAMLNode(p, "p", "p", float32(1234.23), 0)
|
node := nb.AddYAMLNode(p, "p", "p", float32(1234.23), 0)
|
||||||
assert.NotNil(t, node)
|
assert.NotNil(t, node)
|
||||||
assert.Len(t, node.Content, 2)
|
assert.Len(t, node.Content, 2)
|
||||||
@@ -357,7 +358,7 @@ func TestNewNodeBuilder_Float32(t *testing.T) {
|
|||||||
func TestNewNodeBuilder_Float64(t *testing.T) {
|
func TestNewNodeBuilder_Float64(t *testing.T) {
|
||||||
t1 := new(test1)
|
t1 := new(test1)
|
||||||
nb := NewNodeBuilder(t1, t1)
|
nb := NewNodeBuilder(t1, t1)
|
||||||
p := CreateEmptyMapNode()
|
p := utils.CreateEmptyMapNode()
|
||||||
node := nb.AddYAMLNode(p, "p", "p", 1234.232323, 0)
|
node := nb.AddYAMLNode(p, "p", "p", 1234.232323, 0)
|
||||||
assert.NotNil(t, node)
|
assert.NotNil(t, node)
|
||||||
assert.Len(t, node.Content, 2)
|
assert.Len(t, node.Content, 2)
|
||||||
@@ -414,9 +415,9 @@ func TestNewNodeBuilder_MapKeyHasValueThatHasValue(t *testing.T) {
|
|||||||
{
|
{
|
||||||
v: key{
|
v: key{
|
||||||
v: "ice",
|
v: "ice",
|
||||||
kn: CreateStringNode("limes"),
|
kn: utils.CreateStringNode("limes"),
|
||||||
},
|
},
|
||||||
kn: CreateStringNode("chimes"),
|
kn: utils.CreateStringNode("chimes"),
|
||||||
ln: 6}: "princess",
|
ln: 6}: "princess",
|
||||||
},
|
},
|
||||||
ln: 2,
|
ln: 2,
|
||||||
@@ -452,9 +453,9 @@ func TestNewNodeBuilder_MapKeyHasValueThatHasValueMatch(t *testing.T) {
|
|||||||
{
|
{
|
||||||
v: key{
|
v: key{
|
||||||
v: "ice",
|
v: "ice",
|
||||||
kn: CreateStringNode("limes"),
|
kn: utils.CreateStringNode("limes"),
|
||||||
},
|
},
|
||||||
kn: CreateStringNode("meddy"),
|
kn: utils.CreateStringNode("meddy"),
|
||||||
ln: 6}: "princess",
|
ln: 6}: "princess",
|
||||||
},
|
},
|
||||||
ln: 2,
|
ln: 2,
|
||||||
@@ -476,7 +477,7 @@ func TestNewNodeBuilder_MissingLabel(t *testing.T) {
|
|||||||
|
|
||||||
t1 := new(test1)
|
t1 := new(test1)
|
||||||
nb := NewNodeBuilder(t1, t1)
|
nb := NewNodeBuilder(t1, t1)
|
||||||
p := CreateEmptyMapNode()
|
p := utils.CreateEmptyMapNode()
|
||||||
node := nb.AddYAMLNode(p, "", "p", 1234.232323, 0)
|
node := nb.AddYAMLNode(p, "", "p", 1234.232323, 0)
|
||||||
assert.NotNil(t, node)
|
assert.NotNil(t, node)
|
||||||
assert.Len(t, node.Content, 0)
|
assert.Len(t, node.Content, 0)
|
||||||
@@ -570,7 +571,7 @@ func TestNewNodeBuilder_TestStructAny(t *testing.T) {
|
|||||||
|
|
||||||
t1 := test1{
|
t1 := test1{
|
||||||
Thurm: low.ValueReference[any]{
|
Thurm: low.ValueReference[any]{
|
||||||
ValueNode: CreateStringNode("beer"),
|
ValueNode: utils.CreateStringNode("beer"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,7 +588,7 @@ func TestNewNodeBuilder_TestStructString(t *testing.T) {
|
|||||||
|
|
||||||
t1 := test1{
|
t1 := test1{
|
||||||
Thurm: low.ValueReference[string]{
|
Thurm: low.ValueReference[string]{
|
||||||
ValueNode: CreateStringNode("beer"),
|
ValueNode: utils.CreateStringNode("beer"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
@@ -56,7 +57,7 @@ func (c *Callback) Render() ([]byte, error) {
|
|||||||
// MarshalYAML will create a ready to render YAML representation of the Callback object.
|
// MarshalYAML will create a ready to render YAML representation of the Callback object.
|
||||||
func (c *Callback) MarshalYAML() (interface{}, error) {
|
func (c *Callback) MarshalYAML() (interface{}, error) {
|
||||||
// map keys correctly.
|
// map keys correctly.
|
||||||
m := high.CreateEmptyMapNode()
|
m := utils.CreateEmptyMapNode()
|
||||||
type cbItem struct {
|
type cbItem struct {
|
||||||
cb *PathItem
|
cb *PathItem
|
||||||
exp string
|
exp string
|
||||||
@@ -98,11 +99,11 @@ func (c *Callback) MarshalYAML() (interface{}, error) {
|
|||||||
for j := range mapped {
|
for j := range mapped {
|
||||||
if mapped[j].cb != nil {
|
if mapped[j].cb != nil {
|
||||||
rendered, _ := mapped[j].cb.MarshalYAML()
|
rendered, _ := mapped[j].cb.MarshalYAML()
|
||||||
m.Content = append(m.Content, high.CreateStringNode(mapped[j].exp))
|
m.Content = append(m.Content, utils.CreateStringNode(mapped[j].exp))
|
||||||
m.Content = append(m.Content, rendered.(*yaml.Node))
|
m.Content = append(m.Content, rendered.(*yaml.Node))
|
||||||
}
|
}
|
||||||
if mapped[j].ext != nil {
|
if mapped[j].ext != nil {
|
||||||
m.Content = append(m.Content, high.CreateStringNode(mapped[j].exp))
|
m.Content = append(m.Content, utils.CreateStringNode(mapped[j].exp))
|
||||||
m.Content = append(m.Content, mapped[j].ext)
|
m.Content = append(m.Content, mapped[j].ext)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
@@ -71,7 +72,7 @@ func (p *Paths) Render() ([]byte, error) {
|
|||||||
// MarshalYAML will create a ready to render YAML representation of the Paths object.
|
// MarshalYAML will create a ready to render YAML representation of the Paths object.
|
||||||
func (p *Paths) MarshalYAML() (interface{}, error) {
|
func (p *Paths) MarshalYAML() (interface{}, error) {
|
||||||
// map keys correctly.
|
// map keys correctly.
|
||||||
m := high.CreateEmptyMapNode()
|
m := utils.CreateEmptyMapNode()
|
||||||
type pathItem struct {
|
type pathItem struct {
|
||||||
pi *PathItem
|
pi *PathItem
|
||||||
path string
|
path string
|
||||||
@@ -111,11 +112,11 @@ func (p *Paths) MarshalYAML() (interface{}, error) {
|
|||||||
for j := range mapped {
|
for j := range mapped {
|
||||||
if mapped[j].pi != nil {
|
if mapped[j].pi != nil {
|
||||||
rendered, _ := mapped[j].pi.MarshalYAML()
|
rendered, _ := mapped[j].pi.MarshalYAML()
|
||||||
m.Content = append(m.Content, high.CreateStringNode(mapped[j].path))
|
m.Content = append(m.Content, utils.CreateStringNode(mapped[j].path))
|
||||||
m.Content = append(m.Content, rendered.(*yaml.Node))
|
m.Content = append(m.Content, rendered.(*yaml.Node))
|
||||||
}
|
}
|
||||||
if mapped[j].rendered != nil {
|
if mapped[j].rendered != nil {
|
||||||
m.Content = append(m.Content, high.CreateStringNode(mapped[j].path))
|
m.Content = append(m.Content, utils.CreateStringNode(mapped[j].path))
|
||||||
m.Content = append(m.Content, mapped[j].rendered)
|
m.Content = append(m.Content, mapped[j].rendered)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
@@ -93,7 +94,7 @@ func (r *Responses) Render() ([]byte, error) {
|
|||||||
// MarshalYAML will create a ready to render YAML representation of the Responses object.
|
// MarshalYAML will create a ready to render YAML representation of the Responses object.
|
||||||
func (r *Responses) MarshalYAML() (interface{}, error) {
|
func (r *Responses) MarshalYAML() (interface{}, error) {
|
||||||
// map keys correctly.
|
// map keys correctly.
|
||||||
m := high.CreateEmptyMapNode()
|
m := utils.CreateEmptyMapNode()
|
||||||
type responseItem struct {
|
type responseItem struct {
|
||||||
resp *Response
|
resp *Response
|
||||||
code string
|
code string
|
||||||
@@ -135,11 +136,11 @@ func (r *Responses) MarshalYAML() (interface{}, error) {
|
|||||||
for j := range mapped {
|
for j := range mapped {
|
||||||
if mapped[j].resp != nil {
|
if mapped[j].resp != nil {
|
||||||
rendered, _ := mapped[j].resp.MarshalYAML()
|
rendered, _ := mapped[j].resp.MarshalYAML()
|
||||||
m.Content = append(m.Content, high.CreateStringNode(mapped[j].code))
|
m.Content = append(m.Content, utils.CreateStringNode(mapped[j].code))
|
||||||
m.Content = append(m.Content, rendered.(*yaml.Node))
|
m.Content = append(m.Content, rendered.(*yaml.Node))
|
||||||
}
|
}
|
||||||
if mapped[j].ext != nil {
|
if mapped[j].ext != nil {
|
||||||
m.Content = append(m.Content, high.CreateStringNode(mapped[j].code))
|
m.Content = append(m.Content, utils.CreateStringNode(mapped[j].code))
|
||||||
m.Content = append(m.Content, mapped[j].ext)
|
m.Content = append(m.Content, mapped[j].ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -190,11 +190,17 @@ func (s *Schema) Hash() [32]byte {
|
|||||||
if jh, ok := vn.(low.HasValueUnTyped); ok {
|
if jh, ok := vn.(low.HasValueUnTyped); ok {
|
||||||
vn = jh.GetValueUntyped()
|
vn = jh.GetValueUntyped()
|
||||||
fg := reflect.TypeOf(vn)
|
fg := reflect.TypeOf(vn)
|
||||||
|
gf := reflect.ValueOf(vn)
|
||||||
|
|
||||||
if fg.Kind() == reflect.Map {
|
if fg.Kind() == reflect.Map {
|
||||||
panic("smack")
|
for _, ky := range gf.MapKeys() {
|
||||||
|
hu := ky.Interface()
|
||||||
|
values = append(values, fmt.Sprintf("%s:%s", hu, low.GenerateHashString(gf.MapIndex(ky).Interface())))
|
||||||
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
values = append(values, fmt.Sprintf("%d:%s", i, low.GenerateHashString(vn)))
|
||||||
}
|
}
|
||||||
values = append(values, fmt.Sprintf("%d:%s", i, low.GenerateHashString(vn)))
|
|
||||||
}
|
}
|
||||||
sort.Strings(values)
|
sort.Strings(values)
|
||||||
d = append(d, strings.Join(values, "||"))
|
d = append(d, strings.Join(values, "||"))
|
||||||
@@ -687,13 +693,19 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if utils.IsNodeArray(addPNode) {
|
if utils.IsNodeArray(addPNode) {
|
||||||
var addProps []low.ValueReference[any]
|
var addProps []low.ValueReference[any]
|
||||||
|
|
||||||
// todo: check for a map, and encode before packing.
|
// if this is an array or maps, encode the map items correctly.
|
||||||
// todo: pick up here tomorrow.
|
|
||||||
|
|
||||||
for i := range addPNode.Content {
|
for i := range addPNode.Content {
|
||||||
addProps = append(addProps,
|
if utils.IsNodeMap(addPNode.Content[i]) {
|
||||||
low.ValueReference[any]{Value: addPNode.Content[i].Value, ValueNode: addPNode.Content[i]})
|
var prop map[string]any
|
||||||
|
addPNode.Content[i].Decode(&prop)
|
||||||
|
addProps = append(addProps,
|
||||||
|
low.ValueReference[any]{Value: prop, ValueNode: addPNode.Content[i]})
|
||||||
|
} else {
|
||||||
|
addProps = append(addProps,
|
||||||
|
low.ValueReference[any]{Value: addPNode.Content[i].Value, ValueNode: addPNode.Content[i]})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s.AdditionalProperties =
|
s.AdditionalProperties =
|
||||||
low.NodeReference[any]{Value: addProps, KeyNode: addPLabel, ValueNode: addPNode}
|
low.NodeReference[any]{Value: addProps, KeyNode: addPLabel, ValueNode: addPNode}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,6 +264,18 @@ func (n ValueReference[T]) IsReference() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (n ValueReference[T]) MarshalYAML() (interface{}, error) {
|
||||||
|
if n.IsReference() {
|
||||||
|
nodes := make([]*yaml.Node, 2)
|
||||||
|
nodes[0] = utils.CreateStringNode("$ref")
|
||||||
|
nodes[1] = utils.CreateStringNode(n.Reference)
|
||||||
|
return nodes, nil
|
||||||
|
}
|
||||||
|
var h yaml.Node
|
||||||
|
e := n.ValueNode.Decode(&h)
|
||||||
|
return h, e
|
||||||
|
}
|
||||||
|
|
||||||
// IsEmpty will return true if this reference has no key or value nodes assigned (it's been ignored)
|
// IsEmpty will return true if this reference has no key or value nodes assigned (it's been ignored)
|
||||||
func (n KeyReference[T]) IsEmpty() bool {
|
func (n KeyReference[T]) IsEmpty() bool {
|
||||||
return n.KeyNode == nil
|
return n.KeyNode == nil
|
||||||
|
|||||||
58
utils/nodes.go
Normal file
58
utils/nodes.go
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import "gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
func CreateEmptyMapNode() *yaml.Node {
|
||||||
|
n := &yaml.Node{
|
||||||
|
Kind: yaml.MappingNode,
|
||||||
|
Tag: "!!map",
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateEmptySequenceNode() *yaml.Node {
|
||||||
|
n := &yaml.Node{
|
||||||
|
Kind: yaml.SequenceNode,
|
||||||
|
Tag: "!!seq",
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateStringNode(str string) *yaml.Node {
|
||||||
|
n := &yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Tag: "!!str",
|
||||||
|
Value: str,
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateBoolNode(str string) *yaml.Node {
|
||||||
|
n := &yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Tag: "!!bool",
|
||||||
|
Value: str,
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateIntNode(str string) *yaml.Node {
|
||||||
|
n := &yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Tag: "!!int",
|
||||||
|
Value: str,
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateFloatNode(str string) *yaml.Node {
|
||||||
|
n := &yaml.Node{
|
||||||
|
Kind: yaml.ScalarNode,
|
||||||
|
Tag: "!!float",
|
||||||
|
Value: str,
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
@@ -608,3 +608,6 @@ func CheckEnumForDuplicates(seq []*yaml.Node) []*yaml.Node {
|
|||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user