Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions datamodel/low/v3/path_item.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package v3

import (
"context"
"errors"
"fmt"
"hash/maphash"
"sort"
Expand Down Expand Up @@ -408,6 +409,10 @@ func (p *PathItem) Build(ctx context.Context, keyNode, root *yaml.Node, idx *ind

// all operations have been superficially built,
// now we need to build out the operation, we will do this asynchronously for speed.
// build errors are collected rather than returned early, so every operation is fully
// constructed even when a sibling operation fails to build.
var opBuildErrors []error
var opBuildErrorsLock sync.Mutex
translateFunc := func(_ int, op low.NodeReference[*Operation]) (any, error) {
ref := ""
var refNode *yaml.Node
Expand All @@ -421,14 +426,13 @@ func (p *PathItem) Build(ctx context.Context, keyNode, root *yaml.Node, idx *ind
op.Value.Reference.SetReference(ref, refNode)
}
if err != nil {
return nil, err
opBuildErrorsLock.Lock()
opBuildErrors = append(opBuildErrors, err)
opBuildErrorsLock.Unlock()
}
return nil, nil
}
err := datamodel.TranslateSliceParallel[low.NodeReference[*Operation], any](ops, translateFunc, nil)
if err != nil {
return err
}
_ = datamodel.TranslateSliceParallel[low.NodeReference[*Operation], any](ops, translateFunc, nil)

// assign additionalOperations if any were found
if additionalOps != nil && additionalOps.Len() > 0 {
Expand All @@ -438,12 +442,15 @@ func (p *PathItem) Build(ctx context.Context, keyNode, root *yaml.Node, idx *ind
extrOps = append(extrOps, appVal)
}

err = datamodel.TranslateSliceParallel[low.NodeReference[*Operation], any](extrOps, translateFunc, nil)
_ = datamodel.TranslateSliceParallel[low.NodeReference[*Operation], any](extrOps, translateFunc, nil)

p.AdditionalOperations = low.NodeReference[*orderedmap.Map[low.KeyReference[string], low.NodeReference[*Operation]]]{
Value: additionalOps,
}
}
if len(opBuildErrors) > 0 {
return errors.Join(opBuildErrors...)
}
return nil
}

Expand Down
29 changes: 29 additions & 0 deletions datamodel/low/v3/path_item_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,35 @@ get:
assert.NotNil(t, n.RootNode)
}

func TestPathItem_Build_NullParameters_BuildsAllOperations(t *testing.T) {
yml := `post:
operationId: createThing
parameters:
put:
operationId: replaceThing
parameters:
delete:
operationId: deleteThing
parameters:`

var idxNode yaml.Node
_ = yaml.Unmarshal([]byte(yml), &idxNode)
idx := index.NewSpecIndex(&idxNode)

var n PathItem
_ = low.BuildModel(idxNode.Content[0], &n)
err := n.Build(context.Background(), nil, idxNode.Content[0], idx)

assert.Error(t, err)
assert.Contains(t, err.Error(), "input is not an array")

// every operation must be fully built out, even though a sibling failed to build first.
assert.NotNil(t, n.Post.Value.Reference)
assert.NotNil(t, n.Put.Value.Reference)
assert.NotNil(t, n.Delete.Value.Reference)
assert.False(t, n.Put.Value.IsReference())
}

func TestPathItem_AdditionalOperations(t *testing.T) {
yml := `get:
description: standard get operation
Expand Down
Loading