diff --git a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs index c2bbc97d0..109799381 100644 --- a/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs +++ b/src/Microsoft.OpenApi.Hidi/Formatters/PowerShellFormatter.cs @@ -7,6 +7,7 @@ using Humanizer.Inflections; using Microsoft.OpenApi.Hidi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; namespace Microsoft.OpenApi.Hidi.Formatters @@ -69,13 +70,13 @@ public override void Visit(OpenApiOperation operation) var operationId = operation.OperationId; var operationTypeExtension = operation.Extensions?.GetExtension("x-ms-docs-operation-type"); - if (operationTypeExtension.IsEquals("function")) - operation.Parameters = ResolveFunctionParameters(operation.Parameters ?? new List()); + if (operationTypeExtension.IsEquals("function") && operation.Parameters is { Count :> 0}) + ResolveFunctionParameters(operation.Parameters); // Order matters. Resolve operationId. operationId = RemoveHashSuffix(operationId); if (operationTypeExtension.IsEquals("action") || operationTypeExtension.IsEquals("function")) - operationId = RemoveKeyTypeSegment(operationId, operation.Parameters ?? new List()); + operationId = RemoveKeyTypeSegment(operationId, operation.Parameters ?? new List()); operationId = SingularizeAndDeduplicateOperationId(operationId.SplitByChar('.')); operationId = ResolveODataCastOperationId(operationId); operationId = ResolveByRefOperationId(operationId); @@ -143,7 +144,7 @@ private static string RemoveHashSuffix(string operationId) return s_hashSuffixRegex.Match(operationId).Value; } - private static string RemoveKeyTypeSegment(string operationId, IList parameters) + private static string RemoveKeyTypeSegment(string operationId, IList parameters) { var segments = operationId.SplitByChar('.'); foreach (var parameter in parameters) @@ -157,9 +158,9 @@ private static string RemoveKeyTypeSegment(string operationId, IList ResolveFunctionParameters(IList parameters) + private static void ResolveFunctionParameters(IList parameters) { - foreach (var parameter in parameters.Where(static p => p.Content?.Any() ?? false)) + foreach (var parameter in parameters.OfType().Where(static p => p.Content?.Any() ?? false)) { // Replace content with a schema object of type array // for structured or collection-valued function parameters @@ -173,7 +174,6 @@ private static IList ResolveFunctionParameters(IList +/// 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 IOpenApiParameter : IOpenApiDescribedElement, IOpenApiSerializable, IOpenApiReadOnlyExtensible +{ + /// + /// REQUIRED. The name of the parameter. Parameter names are case sensitive. + /// If in is "path", the name field MUST correspond to the associated path segment from the path field in the Paths Object. + /// If in is "header" and the name field is "Accept", "Content-Type" or "Authorization", the parameter definition SHALL be ignored. + /// For all other cases, the name corresponds to the parameter name used by the in property. + /// + public string Name { get; } + + /// + /// REQUIRED. The location of the parameter. + /// Possible values are "query", "header", "path" or "cookie". + /// + public ParameterLocation? In { get; } + + /// + /// Determines whether this parameter is mandatory. + /// If the parameter location is "path", this property is REQUIRED and its value MUST be true. + /// Otherwise, the property MAY be included and its default value is false. + /// + public bool Required { get; } + + /// + /// Specifies that a parameter is deprecated and SHOULD be transitioned out of usage. + /// + public bool Deprecated { get; } + + /// + /// Sets the ability to pass empty-valued parameters. + /// This is valid only for query parameters and allows sending a parameter with an empty value. + /// Default value is false. + /// If style is used, and if behavior is n/a (cannot be serialized), + /// the value of allowEmptyValue SHALL be ignored. + /// + public bool AllowEmptyValue { get; } + + /// + /// Describes how the parameter value will be serialized depending on the type of the parameter value. + /// Default values (based on value of in): for query - form; for path - simple; for header - simple; + /// for cookie - form. + /// + public ParameterStyle? Style { get; } + + /// + /// When this is true, parameter values of type array or object generate separate parameters + /// for each value of the array or key-value pair of the map. + /// For other types of parameters this property has no effect. + /// When style is form, the default value is true. + /// For all other styles, the default value is false. + /// + public bool Explode { get; } + + /// + /// Determines whether the parameter value SHOULD allow reserved characters, + /// as defined by RFC3986 :/?#[]@!$&'()*+,;= to be included without percent-encoding. + /// This property only applies to parameters with an in value of query. + /// The default value is false. + /// + public bool AllowReserved { get; } + + /// + /// The schema defining the type used for the parameter. + /// + public OpenApiSchema Schema { get; } + + /// + /// Examples of the media type. Each example SHOULD contain a value + /// in the correct format as specified in the parameter encoding. + /// The examples object is mutually exclusive of the example object. + /// Furthermore, if referencing a schema which contains an example, + /// the examples value SHALL override the example provided by the schema. + /// + public IDictionary Examples { get; } + + /// + /// Example of the media type. The example SHOULD match the specified schema and encoding properties + /// if present. The example object is mutually exclusive of the examples object. + /// Furthermore, if referencing a schema which contains an example, + /// the example value SHALL override the example provided by the schema. + /// To represent examples of media types that cannot naturally be represented in JSON or YAML, + /// a string value can contain the example with escaping where necessary. + /// + public JsonNode Example { get; } + + /// + /// A map containing the representations for the parameter. + /// The key is the media type and the value describes it. + /// The map MUST only contain one entry. + /// For more complex scenarios, the content property can define the media type and schema of the parameter. + /// A parameter MUST contain either a schema property, or a content property, but not both. + /// When example or examples are provided in conjunction with the schema object, + /// the example MUST follow the prescribed serialization strategy for the parameter. + /// + public IDictionary Content { get; } +} diff --git a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs index b171cef5b..f45ecbedd 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiComponents.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiComponents.cs @@ -28,10 +28,10 @@ public class OpenApiComponents : IOpenApiSerializable, IOpenApiExtensible public IDictionary? Responses { get; set; } = new Dictionary(); /// - /// An object to hold reusable Objects. + /// An object to hold reusable Objects. /// - public IDictionary? Parameters { get; set; } = - new Dictionary(); + public IDictionary? Parameters { get; set; } = + new Dictionary(); /// /// An object to hold reusable Objects. @@ -87,7 +87,7 @@ public OpenApiComponents(OpenApiComponents? components) { Schemas = components?.Schemas != null ? new Dictionary(components.Schemas) : null; Responses = components?.Responses != null ? new Dictionary(components.Responses) : null; - Parameters = components?.Parameters != null ? new Dictionary(components.Parameters) : null; + 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; diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index ae92bb60f..1dbc0e23c 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -277,8 +277,8 @@ public void SerializeAsV2(IOpenApiWriter writer) // parameters var parameters = Components?.Parameters != null - ? new Dictionary(Components.Parameters) - : new Dictionary(); + ? new Dictionary(Components.Parameters) + : []; if (Components?.RequestBodies != null) { @@ -592,7 +592,7 @@ public bool AddComponent(string id, T componentToRegister) Components.Schemas.Add(id, openApiSchema); break; case OpenApiParameter openApiParameter: - Components.Parameters ??= new Dictionary(); + Components.Parameters ??= new Dictionary(); Components.Parameters.Add(id, openApiParameter); break; case OpenApiResponse openApiResponse: diff --git a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs index beeb1c7e2..0a2f4259b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiOperation.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiOperation.cs @@ -58,7 +58,7 @@ public class OpenApiOperation : IOpenApiSerializable, IOpenApiExtensible, IOpenA /// The list MUST NOT include duplicated parameters. A unique parameter is defined by a combination of a name and location. /// The list can use the Reference Object to link to parameters that are defined at the OpenAPI Object's components/parameters. /// - public IList? Parameters { get; set; } = new List(); + public IList? Parameters { get; set; } = []; /// /// The request body applicable for this operation. @@ -127,7 +127,7 @@ public OpenApiOperation(OpenApiOperation? operation) Description = operation?.Description ?? Description; ExternalDocs = operation?.ExternalDocs != null ? new(operation?.ExternalDocs) : null; OperationId = operation?.OperationId ?? OperationId; - Parameters = operation?.Parameters != null ? new List(operation.Parameters) : null; + Parameters = operation?.Parameters != null ? new List(operation.Parameters) : null; RequestBody = operation?.RequestBody != null ? new(operation?.RequestBody) : null; Responses = operation?.Responses != null ? new(operation?.Responses) : null; Callbacks = operation?.Callbacks != null ? new Dictionary(operation.Callbacks) : null; @@ -235,7 +235,7 @@ public void SerializeAsV2(IOpenApiWriter writer) // operationId writer.WriteProperty(OpenApiConstants.OperationId, OperationId); - List parameters; + List parameters; if (Parameters == null) { parameters = []; diff --git a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs index 66d03746e..87a761c8b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiParameter.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiParameter.cs @@ -16,138 +16,60 @@ namespace Microsoft.OpenApi.Models /// /// Parameter Object. /// - public class OpenApiParameter : IOpenApiReferenceable, IOpenApiExtensible + public class OpenApiParameter : IOpenApiReferenceable, IOpenApiExtensible, IOpenApiParameter { private bool? _explode; private ParameterStyle? _style; - private OpenApiSchema _schema; - /// - /// Indicates if object is populated with data or is just a reference to the data - /// - public virtual bool UnresolvedReference { get; set; } + /// + public string Name { get; set; } - /// - /// Reference object. - /// - public OpenApiReference Reference { get; set; } + /// + public ParameterLocation? In { get; set; } - /// - /// REQUIRED. The name of the parameter. Parameter names are case sensitive. - /// If in is "path", the name field MUST correspond to the associated path segment from the path field in the Paths Object. - /// If in is "header" and the name field is "Accept", "Content-Type" or "Authorization", the parameter definition SHALL be ignored. - /// For all other cases, the name corresponds to the parameter name used by the in property. - /// - public virtual string Name { get; set; } + /// + public string Description { get; set; } - /// - /// REQUIRED. The location of the parameter. - /// Possible values are "query", "header", "path" or "cookie". - /// - public virtual ParameterLocation? In { get; set; } + /// + public bool Required { get; set; } - /// - /// A brief description of the parameter. This could contain examples of use. - /// CommonMark syntax MAY be used for rich text representation. - /// - public virtual string Description { get; set; } + /// + public bool Deprecated { get; set; } - /// - /// Determines whether this parameter is mandatory. - /// If the parameter location is "path", this property is REQUIRED and its value MUST be true. - /// Otherwise, the property MAY be included and its default value is false. - /// - public virtual bool Required { get; set; } - - /// - /// Specifies that a parameter is deprecated and SHOULD be transitioned out of usage. - /// - public virtual bool Deprecated { get; set; } = false; - - /// - /// Sets the ability to pass empty-valued parameters. - /// This is valid only for query parameters and allows sending a parameter with an empty value. - /// Default value is false. - /// If style is used, and if behavior is n/a (cannot be serialized), - /// the value of allowEmptyValue SHALL be ignored. - /// - public virtual bool AllowEmptyValue { get; set; } = false; + /// + public bool AllowEmptyValue { get; set; } - /// - /// Describes how the parameter value will be serialized depending on the type of the parameter value. - /// Default values (based on value of in): for query - form; for path - simple; for header - simple; - /// for cookie - form. - /// - public virtual ParameterStyle? Style + /// + public ParameterStyle? Style { get => _style ?? GetDefaultStyleValue(); set => _style = value; } - /// - /// When this is true, parameter values of type array or object generate separate parameters - /// for each value of the array or key-value pair of the map. - /// For other types of parameters this property has no effect. - /// When style is form, the default value is true. - /// For all other styles, the default value is false. - /// - public virtual bool Explode + /// + public bool Explode { get => _explode ?? Style == ParameterStyle.Form; set => _explode = value; } - /// - /// Determines whether the parameter value SHOULD allow reserved characters, - /// as defined by RFC3986 :/?#[]@!$&'()*+,;= to be included without percent-encoding. - /// This property only applies to parameters with an in value of query. - /// The default value is false. - /// - public virtual bool AllowReserved { get; set; } + /// + public bool AllowReserved { get; set; } - /// - /// The schema defining the type used for the parameter. - /// - public virtual OpenApiSchema Schema - { - get => _schema; - set => _schema = value; - } + /// + public OpenApiSchema Schema { get; set; } - /// - /// Examples of the media type. Each example SHOULD contain a value - /// in the correct format as specified in the parameter encoding. - /// The examples object is mutually exclusive of the example object. - /// Furthermore, if referencing a schema which contains an example, - /// the examples value SHALL override the example provided by the schema. - /// - public virtual IDictionary Examples { get; set; } = new Dictionary(); + /// + public IDictionary Examples { get; set; } = new Dictionary(); - /// - /// Example of the media type. The example SHOULD match the specified schema and encoding properties - /// if present. The example object is mutually exclusive of the examples object. - /// Furthermore, if referencing a schema which contains an example, - /// the example value SHALL override the example provided by the schema. - /// To represent examples of media types that cannot naturally be represented in JSON or YAML, - /// a string value can contain the example with escaping where necessary. - /// - public virtual JsonNode Example { get; set; } + /// + public JsonNode Example { get; set; } - /// - /// A map containing the representations for the parameter. - /// The key is the media type and the value describes it. - /// The map MUST only contain one entry. - /// For more complex scenarios, the content property can define the media type and schema of the parameter. - /// A parameter MUST contain either a schema property, or a content property, but not both. - /// When example or examples are provided in conjunction with the schema object, - /// the example MUST follow the prescribed serialization strategy for the parameter. - /// - 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(); /// /// A parameterless constructor @@ -157,43 +79,38 @@ public OpenApiParameter() { } /// /// Initializes a clone instance of object /// - public OpenApiParameter(OpenApiParameter parameter) + public OpenApiParameter(IOpenApiParameter parameter) { - UnresolvedReference = parameter?.UnresolvedReference ?? UnresolvedReference; - Reference = parameter?.Reference != null ? new(parameter?.Reference) : null; - Name = parameter?.Name ?? Name; - In = parameter?.In ?? In; - Description = parameter?.Description ?? Description; - Required = parameter?.Required ?? Required; - Style = parameter?.Style ?? Style; - Explode = parameter?.Explode ?? Explode; - AllowReserved = parameter?.AllowReserved ?? AllowReserved; - _schema = parameter?.Schema != null ? new(parameter.Schema) : null; - Examples = parameter?.Examples != null ? new Dictionary(parameter.Examples) : null; - Example = parameter?.Example != null ? JsonNodeCloneHelper.Clone(parameter.Example) : null; - Content = parameter?.Content != null ? new Dictionary(parameter.Content) : null; - Extensions = parameter?.Extensions != null ? new Dictionary(parameter.Extensions) : null; - AllowEmptyValue = parameter?.AllowEmptyValue ?? AllowEmptyValue; - Deprecated = parameter?.Deprecated ?? Deprecated; + Utils.CheckArgumentNull(parameter); + Name = parameter.Name ?? Name; + In = parameter.In ?? In; + Description = parameter.Description ?? Description; + Required = parameter.Required; + Style = parameter.Style ?? Style; + Explode = parameter.Explode; + AllowReserved = parameter.AllowReserved; + Schema = parameter.Schema != null ? new(parameter.Schema) : null; + Examples = parameter.Examples != null ? new Dictionary(parameter.Examples) : null; + Example = parameter.Example != null ? JsonNodeCloneHelper.Clone(parameter.Example) : null; + Content = parameter.Content != null ? new Dictionary(parameter.Content) : null; + Extensions = parameter.Extensions != null ? new Dictionary(parameter.Extensions) : null; + AllowEmptyValue = parameter.AllowEmptyValue; + Deprecated = parameter.Deprecated; } - /// - /// Serialize to Open Api v3.1 - /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + /// + public void SerializeAsV31(IOpenApiWriter writer) { SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(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); @@ -219,13 +136,13 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio writer.WriteProperty(OpenApiConstants.AllowEmptyValue, AllowEmptyValue, false); // style - if (_style.HasValue) + if (Style.HasValue && Style != GetDefaultStyleValue()) { - writer.WriteProperty(OpenApiConstants.Style, _style.Value.GetDisplayName()); + writer.WriteProperty(OpenApiConstants.Style, Style.Value.GetDisplayName()); } // explode - writer.WriteProperty(OpenApiConstants.Explode, _explode, _style is ParameterStyle.Form); + writer.WriteProperty(OpenApiConstants.Explode, _explode, Style is ParameterStyle.Form); // allowReserved writer.WriteProperty(OpenApiConstants.AllowReserved, AllowReserved, false); @@ -248,10 +165,8 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio writer.WriteEndObject(); } - /// - /// Serialize to OpenAPI V2 document without using reference. - /// - public virtual void SerializeAsV2(IOpenApiWriter writer) + /// + public void SerializeAsV2(IOpenApiWriter writer) { Utils.CheckArgumentNull(writer); @@ -372,7 +287,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) internal virtual ParameterStyle? GetDefaultStyleValue() { - Style = In switch + return In switch { ParameterLocation.Query => ParameterStyle.Form, ParameterLocation.Header => ParameterStyle.Simple, @@ -380,8 +295,6 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) ParameterLocation.Cookie => ParameterStyle.Form, _ => (ParameterStyle?)ParameterStyle.Simple, }; - - return Style; } } diff --git a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs b/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs index ea7d628ea..b9fac8c56 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiPathItem.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiPathItem.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 @@ -39,7 +40,7 @@ public class OpenApiPathItem : IOpenApiExtensible, IOpenApiReferenceable /// A list of parameters that are applicable for all the operations described under this path. /// These parameters can be overridden at the operation level, but cannot be removed there. /// - public virtual IList Parameters { get; set; } = new List(); + public virtual IList Parameters { get; set; } = new List(); /// /// This object MAY be extended with Specification Extensions. @@ -80,7 +81,7 @@ public OpenApiPathItem(OpenApiPathItem pathItem) Description = pathItem?.Description ?? Description; Operations = pathItem?.Operations != null ? new Dictionary(pathItem.Operations) : null; Servers = pathItem?.Servers != null ? new List(pathItem.Servers) : null; - Parameters = pathItem?.Parameters != null ? new List(pathItem.Parameters) : null; + Parameters = pathItem?.Parameters != null ? new List(pathItem.Parameters) : null; Extensions = pathItem?.Extensions != null ? new Dictionary(pathItem.Extensions) : null; UnresolvedReference = pathItem?.UnresolvedReference ?? UnresolvedReference; Reference = pathItem?.Reference != null ? new(pathItem?.Reference) : null; diff --git a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs index 0fb16471f..2524c41d6 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiRequestBody.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Writers; namespace Microsoft.OpenApi.Models @@ -112,7 +113,7 @@ public void SerializeAsV2(IOpenApiWriter writer) // RequestBody object does not exist in V2. } - internal virtual OpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) + internal virtual IOpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) { var bodyParameter = new OpenApiBodyParameter { diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs index 93d1163db..da9d1dabd 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiParameterReference.cs @@ -13,13 +13,14 @@ namespace Microsoft.OpenApi.Models.References /// /// Parameter Object Reference. /// - public class OpenApiParameterReference : OpenApiParameter, IOpenApiReferenceHolder + public class OpenApiParameterReference : IOpenApiParameter, IOpenApiReferenceHolder { + /// + public OpenApiReference Reference { get; set; } + + /// + public bool UnresolvedReference { get; set; } internal OpenApiParameter _target; - private readonly OpenApiReference _reference; - private string _description; - private bool? _explode; - private ParameterStyle? _style; /// /// Gets the target parameter. @@ -31,10 +32,8 @@ public OpenApiParameter Target { get { - _target ??= Reference.HostDocument.ResolveReferenceTo(_reference); - OpenApiParameter resolved = new OpenApiParameter(_target); - if (!string.IsNullOrEmpty(_description)) resolved.Description = _description; - return resolved; + _target ??= Reference.HostDocument.ResolveReferenceTo(Reference); + return _target; } } @@ -52,22 +51,33 @@ public OpenApiParameterReference(string referenceId, OpenApiDocument hostDocumen { Utils.CheckArgumentNullOrEmpty(referenceId); - _reference = new OpenApiReference() + Reference = new OpenApiReference() { Id = referenceId, HostDocument = hostDocument, Type = ReferenceType.Parameter, ExternalResource = externalResource }; + } - Reference = _reference; + /// + /// Copy constructor + /// + /// The parameter reference to copy + public OpenApiParameterReference(OpenApiParameterReference parameter) + { + Utils.CheckArgumentNull(parameter); + Reference = parameter.Reference != null ? new(parameter.Reference) : null; + UnresolvedReference = parameter.UnresolvedReference; + //no need to copy summary and description as if they are not overridden, they will be fetched from the target + //if they are, the reference copy will handle it } internal OpenApiParameterReference(OpenApiParameter target, string referenceId) { _target = target; - _reference = new OpenApiReference() + Reference = new OpenApiReference() { Id = referenceId, Type = ReferenceType.Parameter, @@ -75,104 +85,105 @@ internal OpenApiParameterReference(OpenApiParameter target, string referenceId) } /// - public override string Name { get => Target.Name; set => Target.Name = value; } + public string Name { get => Target.Name; } /// - 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 ?? default; } /// - public override bool Deprecated { get => Target.Deprecated; set => Target.Deprecated = value; } + public bool Deprecated { get => Target?.Deprecated ?? default; } /// - public override bool AllowEmptyValue { get => Target.AllowEmptyValue; set => Target.AllowEmptyValue = value; } + public bool AllowEmptyValue { get => Target?.AllowEmptyValue ?? default; } /// - public override bool AllowReserved { get => Target.AllowReserved; set => Target.AllowReserved = value; } + public bool AllowReserved { get => Target?.AllowReserved ?? default; } /// - public override OpenApiSchema Schema { get => Target.Schema; set => Target.Schema = value; } + public OpenApiSchema Schema { get => Target?.Schema; } /// - public override IDictionary Examples { get => Target.Examples; set => Target.Examples = value; } + public IDictionary Examples { get => Target?.Examples; } /// - public override JsonNode Example { get => Target.Example; set => Target.Example = value; } + public JsonNode Example { get => Target?.Example; } /// - public override ParameterLocation? In { get => Target.In; set => Target.In = value; } + public ParameterLocation? In { get => Target?.In; } /// - public override ParameterStyle? Style - { - get => _style ?? GetDefaultStyleValue(); - set => _style = value; - } + public ParameterStyle? Style { get => Target?.Style; } /// - public override bool Explode - { - get => _explode ?? Style == ParameterStyle.Form; - set => _explode = value; - } + public bool Explode { get => Target?.Explode ?? default; } /// - public override IDictionary Content { get => Target.Content; set => Target.Content = value; } + public IDictionary Content { get => Target.Content; } /// - public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } + public IDictionary Extensions { get => Target.Extensions; } /// - 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 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 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 IOpenApiParameter CopyReferenceAsTargetElementWithOverrides(IOpenApiParameter source) + { + return source is OpenApiParameter ? new OpenApiParameter(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/OpenApiPathItemReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs index bc7e8904e..97383efcd 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiPathItemReference.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 @@ -93,7 +94,7 @@ public override string Description public override IList Servers { get => Target.Servers; set => Target.Servers = value; } /// - public override IList Parameters { get => Target.Parameters; set => Target.Parameters = value; } + public override IList Parameters { get => Target.Parameters; set => Target.Parameters = value; } /// public override IDictionary Extensions { get => Target.Extensions; set => Target.Extensions = value; } diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs index 7025ec373..5aa466415 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiRequestBodyReference.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 @@ -121,7 +122,7 @@ private void SerializeInternal(IOpenApiWriter writer, } /// - internal override OpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) + internal override IOpenApiParameter ConvertToBodyParameter(IOpenApiWriter writer) { if (writer.GetSettings().ShouldInlineReference(_reference)) { diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs index 37e146793..e24c10227 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiDocumentDeserializer.cs @@ -7,6 +7,7 @@ using System.Linq; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Services; @@ -302,7 +303,7 @@ private static bool IsHostValid(string host) internal class RequestBodyReferenceFixer : OpenApiVisitorBase { - private IDictionary _requestBodies; + private readonly IDictionary _requestBodies; public RequestBodyReferenceFixer(IDictionary requestBodies) { _requestBodies = requestBodies; @@ -310,7 +311,7 @@ public RequestBodyReferenceFixer(IDictionary request public override void Visit(OpenApiOperation operation) { - var body = operation.Parameters.FirstOrDefault( + var body = operation.Parameters.OfType().FirstOrDefault( p => p.UnresolvedReference && _requestBodies.ContainsKey(p.Reference.Id)); diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs index 35d20ca4a..3fd5743c9 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiOperationDeserializer.cs @@ -8,6 +8,7 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Models.References; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Reader.V2 { @@ -180,7 +181,7 @@ private static OpenApiRequestBody CreateFormBody(ParsingContext context, List>(TempStorageKeys.OperationConsumes) ?? context.GetFromTempStorage>(TempStorageKeys.GlobalConsumes) ?? diff --git a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs index 247d68679..2153d37d2 100644 --- a/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V2/OpenApiParameterDeserializer.cs @@ -184,12 +184,12 @@ private static void ProcessIn(OpenApiParameter o, ParseNode n, OpenApiDocument h } } - public static OpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) { return LoadParameter(node, false, hostDocument); } - public static OpenApiParameter LoadParameter(ParseNode node, bool loadRequestBody, OpenApiDocument hostDocument) + public static IOpenApiParameter LoadParameter(ParseNode node, bool loadRequestBody, OpenApiDocument hostDocument) { // Reset the local variables every time this method is called. node.Context.SetTempStorage(TempStorageKeys.ParameterIsBodyOrFormData, false); diff --git a/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs index 915314d35..c8660d899 100644 --- a/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V3/OpenApiParameterDeserializer.cs @@ -115,7 +115,7 @@ internal static partial class OpenApiV3Deserializer } }; - public static OpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("parameter"); diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs index fecaf58c2..cf5f5b294 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiParameterDeserializer.cs @@ -133,7 +133,7 @@ internal static partial class OpenApiV31Deserializer } }; - public static OpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) + public static IOpenApiParameter LoadParameter(ParseNode node, OpenApiDocument hostDocument) { var mapNode = node.CheckMapNode("parameter"); diff --git a/src/Microsoft.OpenApi/Services/CopyReferences.cs b/src/Microsoft.OpenApi/Services/CopyReferences.cs index 3125d75cc..d520e6f19 100644 --- a/src/Microsoft.OpenApi/Services/CopyReferences.cs +++ b/src/Microsoft.OpenApi/Services/CopyReferences.cs @@ -99,9 +99,9 @@ private void AddParameterToComponents(OpenApiParameter parameter, string referen { EnsureComponentsExist(); EnsureParametersExist(); - if (!Components.Parameters.ContainsKey(referenceId ?? parameter.Reference.Id)) + if (!Components.Parameters.ContainsKey(referenceId)) { - Components.Parameters.Add(referenceId ?? parameter.Reference.Id, parameter); + Components.Parameters.Add(referenceId, parameter); } } @@ -205,7 +205,7 @@ private void EnsureSchemasExist() private void EnsureParametersExist() { - _target.Components.Parameters ??= new Dictionary(); + _target.Components.Parameters ??= new Dictionary(); } private void EnsureResponsesExist() diff --git a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs index 62ecb4c5d..b35163ca0 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiVisitorBase.cs @@ -141,14 +141,14 @@ public virtual void Visit(OpenApiOperation operation) /// /// Visits list of /// - public virtual void Visit(IList parameters) + public virtual void Visit(IList parameters) { } /// /// Visits /// - public virtual void Visit(OpenApiParameter parameter) + public virtual void Visit(IOpenApiParameter parameter) { } diff --git a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs index c578a7653..6173ad3cb 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiWalker.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiWalker.cs @@ -623,7 +623,7 @@ internal void Walk(IList securityRequirements) /// /// Visits list of /// - internal void Walk(IList parameters) + internal void Walk(IList parameters) { if (parameters == null) { @@ -644,7 +644,7 @@ internal void Walk(IList parameters) /// /// Visits and child objects /// - internal void Walk(OpenApiParameter parameter, bool isComponent = false) + internal void Walk(IOpenApiParameter parameter, bool isComponent = false) { if (parameter == null) { @@ -1203,7 +1203,7 @@ internal void Walk(IOpenApiElement element) case OpenApiOAuthFlows e: Walk(e); break; case OpenApiOAuthFlow e: Walk(e); break; case OpenApiOperation e: Walk(e); break; - case OpenApiParameter e: Walk(e); break; + case IOpenApiParameter e: Walk(e); break; case OpenApiPaths e: Walk(e); break; case OpenApiRequestBody e: Walk(e); break; case OpenApiResponse e: Walk(e); break; diff --git a/src/Microsoft.OpenApi/Services/OperationSearch.cs b/src/Microsoft.OpenApi/Services/OperationSearch.cs index 8b1dbd1ee..e0512bf72 100644 --- a/src/Microsoft.OpenApi/Services/OperationSearch.cs +++ b/src/Microsoft.OpenApi/Services/OperationSearch.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Services { @@ -57,14 +58,14 @@ public override void Visit(OpenApiPathItem pathItem) /// Visits list of . /// /// The target list of . - public override void Visit(IList parameters) + public override void Visit(IList parameters) { /* The Parameter.Explode property should be true * if Parameter.Style == Form; but OData query params * as used in Microsoft Graph implement explode: false * ex: $select=id,displayName,givenName */ - foreach (var parameter in parameters.Where(x => x.Style == ParameterStyle.Form)) + foreach (var parameter in parameters.OfType().Where(static x => x.Style == ParameterStyle.Form)) { parameter.Explode = false; } diff --git a/src/Microsoft.OpenApi/Services/SearchResult.cs b/src/Microsoft.OpenApi/Services/SearchResult.cs index 47fff14df..6bbeed27a 100644 --- a/src/Microsoft.OpenApi/Services/SearchResult.cs +++ b/src/Microsoft.OpenApi/Services/SearchResult.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Services { @@ -24,6 +25,6 @@ public class SearchResult /// /// Parameters object /// - public IList Parameters { get; set; } + public IList Parameters { get; set; } } } diff --git a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs index 594d87eaa..7deb2ddcb 100644 --- a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs +++ b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs @@ -105,7 +105,7 @@ public void AddWarning(OpenApiValidatorWarning warning) public override void Visit(OpenApiTag tag) => Validate(tag); /// - public override void Visit(OpenApiParameter parameter) => Validate(parameter); + public override void Visit(IOpenApiParameter parameter) => Validate(parameter); /// public override void Visit(OpenApiSchema schema) => Validate(schema); diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiParameterRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiParameterRules.cs index 812bc7f12..26fa30005 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiParameterRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiParameterRules.cs @@ -3,6 +3,7 @@ using System; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; namespace Microsoft.OpenApi.Validations.Rules @@ -16,7 +17,7 @@ public static class OpenApiParameterRules /// /// Validate the field is required. /// - public static ValidationRule ParameterRequiredFields => + public static ValidationRule ParameterRequiredFields => new(nameof(ParameterRequiredFields), (context, item) => { @@ -42,7 +43,7 @@ public static class OpenApiParameterRules /// /// Validate the "required" field is true when "in" is path. /// - public static ValidationRule RequiredMustBeTrueWhenInIsPath => + public static ValidationRule RequiredMustBeTrueWhenInIsPath => new(nameof(RequiredMustBeTrueWhenInIsPath), (context, item) => { @@ -61,7 +62,7 @@ public static class OpenApiParameterRules /// /// Validate that a path parameter should always appear in the path /// - public static ValidationRule PathParameterShouldBeInThePath => + public static ValidationRule PathParameterShouldBeInThePath => new(nameof(PathParameterShouldBeInThePath), (context, parameter) => { diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs index 110cac88c..8d0e6010a 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Formatters/PowerShellFormatterTests.cs @@ -2,6 +2,7 @@ using Microsoft.OpenApi.Hidi.Formatters; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Xunit; @@ -109,9 +110,9 @@ private static OpenApiDocument GetSampleOpenApiDocument() OperationType.Get, new() { OperationId = "Foo.GetFoo", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "ids", In = ParameterLocation.Query, @@ -133,7 +134,7 @@ private static OpenApiDocument GetSampleOpenApiDocument() } } } - }, + ], Extensions = new Dictionary { { diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs index 8f0d04004..0dceb6127 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Tests.UtilityFiles; @@ -121,9 +122,9 @@ public void CreateFilteredDocumentUsingPredicateFromRequestUrl() { OperationType.Get, new() }, { OperationType.Patch, new() } }, - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "id", In = ParameterLocation.Path, @@ -133,7 +134,7 @@ public void CreateFilteredDocumentUsingPredicateFromRequestUrl() Type = JsonSchemaType.String } } - } + ] } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs index edbf143fe..f2f6386c4 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/UtilityFiles/OpenApiDocumentMock.cs @@ -4,6 +4,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; namespace Microsoft.OpenApi.Tests.UtilityFiles @@ -78,10 +79,10 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "reports.getTeamsUserActivityCounts", Summary = "Invoke function getTeamsUserActivityUserCounts", - Parameters = new List + Parameters = new List { { - new() + new OpenApiParameter() { Name = "period", In = ParameterLocation.Path, @@ -118,10 +119,10 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - Parameters = new List + Parameters = new List { { - new() + new OpenApiParameter() { Name = "period", In = ParameterLocation.Path, @@ -143,10 +144,10 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "reports.getTeamsUserActivityUserDetail-a3f1", Summary = "Invoke function getTeamsUserActivityUserDetail", - Parameters = new List + Parameters = new List { { - new() + new OpenApiParameter() { Name = "period", In = ParameterLocation.Path, @@ -183,9 +184,9 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "period", In = ParameterLocation.Path, @@ -316,9 +317,9 @@ public static OpenApiDocument CreateOpenApiDocument() OperationId = "users.GetMessages", Summary = "Get messages from users", Description = "The messages in a mailbox or folder. Read-only. Nullable.", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "$select", In = ParameterLocation.Query, @@ -370,10 +371,10 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "administrativeUnits.restore", Summary = "Invoke action restore", - Parameters = new List + Parameters = new List { { - new() + new OpenApiParameter() { Name = "administrativeUnit-id", In = ParameterLocation.Path, @@ -504,9 +505,9 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "communications.calls.call.keepAlive", Summary = "Invoke action keepAlive", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "call-id", In = ParameterLocation.Path, @@ -552,9 +553,9 @@ public static OpenApiDocument CreateOpenApiDocument() { OperationId = "groups.group.events.event.calendar.events.delta", Summary = "Invoke function delta", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "group-id", In = ParameterLocation.Path, @@ -571,7 +572,7 @@ public static OpenApiDocument CreateOpenApiDocument() } } }, - new() + new OpenApiParameter() { Name = "event-id", In = ParameterLocation.Path, diff --git a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs index 356f4268d..ad8495494 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs @@ -30,7 +30,7 @@ public async Task LoadParameterReference() var reference = new OpenApiParameterReference("skipParam", result.Document); // Assert - reference.Should().BeEquivalentTo( + Assert.Equivalent( new OpenApiParameter { Name = "skip", @@ -43,7 +43,8 @@ public async Task LoadParameterReference() Format = "int32" } - }, options => options.Excluding(x => x.Reference) + }, + reference ); } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs index 1d7fd39d3..ce7382b65 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs @@ -10,6 +10,7 @@ using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Reader.V2; @@ -30,8 +31,8 @@ public class OpenApiOperationTests Summary = "Updates a pet in the store", Description = "", OperationId = "updatePet", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "petId", @@ -43,7 +44,7 @@ public class OpenApiOperationTests Type = JsonSchemaType.String } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -63,8 +64,8 @@ public class OpenApiOperationTests Summary = "Updates a pet in the store with request body", Description = "", OperationId = "updatePetWithBody", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "petId", @@ -76,7 +77,7 @@ public class OpenApiOperationTests Type = JsonSchemaType.String } }, - }, + ], RequestBody = new OpenApiRequestBody { Description = "Pet to update with", diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs index d33b9964f..be19365d5 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiPathItemTests.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader.ParseNodes; using Microsoft.OpenApi.Reader.V2; using Xunit; @@ -19,9 +20,9 @@ public class OpenApiPathItemTests private static readonly OpenApiPathItem _basicPathItemWithFormData = new() { - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "id", In = ParameterLocation.Path, @@ -37,7 +38,7 @@ public class OpenApiPathItemTests }, Style = ParameterStyle.Simple } - }, + ], Operations = { [OperationType.Put] = new() @@ -45,9 +46,9 @@ public class OpenApiPathItemTests Summary = "Puts a pet in the store with form data", Description = "", OperationId = "putPetWithForm", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "petId", In = ParameterLocation.Path, @@ -58,7 +59,7 @@ public class OpenApiPathItemTests Type = JsonSchemaType.String } } - }, + ], RequestBody = new() { Content = @@ -140,9 +141,9 @@ public class OpenApiPathItemTests Summary = "Posts a pet in the store with form data", Description = "", OperationId = "postPetWithForm", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "petId", In = ParameterLocation.Path, @@ -153,7 +154,7 @@ public class OpenApiPathItemTests Type = JsonSchemaType.String } }, - new() + new OpenApiParameter() { Name = "petName", In = ParameterLocation.Path, @@ -164,7 +165,7 @@ public class OpenApiPathItemTests Type = JsonSchemaType.String } } - }, + ], RequestBody = new() { Content = diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs index 5f8c9e9bb..c2bbf6db6 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs @@ -12,6 +12,7 @@ using Xunit; using VerifyXunit; using VerifyTests; +using Microsoft.OpenApi.Models.Interfaces; namespace Microsoft.OpenApi.Readers.Tests.V31Tests { @@ -106,8 +107,8 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", @@ -135,7 +136,7 @@ public async Task ParseDocumentWithWebhooksShouldSucceed() Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -280,8 +281,8 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", @@ -309,7 +310,7 @@ public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 3622d572b..1b8f26c64 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -11,6 +11,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Tests; @@ -322,8 +323,8 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", @@ -351,7 +352,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -465,8 +466,8 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", @@ -479,7 +480,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -525,8 +526,8 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", @@ -539,7 +540,7 @@ public async Task ParseStandardPetStoreDocumentShouldSucceed() Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["204"] = new OpenApiResponse @@ -769,8 +770,8 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() }, Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", @@ -798,7 +799,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -929,8 +930,8 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", @@ -943,7 +944,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -989,8 +990,8 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", @@ -1003,7 +1004,7 @@ public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["204"] = new OpenApiResponse @@ -1224,6 +1225,19 @@ public async Task ValidateExampleShouldNotHaveDataTypeMismatch() [Fact] public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() { + var parameter = new OpenApiParameter + { + Name = "limit", + In = ParameterLocation.Query, + Description = "Limit the number of pets returned", + Required = false, + Schema = new() + { + Type = JsonSchemaType.Integer, + Format = "int32", + Default = 10 + }, + }; // Arrange var expected = new OpenApiDocument { @@ -1243,24 +1257,7 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() Summary = "Returns all pets", Parameters = [ - new OpenApiParameter - { - Name = "limit", - In = ParameterLocation.Query, - Description = "Limit the number of pets returned", - Required = false, - Schema = new() - { - Type = JsonSchemaType.Integer, - Format = "int32", - Default = 10 - }, - Reference = new OpenApiReference - { - Id = "LimitParameter", - Type = ReferenceType.Parameter - } - } + new OpenApiParameterReference(parameter, "LimitParameter"), ], Responses = new OpenApiResponses() } @@ -1269,21 +1266,9 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() }, Components = new OpenApiComponents { - Parameters = new Dictionary + Parameters = new Dictionary { - ["LimitParameter"] = new OpenApiParameter - { - Name = "limit", - In = ParameterLocation.Query, - Description = "Limit the number of pets returned", - Required = false, - Schema = new() - { - Type = JsonSchemaType.Integer, - Format = "int32", - Default = 10 - }, - } + ["LimitParameter"] = parameter } } }; @@ -1317,10 +1302,15 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() var actualParam = doc.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; var outputDoc = (await doc.SerializeAsYamlAsync(OpenApiSpecVersion.OpenApi3_0)).MakeLineBreaksEnvironmentNeutral(); var expectedParam = expected.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; + var expectedParamReference = Assert.IsType(expectedParam); + expectedParamReference.Reference.HostDocument = doc; + + var actualParamReference = Assert.IsType(actualParam); // Assert - actualParam.Should().BeEquivalentTo(expectedParam, options => options - .Excluding(x => x.Reference.HostDocument) + actualParamReference.Should().BeEquivalentTo(expectedParamReference, options => options + .Excluding(x => x.Reference) + .Excluding(x => x.Target) .Excluding(x => x.Schema.Default.Parent) .Excluding(x => x.Schema.Default.Options) .IgnoringCyclicReferences()); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs index 4b19c2e66..17411a859 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs @@ -9,6 +9,8 @@ using Xunit; using Microsoft.OpenApi.Reader.V3; using System.Threading.Tasks; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; namespace Microsoft.OpenApi.Readers.Tests.V3Tests { @@ -300,6 +302,21 @@ public async Task ParseParameterWithExamplesShouldSucceed() public void ParseParameterWithReferenceWorks() { // Arrange + var parameter = new OpenApiParameter + { + Name = "tags", + In = ParameterLocation.Query, + Description = "tags to filter by", + Required = false, + Schema = new() + { + Type = JsonSchemaType.Array, + Items = new OpenApiSchema + { + Type = JsonSchemaType.String + } + } + }; var document = new OpenApiDocument { Info = new OpenApiInfo @@ -324,44 +341,19 @@ public void ParseParameterWithReferenceWorks() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { - new() { - Reference = new OpenApiReference - { - Type = ReferenceType.Parameter, - Id = "tagsParameter" - } - } - }, + Parameters = + [ + new OpenApiParameterReference (parameter, "tagsParameter"), + ], } } } }, Components = new OpenApiComponents { - Parameters = new Dictionary() + Parameters = new Dictionary() { - ["tagsParameter"] = new OpenApiParameter - { - Name = "tags", - In = ParameterLocation.Query, - Description = "tags to filter by", - Required = false, - Schema = new() - { - Type = JsonSchemaType.Array, - Items = new OpenApiSchema - { - Type = JsonSchemaType.String - } - }, - Reference = new OpenApiReference - { - Type = ReferenceType.Parameter, - Id = "tagsParameter" - } - } + ["tagsParameter"] = parameter, } } }; @@ -377,7 +369,7 @@ public void ParseParameterWithReferenceWorks() var param = OpenApiV3Deserializer.LoadParameter(node, document); // Assert - param.Should().BeEquivalentTo(expected, options => options.Excluding(p => p.Reference.HostDocument)); + Assert.Equivalent(expected, param); } } } diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt index c63fb3250..5d9d7f3da 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt @@ -30,7 +30,6 @@ "name": "tags", "in": "query", "description": "tags to filter by", - "style": "form", "schema": { "type": "array", "items": { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt index f7d8a3f47..5fd0d1e26 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.SerializeAdvancedDocumentWithReferenceAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"openapi":"3.0.4","info":{"title":"Swagger Petstore (Simple)","description":"A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification","termsOfService":"http://helloreverb.com/terms/","contact":{"name":"Swagger API team","url":"http://swagger.io","email":"foo@example.com"},"license":{"name":"MIT","url":"http://opensource.org/licenses/MIT"},"version":"1.0.0"},"servers":[{"url":"http://petstore.swagger.io/api"}],"paths":{"/pets":{"get":{"description":"Returns all pets from the system that the user has access to","operationId":"findPets","parameters":[{"name":"tags","in":"query","description":"tags to filter by","style":"form","schema":{"type":"array","items":{"type":"string"}}},{"name":"limit","in":"query","description":"maximum number of results to return","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"type":"array","items":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}},"application/xml":{"schema":{"type":"array","items":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}},"post":{"description":"Creates a new pet in the store. Duplicates are allowed","operationId":"addPet","requestBody":{"description":"Pet to add to the store","content":{"application/json":{"schema":{"required":["name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}},"required":true},"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}}},"/pets/{id}":{"get":{"description":"Returns a user based on a single ID, if the user does not have access to the pet","operationId":"findPetById","parameters":[{"name":"id","in":"path","description":"ID of pet to fetch","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}},"application/xml":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}},"delete":{"description":"deletes a single pet based on the ID supplied","operationId":"deletePet","parameters":[{"name":"id","in":"path","description":"ID of pet to delete","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"204":{"description":"pet deleted"},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}}}},"components":{"schemas":{"pet":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}},"newPet":{"required":["name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}},"errorModel":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}} +{"openapi":"3.0.4","info":{"title":"Swagger Petstore (Simple)","description":"A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification","termsOfService":"http://helloreverb.com/terms/","contact":{"name":"Swagger API team","url":"http://swagger.io","email":"foo@example.com"},"license":{"name":"MIT","url":"http://opensource.org/licenses/MIT"},"version":"1.0.0"},"servers":[{"url":"http://petstore.swagger.io/api"}],"paths":{"/pets":{"get":{"description":"Returns all pets from the system that the user has access to","operationId":"findPets","parameters":[{"name":"tags","in":"query","description":"tags to filter by","schema":{"type":"array","items":{"type":"string"}}},{"name":"limit","in":"query","description":"maximum number of results to return","schema":{"type":"integer","format":"int32"}}],"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"type":"array","items":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}},"application/xml":{"schema":{"type":"array","items":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}},"post":{"description":"Creates a new pet in the store. Duplicates are allowed","operationId":"addPet","requestBody":{"description":"Pet to add to the store","content":{"application/json":{"schema":{"required":["name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}},"required":true},"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}}},"/pets/{id}":{"get":{"description":"Returns a user based on a single ID, if the user does not have access to the pet","operationId":"findPetById","parameters":[{"name":"id","in":"path","description":"ID of pet to fetch","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"200":{"description":"pet response","content":{"application/json":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}},"application/xml":{"schema":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}}}}},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}},"delete":{"description":"deletes a single pet based on the ID supplied","operationId":"deletePet","parameters":[{"name":"id","in":"path","description":"ID of pet to delete","required":true,"schema":{"type":"integer","format":"int64"}}],"responses":{"204":{"description":"pet deleted"},"4XX":{"description":"unexpected client error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}},"5XX":{"description":"unexpected server error","content":{"text/html":{"schema":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}}}}}},"components":{"schemas":{"pet":{"required":["id","name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}},"newPet":{"required":["name"],"type":"object","properties":{"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"tag":{"type":"string"}}},"errorModel":{"required":["code","message"],"type":"object","properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index 752ec7d9f..f43843051 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -10,6 +10,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Readers; @@ -252,8 +253,8 @@ public OpenApiDocumentTests() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "tags", @@ -281,7 +282,7 @@ public OpenApiDocumentTests() Format = "int32" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -395,8 +396,8 @@ public OpenApiDocumentTests() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", @@ -409,7 +410,7 @@ public OpenApiDocumentTests() Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse @@ -455,8 +456,8 @@ public OpenApiDocumentTests() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", @@ -469,7 +470,7 @@ public OpenApiDocumentTests() Format = "int64" } } - }, + ], Responses = new OpenApiResponses { ["204"] = new OpenApiResponse @@ -628,7 +629,7 @@ public OpenApiDocumentTests() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List + Parameters = new List { new OpenApiParameter { @@ -771,7 +772,7 @@ public OpenApiDocumentTests() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List + Parameters = new List { new OpenApiParameter { @@ -831,7 +832,7 @@ public OpenApiDocumentTests() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List + Parameters = new List { new OpenApiParameter { @@ -975,7 +976,7 @@ public OpenApiDocumentTests() [OperationType.Get] = new OpenApiOperation { OperationId = "addByOperand1AndByOperand2", - Parameters = new List + Parameters = new List { new OpenApiParameter { @@ -1087,9 +1088,9 @@ public OpenApiDocumentTests() { Description = "Returns all pets from the system that the user has access to", OperationId = "findPets", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "tags", In = ParameterLocation.Query, @@ -1104,7 +1105,7 @@ public OpenApiDocumentTests() } } }, - new() + new OpenApiParameter() { Name = "limit", In = ParameterLocation.Query, @@ -1230,9 +1231,9 @@ public OpenApiDocumentTests() Description = "Returns a user based on a single ID, if the user does not have access to the pet", OperationId = "findPetById", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "id", In = ParameterLocation.Path, @@ -1290,9 +1291,9 @@ public OpenApiDocumentTests() { Description = "deletes a single pet based on the ID supplied", OperationId = "deletePet", - Parameters = new List + Parameters = new List { - new() + new OpenApiParameter() { Name = "id", In = ParameterLocation.Path, @@ -1732,8 +1733,8 @@ public async Task SerializeV2DocumentWithNonArraySchemaTypeDoesNotWriteOutCollec { [OperationType.Get] = new OpenApiOperation { - Parameters = new List - { + Parameters = + [ new OpenApiParameter { In = ParameterLocation.Query, @@ -1742,7 +1743,7 @@ public async Task SerializeV2DocumentWithNonArraySchemaTypeDoesNotWriteOutCollec Type = JsonSchemaType.String } } - }, + ], Responses = new OpenApiResponses() } } @@ -1799,8 +1800,8 @@ public async Task SerializeV2DocumentWithStyleAsNullDoesNotWriteOutStyleValue() { [OperationType.Get] = new OpenApiOperation { - Parameters = new List - { + Parameters = + [ new OpenApiParameter { Name = "id", @@ -1814,7 +1815,7 @@ public async Task SerializeV2DocumentWithStyleAsNullDoesNotWriteOutStyleValue() } } } - }, + ], Responses = new OpenApiResponses { ["200"] = new OpenApiResponse diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs index 1b0b27ada..81da044bf 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; using Xunit; @@ -25,19 +26,19 @@ public class OpenApiOperationTests Url = new("http://external.com") }, OperationId = "operationId1", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { In = ParameterLocation.Path, Name = "parameter1", }, - new() + new OpenApiParameter() { In = ParameterLocation.Header, Name = "parameter2" } - }, + ], RequestBody = new() { Description = "description2", @@ -99,19 +100,19 @@ public class OpenApiOperationTests Url = new("http://external.com") }, OperationId = "operationId1", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { In = ParameterLocation.Path, Name = "parameter1" }, - new() + new OpenApiParameter() { In = ParameterLocation.Header, Name = "parameter2" } - }, + ], RequestBody = new() { Description = "description2", @@ -176,9 +177,9 @@ public class OpenApiOperationTests Summary = "Updates a pet in the store with form data", Description = "", OperationId = "updatePetWithForm", - Parameters = new List - { - new() + Parameters = + [ + new OpenApiParameter() { Name = "petId", In = ParameterLocation.Path, @@ -189,7 +190,7 @@ public class OpenApiOperationTests Type = JsonSchemaType.String } } - }, + ], RequestBody = new() { Content = diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=False.verified.txt index 5d3060ec5..d450bda88 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=False.verified.txt @@ -2,7 +2,6 @@ "name": "name1", "in": "query", "description": "description1", - "style": "form", "explode": false, "schema": { "type": "array", diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=True.verified.txt index a4b87db10..33a58c93f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeFalseWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"name":"name1","in":"query","description":"description1","style":"form","explode":false,"schema":{"type":"array","items":{"enum":["value1","value2"]}}} \ No newline at end of file +{"name":"name1","in":"query","description":"description1","explode":false,"schema":{"type":"array","items":{"enum":["value1","value2"]}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=False.verified.txt index 36a9c0168..56944b8db 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=False.verified.txt @@ -2,7 +2,6 @@ "name": "name1", "in": "query", "description": "description1", - "style": "form", "schema": { "type": "array", "items": { diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=True.verified.txt index 206902b7b..b9e1ee95f 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.SerializeParameterWithFormStyleAndExplodeTrueWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"name":"name1","in":"query","description":"description1","style":"form","schema":{"type":"array","items":{"enum":["value1","value2"]}}} \ No newline at end of file +{"name":"name1","in":"query","description":"description1","schema":{"type":"array","items":{"enum":["value1","value2"]}}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs index b76dcf342..edec7bbd8 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiParameterTests.cs @@ -260,7 +260,6 @@ public async Task SerializeAdvancedParameterAsV3JsonWorks() "in": "path", "description": "description1", "required": true, - "style": "simple", "explode": true, "schema": { "title": "title2", diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt index 237298009..cd30a5fc2 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=False.verified.txt @@ -2,7 +2,6 @@ "name": "limit", "in": "query", "description": "Results to return", - "style": "form", "schema": { "maximum": 100, "minimum": 1, diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt index e8eac1b64..da4f04c14 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV31JsonWorks_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"name":"limit","in":"query","description":"Results to return","style":"form","schema":{"maximum":100,"minimum":1,"type":"integer"}} \ No newline at end of file +{"name":"limit","in":"query","description":"Results to return","schema":{"maximum":100,"minimum":1,"type":"integer"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt index 237298009..cd30a5fc2 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=False.verified.txt @@ -2,7 +2,6 @@ "name": "limit", "in": "query", "description": "Results to return", - "style": "form", "schema": { "maximum": 100, "minimum": 1, diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt index e8eac1b64..da4f04c14 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.SerializeParameterReferenceAsV3JsonWorks_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -{"name":"limit","in":"query","description":"Results to return","style":"form","schema":{"maximum":100,"minimum":1,"type":"integer"}} \ No newline at end of file +{"name":"limit","in":"query","description":"Results to return","schema":{"maximum":100,"minimum":1,"type":"integer"}} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index e881f649d..f89d60453 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -371,6 +371,21 @@ namespace Microsoft.OpenApi.Models.Interfaces Microsoft.OpenApi.Models.RuntimeExpressionAnyWrapper RequestBody { get; } Microsoft.OpenApi.Models.OpenApiServer Server { get; } } + public interface IOpenApiParameter : 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; } + Microsoft.OpenApi.Models.ParameterLocation? In { get; } + string Name { 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; } @@ -409,7 +424,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary? Extensions { 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? Parameters { get; set; } public System.Collections.Generic.IDictionary? PathItems { get; set; } public System.Collections.Generic.IDictionary? RequestBodies { get; set; } public System.Collections.Generic.IDictionary? Responses { get; set; } @@ -798,7 +813,7 @@ namespace Microsoft.OpenApi.Models public System.Collections.Generic.IDictionary? Extensions { get; set; } public Microsoft.OpenApi.Models.OpenApiExternalDocs? ExternalDocs { get; set; } public string? OperationId { get; set; } - public System.Collections.Generic.IList? Parameters { get; set; } + public System.Collections.Generic.IList? Parameters { get; set; } public Microsoft.OpenApi.Models.OpenApiRequestBody? RequestBody { get; set; } public Microsoft.OpenApi.Models.OpenApiResponses? Responses { get; set; } public System.Collections.Generic.IList? Security { get; set; } @@ -809,29 +824,27 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiParameter : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiParameter : 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.IOpenApiParameter { public OpenApiParameter() { } - public OpenApiParameter(Microsoft.OpenApi.Models.OpenApiParameter parameter) { } - 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 Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } - public virtual string Name { 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 OpenApiParameter(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter parameter) { } + 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 Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } + public string Name { 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 OpenApiPathItem : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiReferenceable, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -842,7 +855,7 @@ namespace Microsoft.OpenApi.Models public virtual string Description { get; set; } public virtual System.Collections.Generic.IDictionary Extensions { get; set; } public virtual System.Collections.Generic.IDictionary Operations { get; set; } - public virtual System.Collections.Generic.IList Parameters { get; set; } + public virtual System.Collections.Generic.IList Parameters { get; set; } public virtual System.Collections.Generic.IList Servers { get; set; } public virtual string Summary { get; set; } public void AddOperation(Microsoft.OpenApi.Models.OperationType operationType, Microsoft.OpenApi.Models.OpenApiOperation operation) { } @@ -1216,27 +1229,31 @@ namespace Microsoft.OpenApi.Models.References public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } - public class OpenApiParameterReference : Microsoft.OpenApi.Models.OpenApiParameter, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable + public class OpenApiParameterReference : 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.IOpenApiParameter { + public OpenApiParameterReference(Microsoft.OpenApi.Models.References.OpenApiParameterReference parameter) { } public OpenApiParameterReference(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.ParameterLocation? In { get; } + public string Name { 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.OpenApiParameter 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 Microsoft.OpenApi.Models.ParameterLocation? In { get; set; } - public override string Name { 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.IOpenApiParameter CopyReferenceAsTargetElementWithOverrides(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter 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 OpenApiPathItemReference : Microsoft.OpenApi.Models.OpenApiPathItem, Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiReferenceHolder, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { @@ -1245,7 +1262,7 @@ namespace Microsoft.OpenApi.Models.References public override string Description { get; set; } public override System.Collections.Generic.IDictionary Extensions { get; set; } public override System.Collections.Generic.IDictionary Operations { get; set; } - public override System.Collections.Generic.IList Parameters { get; set; } + public override System.Collections.Generic.IList Parameters { get; set; } public override System.Collections.Generic.IList Servers { get; set; } public override string Summary { get; set; } public override void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -1546,6 +1563,7 @@ namespace Microsoft.OpenApi.Services 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.Interfaces.IOpenApiLink link) { } + public virtual void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter parameter) { } 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) { } @@ -1556,7 +1574,6 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(Microsoft.OpenApi.Models.OpenApiMediaType mediaType) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiOAuthFlow openApiOAuthFlow) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } - public virtual void Visit(Microsoft.OpenApi.Models.OpenApiParameter parameter) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiPathItem pathItem) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } public virtual void Visit(Microsoft.OpenApi.Models.OpenApiRequestBody requestBody) { } @@ -1579,7 +1596,7 @@ namespace Microsoft.OpenApi.Services public virtual void Visit(System.Collections.Generic.IDictionary webhooks) { } public virtual void Visit(System.Collections.Generic.IDictionary serverVariables) { } public virtual void Visit(System.Collections.Generic.IList example) { } - public virtual void Visit(System.Collections.Generic.IList parameters) { } + public virtual void Visit(System.Collections.Generic.IList parameters) { } public virtual void Visit(System.Collections.Generic.IList openApiSecurityRequirements) { } public virtual void Visit(System.Collections.Generic.IList servers) { } public virtual void Visit(System.Collections.Generic.IList openApiTags) { } @@ -1610,14 +1627,14 @@ namespace Microsoft.OpenApi.Services public OperationSearch(System.Func predicate) { } public System.Collections.Generic.IList SearchResults { get; } public override void Visit(Microsoft.OpenApi.Models.OpenApiPathItem pathItem) { } - public override void Visit(System.Collections.Generic.IList parameters) { } + public override void Visit(System.Collections.Generic.IList parameters) { } } public class SearchResult { public SearchResult() { } public Microsoft.OpenApi.Services.CurrentKeys CurrentKeys { get; set; } public Microsoft.OpenApi.Models.OpenApiOperation Operation { get; set; } - public System.Collections.Generic.IList Parameters { get; set; } + public System.Collections.Generic.IList Parameters { get; set; } } } namespace Microsoft.OpenApi.Validations @@ -1645,6 +1662,7 @@ namespace Microsoft.OpenApi.Validations 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.Interfaces.IOpenApiLink link) { } + public override void Visit(Microsoft.OpenApi.Models.Interfaces.IOpenApiParameter parameter) { } 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) { } @@ -1655,7 +1673,6 @@ namespace Microsoft.OpenApi.Validations public override void Visit(Microsoft.OpenApi.Models.OpenApiMediaType mediaType) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiOAuthFlow openApiOAuthFlow) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiOperation operation) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiParameter parameter) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiPathItem pathItem) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiPaths paths) { } public override void Visit(Microsoft.OpenApi.Models.OpenApiRequestBody requestBody) { } @@ -1777,9 +1794,9 @@ namespace Microsoft.OpenApi.Validations.Rules [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiParameterRules { - public static Microsoft.OpenApi.Validations.ValidationRule ParameterRequiredFields { get; } - public static Microsoft.OpenApi.Validations.ValidationRule PathParameterShouldBeInThePath { get; } - public static Microsoft.OpenApi.Validations.ValidationRule RequiredMustBeTrueWhenInIsPath { get; } + public static Microsoft.OpenApi.Validations.ValidationRule ParameterRequiredFields { get; } + public static Microsoft.OpenApi.Validations.ValidationRule PathParameterShouldBeInThePath { get; } + public static Microsoft.OpenApi.Validations.ValidationRule RequiredMustBeTrueWhenInIsPath { get; } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiPathsRules diff --git a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs index c08c88471..13328046e 100644 --- a/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Validations/OpenApiParameterValidationTests.cs @@ -6,6 +6,7 @@ using System.Text.Json.Nodes; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Properties; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Validations.Rules; @@ -49,7 +50,7 @@ public void ValidateRequiredIsTrueWhenInIsPathInParameter() var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); validator.Enter("{name}"); var walker = new OpenApiWalker(validator); - walker.Walk(parameter); + walker.Walk((IOpenApiParameter)parameter); var errors = validator.Errors; // Assert Assert.NotEmpty(errors); @@ -93,8 +94,6 @@ public void ValidateExampleShouldNotHaveDataTypeMismatchForSimpleSchema() public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() { // Arrange - IEnumerable warnings; - var parameter = new OpenApiParameter { Name = "parameter1", @@ -140,26 +139,21 @@ public void ValidateExamplesShouldNotHaveDataTypeMismatchForSimpleSchema() // Act var defaultRuleSet = ValidationRuleSet.GetDefaultRuleSet(); - defaultRuleSet.Add(typeof(OpenApiParameter), OpenApiNonDefaultRules.ParameterMismatchedDataType); + defaultRuleSet.Add(typeof(IOpenApiParameter), OpenApiNonDefaultRules.ParameterMismatchedDataType); var validator = new OpenApiValidator(defaultRuleSet); validator.Enter("{parameter1}"); var walker = new OpenApiWalker(validator); - walker.Walk(parameter); - - warnings = validator.Warnings; - var result = !warnings.Any(); + walker.Walk((IOpenApiParameter)parameter); // Assert - Assert.False(result); + Assert.NotEmpty(validator.Warnings); } [Fact] public void PathParameterNotInThePathShouldReturnAnError() { // Arrange - IEnumerable errors; - var parameter = new OpenApiParameter { Name = "parameter1", @@ -175,21 +169,18 @@ public void PathParameterNotInThePathShouldReturnAnError() var validator = new OpenApiValidator(ValidationRuleSet.GetDefaultRuleSet()); var walker = new OpenApiWalker(validator); - walker.Walk(parameter); - - errors = validator.Errors; - var result = errors.Any(); + walker.Walk((IOpenApiParameter)parameter); // Assert - Assert.True(result); + Assert.NotEmpty(validator.Errors); Assert.Equivalent(new[] { "PathParameterShouldBeInThePath" - }, errors.OfType().Select(e => e.RuleName)); + }, validator.Errors.OfType().Select(e => e.RuleName)); Assert.Equivalent(new[] { "#/in" - }, errors.Select(e => e.Pointer)); + }, validator.Errors.Select(e => e.Pointer)); } [Fact] diff --git a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs index f2634be52..302f8937a 100644 --- a/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Visitors/InheritanceTests.cs @@ -30,8 +30,8 @@ public void ExpectedVirtualsInvolved() visitor.Visit(default(OpenApiServerVariable)); visitor.Visit(default(IDictionary)); visitor.Visit(default(OpenApiOperation)); - visitor.Visit(default(IList)); - visitor.Visit(default(OpenApiParameter)); + visitor.Visit(default(IList)); + visitor.Visit(default(IOpenApiParameter)); visitor.Visit(default(OpenApiRequestBody)); visitor.Visit(default(IDictionary)); visitor.Visit(default(IDictionary)); @@ -154,13 +154,13 @@ public override void Visit(OpenApiOperation operation) base.Visit(operation); } - public override void Visit(IList parameters) + public override void Visit(IList parameters) { EncodeCall(); base.Visit(parameters); } - public override void Visit(OpenApiParameter parameter) + public override void Visit(IOpenApiParameter parameter) { EncodeCall(); base.Visit(parameter);