From 5ea4f2b76234a72705ceb4e76ab9c95094f5dd81 Mon Sep 17 00:00:00 2001 From: quobix Date: Tue, 13 Feb 2024 07:27:26 -0500 Subject: [PATCH] Fixed last known lookup bug All known gaps (well known in my own head) seem to have been closed now, the final TODO in this area has been cleaned up, highlighted by an issue reported by speakeasy. Signed-off-by: quobix --- datamodel/low/base/schema.go | 29 +++++++++------ index/extract_refs.go | 72 +++++++++++++++++++++--------------- index/search_index.go | 2 +- 3 files changed, 61 insertions(+), 42 deletions(-) diff --git a/datamodel/low/base/schema.go b/datamodel/low/base/schema.go index 536be2b9..340d2bb4 100644 --- a/datamodel/low/base/schema.go +++ b/datamodel/low/base/schema.go @@ -1015,23 +1015,25 @@ func buildPropertyMap(ctx context.Context, root *yaml.Node, idx *index.SpecIndex } foundCtx := ctx + foundIdx := idx // check our prop isn't reference refString := "" var refNode *yaml.Node if h, _, l := utils.IsNodeRefValue(prop); h { - ref, _, _, fctx := low.LocateRefNodeWithContext(ctx, prop, idx) + ref, fIdx, _, fctx := low.LocateRefNodeWithContext(ctx, prop, idx) if ref != nil { refNode = prop prop = ref refString = l foundCtx = fctx + foundIdx = fIdx } else { 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) } } - sp := &SchemaProxy{ctx: foundCtx, kn: currentProp, vn: prop, idx: idx} + sp := &SchemaProxy{ctx: foundCtx, kn: currentProp, vn: prop, idx: foundIdx} sp.SetReference(refString, refNode) propertyMap.Set(low.KeyReference[string]{ @@ -1200,14 +1202,16 @@ func ExtractSchema(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) ( refLocation := "" var refNode *yaml.Node + foundIndex := idx + foundCtx := ctx if rf, rl, _ := utils.IsNodeRefValue(root); rf { // locate reference in index. ref, fIdx, _, nCtx := low.LocateRefNodeWithContext(ctx, root, idx) if ref != nil { schNode = ref schLabel = rl - ctx = nCtx - idx = fIdx + foundCtx = nCtx + foundIndex = fIdx } else { v := root.Content[1].Value if root.Content[1].Value == "" { @@ -1227,18 +1231,19 @@ func ExtractSchema(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) ( } if idx.GetSpecAbsolutePath() != specPath && (!strings.HasPrefix(refLocation, "http") && !strings.HasPrefix(idx.GetSpecAbsolutePath(), "http")) { - ctx = context.WithValue(ctx, index.CurrentPathKey, idx.GetSpecAbsolutePath()) + if !strings.HasSuffix(idx.GetSpecAbsolutePath(), "root.yaml") { + ctx = context.WithValue(ctx, index.CurrentPathKey, idx.GetSpecAbsolutePath()) + } } - ref, _, _, nCtx := low.LocateRefNodeWithContext(ctx, schNode, idx) + ref, fIdx, _, nCtx := low.LocateRefNodeWithContext(ctx, schNode, idx) if ref != nil { refNode = schNode schNode = ref - //if foundIdx != nil { - // TODO: check on this - // idx = foundIdx - //} - ctx = nCtx + if fIdx != nil { + foundIndex = fIdx + } + foundCtx = nCtx } else { v := schNode.Content[1].Value if schNode.Content[1].Value == "" { @@ -1253,7 +1258,7 @@ func ExtractSchema(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) ( if schNode != nil { // check if schema has already been built. - schema := &SchemaProxy{kn: schLabel, vn: schNode, idx: idx, ctx: ctx} + schema := &SchemaProxy{kn: schLabel, vn: schNode, idx: foundIndex, ctx: foundCtx} schema.SetReference(refLocation, refNode) n := &low.NodeReference[*SchemaProxy]{ diff --git a/index/extract_refs.go b/index/extract_refs.go index 8cbffa91..3eb516ee 100644 --- a/index/extract_refs.go +++ b/index/extract_refs.go @@ -6,14 +6,13 @@ package index import ( "errors" "fmt" + "github.com/pb33f/libopenapi/utils" + "golang.org/x/exp/slices" + "gopkg.in/yaml.v3" "net/url" "os" "path/filepath" "strings" - - "github.com/pb33f/libopenapi/utils" - "golang.org/x/exp/slices" - "gopkg.in/yaml.v3" ) // ExtractRefs will return a deduplicated slice of references for every unique ref found in the document. @@ -606,38 +605,54 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc } locate := func(ref *Reference, refIndex int, sequence []*ReferenceMapped) { - located := index.FindComponent(ref.FullDefinition) - if located != nil { - - // have we already mapped this? - index.refLock.Lock() - if index.allMappedRefs[ref.FullDefinition] == nil { - found = append(found, located) - index.allMappedRefs[located.FullDefinition] = located - } + index.refLock.Lock() + if index.allMappedRefs[ref.FullDefinition] != nil { rm := &ReferenceMapped{ OriginalReference: ref, - Reference: located, - Definition: located.Definition, - FullDefinition: located.FullDefinition, + Reference: index.allMappedRefs[ref.FullDefinition], + Definition: index.allMappedRefs[ref.FullDefinition].Definition, + FullDefinition: index.allMappedRefs[ref.FullDefinition].FullDefinition, } sequence[refIndex] = rm + if !index.config.ExtractRefsSequentially { + c <- true + } index.refLock.Unlock() - } else { + index.refLock.Unlock() + located := index.FindComponent(ref.FullDefinition) + if located != nil { + + // have we already mapped this? + index.refLock.Lock() + if index.allMappedRefs[ref.FullDefinition] == nil { + found = append(found, located) + index.allMappedRefs[located.FullDefinition] = located + } + rm := &ReferenceMapped{ + OriginalReference: ref, + Reference: located, + Definition: located.Definition, + FullDefinition: located.FullDefinition, + } + sequence[refIndex] = rm + index.refLock.Unlock() - _, path := utils.ConvertComponentIdIntoFriendlyPathSearch(ref.Definition) - indexError := &IndexingError{ - Err: fmt.Errorf("component '%s' does not exist in the specification", ref.Definition), - Node: ref.Node, - Path: path, + } else { + + _, path := utils.ConvertComponentIdIntoFriendlyPathSearch(ref.Definition) + indexError := &IndexingError{ + Err: fmt.Errorf("component '%s' does not exist in the specification", ref.Definition), + Node: ref.Node, + Path: path, + } + index.errorLock.Lock() + index.refErrors = append(index.refErrors, indexError) + index.errorLock.Unlock() + } + if !index.config.ExtractRefsSequentially { + c <- true } - index.errorLock.Lock() - index.refErrors = append(index.refErrors, indexError) - index.errorLock.Unlock() - } - if !index.config.ExtractRefsSequentially { - c <- true } } @@ -653,7 +668,6 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc } else { locate(refsToCheck[r], r, mappedRefsInSequence) // run synchronously } - } if !index.config.ExtractRefsSequentially { diff --git a/index/search_index.go b/index/search_index.go index 524f97c7..607acee6 100644 --- a/index/search_index.go +++ b/index/search_index.go @@ -152,7 +152,7 @@ func (index *SpecIndex) SearchIndexForReferenceByReferenceWithContext(ctx contex Index: rFile.GetIndex(), Node: node.Content[0], ParentNode: node, - }, rFile.GetIndex(), ctx + }, rFile.GetIndex(), context.WithValue(ctx, CurrentPathKey, rFile.GetFullPath()) } else { return nil, index, ctx }