From 2a10cd95d254001c397a7cd28568e468800e6644 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 24 Jan 2025 14:19:09 -0500 Subject: [PATCH 1/6] feat: splits described and summarized interfaces Signed-off-by: Vincent Biret --- .../Models/Interfaces/IOpenApiDescribedElement.cs | 7 +------ .../Models/Interfaces/IOpenApiExample.cs | 2 +- .../Models/Interfaces/IOpenApiSummarizedElement.cs | 13 +++++++++++++ 3 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSummarizedElement.cs diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs index 76a945548..ca035cc51 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs @@ -3,15 +3,10 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// -/// Describes an element that has a summary and description. +/// Describes an element that has a description. /// public interface IOpenApiDescribedElement : IOpenApiElement { - /// - /// Short description for the example. - /// - public string Summary { get; set; } - /// /// Long description for the example. /// CommonMark syntax MAY be used for rich text representation. diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs index 3711df4b8..bc7639c04 100644 --- a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiExample.cs @@ -7,7 +7,7 @@ namespace Microsoft.OpenApi.Models.Interfaces; /// Defines the base properties for the example object. /// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. /// -public interface IOpenApiExample : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +public interface IOpenApiExample : IOpenApiDescribedElement, IOpenApiSummarizedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible { /// /// Embedded literal example. The value field and externalValue field are mutually diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSummarizedElement.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSummarizedElement.cs new file mode 100644 index 000000000..3273b03f5 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiSummarizedElement.cs @@ -0,0 +1,13 @@ +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; +/// +/// Describes an element that has a summary. +/// +public interface IOpenApiSummarizedElement : IOpenApiElement +{ + /// + /// Short description for the example. + /// + public string Summary { get; set; } +} From 68b25cc5cc9ffd809a45ce532200ce3262f39ad2 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 24 Jan 2025 14:22:38 -0500 Subject: [PATCH 2/6] fix: aligns callback parameter name with interface Signed-off-by: Vincent Biret --- .../Models/References/OpenApiCallbackReference.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs index bc75e8e5c..536b30086 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs @@ -117,11 +117,11 @@ public void SerializeAsV31(IOpenApiWriter writer) } /// - public IOpenApiCallback CopyReferenceAsTargetElementWithOverrides(IOpenApiCallback openApiExample) + public IOpenApiCallback CopyReferenceAsTargetElementWithOverrides(IOpenApiCallback source) { // the copy here is never called since callbacks do not have any overridable fields. // if the spec evolves to include overridable fields for callbacks, the serialize methods will need to call this copy method. - return openApiExample is OpenApiCallback ? new OpenApiCallback(this) : openApiExample; + return source is OpenApiCallback ? new OpenApiCallback(this) : source; } /// From d7e1f919ee61e7cd4596f216890e16c7719e99c9 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 24 Jan 2025 14:22:56 -0500 Subject: [PATCH 3/6] fix: aligns parameter name with interface definition for example Signed-off-by: Vincent Biret --- .../Models/References/OpenApiExampleReference.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs index dc1a22ee9..8d4eeabb1 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiExampleReference.cs @@ -146,9 +146,9 @@ public void SerializeAsV31(IOpenApiWriter writer) } /// - public IOpenApiExample CopyReferenceAsTargetElementWithOverrides(IOpenApiExample openApiExample) + public IOpenApiExample CopyReferenceAsTargetElementWithOverrides(IOpenApiExample source) { - return openApiExample is OpenApiExample ? new OpenApiExample(this) : openApiExample; + return source is OpenApiExample ? new OpenApiExample(this) : source; } /// From 77e0ad10ca213c449523e9ff1802da6a6bd800e2 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 24 Jan 2025 14:51:08 -0500 Subject: [PATCH 4/6] fix: Open API header proxy design pattern implementation Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi.Hidi/StatsVisitor.cs | 2 +- .../StatsVisitor.cs | 2 +- .../OpenApiReferencableExtensions.cs | 23 ++-- .../Models/Interfaces/IOpenApiHeader.cs | 65 ++++++++++ .../Models/OpenApiComponents.cs | 6 +- .../Models/OpenApiDocument.cs | 2 +- .../Models/OpenApiEncoding.cs | 5 +- src/Microsoft.OpenApi/Models/OpenApiHeader.cs | 105 +++++----------- .../Models/OpenApiResponse.cs | 5 +- .../References/OpenApiHeaderReference.cs | 103 ++++++++------- .../References/OpenApiResponseReference.cs | 5 +- .../Reader/V2/OpenApiHeaderDeserializer.cs | 3 +- .../Reader/V3/OpenApiHeaderDeserializer.cs | 3 +- .../Reader/V31/OpenApiHeaderDeserializer.cs | 3 +- .../Services/CopyReferences.cs | 6 +- .../Services/OpenApiVisitorBase.cs | 4 +- .../Services/OpenApiWalker.cs | 4 +- .../Validations/OpenApiValidator.cs | 4 +- .../Rules/OpenApiNonDefaultRules.cs | 2 +- .../Services/OpenApiFilterServiceTests.cs | 3 +- .../V3Tests/OpenApiDocumentTests.cs | 3 +- .../V3Tests/OpenApiEncodingTests.cs | 2 +- .../References/OpenApiHeaderReferenceTests.cs | 2 +- .../PublicApi/PublicApi.approved.txt | 118 ++++++++++-------- .../OpenApiHeaderValidationTests.cs | 12 +- .../Visitors/InheritanceTests.cs | 8 +- .../Walkers/WalkerLocationTests.cs | 16 +-- .../Workspaces/OpenApiReferencableTests.cs | 4 +- .../Workspaces/OpenApiWorkspaceTests.cs | 2 +- 29 files changed, 294 insertions(+), 228 deletions(-) create mode 100644 src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs diff --git a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs index a0dc1ae0e..a6ea032f1 100644 --- a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs @@ -27,7 +27,7 @@ public override void Visit(OpenApiSchema schema) public int HeaderCount { get; set; } - public override void Visit(IDictionary headers) + public override void Visit(IDictionary headers) { HeaderCount++; } diff --git a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs index db9f1add9..3e3b1cf93 100644 --- a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs @@ -27,7 +27,7 @@ public override void Visit(OpenApiSchema schema) public int HeaderCount { get; set; } - public override void Visit(IDictionary headers) + public override void Visit(IDictionary headers) { HeaderCount++; } diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs b/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs index 3a160b135..da51f3b55 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiReferencableExtensions.cs @@ -92,15 +92,24 @@ private static IOpenApiReferenceable ResolveReferenceOnResponseElement( string mapKey, JsonPointer pointer) { - switch (propertyName) + if (!string.IsNullOrEmpty(mapKey)) { - case OpenApiConstants.Headers when mapKey != null: - return responseElement.Headers[mapKey]; - case OpenApiConstants.Links when mapKey != null: - return responseElement.Links[mapKey]; - default: - throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer)); + if (OpenApiConstants.Headers.Equals(propertyName, StringComparison.Ordinal) && + responseElement?.Headers != null && + responseElement.Headers.TryGetValue(mapKey, out var headerElement) && + headerElement is IOpenApiReferenceable referenceable) + { + return referenceable; + } + if (OpenApiConstants.Links.Equals(propertyName, StringComparison.Ordinal) && + responseElement?.Links != null && + responseElement.Links.TryGetValue(mapKey, out var linkElement) && + linkElement is IOpenApiReferenceable referenceable2) + { + return referenceable2; + } } + throw new OpenApiException(string.Format(SRResource.InvalidReferenceId, pointer)); } } } diff --git a/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs new file mode 100644 index 000000000..9931775c7 --- /dev/null +++ b/src/Microsoft.OpenApi/Models/Interfaces/IOpenApiHeader.cs @@ -0,0 +1,65 @@ + +using System.Collections.Generic; +using System.Text.Json.Nodes; +using Microsoft.OpenApi.Interfaces; + +namespace Microsoft.OpenApi.Models.Interfaces; + +/// +/// Defines the base properties for the headers object. +/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking. +/// +public interface IOpenApiHeader : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +{ + /// + /// Determines whether this header is mandatory. + /// + public bool Required { get; } + + /// + /// Specifies that a header is deprecated and SHOULD be transitioned out of usage. + /// + public bool Deprecated { get; } + + /// + /// Sets the ability to pass empty-valued headers. + /// + public bool AllowEmptyValue { get; } + + /// + /// Describes how the header value will be serialized depending on the type of the header value. + /// + public ParameterStyle? Style { get; } + + /// + /// When this is true, header values of type array or object generate separate parameters + /// for each value of the array or key-value pair of the map. + /// + public bool Explode { get; } + + /// + /// Determines whether the header value SHOULD allow reserved characters, as defined by RFC3986. + /// + public bool AllowReserved { get; } + + /// + /// The schema defining the type used for the request body. + /// + public OpenApiSchema Schema { get; } + + /// + /// Example of the media type. + /// + public JsonNode Example { get; } + + /// + /// Examples of the media type. + /// + public IDictionary Examples { get; } + + /// + /// A map containing the representations for the header. + /// + public IDictionary Content { get; } + +} diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs index 686ed1326..c578ddc9a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs @@ -45,9 +45,9 @@ public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public IDictionary? Headers { get; set; } = new Dictionary(); + public IDictionary? Headers { get; set; } = new Dictionary(); /// /// An object to hold reusable Objects. @@ -90,7 +90,7 @@ public OpenApiComponents(OpenApiComponents? components) Parameters = components?.Parameters != null ? new Dictionary(components.Parameters) : null; Examples = components?.Examples != null ? new Dictionary(components.Examples) : null; RequestBodies = components?.RequestBodies != null ? new Dictionary(components.RequestBodies) : null; - Headers = components?.Headers != null ? new Dictionary(components.Headers) : null; + Headers = components?.Headers != null ? new Dictionary(components.Headers) : null; SecuritySchemes = components?.SecuritySchemes != null ? new Dictionary(components.SecuritySchemes) : null; Links = components?.Links != null ? new Dictionary(components.Links) : null; Callbacks = components?.Callbacks != null ? new Dictionary(components.Callbacks) : null; diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 0e9f510ea..6985aea1a 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -620,7 +620,7 @@ public bool AddComponent(string id, T componentToRegister) Components.Examples.Add(id, openApiExample); break; case OpenApiHeader openApiHeader: - Components.Headers ??= new Dictionary(); + Components.Headers ??= new Dictionary(); Components.Headers.Add(id, openApiHeader); break; case OpenApiSecurityScheme openApiSecurityScheme: diff --git a/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs b/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs index 9ab0e7468..bb8bfab17 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiEncoding.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -24,7 +25,7 @@ public class OpenApiEncoding : IOpenApiSerializable, IOpenApiExtensible /// /// A map allowing additional information to be provided as headers. /// - public IDictionary Headers { get; set; } = new Dictionary(); + public IDictionary Headers { get; set; } = new Dictionary(); /// /// Describes how a specific property value will be serialized depending on its type. @@ -64,7 +65,7 @@ public OpenApiEncoding() { } public OpenApiEncoding(OpenApiEncoding encoding) { ContentType = encoding?.ContentType ?? ContentType; - Headers = encoding?.Headers != null ? new Dictionary(encoding.Headers) : null; + Headers = encoding?.Headers != null ? new Dictionary(encoding.Headers) : null; Style = encoding?.Style ?? Style; Explode = encoding?.Explode ?? Explode; AllowReserved = encoding?.AllowReserved ?? AllowReserved; diff --git a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs index c27d18f8d..1f382220b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiHeader.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiHeader.cs @@ -16,84 +16,43 @@ namespace Microsoft.OpenApi.Models /// Header Object. /// The Header Object follows the structure of the Parameter Object. /// - public class OpenApiHeader : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiHeader : IOpenApiHeader, IOpenApiReferenceable, IOpenApiExtensible { - private OpenApiSchema _schema; + /// + public string Description { get; set; } - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public virtual bool UnresolvedReference { get; set; } - - /// - /// Reference pointer. - /// - public OpenApiReference Reference { get; set; } - - /// - /// A brief description of the header. - /// - public virtual string Description { get; set; } + /// + public bool Required { get; set; } - /// - /// Determines whether this header is mandatory. - /// - public virtual bool Required { get; set; } - - /// - /// Specifies that a header is deprecated and SHOULD be transitioned out of usage. - /// - public virtual bool Deprecated { get; set; } + /// + public bool Deprecated { get; set; } - /// - /// Sets the ability to pass empty-valued headers. - /// - public virtual bool AllowEmptyValue { get; set; } + /// + public bool AllowEmptyValue { get; set; } - /// - /// Describes how the header value will be serialized depending on the type of the header value. - /// - public virtual ParameterStyle? Style { get; set; } + /// + public ParameterStyle? Style { get; set; } - /// - /// When this is true, header values of type array or object generate separate parameters - /// for each value of the array or key-value pair of the map. - /// - public virtual bool Explode { get; set; } + /// + public bool Explode { get; set; } - /// - /// Determines whether the header value SHOULD allow reserved characters, as defined by RFC3986. - /// - public virtual bool AllowReserved { get; set; } + /// + public bool AllowReserved { get; set; } - /// - /// The schema defining the type used for the request body. - /// - public virtual OpenApiSchema Schema - { - get => _schema; - set => _schema = value; - } + /// + public OpenApiSchema Schema { get; set; } - /// - /// Example of the media type. - /// - public virtual JsonNode Example { get; set; } + /// + public JsonNode Example { get; set; } - /// - /// Examples of the media type. - /// - public virtual IDictionary Examples { get; set; } = new Dictionary(); + /// + public IDictionary Examples { get; set; } = new Dictionary(); - /// - /// A map containing the representations for the header. - /// - public virtual IDictionary Content { get; set; } = new Dictionary(); + /// + public IDictionary Content { get; set; } = new Dictionary(); - /// - /// This object MAY be extended with Specification Extensions. - /// - public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + public IDictionary Extensions { get; set; } = new Dictionary(); /// /// Parameter-less constructor @@ -103,10 +62,8 @@ public OpenApiHeader() { } /// /// Initializes a copy of an object /// - public OpenApiHeader(OpenApiHeader header) + public OpenApiHeader(IOpenApiHeader header) { - UnresolvedReference = header?.UnresolvedReference ?? UnresolvedReference; - Reference = header?.Reference != null ? new(header?.Reference) : null; Description = header?.Description ?? Description; Required = header?.Required ?? Required; Deprecated = header?.Deprecated ?? Deprecated; @@ -114,7 +71,7 @@ public OpenApiHeader(OpenApiHeader header) Style = header?.Style ?? Style; Explode = header?.Explode ?? Explode; AllowReserved = header?.AllowReserved ?? AllowReserved; - _schema = header?.Schema != null ? new(header.Schema) : null; + Schema = header?.Schema != null ? new(header.Schema) : null; Example = header?.Example != null ? JsonNodeCloneHelper.Clone(header.Example) : null; Examples = header?.Examples != null ? new Dictionary(header.Examples) : null; Content = header?.Content != null ? new Dictionary(header.Content) : null; @@ -124,7 +81,7 @@ public OpenApiHeader(OpenApiHeader header) /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV31(writer)); } @@ -132,12 +89,12 @@ public virtual void SerializeAsV31(IOpenApiWriter writer) /// /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, + internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { Utils.CheckArgumentNull(writer); @@ -186,7 +143,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio /// /// Serialize to OpenAPI V2 document without using reference. /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); diff --git a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs index 0aed7bb0d..755af74cd 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiResponse.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiResponse.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -22,7 +23,7 @@ public class OpenApiResponse : IOpenApiReferenceable, IOpenApiExtensible /// /// Maps a header name to its definition. /// - public virtual IDictionary Headers { get; set; } = new Dictionary(); + public virtual IDictionary Headers { get; set; } = new Dictionary(); /// /// A map containing descriptions of potential response payloads. @@ -63,7 +64,7 @@ public OpenApiResponse() { } public OpenApiResponse(OpenApiResponse response) { Description = response?.Description ?? Description; - Headers = response?.Headers != null ? new Dictionary(response.Headers) : null; + Headers = response?.Headers != null ? new Dictionary(response.Headers) : null; Content = response?.Content != null ? new Dictionary(response.Content) : null; Links = response?.Links != null ? new Dictionary(response.Links) : null; Extensions = response?.Extensions != null ? new Dictionary(response.Extensions) : null; diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs index d9f451c0a..3650190f3 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs @@ -13,12 +13,14 @@ namespace Microsoft.OpenApi.Models.References /// /// Header Object Reference. /// - public class OpenApiHeaderReference : OpenApiHeader, IOpenApiReferenceHolder + public class OpenApiHeaderReference : IOpenApiHeader, IOpenApiReferenceHolder { - internal OpenApiHeader _target; - private readonly OpenApiReference _reference; - private string _description; + /// + public OpenApiReference Reference { get; set; } + /// + public bool UnresolvedReference { get; set; } + internal OpenApiHeader _target; /// /// Gets the target header. /// @@ -29,10 +31,8 @@ public OpenApiHeader Target { get { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiHeader resolved = new OpenApiHeader(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - return resolved; + _target ??= Reference.HostDocument.ResolveReferenceTo(Reference); + return _target; } } @@ -50,22 +50,33 @@ public OpenApiHeaderReference(string referenceId, OpenApiDocument hostDocument, { Utils.CheckArgumentNullOrEmpty(referenceId); - _reference = new OpenApiReference() + Reference = new OpenApiReference() { Id = referenceId, HostDocument = hostDocument, Type = ReferenceType.Header, ExternalResource = externalResource }; + } - Reference = _reference; + /// + /// Copy constructor + /// + /// The object to copy + public OpenApiHeaderReference(OpenApiHeaderReference header) + { + Utils.CheckArgumentNull(header); + Reference = header.Reference != null ? new(header.Reference) : null; + UnresolvedReference = header.UnresolvedReference; + //no need to copy description as if they are not overridden, they will be fetched from the target + //if they are, the reference copy will handle it } internal OpenApiHeaderReference(OpenApiHeader target, string referenceId) { _target = target; - _reference = new OpenApiReference() + Reference = new OpenApiReference() { Id = referenceId, Type = ReferenceType.Header, @@ -73,90 +84,98 @@ internal OpenApiHeaderReference(OpenApiHeader target, string referenceId) } /// - public override string Description + public string Description { - get => string.IsNullOrEmpty(_description) ? Target.Description : _description; - set => _description = value; + get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description; + set + { + if (Reference is not null) + { + Reference.Description = value; + } + } } /// - public override bool Required { get => Target.Required; set => Target.Required = value; } + public bool Required { get => Target.Required; } /// - public override bool Deprecated { get => Target.Deprecated; set => Target.Deprecated = value; } + public bool Deprecated { get => Target.Deprecated; } /// - public override bool AllowEmptyValue { get => Target.AllowEmptyValue; set => Target.AllowEmptyValue = value; } + public bool AllowEmptyValue { get => Target.AllowEmptyValue; } /// - public override OpenApiSchema Schema { get => Target.Schema; set => Target.Schema = value; } + public OpenApiSchema Schema { get => Target.Schema; } /// - public override ParameterStyle? Style { get => Target.Style; set => Target.Style = value; } + public ParameterStyle? Style { get => Target.Style; } /// - public override bool Explode { get => Target.Explode; set => Target.Explode = value; } + public bool Explode { get => Target.Explode; } /// - public override bool AllowReserved { get => Target.AllowReserved; set => Target.AllowReserved = value; } + public bool AllowReserved { get => Target.AllowReserved; } /// - public override JsonNode Example { get => Target.Example; set => Target.Example = value; } + public JsonNode Example { get => Target.Example; } /// - public override IDictionary Examples { get => Target.Examples; set => Target.Examples = value; } + public IDictionary Examples { get => Target.Examples; } /// - public override IDictionary Content { get => Target.Content; set => Target.Content = value; } + public IDictionary Content { get => Target.Content; } /// - public override IDictionary Extensions { get => base.Extensions; set => base.Extensions = value; } - + public IDictionary Extensions { get => Target.Extensions; } + /// - public override void SerializeAsV31(IOpenApiWriter writer) + public void SerializeAsV31(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) + if (!writer.GetSettings().ShouldInlineReference(Reference)) { - _reference.SerializeAsV31(writer); - return; + Reference.SerializeAsV31(writer); } else { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); + SerializeInternal(writer, (writer, element) => CopyReferenceAsTargetElementWithOverrides(element).SerializeAsV31(writer)); } } /// - public override void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV3(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) + if (!writer.GetSettings().ShouldInlineReference(Reference)) { - _reference.SerializeAsV3(writer); - return; + Reference.SerializeAsV3(writer); } else { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); + SerializeInternal(writer, (writer, element) => CopyReferenceAsTargetElementWithOverrides(element).SerializeAsV3(writer)); } } /// - public override void SerializeAsV2(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) { - if (!writer.GetSettings().ShouldInlineReference(_reference)) + if (!writer.GetSettings().ShouldInlineReference(Reference)) { - _reference.SerializeAsV2(writer); - return; + Reference.SerializeAsV2(writer); } else { - SerializeInternal(writer, (writer, element) => element.SerializeAsV2(writer)); + SerializeInternal(writer, (writer, element) => CopyReferenceAsTargetElementWithOverrides(element).SerializeAsV2(writer)); } } + /// + public IOpenApiHeader CopyReferenceAsTargetElementWithOverrides(IOpenApiHeader source) + { + return source is OpenApiHeader ? new OpenApiHeader(this) : source; + } /// private void SerializeInternal(IOpenApiWriter writer, - Action action) + Action action) { Utils.CheckArgumentNull(writer); action(writer, Target); diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs index 0983bd3b6..0f74e3ad5 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiResponseReference.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models.References @@ -81,9 +82,9 @@ public override string Description /// public override IDictionary Content { get => _content is not null ? _content : Target?.Content; set => _content = value; } - private IDictionary _headers; + private IDictionary _headers; /// - public override IDictionary Headers { get => _headers is not null ? _headers : Target?.Headers; set => _headers = value; } + public override IDictionary Headers { get => _headers is not null ? _headers : Target?.Headers; set => _headers = value; } private IDictionary _links; /// diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs index 4a994bdc5..bc2333e46 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiHeaderDeserializer.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Exceptions; using Microsoft.OpenApi.Reader.ParseNodes; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.V2 { @@ -102,7 +103,7 @@ private static OpenApiSchema GetOrCreateSchema(OpenApiHeader p) return p.Schema ??= new(); } - public static OpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("header"); var header = new OpenApiHeader(); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs index 7830c394e..8553c1b70 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiHeaderDeserializer.cs @@ -3,6 +3,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -70,7 +71,7 @@ internal static partial class OpenApiV3Deserializer {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("header"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs index 32c2b73fc..43a4f3292 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiHeaderDeserializer.cs @@ -1,5 +1,6 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; @@ -84,7 +85,7 @@ internal static partial class OpenApiV31Deserializer {s => s.StartsWith("x-"), (o, p, n, _) => o.AddExtension(p, LoadExtension(p,n))} }; - public static OpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiHeader LoadHeader(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("header"); diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs index 944fabe87..2575a6f77 100644 --- a/src/Microsoft.OpenApi/Services/CopyReferences.cs +++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs @@ -145,9 +145,9 @@ private void AddHeaderToComponents(OpenApiHeader header, string referenceId = nu { EnsureComponentsExist(); EnsureHeadersExist(); - if (!Components.Headers.ContainsKey(referenceId ?? header.Reference.Id)) + if (!Components.Headers.ContainsKey(referenceId)) { - Components.Headers.Add(referenceId ?? header.Reference.Id, header); + Components.Headers.Add(referenceId, header); } } private void AddExampleToComponents(OpenApiExample example, string referenceId = null) @@ -225,7 +225,7 @@ private void EnsureExamplesExist() private void EnsureHeadersExist() { - _target.Components.Headers ??= new Dictionary(); + _target.Components.Headers ??= new Dictionary(); } private void EnsureCallbacksExist() diff --git a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs index 1bd202ff7..30fe66774 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs @@ -162,7 +162,7 @@ public virtual void Visit(OpenApiRequestBody requestBody) /// /// Visits headers. /// - public virtual void Visit(IDictionary headers) + public virtual void Visit(IDictionary headers) { } @@ -274,7 +274,7 @@ public virtual void Visit(OpenApiTagReference tag) /// /// Visits /// - public virtual void Visit(OpenApiHeader header) + public virtual void Visit(IOpenApiHeader header) { } diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs index 47a4f4c2e..3451a9690 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs @@ -740,7 +740,7 @@ internal void Walk(OpenApiRequestBody requestBody, bool isComponent = false) /// /// Visits dictionary of /// - internal void Walk(IDictionary headers) + internal void Walk(IDictionary headers) { if (headers == null) { @@ -1105,7 +1105,7 @@ internal void Walk(OpenApiLink link, bool isComponent = false) /// /// Visits and child objects /// - internal void Walk(OpenApiHeader header, bool isComponent = false) + internal void Walk(IOpenApiHeader header, bool isComponent = false) { if (header == null) { diff --git a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs index 8ec8d4ca0..e93113536 100644 --- a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs +++ b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs @@ -81,7 +81,7 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(OpenApiComponents components) => Validate(components); /// - public override void Visit(OpenApiHeader header) => Validate(header); + public override void Visit(IOpenApiHeader header) => Validate(header); /// public override void Visit(OpenApiResponse response) => Validate(response); @@ -157,7 +157,7 @@ public void AddWarning(OpenApiValidatorWarning warning) /// public override void Visit(IDictionary operations) => Validate(operations, operations.GetType()); /// - public override void Visit(IDictionary headers) => Validate(headers, headers.GetType()); + public override void Visit(IDictionary headers) => Validate(headers, headers.GetType()); /// public override void Visit(IDictionary callbacks) => Validate(callbacks, callbacks.GetType()); /// diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs index 759aafe47..1d38af4ce 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiNonDefaultRules.cs @@ -17,7 +17,7 @@ public static class OpenApiNonDefaultRules /// /// Validate the data matches with the given data type. /// - public static ValidationRule HeaderMismatchedDataType => + public static ValidationRule HeaderMismatchedDataType => new(nameof(HeaderMismatchedDataType), (context, header) => { diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs index e8c49bbc8..8f0d04004 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs @@ -243,7 +243,8 @@ public async Task CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly( // Assert Assert.Same(doc.Servers, subsetOpenApiDocument.Servers); - Assert.False(responseHeader?.UnresolvedReference); + var headerReference = Assert.IsType(responseHeader); + Assert.False(headerReference.UnresolvedReference); var exampleReference = Assert.IsType(mediaTypeExample); Assert.False(exampleReference?.UnresolvedReference); Assert.NotNull(targetHeaders); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 41f2c6a1e..3622d572b 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -1132,8 +1132,7 @@ public async Task HeaderParameterShouldAllowExample() Format = "uuid" }, }, options => options.IgnoringCyclicReferences() - .Excluding(e => e.Example.Parent) - .Excluding(x => x.Reference)); + .Excluding(e => e.Example.Parent)); var examplesHeader = result.Document.Components?.Headers?["examples-header"]; Assert.NotNull(examplesHeader); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs index 874cf6b04..c103db5d8 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs @@ -49,7 +49,7 @@ public async Task ParseAdvancedEncodingShouldSucceed() Headers = { ["X-Rate-Limit-Limit"] = - new() + new OpenApiHeader() { Description = "The number of allowed requests in the current period", Schema = new() diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs index d7fef6396..daff6e479 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs @@ -166,7 +166,7 @@ public void OpenApiHeaderTargetShouldResolveReference() { Components = new OpenApiComponents { - Headers = new System.Collections.Generic.Dictionary + Headers = { { "header1", new OpenApiHeader { diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 69d509df5..3ae26aa75 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -344,13 +344,29 @@ namespace Microsoft.OpenApi.Models.Interfaces public interface IOpenApiDescribedElement : Microsoft.OpenApi.Interfaces.IOpenApiElement { string Description { get; set; } - string Summary { get; set; } } - public interface IOpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + public interface IOpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { string ExternalValue { get; } System.Text.Json.Nodes.JsonNode Value { get; } } + public interface IOpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement + { + bool AllowEmptyValue { get; } + bool AllowReserved { get; } + System.Collections.Generic.IDictionary Content { get; } + bool Deprecated { get; } + System.Text.Json.Nodes.JsonNode Example { get; } + System.Collections.Generic.IDictionary Examples { get; } + bool Explode { get; } + bool Required { get; } + Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + Microsoft.OpenApi.Models.ParameterStyle? Style { get; } + } + public interface IOpenApiSummarizedElement : Microsoft.OpenApi.Interfaces.IOpenApiElement + { + string Summary { get; set; } + } } namespace Microsoft.OpenApi.Models { @@ -383,7 +399,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary? Callbacks { get; set; } public System.Collections.Generic.IDictionary? Examples { get; set; } public System.Collections.Generic.IDictionary? Extensions { get; set; } - public System.Collections.Generic.IDictionary? Headers { get; set; } + public System.Collections.Generic.IDictionary? Headers { get; set; } public System.Collections.Generic.IDictionary? Links { get; set; } public System.Collections.Generic.IDictionary? Parameters { get; set; } public System.Collections.Generic.IDictionary? PathItems { get; set; } @@ -611,7 +627,7 @@ namespace Microsoft.OpenApi.Models public string ContentType { get; set; } public bool? Explode { get; set; } public System.Collections.Generic.IDictionary Extensions { get; set; } - public System.Collections.Generic.IDictionary Headers { get; set; } + public System.Collections.Generic.IDictionary Headers { get; set; } public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -626,7 +642,7 @@ namespace Microsoft.OpenApi.Models public string Pointer { get; set; } public override string ToString() { } } - public class OpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample + public class OpenApiExample : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { public OpenApiExample() { } public OpenApiExample(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample example) { } @@ -660,27 +676,25 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiHeader : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader { public OpenApiHeader() { } - public OpenApiHeader(Microsoft.OpenApi.Models.OpenApiHeader header) { } - public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } - public virtual bool AllowEmptyValue { get; set; } - public virtual bool AllowReserved { get; set; } - public virtual System.Collections.Generic.IDictionary Content { get; set; } - public virtual bool Deprecated { get; set; } - public virtual string Description { get; set; } - public virtual System.Text.Json.Nodes.JsonNode Example { get; set; } - public virtual System.Collections.Generic.IDictionary Examples { get; set; } - public virtual bool Explode { get; set; } - public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual bool Required { get; set; } - public virtual Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } - public virtual Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } - public virtual bool UnresolvedReference { get; set; } - public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public OpenApiHeader(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader header) { } + public bool AllowEmptyValue { get; set; } + public bool AllowReserved { get; set; } + public System.Collections.Generic.IDictionary Content { get; set; } + public bool Deprecated { get; set; } + public string Description { get; set; } + public System.Text.Json.Nodes.JsonNode Example { get; set; } + public System.Collections.Generic.IDictionary Examples { get; set; } + public bool Explode { get; set; } + public System.Collections.Generic.IDictionary Extensions { get; set; } + public bool Required { get; set; } + public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } + public Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiInfo : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -877,7 +891,7 @@ namespace Microsoft.OpenApi.Models public virtual System.Collections.Generic.IDictionary Content { get; set; } public virtual string Description { get; set; } public virtual System.Collections.Generic.IDictionary Extensions { get; set; } - public virtual System.Collections.Generic.IDictionary Headers { get; set; } + public virtual System.Collections.Generic.IDictionary Headers { get; set; } public virtual System.Collections.Generic.IDictionary Links { get; set; } public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -1131,12 +1145,12 @@ namespace Microsoft.OpenApi.Models.References public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } public Microsoft.OpenApi.Models.OpenApiCallback Target { get; } public bool UnresolvedReference { get; set; } - public Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback openApiExample) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback source) { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiExampleReference : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample + public class OpenApiExampleReference : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiExample, Microsoft.OpenApi.Models.Interfaces.IOpenApiSummarizedElement { public OpenApiExampleReference(Microsoft.OpenApi.Models.References.OpenApiExampleReference example) { } public OpenApiExampleReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } @@ -1148,30 +1162,34 @@ namespace Microsoft.OpenApi.Models.References public Microsoft.OpenApi.Models.OpenApiExample Target { get; } public bool UnresolvedReference { get; set; } public System.Text.Json.Nodes.JsonNode Value { get; } - public Microsoft.OpenApi.Models.Interfaces.IOpenApiExample CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample openApiExample) { } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiExample CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample source) { } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiHeaderReference : Microsoft.OpenApi.Models.OpenApiHeader, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiHeaderReference : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReadOnlyExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable, Microsoft.OpenApi.Models.Interfaces.IOpenApiDescribedElement, Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader { + public OpenApiHeaderReference(Microsoft.OpenApi.Models.References.OpenApiHeaderReference header) { } public OpenApiHeaderReference(string referenceId, Microsoft.OpenApi.Models.OpenApiDocument hostDocument, string externalResource = null) { } + public bool AllowEmptyValue { get; } + public bool AllowReserved { get; } + public System.Collections.Generic.IDictionary Content { get; } + public bool Deprecated { get; } + public string Description { get; set; } + public System.Text.Json.Nodes.JsonNode Example { get; } + public System.Collections.Generic.IDictionary Examples { get; } + public bool Explode { get; } + public System.Collections.Generic.IDictionary Extensions { get; } + public Microsoft.OpenApi.Models.OpenApiReference Reference { get; set; } + public bool Required { get; } + public Microsoft.OpenApi.Models.OpenApiSchema Schema { get; } + public Microsoft.OpenApi.Models.ParameterStyle? Style { get; } public Microsoft.OpenApi.Models.OpenApiHeader Target { get; } - public override bool AllowEmptyValue { get; set; } - public override bool AllowReserved { get; set; } - public override System.Collections.Generic.IDictionary Content { get; set; } - public override bool Deprecated { get; set; } - public override string Description { get; set; } - public override System.Text.Json.Nodes.JsonNode Example { get; set; } - public override System.Collections.Generic.IDictionary Examples { get; set; } - public override bool Explode { get; set; } - public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override bool Required { get; set; } - public override Microsoft.OpenApi.Models.OpenApiSchema Schema { get; set; } - public override Microsoft.OpenApi.Models.ParameterStyle? Style { get; set; } - public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public bool UnresolvedReference { get; set; } + public Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader source) { } + public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } + public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiLinkReference : Microsoft.OpenApi.Models.OpenApiLink, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -1239,7 +1257,7 @@ namespace Microsoft.OpenApi.Models.References public override System.Collections.Generic.IDictionary Content { get; set; } public override string Description { get; set; } public override System.Collections.Generic.IDictionary Extensions { get; set; } - public override System.Collections.Generic.IDictionary Headers { get; set; } + public override System.Collections.Generic.IDictionary Headers { get; set; } public override System.Collections.Generic.IDictionary Links { get; set; } public override void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public override void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -1515,12 +1533,12 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder referenceHolder) { } public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback callback) { } public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample example) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader header) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiEncoding encoding) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiExternalDocs externalDocs) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiHeader header) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiInfo info) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiLicense license) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiLink link) { } @@ -1543,8 +1561,8 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(System.Collections.Generic.IDictionary operations) { } public virtual void Visit(System.Collections.Generic.IDictionary callbacks) { } public virtual void Visit(System.Collections.Generic.IDictionary examples) { } + public virtual void Visit(System.Collections.Generic.IDictionary headers) { } public virtual void Visit(System.Collections.Generic.IDictionary encodings) { } - public virtual void Visit(System.Collections.Generic.IDictionary headers) { } public virtual void Visit(System.Collections.Generic.IDictionary links) { } public virtual void Visit(System.Collections.Generic.IDictionary content) { } public virtual void Visit(System.Collections.Generic.IDictionary webhooks) { } @@ -1614,12 +1632,12 @@ namespace Microsoft.OpenApi.Validations public override void Visit(Microsoft.OpenApi.Interfaces.IOpenApiExtension openApiExtension) { } public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiCallback callback) { } public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiExample example) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiHeader header) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiEncoding encoding) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiExternalDocs externalDocs) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiHeader header) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiInfo info) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiLicense license) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiLink link) { } @@ -1641,8 +1659,8 @@ namespace Microsoft.OpenApi.Validations public override void Visit(System.Collections.Generic.IDictionary operations) { } public override void Visit(System.Collections.Generic.IDictionary callbacks) { } public override void Visit(System.Collections.Generic.IDictionary examples) { } + public override void Visit(System.Collections.Generic.IDictionary headers) { } public override void Visit(System.Collections.Generic.IDictionary encodings) { } - public override void Visit(System.Collections.Generic.IDictionary headers) { } public override void Visit(System.Collections.Generic.IDictionary links) { } public override void Visit(System.Collections.Generic.IDictionary content) { } public override void Visit(System.Collections.Generic.IDictionary serverVariables) { } @@ -1735,7 +1753,7 @@ namespace Microsoft.OpenApi.Validations.Rules } public static class OpenApiNonDefaultRules { - public static Microsoft.OpenApi.Validations.ValidationRule HeaderMismatchedDataType { get; } + public static Microsoft.OpenApi.Validations.ValidationRule HeaderMismatchedDataType { get; } public static Microsoft.OpenApi.Validations.ValidationRule MediaTypeMismatchedDataType { get; } public static Microsoft.OpenApi.Validations.ValidationRule ParameterMismatchedDataType { get; } public static Microsoft.OpenApi.Validations.ValidationRule SchemaMismatchedDataType { get; } diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs index 485f8587c..6c96c3d97 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiHeaderValidationTests.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text.Json.Nodes; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Validations.Rules; using Xunit; @@ -17,7 +18,6 @@ public class OpenApiHeaderValidationTests public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() { // Arrange - IEnumerable errors; var header = new OpenApiHeader { Required = true, @@ -30,18 +30,14 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() // Act var defaultRuleSet = ValidationRuleSet.GetDefaultRuleSet(); - defaultRuleSet.Add(typeof(OpenApiHeader), OpenApiNonDefaultRules.HeaderMismatchedDataType); + defaultRuleSet.Add(typeof(IOpenApiHeader), OpenApiNonDefaultRules.HeaderMismatchedDataType); var validator = new OpenApiValidator(defaultRuleSet); var walker = new OpenApiWalker(validator); - walker.Walk(header); - - errors = validator.Errors; - var warnings = validator.Warnings; - var result = !warnings.Any(); + walker.Walk((IOpenApiHeader)header); // Assert - Assert.False(result); + Assert.NotEmpty(validator.Warnings); } [Fact] diff --git a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs index 4acb0aadf..c78e41f19 100644 --- a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs @@ -33,7 +33,7 @@ public void ExpectedVirtualsInvolved() visitor.Visit(default(IList)); visitor.Visit(default(OpenApiParameter)); visitor.Visit(default(OpenApiRequestBody)); - visitor.Visit(default(IDictionary)); + visitor.Visit(default(IDictionary)); visitor.Visit(default(IDictionary)); visitor.Visit(default(OpenApiResponse)); visitor.Visit(default(OpenApiResponses)); @@ -48,7 +48,7 @@ public void ExpectedVirtualsInvolved() visitor.Visit(default(OpenApiLink)); visitor.Visit(default(IOpenApiCallback)); visitor.Visit(default(OpenApiTag)); - visitor.Visit(default(OpenApiHeader)); + visitor.Visit(default(IOpenApiHeader)); visitor.Visit(default(OpenApiOAuthFlow)); visitor.Visit(default(OpenApiSecurityRequirement)); visitor.Visit(default(OpenApiSecurityScheme)); @@ -172,7 +172,7 @@ public override void Visit(OpenApiRequestBody requestBody) base.Visit(requestBody); } - public override void Visit(IDictionary headers) + public override void Visit(IDictionary headers) { EncodeCall(); base.Visit(headers); @@ -262,7 +262,7 @@ public override void Visit(OpenApiTag tag) base.Visit(tag); } - public override void Visit(OpenApiHeader header) + public override void Visit(IOpenApiHeader header) { EncodeCall(); base.Visit(header); diff --git a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs index c307229cf..cbb61987d 100644 --- a/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Walkers/WalkerLocationTests.cs @@ -172,16 +172,12 @@ public void LocateReferences() }, UnresolvedReference = false }; + var testHeader = new OpenApiHeader() { Schema = derivedSchema, - Reference = new() - { - Id = "test-header", - Type = ReferenceType.Header - }, - UnresolvedReference = false }; + var testHeaderReference = new OpenApiHeaderReference(testHeader, "test-header"); var doc = new OpenApiDocument { @@ -204,9 +200,9 @@ public void LocateReferences() Schema = derivedSchema } }, - Headers = new Dictionary + Headers = { - ["test-header"] = testHeader + ["test-header"] = testHeaderReference } } } @@ -221,7 +217,7 @@ public void LocateReferences() ["derived"] = derivedSchema, ["base"] = baseSchema, }, - Headers = new Dictionary + Headers = { ["test-header"] = testHeader }, @@ -238,7 +234,7 @@ public void LocateReferences() Assert.Equivalent(new List { "referenceAt: #/paths/~1/get/responses/200/content/application~1json/schema", - "referenceAt: #/paths/~1/get/responses/200/headers/test-header/schema", + "referenceAt: #/paths/~1/get/responses/200/headers/test-header", "referenceAt: #/components/schemas/derived/anyOf/0", "referenceAt: #/components/securitySchemes/test-secScheme", "referenceAt: #/components/headers/test-header/schema" diff --git a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiReferencableTests.cs b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiReferencableTests.cs index cb554d4f6..167d5e359 100644 --- a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiReferencableTests.cs +++ b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiReferencableTests.cs @@ -36,11 +36,11 @@ public class OpenApiReferencableTests private static readonly OpenApiRequestBody _requestBodyFragment = new(); private static readonly OpenApiResponse _responseFragment = new() { - Headers = new Dictionary + Headers = { { "header1", new OpenApiHeader() } }, - Links = new Dictionary + Links = { { "link1", new OpenApiLink() } } diff --git a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs index f8bde4f85..05f8dda64 100644 --- a/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Workspaces/OpenApiWorkspaceTests.cs @@ -112,7 +112,7 @@ public void OpenApiWorkspacesCanResolveReferencesToDocumentFragmentsWithJsonPoin var workspace = new OpenApiWorkspace(); var responseFragment = new OpenApiResponse { - Headers = new Dictionary + Headers = { { "header1", new OpenApiHeader() } } From aa80b1968d9ec6ad26f8b45578040026883d5890 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 24 Jan 2025 15:11:08 -0500 Subject: [PATCH 5/6] fix: do not allow null argument for example copy constructor Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi/Models/OpenApiExample.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiExample.cs b/src/Microsoft.OpenApi/Models/OpenApiExample.cs index c35480fc2..be543c525 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExample.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExample.cs @@ -41,11 +41,12 @@ public OpenApiExample() { } /// The object public OpenApiExample(IOpenApiExample example) { - Summary = example?.Summary ?? Summary; - Description = example?.Description ?? Description; - Value = example?.Value != null ? JsonNodeCloneHelper.Clone(example.Value) : null; - ExternalValue = example?.ExternalValue ?? ExternalValue; - Extensions = example?.Extensions != null ? new Dictionary(example.Extensions) : null; + Utils.CheckArgumentNull(example); + Summary = example.Summary ?? Summary; + Description = example.Description ?? Description; + Value = example.Value != null ? JsonNodeCloneHelper.Clone(example.Value) : null; + ExternalValue = example.ExternalValue ?? ExternalValue; + Extensions = example.Extensions != null ? new Dictionary(example.Extensions) : null; } /// From 0cb4ccb925ab54e15351cbf2b0f4ae58c6b866c8 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 24 Jan 2025 15:18:28 -0500 Subject: [PATCH 6/6] fix: adds missing null propagation operators for callback and header references Signed-off-by: Vincent Biret --- .../References/OpenApiCallbackReference.cs | 4 ++-- .../References/OpenApiHeaderReference.cs | 22 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs index 536b30086..b9d9758f1 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiCallbackReference.cs @@ -85,10 +85,10 @@ internal OpenApiCallbackReference(OpenApiCallback target, string referenceId) } /// - public Dictionary PathItems { get => Target.PathItems; } + public Dictionary PathItems { get => Target?.PathItems; } /// - public IDictionary Extensions { get => Target.Extensions; } + public IDictionary Extensions { get => Target?.Extensions; } /// public void SerializeAsV3(IOpenApiWriter writer) diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs index 3650190f3..71e8cace0 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiHeaderReference.cs @@ -97,37 +97,37 @@ public string Description } /// - public bool Required { get => Target.Required; } + public bool Required { get => Target?.Required ?? default; } /// - public bool Deprecated { get => Target.Deprecated; } + public bool Deprecated { get => Target?.Deprecated ?? default; } /// - public bool AllowEmptyValue { get => Target.AllowEmptyValue; } + public bool AllowEmptyValue { get => Target?.AllowEmptyValue ?? default; } /// - public OpenApiSchema Schema { get => Target.Schema; } + public OpenApiSchema Schema { get => Target?.Schema; } /// - public ParameterStyle? Style { get => Target.Style; } + public ParameterStyle? Style { get => Target?.Style; } /// - public bool Explode { get => Target.Explode; } + public bool Explode { get => Target?.Explode ?? default; } /// - public bool AllowReserved { get => Target.AllowReserved; } + public bool AllowReserved { get => Target?.AllowReserved ?? default; } /// - public JsonNode Example { get => Target.Example; } + public JsonNode Example { get => Target?.Example; } /// - public IDictionary Examples { get => Target.Examples; } + public IDictionary Examples { get => Target?.Examples; } /// - public IDictionary Content { get => Target.Content; } + public IDictionary Content { get => Target?.Content; } /// - public IDictionary Extensions { get => Target.Extensions; } + public IDictionary Extensions { get => Target?.Extensions; } /// public void SerializeAsV31(IOpenApiWriter writer)