Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for configurable levels of circular reference checking … #173

Merged
merged 8 commits into from
Sep 21, 2023

Conversation

daveshanley
Copy link
Member

@daveshanley daveshanley commented Sep 19, 2023

Circular references mean different things to different consumers. They may or may not be valid use cases. So after much discussion, I've decided to allow engineers to override my opinions on circular references.

Polymorphic based references, or array based references may or may not be valid circles, an empty array can break the loop for example. This isn't clear in the spec as there can be no way of knowing. The default position of libopenapi is to not ignore polymorphic (anyOf, oneOf, allOf) loops, or array based loops.

Now this can be configured, Choose to ignore polymorphic loops, or array loops, or both.

To configure the resolver directly, there are two new methods available:

IgnorePolymorphicCircularReferences() and IgnoreArrayCircularReferences()

The same properties exist on the datamodel.DocumentConfiguration struct that allows them to be ignored when building a document. For example:

var d = `openapi: 3.1.0
components:
  schemas:
    ProductCategory:
      type: "object"
      properties:
        name:
          type: "string"
        children:
          type: "object"
          anyOf:
            - $ref: "#/components/schemas/ProductCategory"
          description: "Array of sub-categories in the same format."
      required:
        - "name"
        - "children"`

	config := datamodel.NewClosedDocumentConfiguration()
        
        // ignore polymorphic circular references.
	config.IgnorePolymorphicCircularReferences = true

	doc, err := NewDocumentWithConfiguration([]byte(d), config)
	if err != nil {
		panic(err)
	}

	m, errs := doc.BuildV3Model()

	assert.Len(t, errs, 0)
	assert.Len(t, m.Index.GetCircularReferences(), 0)

The second update in this release is that the datamodel.CircularReferenceResult contains more detail on
what type of circular reference was located. This is valuable to determine if you should programmatically ignore the loop.

type CircularReferenceResult struct {
	Journey             []*Reference
	Start               *Reference
	LoopIndex           int
	LoopPoint           *Reference
	IsArrayResult       bool   // if this result comes from an array loop.
	PolymorphicType     string // which type of polymorphic loop is this? (oneOf, anyOf, allOf)
	IsPolymorphicResult bool   // if this result comes from a polymorphic loop.
	IsInfiniteLoop      bool   // if all the definitions in the reference loop are marked as required, this is an infinite circular reference, thus is not allowed.
}

The IsArrayResult will be true if the loop has come through an array

The PolymorphicTypeResult will be oneOf, anyOf or allOf depending on which type was used and the
isPolymorphicResult value will also be true, as before.

The docs have been updated for some more detail if required:

https://pb33f.io/libopenapi/circular-references/#circular-reference-results

@codecov
Copy link

codecov bot commented Sep 19, 2023

Codecov Report

Patch coverage: 100.00% and no project coverage change.

Comparison is base (53a46f4) 99.80% compared to head (19fb910) 99.80%.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #173   +/-   ##
=======================================
  Coverage   99.80%   99.80%           
=======================================
  Files         148      148           
  Lines       10643    10673   +30     
=======================================
+ Hits        10622    10652   +30     
  Misses         21       21           
Flag Coverage Δ
unittests 99.80% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files Changed Coverage Δ
datamodel/document_config.go 100.00% <ø> (ø)
index/circular_reference_result.go 100.00% <ø> (ø)
index/index_model.go 100.00% <ø> (ø)
datamodel/low/v3/create_document.go 100.00% <100.00%> (ø)
resolver/resolver.go 99.54% <100.00%> (+0.05%) ⬆️
utils/utils.go 100.00% <100.00%> (ø)

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

adding new properties to top level configs should work nicely.

Signed-off-by: quobix <dave@quobix.com>
re-enabled missing converage

Signed-off-by: quobix <dave@quobix.com>
Signed-off-by: quobix <dave@quobix.com>
Now a document can be pre-configured to ignore polymorphic circular references, and array references.

Signed-off-by: quobix <dave@quobix.com>
Signed-off-by: quobix <dave@quobix.com>
Signed-off-by: quobix <dave@quobix.com>
Signed-off-by: quobix <dave@quobix.com>
@daveshanley daveshanley marked this pull request as ready for review September 20, 2023 13:02
@TristanSpeakEasy
Copy link
Contributor

LGTM @daveshanley :shipit:

@daveshanley
Copy link
Member Author

LGTM @daveshanley :shipit:

Rock and roll!

@daveshanley daveshanley merged commit 3c9415b into main Sep 21, 2023
3 checks passed
@daveshanley daveshanley deleted the v0.11.0 branch November 4, 2023 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants