Skip to content

Commit

Permalink
Merge branch 'main' into improve-yaml-to-json
Browse files Browse the repository at this point in the history
  • Loading branch information
TristanSpeakEasy committed Aug 5, 2024
2 parents e9aaa58 + 82f5800 commit f803820
Show file tree
Hide file tree
Showing 53 changed files with 934 additions and 46 deletions.
2 changes: 1 addition & 1 deletion bundler/bundler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ components:
assert.ErrorIs(t, unwrap[0], ErrInvalidModel)
unwrapNext := utils.UnwrapErrors(unwrap[1])
require.Len(t, unwrapNext, 2)
assert.Equal(t, "component 'bork' does not exist in the specification", unwrapNext[0].Error())
assert.Equal(t, "component `bork` does not exist in the specification", unwrapNext[0].Error())
assert.Equal(t, "cannot resolve reference `bork`, it's missing: $bork [5:7]", unwrapNext[1].Error())

logEntries := strings.Split(byteBuf.String(), "\n")
Expand Down
8 changes: 8 additions & 0 deletions datamodel/high/base/schema_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ func CreateSchemaProxyRef(ref string) *SchemaProxy {
return &SchemaProxy{refStr: ref, lock: &sync.Mutex{}}
}

// GetValueNode returns the value node of the SchemaProxy.
func (sp *SchemaProxy) GetValueNode() *yaml.Node {
if sp.schema != nil {
return sp.schema.ValueNode
}
return nil
}

// Schema will create a new Schema instance using NewSchema from the low-level SchemaProxy backing this high-level one.
// If there is a problem building the Schema, then this method will return nil. Use GetBuildError to gain access
// to that building error.
Expand Down
14 changes: 14 additions & 0 deletions datamodel/high/base/schema_proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@ func TestCreateSchemaProxy(t *testing.T) {
sp := CreateSchemaProxy(&Schema{Description: "iAmASchema"})
assert.Equal(t, "iAmASchema", sp.rendered.Description)
assert.False(t, sp.IsReference())
assert.Nil(t, sp.GetValueNode())
}

func TestCreateSchemaProxy_NoNilValue(t *testing.T) {
sp := CreateSchemaProxy(&Schema{Description: "iAmASchema"})
sp.Schema()

// jerry rig the test.
nodeRef := low.NodeReference[*lowbase.SchemaProxy]{}
nodeRef.ValueNode = &yaml.Node{}
sp.schema = &nodeRef

assert.Equal(t, "iAmASchema", sp.rendered.Description)
assert.NotNil(t, sp.GetValueNode())
}

func TestCreateSchemaProxyRef(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion datamodel/high/node_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, entry *nodes.NodeEntry) *ya
lr := lut.(low.IsReferenced)
ut := reflect.ValueOf(lr)
if !ut.IsNil() {
if lut.(low.IsReferenced).IsReference() {
if lr != nil && lr.IsReference() {
if !n.Resolve {
valueNode = n.renderReference(lut.(low.IsReferenced))
break
Expand Down
5 changes: 5 additions & 0 deletions datamodel/high/v3/document.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ func (d *Document) GoLow() *low.Document {
return d.low
}

// GoLowUntyped returns the low-level Document that was used to create the high level one, however, it's untyped.
func (d *Document) GoLowUntyped() any {
return d.low
}

// Render will return a YAML representation of the Document object as a byte slice.
func (d *Document) Render() ([]byte, error) {
return yaml.Marshal(d)
Expand Down
1 change: 1 addition & 0 deletions datamodel/high/v3/document_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ func TestNewDocument_Info(t *testing.T) {
assert.Equal(t, "1.2", highDoc.Info.Version)
assert.Equal(t, "https://pb33f.io/schema", highDoc.JsonSchemaDialect)

assert.NotNil(t, highDoc.GoLowUntyped())
wentLow := highDoc.GoLow()
assert.Equal(t, 1, wentLow.Version.ValueNode.Line)
assert.Equal(t, 3, wentLow.Info.Value.Title.KeyNode.Line)
Expand Down
6 changes: 3 additions & 3 deletions datamodel/low/base/contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ type Contact struct {
KeyNode *yaml.Node
RootNode *yaml.Node
*low.Reference
low.NodeMap
}

// Build is not implemented for Contact (there is nothing to build).
func (c *Contact) Build(_ context.Context, keyNode, root *yaml.Node, _ *index.SpecIndex) error {
func (c *Contact) Build(ctx context.Context, keyNode, root *yaml.Node, _ *index.SpecIndex) error {
c.KeyNode = keyNode
c.RootNode = root
c.Reference = new(low.Reference)
// not implemented.
c.Nodes = low.ExtractNodes(ctx, root)
return nil
}

Expand Down
30 changes: 30 additions & 0 deletions datamodel/low/base/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2023-2024 Princess Beef Heavy Industries, LLC / Dave Shanley
// https://pb33f.io

package base

import (
"golang.org/x/net/context"
"sync"
)

// ModelContext is a struct that holds various persistent data structures for the model
// that passes through the entire model building process.
type ModelContext struct {
SchemaCache *sync.Map
}

// GetModelContext will return the ModelContext from a context.Context object
// if it is available, otherwise it will return nil.
func GetModelContext(ctx context.Context) *ModelContext {
if ctx == nil {
return nil
}
if ctx.Value("modelCtx") == nil {
return nil
}
if c, ok := ctx.Value("modelCtx").(*ModelContext); ok {
return c
}
return nil
}
23 changes: 23 additions & 0 deletions datamodel/low/base/context_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2023-2024 Princess Beef Heavy Industries, LLC / Dave Shanley
// https://pb33f.io

package base

import (
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
"testing"
)

func TestGetModelContext(t *testing.T) {

assert.Nil(t, GetModelContext(nil))
assert.Nil(t, GetModelContext(context.Background()))

ctx := context.WithValue(context.Background(), "modelCtx", &ModelContext{})
assert.NotNil(t, GetModelContext(ctx))

ctx = context.WithValue(context.Background(), "modelCtx", "wrong")
assert.Nil(t, GetModelContext(ctx))

}
14 changes: 14 additions & 0 deletions datamodel/low/base/discriminator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package base

import (
"crypto/sha256"
"gopkg.in/yaml.v3"
"strings"

"github.com/pb33f/libopenapi/datamodel/low"
Expand All @@ -23,7 +24,20 @@ import (
type Discriminator struct {
PropertyName low.NodeReference[string]
Mapping low.NodeReference[*orderedmap.Map[low.KeyReference[string], low.ValueReference[string]]]
KeyNode *yaml.Node
RootNode *yaml.Node
low.Reference
low.NodeMap
}

// GetRootNode will return the root yaml node of the Discriminator object
func (d *Discriminator) GetRootNode() *yaml.Node {
return d.RootNode
}

// GetKeyNode will return the key yaml node of the Discriminator object
func (d *Discriminator) GetKeyNode() *yaml.Node {
return d.KeyNode
}

// FindMappingValue will return a ValueReference containing the string mapping value
Expand Down
5 changes: 5 additions & 0 deletions datamodel/low/base/discriminator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ propertyName: freshCakes`
var rDoc Discriminator
_ = low.BuildModel(lNode.Content[0], &lDoc)
_ = low.BuildModel(rNode.Content[0], &rDoc)
lDoc.RootNode = &lNode
lDoc.KeyNode = &rNode

assert.Equal(t, lDoc.Hash(), rDoc.Hash())
assert.NotNil(t, lDoc.GetRootNode())
assert.NotNil(t, lDoc.GetKeyNode())

}
13 changes: 12 additions & 1 deletion datamodel/low/base/example.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type Example struct {
KeyNode *yaml.Node
RootNode *yaml.Node
*low.Reference
low.NodeMap
}

// FindExtension returns a ValueReference containing the extension value, if found.
Expand Down Expand Up @@ -67,12 +68,13 @@ func (ex *Example) Hash() [32]byte {
}

// Build extracts extensions and example value
func (ex *Example) Build(_ context.Context, keyNode, root *yaml.Node, _ *index.SpecIndex) error {
func (ex *Example) Build(ctx context.Context, keyNode, root *yaml.Node, _ *index.SpecIndex) error {
ex.KeyNode = keyNode
root = utils.NodeAlias(root)
ex.RootNode = root
utils.CheckForMergeNodes(root)
ex.Reference = new(low.Reference)
ex.Nodes = low.ExtractNodes(ctx, root)
ex.Extensions = low.ExtractExtensions(root)
_, ln, vn := utils.FindKeyNodeFull(ValueLabel, root.Content)

Expand All @@ -82,6 +84,15 @@ func (ex *Example) Build(_ context.Context, keyNode, root *yaml.Node, _ *index.S
KeyNode: ln,
ValueNode: vn,
}

// extract nodes for all value nodes down the tree.
expChildNodes := low.ExtractNodesRecursive(ctx, vn)
expChildNodes.Range(func(k, v interface{}) bool {
if arr, ko := v.([]*yaml.Node); ko {
ex.Nodes.Store(k, arr)
}
return true
})
return nil
}
return nil
Expand Down
4 changes: 3 additions & 1 deletion datamodel/low/base/external_doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ type ExternalDoc struct {
KeyNode *yaml.Node
RootNode *yaml.Node
*low.Reference
low.NodeMap
}

// FindExtension returns a ValueReference containing the extension value, if found.
Expand All @@ -46,12 +47,13 @@ func (ex *ExternalDoc) GetKeyNode() *yaml.Node {
}

// Build will extract extensions from the ExternalDoc instance.
func (ex *ExternalDoc) Build(_ context.Context, keyNode, root *yaml.Node, idx *index.SpecIndex) error {
func (ex *ExternalDoc) Build(ctx context.Context, keyNode, root *yaml.Node, idx *index.SpecIndex) error {
ex.KeyNode = keyNode
root = utils.NodeAlias(root)
ex.RootNode = root
utils.CheckForMergeNodes(root)
ex.Reference = new(low.Reference)
ex.Nodes = low.ExtractNodes(ctx, root)
ex.Extensions = low.ExtractExtensions(root)
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions datamodel/low/base/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type Info struct {
KeyNode *yaml.Node
RootNode *yaml.Node
*low.Reference
low.NodeMap
}

// FindExtension attempts to locate an extension with the supplied key
Expand Down Expand Up @@ -64,6 +65,7 @@ func (i *Info) Build(ctx context.Context, keyNode, root *yaml.Node, idx *index.S
i.RootNode = root
utils.CheckForMergeNodes(root)
i.Reference = new(low.Reference)
i.Nodes = low.ExtractNodes(ctx, root)
i.Extensions = low.ExtractExtensions(root)

// extract contact
Expand Down
3 changes: 3 additions & 0 deletions datamodel/low/base/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type License struct {
KeyNode *yaml.Node
RootNode *yaml.Node
*low.Reference
low.NodeMap
}

// Build out a license, complain if both a URL and identifier are present as they are mutually exclusive
Expand All @@ -34,6 +35,8 @@ func (l *License) Build(ctx context.Context, keyNode, root *yaml.Node, idx *inde
l.RootNode = root
utils.CheckForMergeNodes(root)
l.Reference = new(low.Reference)
no := low.ExtractNodes(ctx, root)
l.Nodes = no
if l.URL.Value != "" && l.Identifier.Value != "" {
return fmt.Errorf("license cannot have both a URL and an identifier, they are mutually exclusive")
}
Expand Down
Loading

0 comments on commit f803820

Please sign in to comment.