mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 12:37:49 +00:00
Addressed comments from review and fixed bug with schema props
props did not have context, therefore they had no idea where they were or where to resolve from. Signed-off-by: quobix <dave@quobix.com>
This commit is contained in:
@@ -720,7 +720,7 @@ func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecInde
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle properties
|
// handle properties
|
||||||
props, err := buildPropertyMap(root, idx, PropertiesLabel)
|
props, err := buildPropertyMap(ctx, root, idx, PropertiesLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -729,7 +729,7 @@ func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecInde
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle dependent schemas
|
// handle dependent schemas
|
||||||
props, err = buildPropertyMap(root, idx, DependentSchemasLabel)
|
props, err = buildPropertyMap(ctx, root, idx, DependentSchemasLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -738,7 +738,7 @@ func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecInde
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle pattern properties
|
// handle pattern properties
|
||||||
props, err = buildPropertyMap(root, idx, PatternPropertiesLabel)
|
props, err = buildPropertyMap(ctx, root, idx, PatternPropertiesLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1036,11 +1036,11 @@ func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecInde
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SchemaProxy]], error) {
|
func buildPropertyMap(ctx context.Context, root *yaml.Node, idx *index.SpecIndex, label string) (*low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*SchemaProxy]], error) {
|
||||||
// for property, build in a new thread!
|
// for property, build in a new thread!
|
||||||
bChan := make(chan schemaProxyBuildResult)
|
bChan := make(chan schemaProxyBuildResult)
|
||||||
|
|
||||||
buildProperty := func(label *yaml.Node, value *yaml.Node, c chan schemaProxyBuildResult, isRef bool,
|
buildProperty := func(ctx context.Context, label *yaml.Node, value *yaml.Node, c chan schemaProxyBuildResult, isRef bool,
|
||||||
refString string,
|
refString string,
|
||||||
) {
|
) {
|
||||||
c <- schemaProxyBuildResult{
|
c <- schemaProxyBuildResult{
|
||||||
@@ -1049,7 +1049,7 @@ func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low
|
|||||||
Value: label.Value,
|
Value: label.Value,
|
||||||
},
|
},
|
||||||
v: low.ValueReference[*SchemaProxy]{
|
v: low.ValueReference[*SchemaProxy]{
|
||||||
Value: &SchemaProxy{kn: label, vn: value, idx: idx, isReference: isRef, referenceLookup: refString},
|
Value: &SchemaProxy{ctx: ctx, kn: label, vn: value, idx: idx, isReference: isRef, referenceLookup: refString},
|
||||||
ValueNode: value,
|
ValueNode: value,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1066,22 +1066,24 @@ func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foundCtx := ctx
|
||||||
// check our prop isn't reference
|
// check our prop isn't reference
|
||||||
isRef := false
|
isRef := false
|
||||||
refString := ""
|
refString := ""
|
||||||
if h, _, l := utils.IsNodeRefValue(prop); h {
|
if h, _, l := utils.IsNodeRefValue(prop); h {
|
||||||
ref, _, _ := low.LocateRefNode(prop, idx)
|
ref, _, _, fctx := low.LocateRefNodeWithContext(ctx, prop, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
isRef = true
|
isRef = true
|
||||||
prop = ref
|
prop = ref
|
||||||
refString = l
|
refString = l
|
||||||
|
foundCtx = fctx
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("schema properties build failed: cannot find reference %s, line %d, col %d",
|
return nil, fmt.Errorf("schema properties build failed: cannot find reference %s, line %d, col %d",
|
||||||
prop.Content[1].Value, prop.Content[1].Line, prop.Content[1].Column)
|
prop.Content[1].Value, prop.Content[1].Line, prop.Content[1].Column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalProps++
|
totalProps++
|
||||||
go buildProperty(currentProp, prop, bChan, isRef, refString)
|
go buildProperty(foundCtx, currentProp, prop, bChan, isRef, refString)
|
||||||
}
|
}
|
||||||
completedProps := 0
|
completedProps := 0
|
||||||
for completedProps < totalProps {
|
for completedProps < totalProps {
|
||||||
|
|||||||
@@ -109,8 +109,17 @@ func LocateRefNodeWithContext(ctx context.Context, root *yaml.Node, idx *index.S
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
if specPath != "" {
|
if specPath != "" {
|
||||||
|
var abs string
|
||||||
abs, _ := filepath.Abs(filepath.Join(filepath.Dir(specPath), explodedRefValue[0]))
|
// multi file ref, looking for the root.
|
||||||
|
if filepath.Base(specPath) == "root.yaml" && explodedRefValue[0] == "" {
|
||||||
|
abs = specPath
|
||||||
|
} else {
|
||||||
|
if explodedRefValue[0] == "" {
|
||||||
|
abs = specPath
|
||||||
|
} else {
|
||||||
|
abs, _ = filepath.Abs(filepath.Join(filepath.Dir(specPath), explodedRefValue[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
rv = fmt.Sprintf("%s#%s", abs, explodedRefValue[1])
|
rv = fmt.Sprintf("%s#%s", abs, explodedRefValue[1])
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -28,8 +28,18 @@ type ResolvingError struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *ResolvingError) Error() string {
|
func (r *ResolvingError) Error() string {
|
||||||
return fmt.Sprintf("%s: %s [%d:%d]", r.ErrorRef.Error(),
|
errs := utils.UnwrapErrors(r.ErrorRef)
|
||||||
r.Path, r.Node.Line, r.Node.Column)
|
var msgs []string
|
||||||
|
for _, e := range errs {
|
||||||
|
if idxErr, ok := e.(*IndexingError); ok {
|
||||||
|
msgs = append(msgs, fmt.Sprintf("%s: %s [%d:%d]", idxErr.Error(),
|
||||||
|
idxErr.Path, idxErr.Node.Line, idxErr.Node.Column))
|
||||||
|
} else {
|
||||||
|
msgs = append(msgs, fmt.Sprintf("%s: %s [%d:%d]", e.Error(),
|
||||||
|
r.Path, r.Node.Line, r.Node.Column))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(msgs, "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolver will use a *index.SpecIndex to stitch together a resolved root tree using all the discovered
|
// Resolver will use a *index.SpecIndex to stitch together a resolved root tree using all the discovered
|
||||||
|
|||||||
@@ -30,19 +30,13 @@ import (
|
|||||||
// how the index is set up.
|
// how the index is set up.
|
||||||
func NewSpecIndexWithConfig(rootNode *yaml.Node, config *SpecIndexConfig) *SpecIndex {
|
func NewSpecIndexWithConfig(rootNode *yaml.Node, config *SpecIndexConfig) *SpecIndex {
|
||||||
index := new(SpecIndex)
|
index := new(SpecIndex)
|
||||||
//if config != nil && config.seenRemoteSources == nil {
|
|
||||||
// config.seenRemoteSources = &syncmap.Map{}
|
|
||||||
//}
|
|
||||||
//config.remoteLock = &sync.Mutex{}
|
|
||||||
index.config = config
|
index.config = config
|
||||||
index.rolodex = config.Rolodex
|
index.rolodex = config.Rolodex
|
||||||
//index.parentIndex = config.ParentIndex
|
|
||||||
index.uri = config.uri
|
index.uri = config.uri
|
||||||
index.specAbsolutePath = config.SpecAbsolutePath
|
index.specAbsolutePath = config.SpecAbsolutePath
|
||||||
if rootNode == nil || len(rootNode.Content) <= 0 {
|
if rootNode == nil || len(rootNode.Content) <= 0 {
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.Logger != nil {
|
if config.Logger != nil {
|
||||||
index.logger = config.Logger
|
index.logger = config.Logger
|
||||||
} else {
|
} else {
|
||||||
@@ -50,7 +44,6 @@ func NewSpecIndexWithConfig(rootNode *yaml.Node, config *SpecIndexConfig) *SpecI
|
|||||||
Level: slog.LevelError,
|
Level: slog.LevelError,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
boostrapIndexCollections(rootNode, index)
|
boostrapIndexCollections(rootNode, index)
|
||||||
return createNewIndex(rootNode, index, config.AvoidBuildIndex)
|
return createNewIndex(rootNode, index, config.AvoidBuildIndex)
|
||||||
}
|
}
|
||||||
@@ -99,15 +92,10 @@ func createNewIndex(rootNode *yaml.Node, index *SpecIndex, avoidBuildOut bool) *
|
|||||||
index.BuildIndex()
|
index.BuildIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
// do a copy!
|
|
||||||
//index.config.seenRemoteSources.Range(func(k, v any) bool {
|
|
||||||
// index.seenRemoteSources[k.(string)] = v.(*yaml.Node)
|
|
||||||
// return true
|
|
||||||
//})
|
|
||||||
return index
|
return index
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildIndex will run all of the count operations required to build up maps of everything. It's what makes the index
|
// BuildIndex will run all the count operations required to build up maps of everything. It's what makes the index
|
||||||
// useful for looking up things, the count operations are all run in parallel and then the final calculations are run
|
// useful for looking up things, the count operations are all run in parallel and then the final calculations are run
|
||||||
// the index is ready.
|
// the index is ready.
|
||||||
func (index *SpecIndex) BuildIndex() {
|
func (index *SpecIndex) BuildIndex() {
|
||||||
@@ -446,11 +434,6 @@ func (index *SpecIndex) GetAllOperationsServers() map[string]map[string][]*Refer
|
|||||||
return index.opServersRefs
|
return index.opServersRefs
|
||||||
}
|
}
|
||||||
|
|
||||||
//// GetAllExternalIndexes will return all indexes for external documents
|
|
||||||
//func (index *SpecIndex) GetAllExternalIndexes() map[string]*SpecIndex {
|
|
||||||
// return index.externalSpecIndex
|
|
||||||
//}
|
|
||||||
|
|
||||||
// SetAllowCircularReferenceResolving will flip a bit that can be used by any consumers to determine if they want
|
// SetAllowCircularReferenceResolving will flip a bit that can be used by any consumers to determine if they want
|
||||||
// to allow or disallow circular references to be resolved or visited
|
// to allow or disallow circular references to be resolved or visited
|
||||||
func (index *SpecIndex) SetAllowCircularReferenceResolving(allow bool) {
|
func (index *SpecIndex) SetAllowCircularReferenceResolving(allow bool) {
|
||||||
@@ -984,12 +967,10 @@ func (index *SpecIndex) GetOperationCount() int {
|
|||||||
Path: fmt.Sprintf("$.paths.%s.%s", p.Value, m.Value),
|
Path: fmt.Sprintf("$.paths.%s.%s", p.Value, m.Value),
|
||||||
ParentNode: m,
|
ParentNode: m,
|
||||||
}
|
}
|
||||||
//index.pathRefsLock.Lock()
|
|
||||||
if locatedPathRefs[p.Value] == nil {
|
if locatedPathRefs[p.Value] == nil {
|
||||||
locatedPathRefs[p.Value] = make(map[string]*Reference)
|
locatedPathRefs[p.Value] = make(map[string]*Reference)
|
||||||
}
|
}
|
||||||
locatedPathRefs[p.Value][ref.Name] = ref
|
locatedPathRefs[p.Value][ref.Name] = ref
|
||||||
//index.pathRefsLock.Unlock()
|
|
||||||
// update
|
// update
|
||||||
opCount++
|
opCount++
|
||||||
}
|
}
|
||||||
@@ -997,11 +978,9 @@ func (index *SpecIndex) GetOperationCount() int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index.pathRefsLock.Lock()
|
|
||||||
for k, v := range locatedPathRefs {
|
for k, v := range locatedPathRefs {
|
||||||
index.pathRefs[k] = v
|
index.pathRefs[k] = v
|
||||||
}
|
}
|
||||||
index.pathRefsLock.Unlock()
|
|
||||||
index.operationCount = opCount
|
index.operationCount = opCount
|
||||||
return opCount
|
return opCount
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,9 @@ func UnwrapErrors(err error) []error {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return []error{}
|
return []error{}
|
||||||
}
|
}
|
||||||
return err.(interface{ Unwrap() []error }).Unwrap()
|
if uw, ok := err.(interface{ Unwrap() []error }); ok {
|
||||||
|
return uw.Unwrap()
|
||||||
|
} else {
|
||||||
|
return []error{err}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,3 +30,7 @@ func TestUnwrapErrors(t *testing.T) {
|
|||||||
func TestUnwrapErrors_Empty(t *testing.T) {
|
func TestUnwrapErrors_Empty(t *testing.T) {
|
||||||
assert.Len(t, UnwrapErrors(nil), 0)
|
assert.Len(t, UnwrapErrors(nil), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnwrapErrors_SingleError(t *testing.T) {
|
||||||
|
assert.Len(t, UnwrapErrors(errors.New("single error")), 1)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user