From bd9622e239d5a5b2b4629d2f371f674775193af5 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 06:32:21 -0500 Subject: [PATCH 001/127] fix: multiple performance fixes for type serialization feat: adds to identifier mapping to non nullable enum Signed-off-by: Vincent Biret --- .../Extensions/OpenApiTypeMapper.cs | 18 +++- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 96 ++++++++----------- .../PublicApi/PublicApi.approved.txt | 3 +- 3 files changed, 61 insertions(+), 56 deletions(-) diff --git a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs index e6dadd44d..e47eff496 100644 --- a/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs +++ b/src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs @@ -13,12 +13,27 @@ namespace Microsoft.OpenApi.Extensions /// public static class OpenApiTypeMapper { +#nullable enable /// /// Maps a JsonSchema data type to an identifier. /// /// /// - public static string ToIdentifier(this JsonSchemaType? schemaType) + public static string? ToIdentifier(this JsonSchemaType? schemaType) + { + if (schemaType is null) + { + return null; + } + return schemaType.Value.ToIdentifier(); + } + + /// + /// Maps a JsonSchema data type to an identifier. + /// + /// + /// + public static string? ToIdentifier(this JsonSchemaType schemaType) { return schemaType switch { @@ -32,6 +47,7 @@ public static string ToIdentifier(this JsonSchemaType? schemaType) _ => null, }; } +#nullable restore /// /// Converts a schema type's identifier into the enum equivalent diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 59b7e2025..c2456286c 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -476,10 +476,7 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, writer.WriteOptionalCollection(OpenApiConstants.Enum, Enum, (nodeWriter, s) => nodeWriter.WriteAny(s)); // type - if (Type is not null) - { - SerializeTypeProperty(Type, writer, version); - } + SerializeTypeProperty(Type, writer, version); // allOf writer.WriteOptionalCollection(OpenApiConstants.AllOf, AllOf, callback); @@ -660,10 +657,7 @@ internal void SerializeAsV2( writer.WriteStartObject(); // type - if (Type is not null) - { - SerializeTypeProperty(Type, writer, OpenApiSpecVersion.OpenApi2_0); - } + SerializeTypeProperty(Type, writer, OpenApiSpecVersion.OpenApi2_0); // description writer.WriteProperty(OpenApiConstants.Description, Description); @@ -794,8 +788,11 @@ internal void SerializeAsV2( private void SerializeTypeProperty(JsonSchemaType? type, IOpenApiWriter writer, OpenApiSpecVersion version) { - var flagsCount = CountEnumSetFlags(type); - if (flagsCount is 1) + if (type is null) + { + return; + } + if (!HasMultipleTypes(type.Value)) { // check whether nullable is true for upcasting purposes if (version is OpenApiSpecVersion.OpenApi3_1 && (Nullable || Extensions.ContainsKey(OpenApiConstants.NullableExtension))) @@ -804,53 +801,42 @@ private void SerializeTypeProperty(JsonSchemaType? type, IOpenApiWriter writer, } else { - writer.WriteProperty(OpenApiConstants.Type, type.ToIdentifier()); + writer.WriteProperty(OpenApiConstants.Type, type.Value.ToIdentifier()); } } - else if(flagsCount > 1) + else { // type if (version is OpenApiSpecVersion.OpenApi2_0 || version is OpenApiSpecVersion.OpenApi3_0) { - DowncastTypeArrayToV2OrV3(type, writer, version, flagsCount); + DowncastTypeArrayToV2OrV3(type.Value, writer, version); } else { - if (type is not null) + var list = new List(); + foreach (JsonSchemaType flag in jsonSchemaTypeValues) { - var list = new List(); - foreach (JsonSchemaType flag in System.Enum.GetValues(typeof(JsonSchemaType))) + if (type.Value.HasFlag(flag)) { - if (type.Value.HasFlag(flag)) - { - list.Add(flag); - } + list.Add(flag); } + } - writer.WriteOptionalCollection(OpenApiConstants.Type, list, (w, s) => w.WriteValue(s.ToIdentifier())); - } + writer.WriteOptionalCollection(OpenApiConstants.Type, list, (w, s) => w.WriteValue(s.ToIdentifier())); } } } - private static int CountEnumSetFlags(JsonSchemaType? schemaType) + private static bool IsPowerOfTwo(int x) { - int count = 0; - - if (schemaType != null) - { - // Check each flag in the enum - foreach (JsonSchemaType value in System.Enum.GetValues(typeof(JsonSchemaType))) - { - // Check if the flag is set - if (schemaType.Value.HasFlag(value)) - { - count++; - } - } - } + return x != 0 && (x & (x - 1)) == 0; + } - return count; + private static bool HasMultipleTypes(JsonSchemaType schemaType) + { + var schemaTypeNumeric = (int)schemaType; + return !IsPowerOfTwo(schemaTypeNumeric) && // Boolean, Integer, Number, String, Array, Object + schemaTypeNumeric != (int)JsonSchemaType.Null; } private void UpCastSchemaTypeToV31(JsonSchemaType? type, IOpenApiWriter writer) @@ -858,7 +844,7 @@ private void UpCastSchemaTypeToV31(JsonSchemaType? type, IOpenApiWriter writer) // create a new array and insert the type and "null" as values Type = type | JsonSchemaType.Null; var list = new List(); - foreach (JsonSchemaType? flag in System.Enum.GetValues(typeof(JsonSchemaType))) + foreach (JsonSchemaType? flag in jsonSchemaTypeValues) { // Check if the flag is set in 'type' using a bitwise AND operation if (Type.Value.HasFlag(flag)) @@ -870,7 +856,9 @@ private void UpCastSchemaTypeToV31(JsonSchemaType? type, IOpenApiWriter writer) writer.WriteOptionalCollection(OpenApiConstants.Type, list, (w, s) => w.WriteValue(s)); } - private void DowncastTypeArrayToV2OrV3(JsonSchemaType? schemaType, IOpenApiWriter writer, OpenApiSpecVersion version, int flagsCount) + private static readonly Array jsonSchemaTypeValues = System.Enum.GetValues(typeof(JsonSchemaType)); + + private void DowncastTypeArrayToV2OrV3(JsonSchemaType schemaType, IOpenApiWriter writer, OpenApiSpecVersion version) { /* If the array has one non-null value, emit Type as string * If the array has one null value, emit x-nullable as true @@ -882,23 +870,12 @@ private void DowncastTypeArrayToV2OrV3(JsonSchemaType? schemaType, IOpenApiWrite ? OpenApiConstants.NullableExtension : OpenApiConstants.Nullable; - if (flagsCount is 1) + if (!HasMultipleTypes(schemaType ^ JsonSchemaType.Null) && (schemaType & JsonSchemaType.Null) == JsonSchemaType.Null) // checks for two values and one is null { - if (schemaType is JsonSchemaType.Null) - { - writer.WriteProperty(nullableProp, true); - } - else - { - writer.WriteProperty(OpenApiConstants.Type, schemaType.ToIdentifier()); - } - } - else if (flagsCount is 2 && (schemaType & JsonSchemaType.Null) == JsonSchemaType.Null) // checks for two values and one is null - { - foreach (JsonSchemaType? flag in System.Enum.GetValues(typeof(JsonSchemaType))) + foreach (JsonSchemaType? flag in jsonSchemaTypeValues) { // Skip if the flag is not set or if it's the Null flag - if (schemaType.Value.HasFlag(flag) && flag != JsonSchemaType.Null) + if (schemaType.HasFlag(flag) && flag != JsonSchemaType.Null) { // Write the non-null flag value to the writer writer.WriteProperty(OpenApiConstants.Type, flag.ToIdentifier()); @@ -909,6 +886,17 @@ private void DowncastTypeArrayToV2OrV3(JsonSchemaType? schemaType, IOpenApiWrite writer.WriteProperty(nullableProp, true); } } + else if (!HasMultipleTypes(schemaType)) + { + if (schemaType is JsonSchemaType.Null) + { + writer.WriteProperty(nullableProp, true); + } + else + { + writer.WriteProperty(OpenApiConstants.Type, schemaType.ToIdentifier()); + } + } } } } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index ef18b4cfb..3fe034011 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -192,7 +192,8 @@ namespace Microsoft.OpenApi.Extensions { public static System.Type MapOpenApiPrimitiveTypeToSimpleType(this Microsoft.OpenApi.Models.OpenApiSchema schema) { } public static Microsoft.OpenApi.Models.OpenApiSchema MapTypeToOpenApiPrimitiveType(this System.Type type) { } - public static string ToIdentifier(this Microsoft.OpenApi.Models.JsonSchemaType? schemaType) { } + public static string? ToIdentifier(this Microsoft.OpenApi.Models.JsonSchemaType schemaType) { } + public static string? ToIdentifier(this Microsoft.OpenApi.Models.JsonSchemaType? schemaType) { } public static Microsoft.OpenApi.Models.JsonSchemaType ToJsonSchemaType(this string identifier) { } } public static class StringExtensions From ba81e371277f3eb5428ab6b63c86621a0e0238d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Nov 2024 21:59:46 +0000 Subject: [PATCH 002/127] chore(deps): bump Microsoft.Extensions.Logging.Abstractions Bumps [Microsoft.Extensions.Logging.Abstractions](https://github.com/dotnet/runtime) from 8.0.2 to 9.0.0. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.2...v9.0.0) --- updated-dependencies: - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 07f2e3e7d..549864fa3 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -30,7 +30,7 @@ - + From 0ab2350ef305e6f3984aa1a02012d3482a1ae073 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 09:27:38 +0300 Subject: [PATCH 003/127] chore(deps): bump System.Text.Json from 8.0.5 to 9.0.0 (#1920) Bumps [System.Text.Json](https://github.com/dotnet/runtime) from 8.0.5 to 9.0.0. - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.5...v9.0.0) --- updated-dependencies: - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj | 2 +- src/Microsoft.OpenApi/Microsoft.OpenApi.csproj | 2 +- .../Microsoft.OpenApi.Readers.Tests.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 07f2e3e7d..8bdebc507 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -45,7 +45,7 @@ - + diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj index cdd32b997..8ad99192a 100644 --- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj +++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj @@ -31,7 +31,7 @@ - + diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index b549decd7..7113d0a10 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -22,7 +22,7 @@ true - + diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index 91660802a..daf6dbd1c 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -24,7 +24,7 @@ - + From d5b11ea2c8a8b68e5060392df765b34f155bbe0b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 09:28:18 +0300 Subject: [PATCH 004/127] chore(deps): bump System.Formats.Asn1 and Microsoft.Windows.Compatibility (#1921) Bumps [System.Formats.Asn1](https://github.com/dotnet/runtime) and [Microsoft.Windows.Compatibility](https://github.com/dotnet/windowsdesktop). These dependencies needed to be updated together. Updates `System.Formats.Asn1` from 8.0.1 to 9.0.0 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v9.0.0) Updates `Microsoft.Windows.Compatibility` from 8.0.10 to 9.0.0 - [Release notes](https://github.com/dotnet/windowsdesktop/releases) - [Commits](https://github.com/dotnet/windowsdesktop/compare/v8.0.10...v9.0.0) --- updated-dependencies: - dependency-name: System.Formats.Asn1 dependency-type: direct:production update-type: version-update:semver-major - dependency-name: Microsoft.Windows.Compatibility dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .../Microsoft.OpenApi.Workbench.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj b/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj index 3ea08878d..57e1c6e13 100644 --- a/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj +++ b/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj @@ -12,9 +12,9 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + - + From d9fccee5e0254a5c44c59b894aec48b484cb50bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:20:46 +0000 Subject: [PATCH 005/127] chore(deps): bump Verify.Xunit from 28.2.0 to 28.2.1 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 28.2.0 to 28.2.1. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/28.2.0...28.2.1) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index fe422d3e7..0d532f1ec 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -15,7 +15,7 @@ - + From 243d6808f389c44e4bca2273d5cf9a26f66683e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:21:07 +0000 Subject: [PATCH 006/127] chore(deps): bump Microsoft.Extensions.Logging and Microsoft.Extensions.Logging.Abstractions Bumps [Microsoft.Extensions.Logging](https://github.com/dotnet/runtime) and [Microsoft.Extensions.Logging.Abstractions](https://github.com/dotnet/runtime). These dependencies needed to be updated together. Updates `Microsoft.Extensions.Logging` from 8.0.1 to 9.0.0 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v9.0.0) Updates `Microsoft.Extensions.Logging.Abstractions` from 9.0.0 to 9.0.0 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v9.0.0...v9.0.0) --- updated-dependencies: - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-major - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 720163977..ecdb2f382 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -29,7 +29,7 @@ - + From 342e643dd5d74268b1bc1e8a4b68426db88e6ada Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:21:26 +0000 Subject: [PATCH 007/127] chore(deps): bump Microsoft.OData.Edm from 8.2.0 to 8.2.1 Bumps Microsoft.OData.Edm from 8.2.0 to 8.2.1. --- updated-dependencies: - dependency-name: Microsoft.OData.Edm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 720163977..0cd90d008 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -38,7 +38,7 @@ all - + From b5ebf59e8cf6fa114d992fbeb9034f3dc5df4e3e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Nov 2024 21:22:21 +0000 Subject: [PATCH 008/127] chore(deps): bump Microsoft.VisualStudio.Threading.Analyzers Bumps [Microsoft.VisualStudio.Threading.Analyzers](https://github.com/microsoft/vs-threading) from 17.11.20 to 17.12.19. - [Release notes](https://github.com/microsoft/vs-threading/releases) - [Commits](https://github.com/microsoft/vs-threading/commits) --- updated-dependencies: - dependency-name: Microsoft.VisualStudio.Threading.Analyzers dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj | 2 +- .../Microsoft.OpenApi.Workbench.csproj | 2 +- src/Microsoft.OpenApi/Microsoft.OpenApi.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 720163977..9af98f513 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -33,7 +33,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj index 8ad99192a..c67e68b2f 100644 --- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj +++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj @@ -25,7 +25,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj b/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj index 57e1c6e13..3210463df 100644 --- a/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj +++ b/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj @@ -8,7 +8,7 @@ true - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index 7113d0a10..a4ea950f2 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -45,7 +45,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all From 3ca0672ad0f12c97ce34edfe81d3d75be5f9d781 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 14 Nov 2024 07:32:31 -0500 Subject: [PATCH 009/127] chore: removes newtonsoft dependency all together --- .../Microsoft.OpenApi.Hidi.Tests.csproj | 1 - .../Microsoft.OpenApi.Readers.Tests.csproj | 1 - .../Microsoft.OpenApi.Tests.csproj | 1 - .../Writers/OpenApiJsonWriterTests.cs | 72 ++++++++++++++++--- 4 files changed, 61 insertions(+), 14 deletions(-) diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj index 397831833..07a571a57 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj +++ b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj @@ -14,7 +14,6 @@ - diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index daf6dbd1c..e528cdcd5 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -19,7 +19,6 @@ - diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 0d532f1ec..d71445022 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -13,7 +13,6 @@ - diff --git a/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs b/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs index a967c43a0..30247333f 100644 --- a/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs +++ b/test/Microsoft.OpenApi.Tests/Writers/OpenApiJsonWriterTests.cs @@ -8,12 +8,14 @@ using System.IO; using System.Linq; using System.Text; +using System.Text.Encodings.Web; +using System.Text.Json; using System.Text.Json.Nodes; +using System.Text.Json.Serialization; using FluentAssertions; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Writers; -using Newtonsoft.Json; using Xunit; namespace Microsoft.OpenApi.Tests.Writers @@ -62,9 +64,9 @@ public void WriteStringListAsJsonShouldMatchExpected(string[] stringValues, bool writer.WriteEndArray(); writer.Flush(); - var parsedObject = JsonConvert.DeserializeObject(outputString.GetStringBuilder().ToString()); + var parsedObject = JsonSerializer.Deserialize>(outputString.GetStringBuilder().ToString()); var expectedObject = - JsonConvert.DeserializeObject(JsonConvert.SerializeObject(new List(stringValues))); + JsonSerializer.Deserialize>(JsonSerializer.Serialize(new List(stringValues))); // Assert parsedObject.Should().BeEquivalentTo(expectedObject); @@ -222,17 +224,17 @@ private void WriteValueRecursive(OpenApiJsonWriter writer, object value) public void WriteMapAsJsonShouldMatchExpected(IDictionary inputMap, bool produceTerseOutput) { // Arrange - var outputString = new StringWriter(CultureInfo.InvariantCulture); + using var outputString = new StringWriter(CultureInfo.InvariantCulture); var writer = new OpenApiJsonWriter(outputString, new() { Terse = produceTerseOutput }); // Act WriteValueRecursive(writer, inputMap); - var parsedObject = JsonConvert.DeserializeObject(outputString.GetStringBuilder().ToString()); - var expectedObject = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(inputMap)); + using var parsedObject = JsonDocument.Parse(outputString.GetStringBuilder().ToString()); + using var expectedObject = JsonDocument.Parse(JsonSerializer.Serialize(inputMap, _jsonSerializerOptions.Value)); // Assert - parsedObject.Should().BeEquivalentTo(expectedObject); + Assert.True(JsonElement.DeepEquals(parsedObject.RootElement, expectedObject.RootElement)); } public static IEnumerable WriteDateTimeAsJsonTestCases() @@ -248,6 +250,57 @@ from shouldBeTerse in shouldProduceTerseOutputValues select new object[] { input, shouldBeTerse }; } + public class CustomDateTimeOffsetConverter : JsonConverter + { + public CustomDateTimeOffsetConverter(string format) + { + ArgumentException.ThrowIfNullOrEmpty(format); + Format = format; + } + + public string Format { get; } + + public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return DateTime.ParseExact(reader.GetString(), Format, CultureInfo.InvariantCulture); + } + + public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString(Format)); + } + } + public class CustomDateTimeConverter : JsonConverter + { + public CustomDateTimeConverter(string format) + { + ArgumentException.ThrowIfNullOrEmpty(format); + Format = format; + } + + public string Format { get; } + + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return DateTime.ParseExact(reader.GetString(), Format, CultureInfo.InvariantCulture); + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString(Format)); + } + } + private static readonly Lazy _jsonSerializerOptions = new(() => + { + var options = new JsonSerializerOptions + { + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping + }; + options.Converters.Add(new CustomDateTimeOffsetConverter("yyyy-MM-ddTHH:mm:ss.fffffffK")); + options.Converters.Add(new CustomDateTimeConverter("yyyy-MM-ddTHH:mm:ss.fffffffK")); + return options; + }); + [Theory] [MemberData(nameof(WriteDateTimeAsJsonTestCases))] public void WriteDateTimeAsJsonShouldMatchExpected(DateTimeOffset dateTimeOffset, bool produceTerseOutput) @@ -260,10 +313,7 @@ public void WriteDateTimeAsJsonShouldMatchExpected(DateTimeOffset dateTimeOffset writer.WriteValue(dateTimeOffset); var writtenString = outputString.GetStringBuilder().ToString(); - var expectedString = JsonConvert.SerializeObject(dateTimeOffset, new JsonSerializerSettings - { - DateFormatString = "yyyy-MM-ddTHH:mm:ss.fffffffK", - }); + var expectedString = JsonSerializer.Serialize(dateTimeOffset, _jsonSerializerOptions.Value); // Assert writtenString.Should().Be(expectedString); From 36752ada9303a5113e1359e4ac1a267b8a4c8e49 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 02:14:47 +0300 Subject: [PATCH 010/127] chore(deps): bump Microsoft.Extensions.Logging, Microsoft.Extensions.Logging.Abstractions, Microsoft.Extensions.Logging.Console and System.Text.Json (#1932) Bumps [Microsoft.Extensions.Logging](https://github.com/dotnet/runtime), [Microsoft.Extensions.Logging.Abstractions](https://github.com/dotnet/runtime), [Microsoft.Extensions.Logging.Console](https://github.com/dotnet/runtime) and [System.Text.Json](https://github.com/dotnet/runtime). These dependencies needed to be updated together. Updates `Microsoft.Extensions.Logging` from 9.0.0 to 9.0.0 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v9.0.0...v9.0.0) Updates `Microsoft.Extensions.Logging.Abstractions` from 9.0.0 to 9.0.0 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v9.0.0...v9.0.0) Updates `Microsoft.Extensions.Logging.Console` from 8.0.1 to 9.0.0 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v8.0.1...v9.0.0) Updates `System.Text.Json` from 9.0.0 to 9.0.0 - [Release notes](https://github.com/dotnet/runtime/releases) - [Commits](https://github.com/dotnet/runtime/compare/v9.0.0...v9.0.0) --- updated-dependencies: - dependency-name: Microsoft.Extensions.Logging dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: Microsoft.Extensions.Logging.Abstractions dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: Microsoft.Extensions.Logging.Console dependency-type: direct:production update-type: version-update:semver-major - dependency-name: System.Text.Json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 995d50008..ec5d4c1cc 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -31,7 +31,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive From a44e7899968770b25cb9a2710b8fa6de8028e244 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Nov 2024 21:51:52 +0000 Subject: [PATCH 011/127] chore(deps): bump Verify.Xunit from 28.2.1 to 28.3.1 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 28.2.1 to 28.3.1. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/28.2.1...28.3.1) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index d71445022..c052fa1b7 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -14,7 +14,7 @@ - + From e1eafeadfee8b7830a26ba773ef72bb2bbd5b80c Mon Sep 17 00:00:00 2001 From: Mike Kistler Date: Sun, 17 Nov 2024 07:19:53 -0800 Subject: [PATCH 012/127] Fix link to OpenAPI specification --- src/Microsoft.OpenApi/Models/OpenApiDocument.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 0261fcff9..bf8458f2c 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -21,7 +21,7 @@ namespace Microsoft.OpenApi.Models { /// - /// Describes an OpenAPI object (OpenAPI document). See: https://swagger.io/specification + /// Describes an OpenAPI object (OpenAPI document). See: https://spec.openapis.org /// public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenApiAnnotatable { From 0cab0e724f70cdb702a67b7c46622b766bd0cd58 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 18 Nov 2024 14:35:28 +0300 Subject: [PATCH 013/127] Clean up tags serialization logic --- src/Microsoft.OpenApi/Models/OpenApiTag.cs | 46 +++------------------- 1 file changed, 6 insertions(+), 40 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiTag.cs b/src/Microsoft.OpenApi/Models/OpenApiTag.cs index 6f79e0999..51175cd12 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiTag.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiTag.cs @@ -64,47 +64,22 @@ public OpenApiTag(OpenApiTag tag) /// /// Serialize to Open Api v3.1 /// - public virtual void SerializeAsV31(IOpenApiWriter writer) + public virtual void SerializeAsV31(IOpenApiWriter writer) { - SerializeInternal(writer, (writer, element) => element.SerializeAsV31(writer)); - } - - /// - /// Serialize to Open Api v3.0 - /// - public virtual void SerializeAsV3(IOpenApiWriter writer) - { - SerializeInternal(writer, (writer, element) => element.SerializeAsV3(writer)); - } - - /// - /// Serialize to Open Api v3.0 - /// - private void SerializeInternal(IOpenApiWriter writer, Action callback) - { - Utils.CheckArgumentNull(writer); - writer.WriteValue(Name); - } - - /// - /// Serialize to OpenAPI V3 document without using reference. - /// - public virtual void SerializeAsV31WithoutReference(IOpenApiWriter writer) - { - SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_1, + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1, (writer, element) => element.SerializeAsV31(writer)); } /// - /// Serialize to OpenAPI V3 document without using reference. + /// Serialize to Open Api v3.0 /// - public virtual void SerializeAsV3WithoutReference(IOpenApiWriter writer) + public virtual void SerializeAsV3(IOpenApiWriter writer) { - SerializeInternalWithoutReference(writer, OpenApiSpecVersion.OpenApi3_0, + SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0, (writer, element) => element.SerializeAsV3(writer)); } - internal virtual void SerializeInternalWithoutReference(IOpenApiWriter writer, OpenApiSpecVersion version, + internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, Action callback) { writer.WriteStartObject(); @@ -128,15 +103,6 @@ internal virtual void SerializeInternalWithoutReference(IOpenApiWriter writer, O /// Serialize to Open Api v2.0 /// public virtual void SerializeAsV2(IOpenApiWriter writer) - { - Utils.CheckArgumentNull(writer); - writer.WriteValue(Name); - } - - /// - /// Serialize to OpenAPI V2 document without using reference. - /// - public void SerializeAsV2WithoutReference(IOpenApiWriter writer) { writer.WriteStartObject(); From 5a51460dbdbef7482c3acd9426a2000f476045dd Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 18 Nov 2024 14:36:03 +0300 Subject: [PATCH 014/127] Add test to validate --- .../Models/OpenApiDocumentTests.cs | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index 884ffa68c..1e9caeecd 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -992,7 +992,7 @@ public OpenApiDocumentTests() { ["my-extension"] = new OpenApiAny(4) } - }, + }, Extensions = new Dictionary { ["my-extension"] = new OpenApiAny(4), @@ -2072,5 +2072,59 @@ public void SerializeDocWithDollarIdInDollarRefSucceeds() var actual = doc.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_1); actual.MakeLineBreaksEnvironmentNeutral().Should().BeEquivalentTo(expected.MakeLineBreaksEnvironmentNeutral()); } + + [Fact] + public void SerializeDocumentTagsWithMultipleExtensionsWorks() + { + var expected = @"{ + ""openapi"": ""3.0.4"", + ""info"": { + ""title"": ""Test"", + ""version"": ""1.0.0"" + }, + ""paths"": { }, + ""tags"": [ + { + ""name"": ""tag1"", + ""x-tag1"": ""tag1"" + }, + { + ""name"": ""tag2"", + ""x-tag2"": ""tag2"" + } + ] +}"; + var doc = new OpenApiDocument + { + Info = new OpenApiInfo + { + Title = "Test", + Version = "1.0.0" + }, + Paths = new OpenApiPaths(), + Tags = new List + { + new OpenApiTag + { + Name = "tag1", + Extensions = new Dictionary + { + ["x-tag1"] = new OpenApiAny("tag1") + } + }, + new OpenApiTag + { + Name = "tag2", + Extensions = new Dictionary + { + ["x-tag2"] = new OpenApiAny("tag2") + } + } + } + }; + + var actual = doc.SerializeAsJson(OpenApiSpecVersion.OpenApi3_0); + actual.MakeLineBreaksEnvironmentNeutral().Should().BeEquivalentTo(expected.MakeLineBreaksEnvironmentNeutral()); + } } } From 262acd4b4c611dfb0e248e67858e5baa5a9acce3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 21:37:56 +0000 Subject: [PATCH 015/127] chore(deps): bump Verify.Xunit from 28.3.1 to 28.3.2 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 28.3.1 to 28.3.2. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/28.3.1...28.3.2) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index c052fa1b7..c1af0c914 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -14,7 +14,7 @@ - + From 66150791aabe593f479e0389f8f0fe05336a4caf Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 19 Nov 2024 13:15:39 +0300 Subject: [PATCH 016/127] Use range for STJ reference and suppress warnings --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 4 +++- .../Microsoft.OpenApi.Readers.csproj | 4 +++- src/Microsoft.OpenApi/Microsoft.OpenApi.csproj | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index ec5d4c1cc..1e4f0bc95 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -45,7 +45,9 @@ - + + + diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj index c67e68b2f..2d4f53610 100644 --- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj +++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj @@ -31,7 +31,9 @@ - + + + diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index a4ea950f2..070ca8108 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -22,7 +22,9 @@ true - + + + From c98ca2826ea1c2211d17f90308d555e60ec92934 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 19 Nov 2024 13:21:57 +0300 Subject: [PATCH 017/127] Revert change for hidi --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 1e4f0bc95..ec5d4c1cc 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -45,9 +45,7 @@ - - - + From b0a0e8ef2da22056bde57067e1d325c73b251df3 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 19 Nov 2024 19:54:04 +0300 Subject: [PATCH 018/127] Add const keyword and serialization logic --- src/Microsoft.OpenApi/Models/OpenApiConstants.cs | 5 +++++ src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 7 +++++++ .../Models/References/OpenApiSchemaReference.cs | 2 ++ 3 files changed, 14 insertions(+) diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs index c629f78be..8877faac8 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs @@ -50,6 +50,11 @@ public static class OpenApiConstants /// public const string Title = "title"; + /// + /// Field: Const + /// + public const string Const = "const"; + /// /// Field: Type /// diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index c2456286c..0215ac522 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -83,6 +83,11 @@ public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiRe /// public virtual JsonSchemaType? Type { get; set; } + /// + /// Follow JSON Schema definition: https://json-schema.org/draft/2020-12/json-schema-validation + /// + public virtual string Const { get; set; } + /// /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 /// While relying on JSON Schema's defined formats, @@ -347,6 +352,7 @@ public OpenApiSchema(OpenApiSchema schema) { Title = schema?.Title ?? Title; Id = schema?.Id ?? Id; + Const = schema?.Const ?? Const; Schema = schema?.Schema ?? Schema; Comment = schema?.Comment ?? Comment; Vocabulary = schema?.Vocabulary != null ? new Dictionary(schema.Vocabulary) : null; @@ -563,6 +569,7 @@ internal void WriteV31Properties(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.Id, Id); writer.WriteProperty(OpenApiConstants.DollarSchema, Schema); writer.WriteProperty(OpenApiConstants.Comment, Comment); + writer.WriteProperty(OpenApiConstants.Const, Const); writer.WriteOptionalMap(OpenApiConstants.Vocabulary, Vocabulary, (w, s) => w.WriteValue(s)); writer.WriteOptionalMap(OpenApiConstants.Defs, Definitions, (w, s) => s.SerializeAsV31(w)); writer.WriteProperty(OpenApiConstants.DynamicRef, DynamicRef); diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs index a7b55e109..a930ef3b5 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs @@ -90,6 +90,8 @@ internal OpenApiSchemaReference(OpenApiSchema target, string referenceId) /// public override JsonSchemaType? Type { get => Target.Type; set => Target.Type = value; } /// + public override string Const { get => Target.Const; set => Target.Const = value; } + /// public override string Format { get => Target.Format; set => Target.Format = value; } /// public override string Description From 067fbddde24b19fe646ed26959f349e3c1069312 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 19 Nov 2024 19:54:16 +0300 Subject: [PATCH 019/127] Deserialize const keyword --- src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs index 5dc76b7fb..9c035da0d 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs @@ -131,6 +131,10 @@ internal static partial class OpenApiV31Deserializer } } }, + { + "const", + (o, n, _) => o.Const = n.GetScalarValue() + }, { "allOf", (o, n, t) => o.AllOf = n.CreateList(LoadSchema, t) From 70c7d437b1d16c7607472c48d50a0da734ebc76e Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 19 Nov 2024 20:15:49 +0300 Subject: [PATCH 020/127] Add test and update API --- .../V31Tests/OpenApiSchemaTests.cs | 43 +++++++++++++++++++ .../OpenApiSchema/schemaWithConst.json | 21 +++++++++ .../PublicApi/PublicApi.approved.txt | 3 ++ 3 files changed, 67 insertions(+) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithConst.json diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs index 967bb0f3e..5f149b021 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs @@ -452,5 +452,48 @@ public void SerializeSchemaWithJsonSchemaKeywordsWorks() schema.Vocabulary.Keys.Count.Should().Be(5); schemaString.MakeLineBreaksEnvironmentNeutral().Should().Be(expected.MakeLineBreaksEnvironmentNeutral()); } + + [Fact] + public void ParseSchemaWithConstWorks() + { + var expected = @"{ + ""$schema"": ""https://json-schema.org/draft/2020-12/schema"", + ""required"": [ + ""status"" + ], + ""type"": ""object"", + ""properties"": { + ""status"": { + ""const"": ""active"", + ""type"": ""string"" + }, + ""user"": { + ""required"": [ + ""role"" + ], + ""type"": ""object"", + ""properties"": { + ""role"": { + ""const"": ""admin"", + ""type"": ""string"" + } + } + } + } +}"; + + var path = Path.Combine(SampleFolderPath, "schemaWithConst.json"); + + // Act + var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_1, out _); + schema.Properties["status"].Const.Should().Be("active"); + schema.Properties["user"].Properties["role"].Const.Should().Be("admin"); + + // serialization + var writer = new StringWriter(); + schema.SerializeAsV31(new OpenApiJsonWriter(writer)); + var schemaString = writer.ToString(); + schemaString.MakeLineBreaksEnvironmentNeutral().Should().Be(expected.MakeLineBreaksEnvironmentNeutral()); + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithConst.json b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithConst.json new file mode 100644 index 000000000..ec0a0c794 --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithConst.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "type": "object", + "properties": { + "status": { + "type": "string", + "const": "active" + }, + "user": { + "type": "object", + "properties": { + "role": { + "type": "string", + "const": "admin" + } + }, + "required": [ "role" ] + } + }, + "required": [ "status" ] +} diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 3fe034011..8f9f8ed41 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -398,6 +398,7 @@ namespace Microsoft.OpenApi.Models public const string Comment = "$comment"; public const string Components = "components"; public const string ComponentsSegment = "/components/"; + public const string Const = "const"; public const string Consumes = "consumes"; public const string Contact = "contact"; public const string Content = "content"; @@ -882,6 +883,7 @@ namespace Microsoft.OpenApi.Models public virtual System.Collections.Generic.IList AllOf { get; set; } public virtual System.Collections.Generic.IList AnyOf { get; set; } public virtual string Comment { get; set; } + public virtual string Const { get; set; } public virtual System.Text.Json.Nodes.JsonNode Default { get; set; } public virtual System.Collections.Generic.IDictionary Definitions { get; set; } public virtual bool Deprecated { get; set; } @@ -1222,6 +1224,7 @@ namespace Microsoft.OpenApi.Models.References public override System.Collections.Generic.IList AllOf { get; set; } public override System.Collections.Generic.IList AnyOf { get; set; } public override string Comment { get; set; } + public override string Const { get; set; } public override System.Text.Json.Nodes.JsonNode Default { get; set; } public override System.Collections.Generic.IDictionary Definitions { get; set; } public override bool Deprecated { get; set; } From 2630ebb7338af4d9d9442f6fedacc7253db57621 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:39:39 +0000 Subject: [PATCH 021/127] chore(deps): bump Microsoft.OData.Edm from 8.2.1 to 8.2.2 Bumps Microsoft.OData.Edm from 8.2.1 to 8.2.2. --- updated-dependencies: - dependency-name: Microsoft.OData.Edm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index ec5d4c1cc..2b0582db7 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -38,7 +38,7 @@ all - + From 36bc99085c9b1648c9b90cb837085ac0bb5c23b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:40:22 +0000 Subject: [PATCH 022/127] chore(deps): bump Microsoft.NET.Test.Sdk from 17.11.1 to 17.12.0 Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.11.1 to 17.12.0. - [Release notes](https://github.com/microsoft/vstest/releases) - [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md) - [Commits](https://github.com/microsoft/vstest/compare/v17.11.1...v17.12.0) --- updated-dependencies: - dependency-name: Microsoft.NET.Test.Sdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .../Microsoft.OpenApi.Hidi.Tests.csproj | 2 +- .../Microsoft.OpenApi.Readers.Tests.csproj | 2 +- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj index 07a571a57..7b214091d 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj +++ b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj @@ -12,7 +12,7 @@ - + diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index e528cdcd5..eeac984a0 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -17,7 +17,7 @@ - + diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index c1af0c914..68ed9fa2c 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -11,7 +11,7 @@ - + From 12ee205fd24c458a7570286b3e0c9c7fcb85e372 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 20 Nov 2024 11:23:34 +0300 Subject: [PATCH 023/127] refactor to use backing fields --- .../References/OpenApiSchemaReference.cs | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs index a930ef3b5..011e0b930 100644 --- a/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs +++ b/src/Microsoft.OpenApi/Models/References/OpenApiSchemaReference.cs @@ -17,6 +17,9 @@ public class OpenApiSchemaReference : OpenApiSchema internal OpenApiSchema _target; private readonly OpenApiReference _reference; private string _description; + private JsonNode _default; + private JsonNode _example; + private IList _examples; private OpenApiSchema Target { @@ -116,7 +119,11 @@ public override string Description /// public override decimal? MultipleOf { get => Target.MultipleOf; set => Target.MultipleOf = value; } /// - public override JsonNode Default { get => Target.Default; set => Target.Default = value; } + public override JsonNode Default + { + get => _default ??= Target.Default; + set => _default = value; + } /// public override bool ReadOnly { get => Target.ReadOnly; set => Target.ReadOnly = value; } /// @@ -154,9 +161,17 @@ public override string Description /// public override OpenApiDiscriminator Discriminator { get => Target.Discriminator; set => Target.Discriminator = value; } /// - public override JsonNode Example { get => Target.Example; set => Target.Example = value; } + public override JsonNode Example + { + get => _example ??= Target.Example; + set => _example = value; + } /// - public override IList Examples { get => Target.Examples; set => Target.Examples = value; } + public override IList Examples + { + get => _examples ??= Target.Examples; + set => Target.Examples = value; + } /// public override IList Enum { get => Target.Enum; set => Target.Enum = value; } /// From c1d831fcd3836413395bf0f4dcb89ba24a0584fc Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 20 Nov 2024 12:44:49 +0300 Subject: [PATCH 024/127] Clean up tests --- .../Models/OpenApiOperationTests.cs | 7 --- ...sync_produceTerseOutput=False.verified.txt | 10 +++- ...Async_produceTerseOutput=True.verified.txt | 2 +- ...sync_produceTerseOutput=False.verified.txt | 10 +++- ...Async_produceTerseOutput=True.verified.txt | 2 +- .../Models/OpenApiTagTests.cs | 47 +++++++++---------- .../PublicApi/PublicApi.approved.txt | 3 -- 7 files changed, 42 insertions(+), 39 deletions(-) diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs index a65bf24c5..5f6b5f4e7 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiOperationTests.cs @@ -89,11 +89,6 @@ public class OpenApiOperationTests { Tags = new List { - new() - { - Name = "tagName1", - Description = "tagDescription1", - }, new OpenApiTagReference("tagId1", null) }, Summary = "summary1", @@ -360,7 +355,6 @@ public void SerializeAdvancedOperationWithTagAndSecurityAsV3JsonWorks() """ { "tags": [ - "tagName1", "tagId1" ], "summary": "summary1", @@ -669,7 +663,6 @@ public void SerializeAdvancedOperationWithTagAndSecurityAsV2JsonWorks() """ { "tags": [ - "tagName1", "tagId1" ], "summary": "summary1", diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt index d3d287dca..2afa516e0 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWorksAsync_produceTerseOutput=False.verified.txt @@ -1 +1,9 @@ -"pet" \ No newline at end of file +{ + "name": "pet", + "description": "Pets operations", + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com" + }, + "x-tag-extension": null +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt index d3d287dca..f0a901938 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -"pet" \ No newline at end of file +{"name":"pet","description":"Pets operations","externalDocs":{"description":"Find more info here","url":"https://example.com"},"x-tag-extension":null} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt index d3d287dca..2afa516e0 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWorksAsync_produceTerseOutput=False.verified.txt @@ -1 +1,9 @@ -"pet" \ No newline at end of file +{ + "name": "pet", + "description": "Pets operations", + "externalDocs": { + "description": "Find more info here", + "url": "https://example.com" + }, + "x-tag-extension": null +} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt index d3d287dca..f0a901938 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWorksAsync_produceTerseOutput=True.verified.txt @@ -1 +1 @@ -"pet" \ No newline at end of file +{"name":"pet","description":"Pets operations","externalDocs":{"description":"Find more info here","url":"https://example.com"},"x-tag-extension":null} \ No newline at end of file diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs index c02f7598c..d685be00d 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs @@ -8,6 +8,7 @@ using FluentAssertions; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Writers; using VerifyXunit; using Xunit; @@ -30,21 +31,7 @@ public class OpenApiTagTests } }; - public static OpenApiTag ReferencedTag = new() - { - Name = "pet", - Description = "Pets operations", - ExternalDocs = OpenApiExternalDocsTests.AdvanceExDocs, - Extensions = new Dictionary - { - {"x-tag-extension", null} - }, - Reference = new() - { - Type = ReferenceType.Tag, - Id = "pet" - } - }; + public static OpenApiTag ReferencedTag = new OpenApiTagReference("pet", null); [Theory] [InlineData(true)] @@ -56,7 +43,7 @@ public async Task SerializeBasicTagAsV3JsonWithoutReferenceWorksAsync(bool produ var writer = new OpenApiJsonWriter(outputStringWriter, new() { Terse = produceTerseOutput }); // Act - BasicTag.SerializeAsV3WithoutReference(writer); + BasicTag.SerializeAsV3(writer); writer.Flush(); // Assert @@ -73,7 +60,7 @@ public async Task SerializeBasicTagAsV2JsonWithoutReferenceWorksAsync(bool produ var writer = new OpenApiJsonWriter(outputStringWriter, new() { Terse = produceTerseOutput }); // Act - BasicTag.SerializeAsV2WithoutReference(writer); + BasicTag.SerializeAsV2(writer); writer.Flush(); // Assert @@ -89,7 +76,7 @@ public void SerializeBasicTagAsV3YamlWithoutReferenceWorks() var expected = "{ }"; // Act - BasicTag.SerializeAsV3WithoutReference(writer); + BasicTag.SerializeAsV3(writer); var actual = outputStringWriter.GetStringBuilder().ToString(); // Assert @@ -107,7 +94,7 @@ public void SerializeBasicTagAsV2YamlWithoutReferenceWorks() var expected = "{ }"; // Act - BasicTag.SerializeAsV2WithoutReference(writer); + BasicTag.SerializeAsV2(writer); writer.Flush(); var actual = outputStringWriter.GetStringBuilder().ToString(); @@ -127,7 +114,7 @@ public async Task SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync(bool pr var writer = new OpenApiJsonWriter(outputStringWriter, new() { Terse = produceTerseOutput }); // Act - AdvancedTag.SerializeAsV3WithoutReference(writer); + AdvancedTag.SerializeAsV3(writer); writer.Flush(); // Assert @@ -144,7 +131,7 @@ public async Task SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync(bool pr var writer = new OpenApiJsonWriter(outputStringWriter, new() { Terse = produceTerseOutput }); // Act - AdvancedTag.SerializeAsV2WithoutReference(writer); + AdvancedTag.SerializeAsV2(writer); writer.Flush(); // Assert @@ -168,7 +155,7 @@ public void SerializeAdvancedTagAsV3YamlWithoutReferenceWorks() """; // Act - AdvancedTag.SerializeAsV3WithoutReference(writer); + AdvancedTag.SerializeAsV3(writer); writer.Flush(); var actual = outputStringWriter.GetStringBuilder().ToString(); @@ -195,7 +182,7 @@ public void SerializeAdvancedTagAsV2YamlWithoutReferenceWorks() """; // Act - AdvancedTag.SerializeAsV2WithoutReference(writer); + AdvancedTag.SerializeAsV2(writer); writer.Flush(); var actual = outputStringWriter.GetStringBuilder().ToString(); @@ -246,7 +233,12 @@ public void SerializeAdvancedTagAsV3YamlWorks() var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); var writer = new OpenApiYamlWriter(outputStringWriter); - var expected = @" pet"; + var expected = @"name: pet +description: Pets operations +externalDocs: + description: Find more info here + url: https://example.com +x-tag-extension:"; // Act AdvancedTag.SerializeAsV3(writer); @@ -266,7 +258,12 @@ public void SerializeAdvancedTagAsV2YamlWorks() var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); var writer = new OpenApiYamlWriter(outputStringWriter); - var expected = @" pet"; + var expected = @"name: pet +description: Pets operations +externalDocs: + description: Find more info here + url: https://example.com +x-tag-extension:"; // Act AdvancedTag.SerializeAsV2(writer); diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 3fe034011..f25547338 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -995,11 +995,8 @@ namespace Microsoft.OpenApi.Models public virtual Microsoft.OpenApi.Models.OpenApiExternalDocs ExternalDocs { get; set; } public virtual string Name { get; set; } public virtual void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public void SerializeAsV2WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public virtual void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public virtual void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV31WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } - public virtual void SerializeAsV3WithoutReference(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } } public class OpenApiXml : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { From 03edbc95184ce975f37d74a5826da6db737c822f Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 25 Nov 2024 13:46:24 +0300 Subject: [PATCH 025/127] Allow empty paths object as valid --- src/Microsoft.OpenApi/Reader/ParsingContext.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/ParsingContext.cs b/src/Microsoft.OpenApi/Reader/ParsingContext.cs index aae60da9d..7a8b07244 100644 --- a/src/Microsoft.OpenApi/Reader/ParsingContext.cs +++ b/src/Microsoft.OpenApi/Reader/ParsingContext.cs @@ -271,9 +271,9 @@ public void PopLoop(string loopid) private void ValidateRequiredFields(OpenApiDocument doc, string version) { - if ((version.is2_0() || version.is3_0()) && (doc.Paths == null || !doc.Paths.Any())) + if ((version.is2_0() || version.is3_0()) && (doc.Paths == null)) { - // paths is a required field in OpenAPI 3.0 but optional in 3.1 + // paths is a required field in OpenAPI 2.0 and 3.0 but optional in 3.1 RootNode.Context.Diagnostic.Errors.Add(new OpenApiError("", $"Paths is a REQUIRED field at {RootNode.Context.GetLocation()}")); } } From 1af4f13158aae6bed57a210b15f9d997b7f45319 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 25 Nov 2024 13:46:44 +0300 Subject: [PATCH 026/127] Add test to validate; clean up tests --- .../OpenApiDiagnosticTests.cs | 5 +-- .../ParseNodeTests.cs | 3 +- .../V2Tests/OpenApiDocumentTests.cs | 11 +----- .../V2Tests/OpenApiServerTests.cs | 3 +- .../V3Tests/OpenApiDocumentTests.cs | 37 ++++++------------- .../V3Tests/OpenApiSchemaTests.cs | 6 +-- .../OpenApiDocument/docWithEmptyPaths.yaml | 5 +++ 7 files changed, 21 insertions(+), 49 deletions(-) create mode 100644 test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithEmptyPaths.yaml diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs index 5ecd58071..c99cc6fa9 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs @@ -56,10 +56,7 @@ public async Task DiagnosticReportMergedForExternalReferenceAsync() Assert.NotNull(result); Assert.NotNull(result.OpenApiDocument.Workspace); - result.OpenApiDiagnostic.Errors.Should().BeEquivalentTo(new List - { - new OpenApiError("", "[File: ./TodoReference.yaml] Paths is a REQUIRED field at #/") - }); + result.OpenApiDiagnostic.Errors.Should().BeEmpty(); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/ParseNodeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/ParseNodeTests.cs index 3f7c669b0..7c43ed124 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/ParseNodeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/ParseNodeTests.cs @@ -34,8 +34,7 @@ public void BrokenSimpleList() var result = OpenApiDocument.Parse(input, "yaml"); result.OpenApiDiagnostic.Errors.Should().BeEquivalentTo(new List() { - new OpenApiError(new OpenApiReaderException("Expected a value.")), - new OpenApiError("", "Paths is a REQUIRED field at #/") + new OpenApiError(new OpenApiReaderException("Expected a value.")) }); } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index 596269644..c97fd1aee 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -96,16 +96,7 @@ public void ParseDocumentWithDifferentCultureShouldSucceed(string culture) .Excluding((IMemberInfo memberInfo) => memberInfo.Path.EndsWith("Parent")) .Excluding((IMemberInfo memberInfo) => - memberInfo.Path.EndsWith("Root"))); - - result.OpenApiDiagnostic.Should().BeEquivalentTo( - new OpenApiDiagnostic { - SpecificationVersion = OpenApiSpecVersion.OpenApi2_0, - Errors = new List() - { - new OpenApiError("", "Paths is a REQUIRED field at #/") - } - }); + memberInfo.Path.EndsWith("Root")));; } [Fact] diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs index 2e5779adb..775145794 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs @@ -310,8 +310,7 @@ public void InvalidHostShouldYieldError() { Errors = { - new OpenApiError("#/", "Invalid host"), - new OpenApiError("", "Paths is a REQUIRED field at #/") + new OpenApiError("#/", "Invalid host") }, SpecificationVersion = OpenApiSpecVersion.OpenApi2_0 }); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 1382d0248..2d3b02820 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -101,11 +101,7 @@ public void ParseDocumentFromInlineStringShouldSucceed() result.OpenApiDiagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { - SpecificationVersion = OpenApiSpecVersion.OpenApi3_0, - Errors = new List() - { - new OpenApiError("", "Paths is a REQUIRED field at #/") - } + SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); } @@ -115,16 +111,7 @@ public void ParseBasicDocumentWithMultipleServersShouldSucceed() var path = System.IO.Path.Combine(SampleFolderPath, "basicDocumentWithMultipleServers.yaml"); var result = OpenApiDocument.Load(path); - result.OpenApiDiagnostic.Should().BeEquivalentTo( - new OpenApiDiagnostic() - { - SpecificationVersion = OpenApiSpecVersion.OpenApi3_0, - Errors = new List() - { - new OpenApiError("", "Paths is a REQUIRED field at #/") - } - }); - + result.OpenApiDiagnostic.Errors.Should().BeEmpty(); result.OpenApiDocument.Should().BeEquivalentTo( new OpenApiDocument { @@ -170,7 +157,6 @@ public void ParseBrokenMinimalDocumentShouldYieldExpectedDiagnostic() { Errors = { - new OpenApiError("", "Paths is a REQUIRED field at #/"), new OpenApiValidatorError(nameof(OpenApiInfoRules.InfoRequiredFields),"#/info/title", "The field 'title' in 'info' object is REQUIRED.") }, SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 @@ -196,11 +182,7 @@ public void ParseMinimalDocumentShouldSucceed() result.OpenApiDiagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { - SpecificationVersion = OpenApiSpecVersion.OpenApi3_0, - Errors = new List() - { - new OpenApiError("", "Paths is a REQUIRED field at #/") - } + SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); } @@ -1388,11 +1370,7 @@ public void ParseBasicDocumentWithServerVariableShouldSucceed() result.OpenApiDiagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic { - SpecificationVersion = OpenApiSpecVersion.OpenApi3_0, - Errors = new List() - { - new OpenApiError("", "Paths is a REQUIRED field at #/") - } + SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); result.OpenApiDocument.Should().BeEquivalentTo(expected, options => options.Excluding(x => x.BaseUri)); @@ -1417,5 +1395,12 @@ public void ParseBasicDocumentWithServerVariableAndNoDefaultShouldFail() result.OpenApiDiagnostic.Errors.Should().NotBeEmpty(); } + + [Fact] + public void ParseDocumentWithEmptyPathsSucceeds() + { + var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "docWithEmptyPaths.yaml")); + result.OpenApiDiagnostic.Errors.Should().BeEmpty(); + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs index 81cb4376b..6c1370626 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs @@ -241,11 +241,7 @@ public void ParseBasicSchemaWithReferenceShouldSucceed() result.OpenApiDiagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { - SpecificationVersion = OpenApiSpecVersion.OpenApi3_0, - Errors = new List() - { - new OpenApiError("", "Paths is a REQUIRED field at #/") - } + SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); var expectedComponents = new OpenApiComponents diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithEmptyPaths.yaml b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithEmptyPaths.yaml new file mode 100644 index 000000000..a325ad743 --- /dev/null +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/Samples/OpenApiDocument/docWithEmptyPaths.yaml @@ -0,0 +1,5 @@ +openapi: 3.0.0 +info: + title: Sample API + version: 1.0.0 +paths: {} \ No newline at end of file From cbc99c16aaa978013b5545223d2b7aa69f598f8f Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 25 Nov 2024 15:03:20 +0300 Subject: [PATCH 027/127] Use the selected format label --- src/Microsoft.OpenApi.Workbench/MainModel.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi.Workbench/MainModel.cs b/src/Microsoft.OpenApi.Workbench/MainModel.cs index d518645a5..96d40e472 100644 --- a/src/Microsoft.OpenApi.Workbench/MainModel.cs +++ b/src/Microsoft.OpenApi.Workbench/MainModel.cs @@ -257,8 +257,7 @@ internal async Task ParseDocumentAsync() } } - var format = OpenApiModelFactory.GetFormat(_inputFile); - var readResult = await OpenApiDocument.LoadAsync(stream, format); + var readResult = await OpenApiDocument.LoadAsync(stream, Format.GetDisplayName()); var document = readResult.OpenApiDocument; var context = readResult.OpenApiDiagnostic; From 9b237c664dbf9c10ea45e4b7caaf068b0c8ed1d8 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 25 Nov 2024 17:16:57 +0300 Subject: [PATCH 028/127] Suppress warnings --- .../Microsoft.OpenApi.Workbench.csproj | 1 + .../Microsoft.OpenApi.Trimming.Tests.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj b/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj index 3210463df..ab6c09b54 100644 --- a/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj +++ b/src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj @@ -6,6 +6,7 @@ true true true + NU1903 diff --git a/test/Microsoft.OpenApi.Trimming.Tests/Microsoft.OpenApi.Trimming.Tests.csproj b/test/Microsoft.OpenApi.Trimming.Tests/Microsoft.OpenApi.Trimming.Tests.csproj index 3e6daf74c..08f51d715 100644 --- a/test/Microsoft.OpenApi.Trimming.Tests/Microsoft.OpenApi.Trimming.Tests.csproj +++ b/test/Microsoft.OpenApi.Trimming.Tests/Microsoft.OpenApi.Trimming.Tests.csproj @@ -7,6 +7,7 @@ true false true + NU1903 false From 171241e228819f23f9c146333d200d9cb4a10c68 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 25 Nov 2024 17:32:53 +0300 Subject: [PATCH 029/127] make property and method static --- src/Microsoft.OpenApi.Workbench/MainModel.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi.Workbench/MainModel.cs b/src/Microsoft.OpenApi.Workbench/MainModel.cs index 96d40e472..356e42fc2 100644 --- a/src/Microsoft.OpenApi.Workbench/MainModel.cs +++ b/src/Microsoft.OpenApi.Workbench/MainModel.cs @@ -49,7 +49,7 @@ public class MainModel : INotifyPropertyChanged /// private OpenApiSpecVersion _version = OpenApiSpecVersion.OpenApi3_0; - private HttpClient _httpClient = new(); + private static readonly HttpClient _httpClient = new(); public string Input { @@ -331,7 +331,7 @@ private string WriteContents(OpenApiDocument document) return new StreamReader(outputStream).ReadToEnd(); } - private MemoryStream CreateStream(string text) + private static MemoryStream CreateStream(string text) { var stream = new MemoryStream(); var writer = new StreamWriter(stream); From 506ef1f3f0fa262fd790e9155d173808719fcb61 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 25 Nov 2024 18:09:51 +0300 Subject: [PATCH 030/127] clean up code --- src/Microsoft.OpenApi.Workbench/MainModel.cs | 33 ++++++-------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/src/Microsoft.OpenApi.Workbench/MainModel.cs b/src/Microsoft.OpenApi.Workbench/MainModel.cs index 356e42fc2..2fdaf0e1c 100644 --- a/src/Microsoft.OpenApi.Workbench/MainModel.cs +++ b/src/Microsoft.OpenApi.Workbench/MainModel.cs @@ -166,31 +166,31 @@ public OpenApiSpecVersion Version public bool IsYaml { get => Format == OpenApiFormat.Yaml; - set => Format = OpenApiFormat.Yaml; + set => Format = value ? OpenApiFormat.Yaml : Format; } public bool IsJson { get => Format == OpenApiFormat.Json; - set => Format = OpenApiFormat.Json; + set => Format = value ? OpenApiFormat.Json : Format; } public bool IsV2_0 { get => Version == OpenApiSpecVersion.OpenApi2_0; - set => Version = OpenApiSpecVersion.OpenApi2_0; + set => Version = value ? OpenApiSpecVersion.OpenApi2_0 : Version; } public bool IsV3_0 { get => Version == OpenApiSpecVersion.OpenApi3_0; - set => Version = OpenApiSpecVersion.OpenApi3_0; + set => Version = value ? OpenApiSpecVersion.OpenApi3_0 : Version; } public bool IsV3_1 { get => Version == OpenApiSpecVersion.OpenApi3_1; - set => Version = OpenApiSpecVersion.OpenApi3_1; + set => Version = value ? OpenApiSpecVersion.OpenApi3_1 : Version; } /// @@ -219,14 +219,8 @@ internal async Task ParseDocumentAsync() { if (!string.IsNullOrWhiteSpace(_inputFile)) { - if (_inputFile.StartsWith("http")) - { - stream = await _httpClient.GetStreamAsync(_inputFile); - } - else - { - stream = new FileStream(_inputFile, FileMode.Open); - } + stream = _inputFile.StartsWith("http") ? await _httpClient.GetStreamAsync(_inputFile) + : new FileStream(_inputFile, FileMode.Open); } else { @@ -245,16 +239,10 @@ internal async Task ParseDocumentAsync() ReferenceResolution = ResolveExternal ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences, RuleSet = ValidationRuleSet.GetDefaultRuleSet() }; - if (ResolveExternal) + if (ResolveExternal && !string.IsNullOrWhiteSpace(_inputFile)) { - if (_inputFile.StartsWith("http")) - { - settings.BaseUrl = new(_inputFile); - } - else - { - settings.BaseUrl = new("file://" + Path.GetDirectoryName(_inputFile) + "/"); - } + settings.BaseUrl = _inputFile.StartsWith("http") ? new(_inputFile) + : new("file://" + Path.GetDirectoryName(_inputFile) + "/"); } var readResult = await OpenApiDocument.LoadAsync(stream, Format.GetDisplayName()); @@ -305,7 +293,6 @@ internal async Task ParseDocumentAsync() stream.Close(); await stream.DisposeAsync(); } - } } From a648591c6dc75f111218d8ec46d8e52812bc0017 Mon Sep 17 00:00:00 2001 From: Darrel Miller Date: Mon, 25 Nov 2024 23:42:06 -0500 Subject: [PATCH 031/127] Refactor readers to reduce surface area --- .../OpenApiYamlReader.cs | 33 +++-- .../Interfaces/IOpenApiReader.cs | 19 ++- .../Models/OpenApiDocument.cs | 27 +--- .../Reader/OpenApiJsonReader.cs | 77 +++++++---- .../Reader/OpenApiModelFactory.cs | 124 +++++++----------- .../V31Tests/OpenApiSchemaTests.cs | 9 ++ .../V3Tests/OpenApiDiscriminatorTests.cs | 8 +- 7 files changed, 154 insertions(+), 143 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index cff6dd1da..1a85e6a27 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -19,17 +19,34 @@ namespace Microsoft.OpenApi.Readers /// public class OpenApiYamlReader : IOpenApiReader { + private const int copyBufferSize = 4096; + /// - public async Task ReadAsync(TextReader input, + public async Task ReadAsync(Stream input, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) + { + if (input is MemoryStream memoryStream) + { + return Read(memoryStream, settings); + } else { + using var preparedStream = new MemoryStream(); + await input.CopyToAsync(preparedStream, copyBufferSize, cancellationToken); + preparedStream.Position = 0; + return Read(preparedStream, settings); + } + } + + /// + public ReadResult Read(MemoryStream input, + OpenApiReaderSettings settings = null) { JsonNode jsonNode; // Parse the YAML text in the TextReader into a sequence of JsonNodes try { - jsonNode = LoadJsonNodesFromYamlDocument(input); + jsonNode = LoadJsonNodesFromYamlDocument(new StreamReader(input)); // Should we leave the stream open? } catch (JsonException ex) { @@ -42,11 +59,11 @@ public async Task ReadAsync(TextReader input, }; } - return await ReadAsync(jsonNode, settings, cancellationToken: cancellationToken); + return Read(jsonNode, settings); } /// - public T ReadFragment(TextReader input, + public T ReadFragment(MemoryStream input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement @@ -56,7 +73,7 @@ public T ReadFragment(TextReader input, // Parse the YAML try { - jsonNode = LoadJsonNodesFromYamlDocument(input); + jsonNode = LoadJsonNodesFromYamlDocument(new StreamReader(input)); } catch (JsonException ex) { @@ -81,10 +98,10 @@ static JsonNode LoadJsonNodesFromYamlDocument(TextReader input) return yamlDocument.ToJsonNode(); } - /// - public async Task ReadAsync(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null, CancellationToken cancellationToken = default) + /// + public ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null) { - return await OpenApiReaderRegistry.DefaultReader.ReadAsync(jsonNode, settings, OpenApiConstants.Yaml, cancellationToken); + return OpenApiReaderRegistry.DefaultReader.Read(jsonNode, settings, OpenApiConstants.Yaml); } /// diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs index 5f8b1cb22..b746b857b 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs @@ -15,33 +15,40 @@ namespace Microsoft.OpenApi.Interfaces public interface IOpenApiReader { /// - /// Reads the TextReader input and parses it into an Open API document. + /// Async method to reads the stream and parse it into an Open API document. /// /// The TextReader input. /// The OpenApi reader settings. /// Propagates notification that an operation should be cancelled. /// - Task ReadAsync(TextReader input, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default); + Task ReadAsync(Stream input, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default); + + /// + /// Provides a synchronous method to read the input memory stream and parse it into an Open API document. + /// + /// + /// + /// + ReadResult Read(MemoryStream input, OpenApiReaderSettings settings = null); /// /// Parses the JsonNode input into an Open API document. /// /// The JsonNode input. /// The Reader settings to be used during parsing. - /// Propagates notifications that operations should be cancelled. /// The OpenAPI format. /// - Task ReadAsync(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null, CancellationToken cancellationToken = default); + ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null); /// - /// Reads the TextReader input and parses the fragment of an OpenAPI description into an Open API Element. + /// Reads the MemoryStream and parses the fragment of an OpenAPI description into an Open API Element. /// /// TextReader containing OpenAPI description to parse. /// Version of the OpenAPI specification that the fragment conforms to. /// Returns diagnostic object containing errors detected during parsing. /// The OpenApiReader settings. /// Instance of newly created IOpenApiElement. - T ReadFragment(TextReader input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement; + T ReadFragment(MemoryStream input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement; /// /// Reads the JsonNode input and parses the fragment of an OpenAPI description into an Open API Element. diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index bf8458f2c..a41e7ca6b 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -553,27 +553,13 @@ public static ReadResult Load(string url, OpenApiReaderSettings? settings = null /// The OpenAPI format to use during parsing. /// The OpenApi reader settings. /// - public static ReadResult Load(Stream stream, + public static ReadResult Load(MemoryStream stream, string format, OpenApiReaderSettings? settings = null) { return OpenApiModelFactory.Load(stream, format, settings); } - /// - /// Reads the text reader content and parses it into an Open API document. - /// - /// TextReader containing OpenAPI description to parse. - /// The OpenAPI format to use during parsing. - /// The OpenApi reader settings. - /// - public static ReadResult Load(TextReader input, - string format, - OpenApiReaderSettings? settings = null) - { - return OpenApiModelFactory.Load(input, format, settings); - } - /// /// Parses a local file path or Url into an Open API document. /// @@ -598,17 +584,6 @@ public static async Task LoadAsync(Stream stream, string format, Ope return await OpenApiModelFactory.LoadAsync(stream, format, settings, cancellationToken); } - /// - /// Reads the text reader content and parses it into an Open API document. - /// - /// TextReader containing OpenAPI description to parse. - /// The OpenAPI format to use during parsing. - /// The OpenApi reader settings. - /// - public static async Task LoadAsync(TextReader input, string format, OpenApiReaderSettings? settings = null) - { - return await OpenApiModelFactory.LoadAsync(input, format, settings); - } /// /// Parses a string into a object. diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 27aad722e..568c94832 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -24,14 +24,47 @@ namespace Microsoft.OpenApi.Reader /// public class OpenApiJsonReader : IOpenApiReader { + /// - /// Reads the stream input and parses it into an Open API document. + /// Reads the memory stream input and parses it into an Open API document. + /// + /// TextReader containing OpenAPI description to parse. + /// The Reader settings to be used during parsing. + /// + public ReadResult Read(MemoryStream input, + OpenApiReaderSettings settings = null) + { + JsonNode jsonNode; + var diagnostic = new OpenApiDiagnostic(); + settings ??= new OpenApiReaderSettings(); + + // Parse the JSON text in the TextReader into JsonNodes + try + { + jsonNode = JsonNode.Parse(input); + } + catch (JsonException ex) + { + diagnostic.Errors.Add(new OpenApiError($"#line={ex.LineNumber}", $"Please provide the correct format, {ex.Message}")); + return new ReadResult + { + OpenApiDocument = null, + OpenApiDiagnostic = diagnostic + }; + } + + return Read(jsonNode, settings); + } + + + /// + /// Reads the stream input asynchronously and parses it into an Open API document. /// /// TextReader containing OpenAPI description to parse. /// The Reader settings to be used during parsing. /// Propagates notifications that operations should be cancelled. /// - public async Task ReadAsync(TextReader input, + public async Task ReadAsync(Stream input, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) { @@ -42,7 +75,7 @@ public async Task ReadAsync(TextReader input, // Parse the JSON text in the TextReader into JsonNodes try { - jsonNode = LoadJsonNodes(input); + jsonNode = await JsonNode.ParseAsync(input);; } catch (JsonException ex) { @@ -54,7 +87,7 @@ public async Task ReadAsync(TextReader input, }; } - return await ReadAsync(jsonNode, settings, cancellationToken: cancellationToken); + return Read(jsonNode, settings); } /// @@ -63,12 +96,10 @@ public async Task ReadAsync(TextReader input, /// The JsonNode input. /// The Reader settings to be used during parsing. /// The OpenAPI format. - /// Propagates notifications that operations should be cancelled. /// - public async Task ReadAsync(JsonNode jsonNode, + public ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, - string format = null, - CancellationToken cancellationToken = default) + string format = null) { var diagnostic = new OpenApiDiagnostic(); var context = new ParsingContext(diagnostic) @@ -84,16 +115,16 @@ public async Task ReadAsync(JsonNode jsonNode, // Parse the OpenAPI Document document = context.Parse(jsonNode); - if (settings.LoadExternalRefs) - { - var diagnosticExternalRefs = await LoadExternalRefsAsync(document, cancellationToken, settings, format); - // Merge diagnostics of external reference - if (diagnosticExternalRefs != null) - { - diagnostic.Errors.AddRange(diagnosticExternalRefs.Errors); - diagnostic.Warnings.AddRange(diagnosticExternalRefs.Warnings); - } - } + // if (settings.LoadExternalRefs) + // { + // var diagnosticExternalRefs = await LoadExternalRefsAsync(document, cancellationToken, settings, format); + // // Merge diagnostics of external reference + // if (diagnosticExternalRefs != null) + // { + // diagnostic.Errors.AddRange(diagnosticExternalRefs.Errors); + // diagnostic.Warnings.AddRange(diagnosticExternalRefs.Warnings); + // } + // } document.SetReferenceHostDocument(); } @@ -124,7 +155,7 @@ public async Task ReadAsync(JsonNode jsonNode, } /// - public T ReadFragment(TextReader input, + public T ReadFragment(MemoryStream input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement @@ -134,7 +165,7 @@ public T ReadFragment(TextReader input, // Parse the JSON try { - jsonNode = LoadJsonNodes(input); + jsonNode = JsonNode.Parse(input); } catch (JsonException ex) { @@ -183,12 +214,6 @@ public T ReadFragment(JsonNode input, return (T)element; } - private JsonNode LoadJsonNodes(TextReader input) - { - var nodes = JsonNode.Parse(input.ReadToEnd()); - return nodes; - } - private async Task LoadExternalRefsAsync(OpenApiDocument document, CancellationToken cancellationToken, OpenApiReaderSettings settings, string format = null) { // Create workspace for all documents to live in. diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index ddabdc6be..ad5d09968 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -2,10 +2,12 @@ // Licensed under the MIT license. using System; +using System.Buffers.Text; using System.IO; using System.Linq; using System.Net.Http; using System.Security; +using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.OpenApi.Interfaces; @@ -45,15 +47,13 @@ public static ReadResult Load(string url, OpenApiReaderSettings settings = null) /// The OpenApi reader settings. /// The OpenAPI format. /// An OpenAPI document instance. - public static ReadResult Load(Stream stream, + public static ReadResult Load(MemoryStream stream, string format, OpenApiReaderSettings settings = null) { settings ??= new OpenApiReaderSettings(); -#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits - var result = LoadAsync(stream, format, settings).GetAwaiter().GetResult(); -#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + var result = InternalLoad(stream, format, settings); if (!settings.LeaveStreamOpen) { @@ -63,22 +63,6 @@ public static ReadResult Load(Stream stream, return result; } - /// - /// Loads the TextReader input and parses it into an Open API document. - /// - /// The TextReader input. - /// The OpenApi reader settings. - /// The Open API format - /// An OpenAPI document instance. - public static ReadResult Load(TextReader input, - string format, - OpenApiReaderSettings settings = null) - { -#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits - var result = LoadAsync(input, format, settings).GetAwaiter().GetResult(); -#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits - return result; - } /// /// Loads the input URL and parses it into an Open API document. @@ -89,12 +73,12 @@ public static ReadResult Load(TextReader input, public static async Task LoadAsync(string url, OpenApiReaderSettings settings = null) { var format = GetFormat(url); - var stream = await GetStreamAsync(url); + var stream = await GetStreamAsync(url); // Get response back and then get Content return await LoadAsync(stream, format, settings); } /// - /// Loads the input stream and parses it into an Open API document. + /// Loads the input stream and parses it into an Open API document. If the stream is not buffered and it contains yaml, it will be buffered before parsing. /// /// The input stream. /// The OpenApi reader settings. @@ -122,24 +106,7 @@ public static async Task LoadAsync(Stream input, string format, Open } // Use StreamReader to process the prepared stream (buffered for YAML, direct for JSON) - using var reader = new StreamReader(preparedStream, default, true, -1, settings.LeaveStreamOpen); - return await LoadAsync(reader, format, settings, cancellationToken); - } - - - /// - /// Loads the TextReader input and parses it into an Open API document. - /// - /// The TextReader input. - /// The Open API format - /// The OpenApi reader settings. - /// Propagates notification that operations should be cancelled. - /// - public static async Task LoadAsync(TextReader input, string format, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) - { - Utils.CheckArgumentNull(format, nameof(format)); - var reader = OpenApiReaderRegistry.GetReader(format); - return await reader.ReadAsync(input, settings, cancellationToken); + return await InternalLoadAsync(preparedStream, format, settings, cancellationToken); } /// @@ -155,29 +122,30 @@ public static ReadResult Parse(string input, { format ??= OpenApiConstants.Json; settings ??= new OpenApiReaderSettings(); - using var reader = new StringReader(input); -#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits - return ParseAsync(input, reader, format, settings).GetAwaiter().GetResult(); -#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits + // Copy string into MemoryStream + var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); + + return InternalLoad(stream, format, settings); } - /// - /// An Async method to prevent synchornously blocking the calling thread. - /// - /// - /// - /// - /// - /// - public static async Task ParseAsync(string input, - StringReader reader, - string format = null, - OpenApiReaderSettings settings = null) + private static async Task InternalLoadAsync(Stream input, string format, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) { - return await LoadAsync(reader, format, settings); + Utils.CheckArgumentNull(format, nameof(format)); + var reader = OpenApiReaderRegistry.GetReader(format); + var readResult = await reader.ReadAsync(input, settings, cancellationToken); + return readResult; } + private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings = null) + { + Utils.CheckArgumentNull(format, nameof(format)); + var reader = OpenApiReaderRegistry.GetReader(format); + var readResult = reader.Read(input, settings); + return readResult; + } + + /// /// Reads the input string and parses it into an Open API document. /// @@ -195,8 +163,8 @@ public static T Parse(string input, { format ??= OpenApiConstants.Json; settings ??= new OpenApiReaderSettings(); - using var reader = new StringReader(input); - return Load(reader, version, out diagnostic, format, settings); + var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); + return Load(stream, version, format, out diagnostic, settings); } /// @@ -218,45 +186,51 @@ public static T Load(string url, OpenApiSpecVersion version, out OpenApiDiagn var stream = GetStreamAsync(url).GetAwaiter().GetResult(); #pragma warning restore VSTHRD002 // Avoid problematic synchronous waits - return Load(stream, version, format, out diagnostic, settings); + return Load(stream as MemoryStream, version, format, out diagnostic, settings); } + /// - /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element. + /// Reads the stream input and ensures it is buffered before passing it to the Load method. /// /// - /// Stream containing OpenAPI description to parse. - /// Version of the OpenAPI specification that the fragment conforms to. + /// + /// /// - /// Returns diagnostic object containing errors detected during parsing. - /// The OpenApiReader settings. - /// Instance of newly created IOpenApiElement. - /// The OpenAPI element. + /// + /// + /// public static T Load(Stream input, OpenApiSpecVersion version, string format, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement { - format ??= OpenApiConstants.Json; - using var reader = new StreamReader(input); - return Load(reader, version, out diagnostic, format, settings); + if (input is MemoryStream memoryStream) + { + return Load(memoryStream, version, format, out diagnostic, settings); + } else { + memoryStream = new MemoryStream(); + input.CopyTo(memoryStream); + memoryStream.Position = 0; + return Load(memoryStream, version, format, out diagnostic, settings); + } } + /// - /// Reads the TextReader input and parses the fragment of an OpenAPI description into an Open API Element. + /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element. /// /// - /// TextReader containing OpenAPI description to parse. + /// Stream containing OpenAPI description to parse. /// Version of the OpenAPI specification that the fragment conforms to. - /// The OpenAPI format. + /// /// Returns diagnostic object containing errors detected during parsing. /// The OpenApiReader settings. /// Instance of newly created IOpenApiElement. /// The OpenAPI element. - public static T Load(TextReader input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, string format, OpenApiReaderSettings settings = null) where T : IOpenApiElement + public static T Load(MemoryStream input, OpenApiSpecVersion version, string format, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement { format ??= OpenApiConstants.Json; return OpenApiReaderRegistry.GetReader(format).ReadFragment(input, version, out diagnostic, settings); } - private static string GetContentType(string url) { if (!string.IsNullOrEmpty(url)) diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs index 967bb0f3e..e591ad6e4 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System; using System.Collections.Generic; using System.IO; using System.Text.Json.Nodes; @@ -18,6 +19,14 @@ public class OpenApiSchemaTests { private const string SampleFolderPath = "V31Tests/Samples/OpenApiSchema/"; + + public MemoryStream GetMemoryStream(string fileName) + { + var filePath = Path.Combine(SampleFolderPath, fileName); + var fileBytes = File.ReadAllBytes(filePath); + return new MemoryStream(fileBytes); + } + public OpenApiSchemaTests() { OpenApiReaderRegistry.RegisterReader("yaml", new OpenApiYamlReader()); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDiscriminatorTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDiscriminatorTests.cs index 6556ade48..bcbc6a02a 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDiscriminatorTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDiscriminatorTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.IO; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; @@ -20,13 +21,16 @@ public OpenApiDiscriminatorTests() } [Fact] - public void ParseBasicDiscriminatorShouldSucceed() + public async Task ParseBasicDiscriminatorShouldSucceed() { // Arrange using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicDiscriminator.yaml")); + // Copy stream to MemoryStream + using var memoryStream = new MemoryStream(); + await stream.CopyToAsync(memoryStream); // Act - var discriminator = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, OpenApiConstants.Yaml, out var diagnostic); + var discriminator = OpenApiModelFactory.Load(memoryStream, OpenApiSpecVersion.OpenApi3_0, OpenApiConstants.Yaml, out var diagnostic); // Assert discriminator.Should().BeEquivalentTo( From c9b01cbec2ecb367c4f64dc7c49cc782ec463d09 Mon Sep 17 00:00:00 2001 From: Darrel Miller Date: Tue, 26 Nov 2024 09:39:31 -0500 Subject: [PATCH 032/127] Moved load external references --- .../Reader/OpenApiJsonReader.cs | 12 +---- .../Reader/OpenApiModelFactory.cs | 44 ++++++++++++++++++- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 568c94832..d24d31b9d 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -214,16 +214,6 @@ public T ReadFragment(JsonNode input, return (T)element; } - private async Task LoadExternalRefsAsync(OpenApiDocument document, CancellationToken cancellationToken, OpenApiReaderSettings settings, string format = null) - { - // Create workspace for all documents to live in. - var baseUrl = settings.BaseUrl ?? new Uri(OpenApiConstants.BaseRegistryUri); - var openApiWorkSpace = new OpenApiWorkspace(baseUrl); - - // Load this root document into the workspace - var streamLoader = new DefaultStreamLoader(settings.BaseUrl); - var workspaceLoader = new OpenApiWorkspaceLoader(openApiWorkSpace, settings.CustomExternalLoader ?? streamLoader, settings); - return await workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource = "/" }, document, format ?? OpenApiConstants.Json, null, cancellationToken); - } + } } diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index ad5d09968..2554c48a5 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -12,6 +12,8 @@ using System.Threading.Tasks; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader.Services; +using Microsoft.OpenApi.Services; namespace Microsoft.OpenApi.Reader { @@ -71,7 +73,16 @@ public static ReadResult Load(MemoryStream stream, /// The OpenApi reader settings. /// public static async Task LoadAsync(string url, OpenApiReaderSettings settings = null) - { + { + // If url is HTTP + // Get the response object. + // Select format based on MediaType + // Get the stream from the response object. + // Load the stream. + // Else + // Determine the format from the file extension. + // Load the file from the local file system. + var format = GetFormat(url); var stream = await GetStreamAsync(url); // Get response back and then get Content return await LoadAsync(stream, format, settings); @@ -134,14 +145,45 @@ private static async Task InternalLoadAsync(Stream input, string for Utils.CheckArgumentNull(format, nameof(format)); var reader = OpenApiReaderRegistry.GetReader(format); var readResult = await reader.ReadAsync(input, settings, cancellationToken); + + if (settings.LoadExternalRefs) + { + var diagnosticExternalRefs = await LoadExternalRefsAsync(readResult.OpenApiDocument, cancellationToken, settings, format); + // Merge diagnostics of external reference + if (diagnosticExternalRefs != null) + { + readResult.OpenApiDiagnostic.Errors.AddRange(diagnosticExternalRefs.Errors); + readResult.OpenApiDiagnostic.Warnings.AddRange(diagnosticExternalRefs.Warnings); + } + } + + return readResult; } + private static async Task LoadExternalRefsAsync(OpenApiDocument document, CancellationToken cancellationToken, OpenApiReaderSettings settings, string format = null) + { + // Create workspace for all documents to live in. + var baseUrl = settings.BaseUrl ?? new Uri(OpenApiConstants.BaseRegistryUri); + var openApiWorkSpace = new OpenApiWorkspace(baseUrl); + + // Load this root document into the workspace + var streamLoader = new DefaultStreamLoader(settings.BaseUrl); + var workspaceLoader = new OpenApiWorkspaceLoader(openApiWorkSpace, settings.CustomExternalLoader ?? streamLoader, settings); + return await workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource = "/" }, document, format ?? OpenApiConstants.Json, null, cancellationToken); + } + private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings = null) { Utils.CheckArgumentNull(format, nameof(format)); + if (settings.LoadExternalRefs) + { + throw new InvalidOperationException("Loading external references are not supported when using synchronous methods."); + } + var reader = OpenApiReaderRegistry.GetReader(format); var readResult = reader.Read(input, settings); + return readResult; } From 1464e2cbde5a8db4372c267632f3b7c90f9fdf35 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 27 Nov 2024 17:28:17 +0300 Subject: [PATCH 033/127] Move load methods to be adjacent --- .../Reader/OpenApiModelFactory.cs | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 2554c48a5..0b7fadb7f 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -65,6 +65,47 @@ public static ReadResult Load(MemoryStream stream, return result; } + /// + /// Reads the stream input and ensures it is buffered before passing it to the Load method. + /// + /// + /// + /// + /// + /// + /// + /// + public static T Load(Stream input, OpenApiSpecVersion version, string format, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement + { + if (input is MemoryStream memoryStream) + { + return Load(memoryStream, version, format, out diagnostic, settings); + } + else + { + memoryStream = new MemoryStream(); + input.CopyTo(memoryStream); + memoryStream.Position = 0; + return Load(memoryStream, version, format, out diagnostic, settings); + } + } + + /// + /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element. + /// + /// + /// Stream containing OpenAPI description to parse. + /// Version of the OpenAPI specification that the fragment conforms to. + /// + /// Returns diagnostic object containing errors detected during parsing. + /// The OpenApiReader settings. + /// Instance of newly created IOpenApiElement. + /// The OpenAPI element. + public static T Load(MemoryStream input, OpenApiSpecVersion version, string format, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement + { + format ??= OpenApiConstants.Json; + return OpenApiReaderRegistry.GetReader(format).ReadFragment(input, version, out diagnostic, settings); + } /// /// Loads the input URL and parses it into an Open API document. From e5883775c5898005b82a057a19dae2e71c359d18 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 27 Nov 2024 17:29:06 +0300 Subject: [PATCH 034/127] Async over sync --- .../Reader/OpenApiModelFactory.cs | 42 ++++++++----------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 0b7fadb7f..9ffa9be2d 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -29,19 +29,6 @@ static OpenApiModelFactory() OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Json, new OpenApiJsonReader()); } - /// - /// Loads the input URL and parses it into an Open API document. - /// - /// The path to the OpenAPI file. - /// The OpenApi reader settings. - /// An OpenAPI document instance. - public static ReadResult Load(string url, OpenApiReaderSettings settings = null) - { -#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits - return LoadAsync(url, settings).GetAwaiter().GetResult(); -#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits - } - /// /// Loads the input stream and parses it into an Open API document. /// @@ -114,19 +101,24 @@ public static T Load(MemoryStream input, OpenApiSpecVersion version, string f /// The OpenApi reader settings. /// public static async Task LoadAsync(string url, OpenApiReaderSettings settings = null) - { - // If url is HTTP - // Get the response object. - // Select format based on MediaType - // Get the stream from the response object. - // Load the stream. - // Else - // Determine the format from the file extension. - // Load the file from the local file system. + { + var result = await RetrieveStreamAndFormatAsync(url); + return await LoadAsync(result.Item1, result.Item2, settings); + } - var format = GetFormat(url); - var stream = await GetStreamAsync(url); // Get response back and then get Content - return await LoadAsync(stream, format, settings); + /// + /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element. + /// + /// + /// The path to the OpenAPI file + /// Version of the OpenAPI specification that the fragment conforms to. + /// The OpenApiReader settings. + /// Instance of newly created IOpenApiElement. + /// The OpenAPI element. + public static async Task LoadAsync(string url, OpenApiSpecVersion version, OpenApiReaderSettings settings = null) where T : IOpenApiElement + { + var result = await RetrieveStreamAndFormatAsync(url); + return Load(result.Item1 as MemoryStream, version, result.Item2, out var diagnostic, settings); } /// From 47e3e253ec99d5d1f6eb87d1d2e2d940717beb13 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 27 Nov 2024 17:30:09 +0300 Subject: [PATCH 035/127] refactor code --- .../Reader/OpenApiModelFactory.cs | 211 +++++------------- 1 file changed, 56 insertions(+), 155 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 9ffa9be2d..65268394a 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -129,7 +129,7 @@ public static async Task LoadAsync(string url, OpenApiSpecVersion version, /// Propagates notification that operations should be cancelled. /// The Open API format /// - public static async Task LoadAsync(Stream input, string format, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) + public static async Task LoadAsync(Stream input, string format = null, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) { Utils.CheckArgumentNull(format, nameof(format)); settings ??= new OpenApiReaderSettings(); @@ -173,6 +173,27 @@ public static ReadResult Parse(string input, return InternalLoad(stream, format, settings); } + /// + /// Reads the input string and parses it into an Open API document. + /// + /// The input string. + /// + /// The diagnostic entity containing information from the reading process. + /// The Open API format + /// The OpenApi reader settings. + /// An OpenAPI document instance. + public static T Parse(string input, + OpenApiSpecVersion version, + out OpenApiDiagnostic diagnostic, + string format = null, + OpenApiReaderSettings settings = null) where T : IOpenApiElement + { + format ??= OpenApiConstants.Json; + settings ??= new OpenApiReaderSettings(); + var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); + return Load(stream, version, format, out diagnostic, settings); + } + private static async Task InternalLoadAsync(Stream input, string format, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) { Utils.CheckArgumentNull(format, nameof(format)); @@ -190,7 +211,6 @@ private static async Task InternalLoadAsync(Stream input, string for } } - return readResult; } @@ -220,168 +240,49 @@ private static ReadResult InternalLoad(MemoryStream input, string format, OpenAp return readResult; } - - /// - /// Reads the input string and parses it into an Open API document. - /// - /// The input string. - /// - /// The diagnostic entity containing information from the reading process. - /// The Open API format - /// The OpenApi reader settings. - /// An OpenAPI document instance. - public static T Parse(string input, - OpenApiSpecVersion version, - out OpenApiDiagnostic diagnostic, - string format = null, - OpenApiReaderSettings settings = null) where T : IOpenApiElement - { - format ??= OpenApiConstants.Json; - settings ??= new OpenApiReaderSettings(); - var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); - return Load(stream, version, format, out diagnostic, settings); - } - - /// - /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element. - /// - /// - /// The path to the OpenAPI file - /// Version of the OpenAPI specification that the fragment conforms to. - /// Returns diagnostic object containing errors detected during parsing. - /// The OpenApiReader settings. - /// Instance of newly created IOpenApiElement. - /// The OpenAPI element. - public static T Load(string url, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement - { - var format = GetFormat(url); - settings ??= new OpenApiReaderSettings(); - -#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits - var stream = GetStreamAsync(url).GetAwaiter().GetResult(); -#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits - - return Load(stream as MemoryStream, version, format, out diagnostic, settings); - } - - - /// - /// Reads the stream input and ensures it is buffered before passing it to the Load method. - /// - /// - /// - /// - /// - /// - /// - /// - public static T Load(Stream input, OpenApiSpecVersion version, string format, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement - { - if (input is MemoryStream memoryStream) - { - return Load(memoryStream, version, format, out diagnostic, settings); - } else { - memoryStream = new MemoryStream(); - input.CopyTo(memoryStream); - memoryStream.Position = 0; - return Load(memoryStream, version, format, out diagnostic, settings); - } - } - - - /// - /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element. - /// - /// - /// Stream containing OpenAPI description to parse. - /// Version of the OpenAPI specification that the fragment conforms to. - /// - /// Returns diagnostic object containing errors detected during parsing. - /// The OpenApiReader settings. - /// Instance of newly created IOpenApiElement. - /// The OpenAPI element. - public static T Load(MemoryStream input, OpenApiSpecVersion version, string format, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement - { - format ??= OpenApiConstants.Json; - return OpenApiReaderRegistry.GetReader(format).ReadFragment(input, version, out diagnostic, settings); - } - - private static string GetContentType(string url) + private static async Task<(Stream, string)> RetrieveStreamAndFormatAsync(string url) { if (!string.IsNullOrEmpty(url)) { -#pragma warning disable VSTHRD002 // Avoid problematic synchronous waits - var response = _httpClient.GetAsync(url).GetAwaiter().GetResult(); -#pragma warning restore VSTHRD002 // Avoid problematic synchronous waits - - var mediaType = response.Content.Headers.ContentType.MediaType; - return mediaType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).First(); - } - - return null; - } + Stream stream; + string format; - /// - /// Infers the OpenAPI format from the input URL. - /// - /// The input URL. - /// The OpenAPI format. - public static string GetFormat(string url) - { - if (!string.IsNullOrEmpty(url)) - { - if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) + if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase) + || url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) { - // URL examples ---> https://example.com/path/to/file.json, https://example.com/path/to/file.yaml - var path = new Uri(url); - var urlSuffix = path.Segments[path.Segments.Length - 1].Split('.').LastOrDefault(); - - return !string.IsNullOrEmpty(urlSuffix) ? urlSuffix : GetContentType(url).Split('/').LastOrDefault(); + var response = await _httpClient.GetAsync(url); + var mediaType = response.Content.Headers.ContentType.MediaType; + var contentType = mediaType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)[0]; + format = contentType.Split('/').LastOrDefault(); + stream = await response.Content.ReadAsStreamAsync(); + return (stream, format); } else { - return Path.GetExtension(url).Split('.').LastOrDefault(); + format = Path.GetExtension(url).Split('.').LastOrDefault(); + + try + { + var fileInput = new FileInfo(url); + stream = fileInput.OpenRead(); + } + catch (Exception ex) when ( + ex is + FileNotFoundException or + PathTooLongException or + DirectoryNotFoundException or + IOException or + UnauthorizedAccessException or + SecurityException or + NotSupportedException) + { + throw new InvalidOperationException($"Could not open the file at {url}", ex); + } + + return (stream, format); } } - return null; - } - - private static async Task GetStreamAsync(string url) - { - Stream stream; - if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) - { - try - { - stream = await _httpClient.GetStreamAsync(new Uri(url)); - } - catch (HttpRequestException ex) - { - throw new InvalidOperationException($"Could not download the file at {url}", ex); - } - } - else - { - try - { - var fileInput = new FileInfo(url); - stream = fileInput.OpenRead(); - } - catch (Exception ex) when ( - ex is - FileNotFoundException or - PathTooLongException or - DirectoryNotFoundException or - IOException or - UnauthorizedAccessException or - SecurityException or - NotSupportedException) - { - throw new InvalidOperationException($"Could not open the file at {url}", ex); - } - } - - return stream; + return (null, null); } } } From 85210821e1d6a24d04e322597ad5497fbd3673ea Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 28 Nov 2024 12:16:06 +0300 Subject: [PATCH 036/127] Use the provided format in hidi options --- src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 7dfb5d797..b100eafb1 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -66,7 +66,7 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog #pragma warning restore CA1308 // Normalize strings to uppercase options.Output = new($"./output{inputExtension}"); - }; + } if (options.CleanOutput && options.Output.Exists) { @@ -97,8 +97,7 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog } // Load OpenAPI document - var format = OpenApiModelFactory.GetFormat(options.OpenApi); - var document = await GetOpenApiAsync(options, format, logger, options.MetadataVersion, cancellationToken).ConfigureAwait(false); + var document = await GetOpenApiAsync(options, openApiFormat.GetDisplayName(), logger, options.MetadataVersion, cancellationToken).ConfigureAwait(false); if (options.FilterOptions != null) { @@ -254,7 +253,7 @@ private static async Task GetOpenApiAsync(HidiOptions options, else if (!string.IsNullOrEmpty(options.OpenApi)) { stream = await GetStreamAsync(options.OpenApi, logger, cancellationToken).ConfigureAwait(false); - var result = await ParseOpenApiAsync(options.OpenApi, options.InlineExternal, logger, stream, cancellationToken).ConfigureAwait(false); + var result = await ParseOpenApiAsync(options.OpenApi, format, options.InlineExternal, logger, stream, cancellationToken).ConfigureAwait(false); document = result.OpenApiDocument; } else throw new InvalidOperationException("No input file path or URL provided"); @@ -351,8 +350,8 @@ private static MemoryStream ApplyFilterToCsdl(Stream csdlStream, string entitySe try { using var stream = await GetStreamAsync(openApi, logger, cancellationToken).ConfigureAwait(false); - - result = await ParseOpenApiAsync(openApi, false, logger, stream, cancellationToken).ConfigureAwait(false); + var openApiFormat = !string.IsNullOrEmpty(openApi) ? GetOpenApiFormat(openApi, logger) : OpenApiFormat.Yaml; + result = await ParseOpenApiAsync(openApi, openApiFormat.GetDisplayName(),false, logger, stream, cancellationToken).ConfigureAwait(false); using (logger.BeginScope("Calculating statistics")) { @@ -380,7 +379,7 @@ private static MemoryStream ApplyFilterToCsdl(Stream csdlStream, string entitySe return result.OpenApiDiagnostic.Errors.Count == 0; } - private static async Task ParseOpenApiAsync(string openApiFile, bool inlineExternal, ILogger logger, Stream stream, CancellationToken cancellationToken = default) + private static async Task ParseOpenApiAsync(string openApiFile, string format, bool inlineExternal, ILogger logger, Stream stream, CancellationToken cancellationToken = default) { ReadResult result; var stopwatch = Stopwatch.StartNew(); @@ -396,7 +395,6 @@ private static async Task ParseOpenApiAsync(string openApiFile, bool new Uri("file://" + new FileInfo(openApiFile).DirectoryName + Path.DirectorySeparatorChar) }; - var format = OpenApiModelFactory.GetFormat(openApiFile); result = await OpenApiDocument.LoadAsync(stream, format, settings, cancellationToken).ConfigureAwait(false); logger.LogTrace("{Timestamp}ms: Completed parsing.", stopwatch.ElapsedMilliseconds); @@ -587,8 +585,8 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl throw new ArgumentException("Please input a file path or URL"); } - var format = OpenApiModelFactory.GetFormat(options.OpenApi); - var document = await GetOpenApiAsync(options, format, logger, null, cancellationToken).ConfigureAwait(false); + var openApiFormat = options.OpenApiFormat ?? (!string.IsNullOrEmpty(options.OpenApi) ? GetOpenApiFormat(options.OpenApi, logger) : OpenApiFormat.Yaml); + var document = await GetOpenApiAsync(options, openApiFormat.GetDisplayName(), logger, null, cancellationToken).ConfigureAwait(false); using (logger.BeginScope("Creating diagram")) { @@ -748,9 +746,11 @@ internal static async Task PluginManifestAsync(HidiOptions options, ILogger logg options.OpenApi = apiDependency.ApiDescripionUrl; } + var openApiFormat = options.OpenApiFormat ?? (!string.IsNullOrEmpty(options.OpenApi) + ? GetOpenApiFormat(options.OpenApi, logger) : OpenApiFormat.Yaml); + // Load OpenAPI document - var format = OpenApiModelFactory.GetFormat(options.OpenApi); - var document = await GetOpenApiAsync(options, format, logger, options.MetadataVersion, cancellationToken).ConfigureAwait(false); + var document = await GetOpenApiAsync(options, openApiFormat.GetDisplayName(), logger, options.MetadataVersion, cancellationToken).ConfigureAwait(false); cancellationToken.ThrowIfCancellationRequested(); From 99a80b986c8e76a41a496f9d4b4f9bac378dd607 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 28 Nov 2024 12:18:28 +0300 Subject: [PATCH 037/127] Clean up tests; refactor to use async --- .../Models/OpenApiDocument.cs | 13 +---- .../Services/OpenApiFilterServiceTests.cs | 4 +- .../OpenApiDiagnosticTests.cs | 8 +-- .../OpenApiStreamReaderTests.cs | 12 ++-- .../UnsupportedSpecVersionTests.cs | 5 +- .../TryLoadReferenceV2Tests.cs | 17 +++--- .../V2Tests/ComparisonTests.cs | 9 +-- .../V2Tests/OpenApiDocumentTests.cs | 22 +++---- .../V31Tests/OpenApiDocumentTests.cs | 29 +++++----- .../V31Tests/OpenApiSchemaTests.cs | 45 +++++++------- .../V3Tests/OpenApiCallbackTests.cs | 15 +++-- .../V3Tests/OpenApiDocumentTests.cs | 58 +++++++++---------- .../V3Tests/OpenApiEncodingTests.cs | 5 +- .../V3Tests/OpenApiExampleTests.cs | 14 ++--- .../V3Tests/OpenApiInfoTests.cs | 9 +-- .../V3Tests/OpenApiMediaTypeTests.cs | 9 +-- .../V3Tests/OpenApiOperationTests.cs | 11 ++-- .../V3Tests/OpenApiParameterTests.cs | 25 ++++---- .../V3Tests/OpenApiResponseTests.cs | 5 +- .../V3Tests/OpenApiSchemaTests.cs | 24 ++++---- .../V3Tests/OpenApiSecuritySchemeTests.cs | 21 +++---- .../Models/OpenApiDocumentTests.cs | 26 ++++----- 22 files changed, 186 insertions(+), 200 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index a41e7ca6b..13de5f7f8 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -137,7 +137,7 @@ public void SerializeAsV31(IOpenApiWriter writer) writer.WriteStartObject(); - // openApi; + // openApi writer.WriteProperty(OpenApiConstants.OpenApi, "3.1.1"); // jsonSchemaDialect @@ -535,17 +535,6 @@ private static string ConvertByteArrayToString(byte[] hash) return Workspace?.ResolveReference(uriLocation); } - /// - /// Parses a local file path or Url into an Open API document. - /// - /// The path to the OpenAPI file. - /// - /// - public static ReadResult Load(string url, OpenApiReaderSettings? settings = null) - { - return OpenApiModelFactory.Load(url, settings); - } - /// /// Reads the stream input and parses it into an Open API document. /// diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs index 3bd9efd2a..602a69021 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs @@ -224,7 +224,7 @@ public void ThrowsInvalidOperationExceptionInCreatePredicateWhenInvalidArguments } [Fact] - public void CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly() + public async Task CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly() { // Arrange var filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "UtilityFiles", "docWithReusableHeadersAndExamples.yaml"); @@ -232,7 +232,7 @@ public void CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly() // Act using var stream = File.OpenRead(filePath); - var doc = OpenApiDocument.Load(stream, "yaml").OpenApiDocument; + var doc = (await OpenApiDocument.LoadAsync(stream, "yaml")).OpenApiDocument; var predicate = OpenApiFilterService.CreatePredicate(operationIds: operationIds); var subsetOpenApiDocument = OpenApiFilterService.CreateFilteredDocument(doc, predicate); diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs index c99cc6fa9..58e6e7cb0 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs @@ -23,18 +23,18 @@ public OpenApiDiagnosticTests() } [Fact] - public void DetectedSpecificationVersionShouldBeV2_0() + public async Task DetectedSpecificationVersionShouldBeV2_0() { - var actual = OpenApiDocument.Load("V2Tests/Samples/basic.v2.yaml"); + var actual = await OpenApiDocument.LoadAsync("V2Tests/Samples/basic.v2.yaml"); actual.OpenApiDiagnostic.Should().NotBeNull(); actual.OpenApiDiagnostic.SpecificationVersion.Should().Be(OpenApiSpecVersion.OpenApi2_0); } [Fact] - public void DetectedSpecificationVersionShouldBeV3_0() + public async Task DetectedSpecificationVersionShouldBeV3_0() { - var actual = OpenApiDocument.Load("V3Tests/Samples/OpenApiDocument/minimalDocument.yaml"); + var actual = await OpenApiDocument.LoadAsync("V3Tests/Samples/OpenApiDocument/minimalDocument.yaml"); actual.OpenApiDiagnostic.Should().NotBeNull(); actual.OpenApiDiagnostic.SpecificationVersion.Should().Be(OpenApiSpecVersion.OpenApi3_0); diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs index 82a410946..91407f0b7 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs @@ -21,20 +21,20 @@ public OpenApiStreamReaderTests() } [Fact] - public void StreamShouldCloseIfLeaveStreamOpenSettingEqualsFalse() + public async Task StreamShouldCloseIfLeaveStreamOpenSettingEqualsFalse() { using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "petStore.yaml")); var settings = new OpenApiReaderSettings { LeaveStreamOpen = false }; - _ = OpenApiDocument.Load(stream, "yaml", settings); + _ = await OpenApiDocument.LoadAsync(stream, "yaml", settings); Assert.False(stream.CanRead); } [Fact] - public void StreamShouldNotCloseIfLeaveStreamOpenSettingEqualsTrue() + public async Task StreamShouldNotCloseIfLeaveStreamOpenSettingEqualsTrue() { using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "petStore.yaml")); var settings = new OpenApiReaderSettings { LeaveStreamOpen = true }; - _ = OpenApiDocument.Load(stream, "yaml", settings); + _ = await OpenApiDocument.LoadAsync(stream, "yaml", settings); Assert.True(stream.CanRead); } @@ -48,7 +48,7 @@ public async Task StreamShouldNotBeDisposedIfLeaveStreamOpenSettingIsTrueAsync() memoryStream.Position = 0; var stream = memoryStream; - var result = OpenApiDocument.Load(stream, "yaml", new OpenApiReaderSettings { LeaveStreamOpen = true }); + _ = await OpenApiDocument.LoadAsync(stream, "yaml", new OpenApiReaderSettings { LeaveStreamOpen = true }); stream.Seek(0, SeekOrigin.Begin); // does not throw an object disposed exception Assert.True(stream.CanRead); } @@ -64,7 +64,7 @@ public async Task StreamShouldReadWhenInitializedAsync() var stream = await httpClient.GetStreamAsync("20fe7a7b720a0e48e5842d002ac418b12a8201df/tests/v3.0/pass/petstore.yaml"); // Read V3 as YAML - var result = OpenApiDocument.Load(stream, "yaml"); + var result = await OpenApiDocument.LoadAsync(stream, "yaml"); Assert.NotNull(result.OpenApiDocument); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/UnsupportedSpecVersionTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/UnsupportedSpecVersionTests.cs index 0b044e78b..1f6cbb7e8 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/UnsupportedSpecVersionTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/UnsupportedSpecVersionTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Exceptions; using Microsoft.OpenApi.Models; @@ -12,11 +13,11 @@ namespace Microsoft.OpenApi.Readers.Tests.OpenApiReaderTests public class UnsupportedSpecVersionTests { [Fact] - public void ThrowOpenApiUnsupportedSpecVersionException() + public async Task ThrowOpenApiUnsupportedSpecVersionException() { try { - _ = OpenApiDocument.Load("OpenApiReaderTests/Samples/unsupported.v1.yaml"); + _ = await OpenApiDocument.LoadAsync("OpenApiReaderTests/Samples/unsupported.v1.yaml"); } catch (OpenApiUnsupportedSpecVersionException exception) { diff --git a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs index d6fb3b8ba..04577149e 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -22,10 +23,10 @@ public TryLoadReferenceV2Tests() } [Fact] - public void LoadParameterReference() + public async Task LoadParameterReference() { // Arrange - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); var reference = new OpenApiParameterReference("skipParam", result.OpenApiDocument); // Assert @@ -47,9 +48,9 @@ public void LoadParameterReference() } [Fact] - public void LoadSecuritySchemeReference() + public async Task LoadSecuritySchemeReference() { - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); var reference = new OpenApiSecuritySchemeReference("api_key_sample", result.OpenApiDocument); @@ -65,9 +66,9 @@ public void LoadSecuritySchemeReference() } [Fact] - public void LoadResponseReference() + public async Task LoadResponseReference() { - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); var reference = new OpenApiResponseReference("NotFound", result.OpenApiDocument); @@ -85,9 +86,9 @@ public void LoadResponseReference() } [Fact] - public void LoadResponseAndSchemaReference() + public async Task LoadResponseAndSchemaReference() { - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); var reference = new OpenApiResponseReference("GeneralError", result.OpenApiDocument); // Assert diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/ComparisonTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/ComparisonTests.cs index b3e30c672..150c4c585 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/ComparisonTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/ComparisonTests.cs @@ -1,7 +1,8 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System.IO; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; @@ -18,13 +19,13 @@ public class ComparisonTests [InlineData("minimal")] [InlineData("basic")] //[InlineData("definitions")] //Currently broken due to V3 references not behaving the same as V2 - public void EquivalentV2AndV3DocumentsShouldProduceEquivalentObjects(string fileName) + public async Task EquivalentV2AndV3DocumentsShouldProduceEquivalentObjects(string fileName) { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); using var streamV2 = Resources.GetStream(Path.Combine(SampleFolderPath, $"{fileName}.v2.yaml")); using var streamV3 = Resources.GetStream(Path.Combine(SampleFolderPath, $"{fileName}.v3.yaml")); - var result1 = OpenApiDocument.Load(Path.Combine(SampleFolderPath, $"{fileName}.v2.yaml")); - var result2 = OpenApiDocument.Load(Path.Combine(SampleFolderPath, $"{fileName}.v3.yaml")); + var result1 = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, $"{fileName}.v2.yaml")); + var result2 = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, $"{fileName}.v3.yaml")); result2.OpenApiDocument.Should().BeEquivalentTo(result1.OpenApiDocument, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index c97fd1aee..a4786325e 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Threading; +using System.Threading.Tasks; using FluentAssertions; using FluentAssertions.Equivalency; using Microsoft.OpenApi.Any; @@ -96,13 +97,13 @@ public void ParseDocumentWithDifferentCultureShouldSucceed(string culture) .Excluding((IMemberInfo memberInfo) => memberInfo.Path.EndsWith("Parent")) .Excluding((IMemberInfo memberInfo) => - memberInfo.Path.EndsWith("Root")));; + memberInfo.Path.EndsWith("Root"))); } [Fact] - public void ShouldParseProducesInAnyOrder() + public async Task ShouldParseProducesInAnyOrder() { - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "twoResponses.json")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "twoResponses.json")); var okSchema = new OpenApiSchema { @@ -259,10 +260,10 @@ public void ShouldParseProducesInAnyOrder() } [Fact] - public void ShouldAssignSchemaToAllResponses() + public async Task ShouldAssignSchemaToAllResponses() { using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "multipleProduces.json")); - var result = OpenApiDocument.Load(stream, OpenApiConstants.Json); + var result = await OpenApiDocument.LoadAsync(stream, OpenApiConstants.Json); Assert.Equal(OpenApiSpecVersion.OpenApi2_0, result.OpenApiDiagnostic.SpecificationVersion); @@ -289,10 +290,10 @@ public void ShouldAssignSchemaToAllResponses() } [Fact] - public void ShouldAllowComponentsThatJustContainAReference() + public async Task ShouldAllowComponentsThatJustContainAReference() { // Act - var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "ComponentRootReference.json")).OpenApiDocument; + var actual = (await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "ComponentRootReference.json"))).OpenApiDocument; var schema1 = actual.Components.Schemas["AllPets"]; Assert.False(schema1.UnresolvedReference); var schema2 = actual.ResolveReferenceTo(schema1.Reference); @@ -304,14 +305,14 @@ public void ShouldAllowComponentsThatJustContainAReference() } [Fact] - public void ParseDocumentWithDefaultContentTypeSettingShouldSucceed() + public async Task ParseDocumentWithDefaultContentTypeSettingShouldSucceed() { var settings = new OpenApiReaderSettings { DefaultContentType = ["application/json"] }; - var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "docWithEmptyProduces.yaml"), settings); + var actual = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "docWithEmptyProduces.yaml"), settings); var mediaType = actual.OpenApiDocument.Paths["/example"].Operations[OperationType.Get].Responses["200"].Content; Assert.Contains("application/json", mediaType); } @@ -320,8 +321,7 @@ public void ParseDocumentWithDefaultContentTypeSettingShouldSucceed() public void testContentType() { var contentType = "application/json; charset = utf-8"; - var res = contentType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).First(); - var expected = res.Split('/').LastOrDefault(); + var res = contentType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)[0]; Assert.Equal("application/json", res); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs index 638d69667..4a0bdb607 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs @@ -26,10 +26,10 @@ public OpenApiDocumentTests() } [Fact] - public void ParseDocumentWithWebhooksShouldSucceed() + public async Task ParseDocumentWithWebhooksShouldSucceed() { // Arrange and Act - var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "documentWithWebhooks.yaml")); + var actual = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "documentWithWebhooks.yaml")); var petSchema = new OpenApiSchemaReference("petSchema", actual.OpenApiDocument); var newPetSchema = new OpenApiSchemaReference("newPetSchema", actual.OpenApiDocument); @@ -205,10 +205,10 @@ public void ParseDocumentWithWebhooksShouldSucceed() } [Fact] - public void ParseDocumentsWithReusablePathItemInWebhooksSucceeds() + public async Task ParseDocumentsWithReusablePathItemInWebhooksSucceeds() { // Arrange && Act - var actual = OpenApiDocument.Load("V31Tests/Samples/OpenApiDocument/documentWithReusablePaths.yaml"); + var actual = await OpenApiDocument.LoadAsync("V31Tests/Samples/OpenApiDocument/documentWithReusablePaths.yaml"); var components = new OpenApiComponents { @@ -397,18 +397,17 @@ public void ParseDocumentsWithReusablePathItemInWebhooksSucceeds() var outputWriter = new StringWriter(CultureInfo.InvariantCulture); var writer = new OpenApiJsonWriter(outputWriter, new() { InlineLocalReferences = true }); actual.OpenApiDocument.SerializeAsV31(writer); - var serialized = outputWriter.ToString(); } [Fact] - public void ParseDocumentWithExampleInSchemaShouldSucceed() + public async Task ParseDocumentWithExampleInSchemaShouldSucceed() { // Arrange var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); var writer = new OpenApiJsonWriter(outputStringWriter, new OpenApiJsonWriterSettings { Terse = false }); // Act - var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "docWithExample.yaml")); + var actual = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "docWithExample.yaml")); actual.OpenApiDocument.SerializeAsV31(writer); // Assert @@ -416,10 +415,10 @@ public void ParseDocumentWithExampleInSchemaShouldSucceed() } [Fact] - public void ParseDocumentWithPatternPropertiesInSchemaWorks() + public async Task ParseDocumentWithPatternPropertiesInSchemaWorks() { // Arrange and Act - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "docWithPatternPropertiesInSchema.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "docWithPatternPropertiesInSchema.yaml")); var actualSchema = result.OpenApiDocument.Paths["/example"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; var expectedSchema = new OpenApiSchema @@ -473,10 +472,10 @@ public void ParseDocumentWithPatternPropertiesInSchemaWorks() } [Fact] - public void ParseDocumentWithReferenceByIdGetsResolved() + public async Task ParseDocumentWithReferenceByIdGetsResolved() { // Arrange and Act - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "docWithReferenceById.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "docWithReferenceById.yaml")); var responseSchema = result.OpenApiDocument.Paths["/resource"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; var requestBodySchema = result.OpenApiDocument.Paths["/resource"].Operations[OperationType.Post].RequestBody.Content["application/json"].Schema; @@ -523,9 +522,9 @@ public async Task ParseExternalDocumentDereferenceToOpenApiDocumentByIdWorks() // Act var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "externalRefById.yaml"), settings); - var doc2 = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "externalResource.yaml")).OpenApiDocument; + var doc2 = (await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "externalResource.yaml"))).OpenApiDocument; - var requestBodySchema = result.OpenApiDocument.Paths["/resource"].Operations[OperationType.Get].Parameters.First().Schema; + var requestBodySchema = result.OpenApiDocument.Paths["/resource"].Operations[OperationType.Get].Parameters[0].Schema; result.OpenApiDocument.Workspace.RegisterComponents(doc2); // Assert @@ -536,10 +535,10 @@ public async Task ParseExternalDocumentDereferenceToOpenApiDocumentByIdWorks() public async Task ParseDocumentWith31PropertiesWorks() { var path = Path.Combine(SampleFolderPath, "documentWith31Properties.yaml"); - var doc = OpenApiDocument.Load(path).OpenApiDocument; + var doc = (await OpenApiDocument.LoadAsync(path)).OpenApiDocument; var outputStringWriter = new StringWriter(); doc.SerializeAsV31(new OpenApiYamlWriter(outputStringWriter)); - outputStringWriter.Flush(); + await outputStringWriter.FlushAsync(); var actual = outputStringWriter.GetStringBuilder().ToString(); // Assert diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs index 731c33f2c..b1ab968a1 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using System.Text.Json.Nodes; +using System.Threading.Tasks; using FluentAssertions; using FluentAssertions.Equivalency; using Microsoft.OpenApi.Models; @@ -20,7 +21,7 @@ public class OpenApiSchemaTests private const string SampleFolderPath = "V31Tests/Samples/OpenApiSchema/"; - public MemoryStream GetMemoryStream(string fileName) + public static MemoryStream GetMemoryStream(string fileName) { var filePath = Path.Combine(SampleFolderPath, fileName); var fileBytes = File.ReadAllBytes(filePath); @@ -33,7 +34,7 @@ public OpenApiSchemaTests() } [Fact] - public void ParseBasicV31SchemaShouldSucceed() + public async Task ParseBasicV31SchemaShouldSucceed() { var expectedObject = new OpenApiSchema() { @@ -84,8 +85,8 @@ public void ParseBasicV31SchemaShouldSucceed() }; // Act - var schema = OpenApiModelFactory.Load( - System.IO.Path.Combine(SampleFolderPath, "jsonSchema.json"), OpenApiSpecVersion.OpenApi3_1, out _); + var schema = await OpenApiModelFactory.LoadAsync( + System.IO.Path.Combine(SampleFolderPath, "jsonSchema.json"), OpenApiSpecVersion.OpenApi3_1); // Assert schema.Should().BeEquivalentTo(expectedObject); @@ -155,12 +156,12 @@ public void TestSchemaCopyConstructorWithTypeArrayWorks() } [Fact] - public void ParseV31SchemaShouldSucceed() + public async Task ParseV31SchemaShouldSucceed() { var path = Path.Combine(SampleFolderPath, "schema.yaml"); // Act - var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_1, out _); + var schema = await OpenApiModelFactory.LoadAsync(path, OpenApiSpecVersion.OpenApi3_1); var expectedSchema = new OpenApiSchema { Type = JsonSchemaType.Object, @@ -179,11 +180,11 @@ public void ParseV31SchemaShouldSucceed() } [Fact] - public void ParseAdvancedV31SchemaShouldSucceed() + public async Task ParseAdvancedV31SchemaShouldSucceed() { // Arrange and Act var path = Path.Combine(SampleFolderPath, "advancedSchema.yaml"); - var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_1, out _); + var schema = await OpenApiModelFactory.LoadAsync(path, OpenApiSpecVersion.OpenApi3_1); var expectedSchema = new OpenApiSchema { @@ -304,7 +305,7 @@ public void CloningSchemaWithExamplesAndEnumsShouldSucceed() } [Fact] - public void SerializeV31SchemaWithMultipleTypesAsV3Works() + public async Task SerializeV31SchemaWithMultipleTypesAsV3Works() { // Arrange var expected = @"type: string @@ -313,7 +314,7 @@ public void SerializeV31SchemaWithMultipleTypesAsV3Works() var path = Path.Combine(SampleFolderPath, "schemaWithTypeArray.yaml"); // Act - var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_1, out _); + var schema = await OpenApiModelFactory.LoadAsync(path, OpenApiSpecVersion.OpenApi3_1); var writer = new StringWriter(); schema.SerializeAsV3(new OpenApiYamlWriter(writer)); @@ -323,7 +324,7 @@ public void SerializeV31SchemaWithMultipleTypesAsV3Works() } [Fact] - public void SerializeV31SchemaWithMultipleTypesAsV2Works() + public async Task SerializeV31SchemaWithMultipleTypesAsV2Works() { // Arrange var expected = @"type: string @@ -332,7 +333,7 @@ public void SerializeV31SchemaWithMultipleTypesAsV2Works() var path = Path.Combine(SampleFolderPath, "schemaWithTypeArray.yaml"); // Act - var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_1, out _); + var schema = await OpenApiModelFactory.LoadAsync(path, OpenApiSpecVersion.OpenApi3_1); var writer = new StringWriter(); schema.SerializeAsV2(new OpenApiYamlWriter(writer)); @@ -342,7 +343,7 @@ public void SerializeV31SchemaWithMultipleTypesAsV2Works() } [Fact] - public void SerializeV3SchemaWithNullableAsV31Works() + public async Task SerializeV3SchemaWithNullableAsV31Works() { // Arrange var expected = @"type: @@ -352,7 +353,7 @@ public void SerializeV3SchemaWithNullableAsV31Works() var path = Path.Combine(SampleFolderPath, "schemaWithNullable.yaml"); // Act - var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_0, out _); + var schema = await OpenApiModelFactory.LoadAsync(path, OpenApiSpecVersion.OpenApi3_0); var writer = new StringWriter(); schema.SerializeAsV31(new OpenApiYamlWriter(writer)); @@ -362,7 +363,7 @@ public void SerializeV3SchemaWithNullableAsV31Works() } [Fact] - public void SerializeV2SchemaWithNullableExtensionAsV31Works() + public async Task SerializeV2SchemaWithNullableExtensionAsV31Works() { // Arrange var expected = @"type: @@ -373,7 +374,7 @@ public void SerializeV2SchemaWithNullableExtensionAsV31Works() var path = Path.Combine(SampleFolderPath, "schemaWithNullableExtension.yaml"); // Act - var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi2_0, out _); + var schema = await OpenApiModelFactory.LoadAsync(path, OpenApiSpecVersion.OpenApi2_0); var writer = new StringWriter(); schema.SerializeAsV31(new OpenApiYamlWriter(writer)); @@ -404,20 +405,20 @@ public void SerializeSchemaWithTypeArrayAndNullableDoesntEmitType() [Theory] [InlineData("schemaWithNullable.yaml")] [InlineData("schemaWithNullableExtension.yaml")] - public void LoadSchemaWithNullableExtensionAsV31Works(string filePath) + public async Task LoadSchemaWithNullableExtensionAsV31Works(string filePath) { // Arrange var path = Path.Combine(SampleFolderPath, filePath); // Act - var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_1, out _); + var schema = await OpenApiModelFactory.LoadAsync(path, OpenApiSpecVersion.OpenApi3_1); // Assert schema.Type.Should().Be(JsonSchemaType.String | JsonSchemaType.Null); } [Fact] - public void SerializeSchemaWithJsonSchemaKeywordsWorks() + public async Task SerializeSchemaWithJsonSchemaKeywordsWorks() { // Arrange var expected = @"$id: https://example.com/schemas/person.schema.yaml @@ -450,7 +451,7 @@ public void SerializeSchemaWithJsonSchemaKeywordsWorks() var path = Path.Combine(SampleFolderPath, "schemaWithJsonSchemaKeywords.yaml"); // Act - var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_1, out _); + var schema = await OpenApiModelFactory.LoadAsync(path, OpenApiSpecVersion.OpenApi3_1); // serialization var writer = new StringWriter(); @@ -463,7 +464,7 @@ public void SerializeSchemaWithJsonSchemaKeywordsWorks() } [Fact] - public void ParseSchemaWithConstWorks() + public async Task ParseSchemaWithConstWorks() { var expected = @"{ ""$schema"": ""https://json-schema.org/draft/2020-12/schema"", @@ -494,7 +495,7 @@ public void ParseSchemaWithConstWorks() var path = Path.Combine(SampleFolderPath, "schemaWithConst.json"); // Act - var schema = OpenApiModelFactory.Load(path, OpenApiSpecVersion.OpenApi3_1, out _); + var schema = await OpenApiModelFactory.LoadAsync(path, OpenApiSpecVersion.OpenApi3_1); schema.Properties["status"].Const.Should().Be("active"); schema.Properties["user"].Properties["role"].Const.Should().Be("admin"); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs index cab621c14..54b468c47 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Expressions; using Microsoft.OpenApi.Models; @@ -21,14 +22,12 @@ public OpenApiCallbackTests() } [Fact] - public void ParseBasicCallbackShouldSucceed() + public async Task ParseBasicCallbackShouldSucceed() { // Act - var callback = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "basicCallback.yaml"), OpenApiSpecVersion.OpenApi3_0, out var diagnostic); + var callback = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "basicCallback.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert - diagnostic.Should().BeEquivalentTo(new OpenApiDiagnostic()); - callback.Should().BeEquivalentTo( new OpenApiCallback { @@ -64,12 +63,12 @@ public void ParseBasicCallbackShouldSucceed() } [Fact] - public void ParseCallbackWithReferenceShouldSucceed() + public async Task ParseCallbackWithReferenceShouldSucceed() { using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "callbackWithReference.yaml")); // Act - var result = OpenApiModelFactory.Load(stream, OpenApiConstants.Yaml); + var result = await OpenApiModelFactory.LoadAsync(stream, OpenApiConstants.Yaml); // Assert var path = result.OpenApiDocument.Paths.First().Value; @@ -122,10 +121,10 @@ public void ParseCallbackWithReferenceShouldSucceed() } [Fact] - public void ParseMultipleCallbacksWithReferenceShouldSucceed() + public async Task ParseMultipleCallbacksWithReferenceShouldSucceed() { // Act - var result = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "multipleCallbacksWithReference.yaml")); + var result = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "multipleCallbacksWithReference.yaml")); // Assert var path = result.OpenApiDocument.Paths.First().Value; diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 2d3b02820..fa6a4dee4 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Interfaces; @@ -106,10 +107,10 @@ public void ParseDocumentFromInlineStringShouldSucceed() } [Fact] - public void ParseBasicDocumentWithMultipleServersShouldSucceed() + public async Task ParseBasicDocumentWithMultipleServersShouldSucceed() { var path = System.IO.Path.Combine(SampleFolderPath, "basicDocumentWithMultipleServers.yaml"); - var result = OpenApiDocument.Load(path); + var result = await OpenApiDocument.LoadAsync(path); result.OpenApiDiagnostic.Errors.Should().BeEmpty(); result.OpenApiDocument.Should().BeEquivalentTo( @@ -137,10 +138,10 @@ public void ParseBasicDocumentWithMultipleServersShouldSucceed() }, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); } [Fact] - public void ParseBrokenMinimalDocumentShouldYieldExpectedDiagnostic() + public async Task ParseBrokenMinimalDocumentShouldYieldExpectedDiagnostic() { using var stream = Resources.GetStream(System.IO.Path.Combine(SampleFolderPath, "brokenMinimalDocument.yaml")); - var result = OpenApiDocument.Load(stream, OpenApiConstants.Yaml); + var result = await OpenApiDocument.LoadAsync(stream, OpenApiConstants.Yaml); result.OpenApiDocument.Should().BeEquivalentTo( new OpenApiDocument @@ -164,9 +165,9 @@ public void ParseBrokenMinimalDocumentShouldYieldExpectedDiagnostic() } [Fact] - public void ParseMinimalDocumentShouldSucceed() + public async Task ParseMinimalDocumentShouldSucceed() { - var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "minimalDocument.yaml")); + var result = await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "minimalDocument.yaml")); result.OpenApiDocument.Should().BeEquivalentTo( new OpenApiDocument @@ -187,10 +188,10 @@ public void ParseMinimalDocumentShouldSucceed() } [Fact] - public void ParseStandardPetStoreDocumentShouldSucceed() + public async Task ParseStandardPetStoreDocumentShouldSucceed() { using var stream = Resources.GetStream(System.IO.Path.Combine(SampleFolderPath, "petStore.yaml")); - var actual = OpenApiDocument.Load(stream, OpenApiConstants.Yaml); + var actual = await OpenApiDocument.LoadAsync(stream, OpenApiConstants.Yaml); var components = new OpenApiComponents { @@ -573,10 +574,10 @@ public void ParseStandardPetStoreDocumentShouldSucceed() } [Fact] - public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() + public async Task ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { using var stream = Resources.GetStream(System.IO.Path.Combine(SampleFolderPath, "petStoreWithTagAndSecurity.yaml")); - var actual = OpenApiDocument.Load(stream, OpenApiConstants.Yaml); + var actual = await OpenApiDocument.LoadAsync(stream, OpenApiConstants.Yaml); var components = new OpenApiComponents { @@ -1085,9 +1086,9 @@ public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() } [Fact] - public void ParsePetStoreExpandedShouldSucceed() + public async Task ParsePetStoreExpandedShouldSucceed() { - var actual = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "petStoreExpanded.yaml")); + var actual = await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "petStoreExpanded.yaml")); // TODO: Create the object in memory and compare with the one read from YAML file. @@ -1096,9 +1097,9 @@ public void ParsePetStoreExpandedShouldSucceed() } [Fact] - public void GlobalSecurityRequirementShouldReferenceSecurityScheme() + public async Task GlobalSecurityRequirementShouldReferenceSecurityScheme() { - var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "securedApi.yaml")); + var result = await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "securedApi.yaml")); var securityRequirement = result.OpenApiDocument.SecurityRequirements.First(); @@ -1107,9 +1108,9 @@ public void GlobalSecurityRequirementShouldReferenceSecurityScheme() } [Fact] - public void HeaderParameterShouldAllowExample() + public async Task HeaderParameterShouldAllowExample() { - var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "apiWithFullHeaderComponent.yaml")); + var result = await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "apiWithFullHeaderComponent.yaml")); var exampleHeader = result.OpenApiDocument.Components?.Headers?["example-header"]; Assert.NotNull(exampleHeader); @@ -1169,7 +1170,7 @@ public void HeaderParameterShouldAllowExample() } [Fact] - public void ParseDocumentWithReferencedSecuritySchemeWorks() + public async Task ParseDocumentWithReferencedSecuritySchemeWorks() { // Act var settings = new OpenApiReaderSettings @@ -1177,7 +1178,7 @@ public void ParseDocumentWithReferencedSecuritySchemeWorks() ReferenceResolution = ReferenceResolutionSetting.ResolveLocalReferences }; - var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "docWithSecuritySchemeReference.yaml"), settings); + var result = await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "docWithSecuritySchemeReference.yaml"), settings); var securityScheme = result.OpenApiDocument.Components.SecuritySchemes["OAuth2"]; // Assert @@ -1186,7 +1187,7 @@ public void ParseDocumentWithReferencedSecuritySchemeWorks() } [Fact] - public void ParseDocumentWithJsonSchemaReferencesWorks() + public async Task ParseDocumentWithJsonSchemaReferencesWorks() { // Arrange using var stream = Resources.GetStream(System.IO.Path.Combine(SampleFolderPath, "docWithJsonSchema.yaml")); @@ -1196,7 +1197,7 @@ public void ParseDocumentWithJsonSchemaReferencesWorks() { ReferenceResolution = ReferenceResolutionSetting.ResolveLocalReferences }; - var result = OpenApiDocument.Load(stream, OpenApiConstants.Yaml, settings); + var result = await OpenApiDocument.LoadAsync(stream, OpenApiConstants.Yaml, settings); var actualSchema = result.OpenApiDocument.Paths["/users/{userId}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; @@ -1206,10 +1207,10 @@ public void ParseDocumentWithJsonSchemaReferencesWorks() } [Fact] - public void ValidateExampleShouldNotHaveDataTypeMismatch() + public async Task ValidateExampleShouldNotHaveDataTypeMismatch() { // Act - var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "documentWithDateExampleInSchema.yaml"), new OpenApiReaderSettings + var result = await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "documentWithDateExampleInSchema.yaml"), new OpenApiReaderSettings { ReferenceResolution = ReferenceResolutionSetting.ResolveLocalReferences @@ -1221,7 +1222,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatch() } [Fact] - public void ParseDocWithRefsUsingProxyReferencesSucceeds() + public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() { // Arrange var expected = new OpenApiDocument @@ -1312,11 +1313,10 @@ public void ParseDocWithRefsUsingProxyReferencesSucceeds() using var stream = Resources.GetStream(System.IO.Path.Combine(SampleFolderPath, "minifiedPetStore.yaml")); // Act - var doc = OpenApiDocument.Load(stream, "yaml").OpenApiDocument; - var actualParam = doc.Paths["/pets"].Operations[OperationType.Get].Parameters.First(); + var doc = (await OpenApiDocument.LoadAsync(stream, "yaml")).OpenApiDocument; + var actualParam = doc.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; var outputDoc = doc.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0).MakeLineBreaksEnvironmentNeutral(); - var output = actualParam.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0); - var expectedParam = expected.Paths["/pets"].Operations[OperationType.Get].Parameters.First(); + var expectedParam = expected.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; // Assert actualParam.Should().BeEquivalentTo(expectedParam, options => options @@ -1397,9 +1397,9 @@ public void ParseBasicDocumentWithServerVariableAndNoDefaultShouldFail() } [Fact] - public void ParseDocumentWithEmptyPathsSucceeds() + public async Task ParseDocumentWithEmptyPathsSucceeds() { - var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "docWithEmptyPaths.yaml")); + var result = await OpenApiDocument.LoadAsync(System.IO.Path.Combine(SampleFolderPath, "docWithEmptyPaths.yaml")); result.OpenApiDiagnostic.Errors.Should().BeEmpty(); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs index eaf802d8c..2d214c9dc 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.IO; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; @@ -20,10 +21,10 @@ public OpenApiEncodingTests() } [Fact] - public void ParseBasicEncodingShouldSucceed() + public async Task ParseBasicEncodingShouldSucceed() { // Act - var encoding = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "basicEncoding.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var encoding = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "basicEncoding.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert encoding.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiExampleTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiExampleTests.cs index 84f028f6b..9b32b0cbf 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiExampleTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiExampleTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Text.Json.Nodes; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; @@ -22,9 +23,9 @@ public OpenApiExampleTests() } [Fact] - public void ParseAdvancedExampleShouldSucceed() + public async Task ParseAdvancedExampleShouldSucceed() { - var example = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "advancedExample.yaml"), OpenApiSpecVersion.OpenApi3_0, out var diagnostic); + var example = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "advancedExample.yaml"), OpenApiSpecVersion.OpenApi3_0); var expected = new OpenApiExample { Value = new JsonObject @@ -62,11 +63,6 @@ public void ParseAdvancedExampleShouldSucceed() } }; - var actualRoot = example.Value["versions"][0]["status"].Root; - var expectedRoot = expected.Value["versions"][0]["status"].Root; - - diagnostic.Errors.Should().BeEmpty(); - example.Should().BeEquivalentTo(expected, options => options.IgnoringCyclicReferences() .Excluding(e => e.Value["versions"][0]["status"].Root) .Excluding(e => e.Value["versions"][0]["id"].Root) @@ -79,9 +75,9 @@ public void ParseAdvancedExampleShouldSucceed() } [Fact] - public void ParseExampleForcedStringSucceed() + public async Task ParseExampleForcedStringSucceed() { - var result= OpenApiDocument.Load(Path.Combine(SampleFolderPath, "explicitString.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "explicitString.yaml")); result.OpenApiDiagnostic.Errors.Should().BeEmpty(); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs index 2fa75cf60..ffe4b9896 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs @@ -4,6 +4,7 @@ using System; using System.IO; using System.Text.Json.Nodes; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; @@ -23,10 +24,10 @@ public OpenApiInfoTests() } [Fact] - public void ParseAdvancedInfoShouldSucceed() + public async Task ParseAdvancedInfoShouldSucceed() { // Act - var openApiInfo = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "advancedInfo.yaml"), OpenApiSpecVersion.OpenApi3_0, out var diagnostic); + var openApiInfo = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "advancedInfo.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert openApiInfo.Should().BeEquivalentTo( @@ -80,10 +81,10 @@ public void ParseAdvancedInfoShouldSucceed() } [Fact] - public void ParseBasicInfoShouldSucceed() + public async Task ParseBasicInfoShouldSucceed() { // Act - var openApiInfo = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "basicInfo.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var openApiInfo = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "basicInfo.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert openApiInfo.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs index 26de35edb..6197cca71 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiMediaTypeTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System.IO; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Models; @@ -24,10 +25,10 @@ public OpenApiMediaTypeTests() } [Fact] - public void ParseMediaTypeWithExampleShouldSucceed() + public async Task ParseMediaTypeWithExampleShouldSucceed() { // Act - var mediaType = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "mediaTypeWithExample.yaml"), OpenApiSpecVersion.OpenApi3_0, out var diagnostic); + var mediaType = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "mediaTypeWithExample.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert mediaType.Should().BeEquivalentTo( @@ -45,10 +46,10 @@ public void ParseMediaTypeWithExampleShouldSucceed() } [Fact] - public void ParseMediaTypeWithExamplesShouldSucceed() + public async Task ParseMediaTypeWithExamplesShouldSucceed() { // Act - var mediaType = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "mediaTypeWithExamples.yaml"), OpenApiSpecVersion.OpenApi3_0, out var diagnostic); + var mediaType = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "mediaTypeWithExamples.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert mediaType.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs index 9ba96bbda..e9c722def 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.References; @@ -21,21 +22,21 @@ public OpenApiOperationTests() } [Fact] - public void OperationWithSecurityRequirementShouldReferenceSecurityScheme() + public async Task OperationWithSecurityRequirementShouldReferenceSecurityScheme() { - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "securedOperation.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "securedOperation.yaml")); - var securityScheme = result.OpenApiDocument.Paths["/"].Operations[OperationType.Get].Security.First().Keys.First(); + var securityScheme = result.OpenApiDocument.Paths["/"].Operations[OperationType.Get].Security[0].Keys.First(); securityScheme.Should().BeEquivalentTo(result.OpenApiDocument.Components.SecuritySchemes.First().Value, options => options.Excluding(x => x.Reference)); } [Fact] - public void ParseOperationWithParameterWithNoLocationShouldSucceed() + public async Task ParseOperationWithParameterWithNoLocationShouldSucceed() { // Act - var operation = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "operationWithParameterWithNoLocation.json"), OpenApiSpecVersion.OpenApi3_0, out _); + var operation = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "operationWithParameterWithNoLocation.json"), OpenApiSpecVersion.OpenApi3_0); var expectedOp = new OpenApiOperation { Tags = diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs index e0f6460aa..837edd165 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs @@ -11,6 +11,7 @@ using Xunit; using Microsoft.OpenApi.Reader.V3; using Microsoft.OpenApi.Services; +using System.Threading.Tasks; namespace Microsoft.OpenApi.Readers.Tests.V3Tests { @@ -49,10 +50,10 @@ public void ParsePathParameterShouldSucceed() } [Fact] - public void ParseQueryParameterShouldSucceed() + public async Task ParseQueryParameterShouldSucceed() { // Act - var parameter = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "queryParameter.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var parameter = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "queryParameter.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( @@ -76,10 +77,10 @@ public void ParseQueryParameterShouldSucceed() } [Fact] - public void ParseQueryParameterWithObjectTypeShouldSucceed() + public async Task ParseQueryParameterWithObjectTypeShouldSucceed() { // Act - var parameter = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "queryParameterWithObjectType.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var parameter = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "queryParameterWithObjectType.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( @@ -144,10 +145,10 @@ public void ParseQueryParameterWithObjectTypeAndContentShouldSucceed() } [Fact] - public void ParseHeaderParameterShouldSucceed() + public async Task ParseHeaderParameterShouldSucceed() { // Act - var parameter = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "headerParameter.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var parameter = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "headerParameter.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( @@ -172,10 +173,10 @@ public void ParseHeaderParameterShouldSucceed() } [Fact] - public void ParseParameterWithNullLocationShouldSucceed() + public async Task ParseParameterWithNullLocationShouldSucceed() { // Act - var parameter = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "parameterWithNullLocation.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var parameter = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "parameterWithNullLocation.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( @@ -241,10 +242,10 @@ public void ParseParameterWithUnknownLocationShouldSucceed() } [Fact] - public void ParseParameterWithExampleShouldSucceed() + public async Task ParseParameterWithExampleShouldSucceed() { // Act - var parameter = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "parameterWithExample.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var parameter = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "parameterWithExample.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( @@ -264,10 +265,10 @@ public void ParseParameterWithExampleShouldSucceed() } [Fact] - public void ParseParameterWithExamplesShouldSucceed() + public async Task ParseParameterWithExamplesShouldSucceed() { // Act - var parameter = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "parameterWithExamples.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var parameter = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "parameterWithExamples.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiResponseTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiResponseTests.cs index 09a1d00a1..4f798ad39 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiResponseTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiResponseTests.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; @@ -21,9 +22,9 @@ public OpenApiResponseTests() } [Fact] - public void ResponseWithReferencedHeaderShouldReferenceComponent() + public async Task ResponseWithReferencedHeaderShouldReferenceComponent() { - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "responseWithHeaderReference.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "responseWithHeaderReference.yaml")); var response = result.OpenApiDocument.Components.Responses["Test"]; var expected = response.Headers.First().Value; diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs index 6c1370626..70bfb4a51 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs @@ -16,6 +16,7 @@ using Microsoft.OpenApi.Reader.V3; using FluentAssertions.Equivalency; using Microsoft.OpenApi.Models.References; +using System.Threading.Tasks; namespace Microsoft.OpenApi.Readers.Tests.V3Tests { @@ -35,7 +36,7 @@ public void ParsePrimitiveSchemaShouldSucceed() using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "primitiveSchema.yaml")); var yamlStream = new YamlStream(); yamlStream.Load(new StreamReader(stream)); - var yamlNode = yamlStream.Documents.First().RootNode; + var yamlNode = yamlStream.Documents[0].RootNode; var diagnostic = new OpenApiDiagnostic(); var context = new ParsingContext(diagnostic); @@ -65,10 +66,9 @@ public void ParseExampleStringFragmentShouldSucceed() ""foo"": ""bar"", ""baz"": [ 1,2] }"; - var diagnostic = new OpenApiDiagnostic(); // Act - var openApiAny = OpenApiModelFactory.Parse(input, OpenApiSpecVersion.OpenApi3_0, out diagnostic); + var openApiAny = OpenApiModelFactory.Parse(input, OpenApiSpecVersion.OpenApi3_0, out var diagnostic); // Assert diagnostic.Should().BeEquivalentTo(new OpenApiDiagnostic()); @@ -89,10 +89,9 @@ public void ParseEnumFragmentShouldSucceed() ""foo"", ""baz"" ]"; - var diagnostic = new OpenApiDiagnostic(); // Act - var openApiAny = OpenApiModelFactory.Parse(input, OpenApiSpecVersion.OpenApi3_0, out diagnostic); + var openApiAny = OpenApiModelFactory.Parse(input, OpenApiSpecVersion.OpenApi3_0, out var diagnostic); // Assert diagnostic.Should().BeEquivalentTo(new OpenApiDiagnostic()); @@ -115,10 +114,9 @@ public void ParsePathFragmentShouldSucceed() '200': description: Ok "; - var diagnostic = new OpenApiDiagnostic(); // Act - var openApiAny = OpenApiModelFactory.Parse(input, OpenApiSpecVersion.OpenApi3_0, out diagnostic, "yaml"); + var openApiAny = OpenApiModelFactory.Parse(input, OpenApiSpecVersion.OpenApi3_0, out var diagnostic, "yaml"); // Assert diagnostic.Should().BeEquivalentTo(new OpenApiDiagnostic()); @@ -150,7 +148,7 @@ public void ParseDictionarySchemaShouldSucceed() { var yamlStream = new YamlStream(); yamlStream.Load(new StreamReader(stream)); - var yamlNode = yamlStream.Documents.First().RootNode; + var yamlNode = yamlStream.Documents[0].RootNode; var diagnostic = new OpenApiDiagnostic(); var context = new ParsingContext(diagnostic); @@ -182,7 +180,7 @@ public void ParseBasicSchemaWithExampleShouldSucceed() using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "basicSchemaWithExample.yaml")); var yamlStream = new YamlStream(); yamlStream.Load(new StreamReader(stream)); - var yamlNode = yamlStream.Documents.First().RootNode; + var yamlNode = yamlStream.Documents[0].RootNode; var diagnostic = new OpenApiDiagnostic(); var context = new ParsingContext(diagnostic); @@ -230,10 +228,10 @@ public void ParseBasicSchemaWithExampleShouldSucceed() } [Fact] - public void ParseBasicSchemaWithReferenceShouldSucceed() + public async Task ParseBasicSchemaWithReferenceShouldSucceed() { // Act - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "basicSchemaWithReference.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "basicSchemaWithReference.yaml")); // Assert var components = result.OpenApiDocument.Components; @@ -296,10 +294,10 @@ public void ParseBasicSchemaWithReferenceShouldSucceed() } [Fact] - public void ParseAdvancedSchemaWithReferenceShouldSucceed() + public async Task ParseAdvancedSchemaWithReferenceShouldSucceed() { // Act - var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "advancedSchemaWithReference.yaml")); + var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "advancedSchemaWithReference.yaml")); var expectedComponents = new OpenApiComponents { diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSecuritySchemeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSecuritySchemeTests.cs index ef1aa0fdb..3f99bb2c5 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSecuritySchemeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSecuritySchemeTests.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; @@ -20,10 +21,10 @@ public OpenApiSecuritySchemeTests() } [Fact] - public void ParseHttpSecuritySchemeShouldSucceed() + public async Task ParseHttpSecuritySchemeShouldSucceed() { // Act - var securityScheme = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "httpSecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var securityScheme = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "httpSecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert securityScheme.Should().BeEquivalentTo( @@ -35,10 +36,10 @@ public void ParseHttpSecuritySchemeShouldSucceed() } [Fact] - public void ParseApiKeySecuritySchemeShouldSucceed() + public async Task ParseApiKeySecuritySchemeShouldSucceed() { // Act - var securityScheme = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "apiKeySecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var securityScheme = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "apiKeySecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert securityScheme.Should().BeEquivalentTo( @@ -51,10 +52,10 @@ public void ParseApiKeySecuritySchemeShouldSucceed() } [Fact] - public void ParseBearerSecuritySchemeShouldSucceed() + public async Task ParseBearerSecuritySchemeShouldSucceed() { // Act - var securityScheme = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "bearerSecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var securityScheme = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "bearerSecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert securityScheme.Should().BeEquivalentTo( @@ -67,10 +68,10 @@ public void ParseBearerSecuritySchemeShouldSucceed() } [Fact] - public void ParseOAuth2SecuritySchemeShouldSucceed() + public async Task ParseOAuth2SecuritySchemeShouldSucceed() { // Act - var securityScheme = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "oauth2SecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var securityScheme = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "oauth2SecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert securityScheme.Should().BeEquivalentTo( @@ -93,10 +94,10 @@ public void ParseOAuth2SecuritySchemeShouldSucceed() } [Fact] - public void ParseOpenIdConnectSecuritySchemeShouldSucceed() + public async Task ParseOpenIdConnectSecuritySchemeShouldSucceed() { // Act - var securityScheme = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "openIdConnectSecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0, out _); + var securityScheme = await OpenApiModelFactory.LoadAsync(Path.Combine(SampleFolderPath, "openIdConnectSecurityScheme.yaml"), OpenApiSpecVersion.OpenApi3_0); // Assert securityScheme.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index 884ffa68c..24ed216db 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -1583,8 +1583,6 @@ public void SerializeDocumentWithReferenceButNoComponents() } }; - var reference = document.Paths["/"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.Reference; - // Act var actual = document.Serialize(OpenApiSpecVersion.OpenApi2_0, OpenApiFormat.Json); @@ -1684,14 +1682,14 @@ public void SerializeRelativeRootPathWithHostAsV2JsonWorks() } [Fact] - public void TestHashCodesForSimilarOpenApiDocuments() + public async Task TestHashCodesForSimilarOpenApiDocuments() { // Arrange var sampleFolderPath = "Models/Samples/"; - var doc1 = ParseInputFile(Path.Combine(sampleFolderPath, "sampleDocument.yaml")); - var doc2 = ParseInputFile(Path.Combine(sampleFolderPath, "sampleDocument.yaml")); - var doc3 = ParseInputFile(Path.Combine(sampleFolderPath, "sampleDocumentWithWhiteSpaces.yaml")); + var doc1 = await ParseInputFileAsync(Path.Combine(sampleFolderPath, "sampleDocument.yaml")); + var doc2 = await ParseInputFileAsync(Path.Combine(sampleFolderPath, "sampleDocument.yaml")); + var doc3 = await ParseInputFileAsync(Path.Combine(sampleFolderPath, "sampleDocumentWithWhiteSpaces.yaml")); // Act && Assert /* @@ -1702,13 +1700,9 @@ And reading in similar documents(one has a whitespace) yields the same hash code Assert.Equal(doc1.HashCode, doc3.HashCode); } - private static OpenApiDocument ParseInputFile(string filePath) + private static async Task ParseInputFileAsync(string filePath) { - // Read in the input yaml file - using FileStream stream = File.OpenRead(filePath); - var format = OpenApiModelFactory.GetFormat(filePath); - var openApiDoc = OpenApiDocument.Load(stream, format).OpenApiDocument; - + var openApiDoc = (await OpenApiDocument.LoadAsync(filePath)).OpenApiDocument; return openApiDoc; } @@ -1999,7 +1993,7 @@ public void SerializeDocumentWithRootJsonSchemaDialectPropertyWorks() } [Fact] - public void SerializeV31DocumentWithRefsInWebhooksWorks() + public async Task SerializeV31DocumentWithRefsInWebhooksWorks() { var expected = @"description: Returns all pets from the system that the user has access to operationId: findPets @@ -2013,7 +2007,7 @@ public void SerializeV31DocumentWithRefsInWebhooksWorks() items: type: object"; - var doc = OpenApiDocument.Load("Models/Samples/docWithReusableWebhooks.yaml").OpenApiDocument; + var doc = (await OpenApiDocument.LoadAsync("Models/Samples/docWithReusableWebhooks.yaml")).OpenApiDocument; var stringWriter = new StringWriter(); var writer = new OpenApiYamlWriter(stringWriter, new OpenApiWriterSettings { InlineLocalReferences = true }); @@ -2025,7 +2019,7 @@ public void SerializeV31DocumentWithRefsInWebhooksWorks() } [Fact] - public void SerializeDocWithDollarIdInDollarRefSucceeds() + public async Task SerializeDocWithDollarIdInDollarRefSucceeds() { var expected = @"openapi: '3.1.1' info: @@ -2067,7 +2061,7 @@ public void SerializeDocWithDollarIdInDollarRefSucceeds() radius: type: number "; - var doc = OpenApiDocument.Load("Models/Samples/docWithDollarId.yaml").OpenApiDocument; + var doc = (await OpenApiDocument.LoadAsync("Models/Samples/docWithDollarId.yaml")).OpenApiDocument; var actual = doc.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_1); actual.MakeLineBreaksEnvironmentNeutral().Should().BeEquivalentTo(expected.MakeLineBreaksEnvironmentNeutral()); From 627d75b37483377d06d7fe36709d35f22fd99978 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 28 Nov 2024 18:46:48 +0300 Subject: [PATCH 038/127] Dispose stream --- src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index 1a85e6a27..08a9190f6 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -29,7 +29,9 @@ public async Task ReadAsync(Stream input, if (input is MemoryStream memoryStream) { return Read(memoryStream, settings); - } else { + } + else + { using var preparedStream = new MemoryStream(); await input.CopyToAsync(preparedStream, copyBufferSize, cancellationToken); preparedStream.Position = 0; @@ -39,14 +41,15 @@ public async Task ReadAsync(Stream input, /// public ReadResult Read(MemoryStream input, - OpenApiReaderSettings settings = null) + OpenApiReaderSettings settings = null) { JsonNode jsonNode; // Parse the YAML text in the TextReader into a sequence of JsonNodes try { - jsonNode = LoadJsonNodesFromYamlDocument(new StreamReader(input)); // Should we leave the stream open? + using var stream = new StreamReader(input); + jsonNode = LoadJsonNodesFromYamlDocument(stream); } catch (JsonException ex) { @@ -73,7 +76,8 @@ public T ReadFragment(MemoryStream input, // Parse the YAML try { - jsonNode = LoadJsonNodesFromYamlDocument(new StreamReader(input)); + using var stream = new StreamReader(input); + jsonNode = LoadJsonNodesFromYamlDocument(stream); } catch (JsonException ex) { From 46718f0e4e978fca7e719f25cc94bfb8fd092cfc Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 28 Nov 2024 18:48:01 +0300 Subject: [PATCH 039/127] clean up and dispose stream if specified in the settings --- .../Reader/OpenApiJsonReader.cs | 4 ---- .../Reader/OpenApiModelFactory.cs | 16 +++++++++++++--- .../V3Tests/OpenApiDiscriminatorTests.cs | 1 + 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index d24d31b9d..25add6e39 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -11,11 +11,7 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.Validations; using System.Linq; -using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Interfaces; -using Microsoft.OpenApi.Reader.Services; -using System.Collections.Generic; -using System; namespace Microsoft.OpenApi.Reader { diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 65268394a..2884dd803 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -118,7 +118,7 @@ public static async Task LoadAsync(string url, OpenApiReaderSettings public static async Task LoadAsync(string url, OpenApiSpecVersion version, OpenApiReaderSettings settings = null) where T : IOpenApiElement { var result = await RetrieveStreamAndFormatAsync(url); - return Load(result.Item1 as MemoryStream, version, result.Item2, out var diagnostic, settings); + return Load(result.Item1, version, result.Item2, out var diagnostic, settings); } /// @@ -149,8 +149,18 @@ public static async Task LoadAsync(Stream input, string format = nul preparedStream.Position = 0; } - // Use StreamReader to process the prepared stream (buffered for YAML, direct for JSON) - return await InternalLoadAsync(preparedStream, format, settings, cancellationToken); + try + { + // Use StreamReader to process the prepared stream (buffered for YAML, direct for JSON) + return await InternalLoadAsync(preparedStream, format, settings, cancellationToken); + } + finally + { + if (!settings.LeaveStreamOpen) + { + input.Dispose(); + } + } } /// diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDiscriminatorTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDiscriminatorTests.cs index bcbc6a02a..ba62c7f33 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDiscriminatorTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDiscriminatorTests.cs @@ -28,6 +28,7 @@ public async Task ParseBasicDiscriminatorShouldSucceed() // Copy stream to MemoryStream using var memoryStream = new MemoryStream(); await stream.CopyToAsync(memoryStream); + memoryStream.Position = 0; // Act var discriminator = OpenApiModelFactory.Load(memoryStream, OpenApiSpecVersion.OpenApi3_0, OpenApiConstants.Yaml, out var diagnostic); From bd6461253543ede124040f02994ec01c4cace41b Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 28 Nov 2024 18:48:09 +0300 Subject: [PATCH 040/127] Update public API --- .../PublicApi/PublicApi.approved.txt | 34 ++++++++----------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 8f9f8ed41..822b3048a 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -219,9 +219,10 @@ namespace Microsoft.OpenApi.Interfaces } public interface IOpenApiReader { - System.Threading.Tasks.Task ReadAsync(System.IO.TextReader input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default); - System.Threading.Tasks.Task ReadAsync(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null, System.Threading.CancellationToken cancellationToken = default); - T ReadFragment(System.IO.TextReader input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) + Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null); + Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null); + System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default); + T ReadFragment(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement; T ReadFragment(System.Text.Json.Nodes.JsonNode input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement; @@ -577,11 +578,8 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SetReferenceHostDocument() { } public static string GenerateHashValue(Microsoft.OpenApi.Models.OpenApiDocument doc) { } - public static Microsoft.OpenApi.Reader.ReadResult Load(string url, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } - public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.Stream stream, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } - public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.TextReader input, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } + public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.MemoryStream stream, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } public static System.Threading.Tasks.Task LoadAsync(string url, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } - public static System.Threading.Tasks.Task LoadAsync(System.IO.TextReader input, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } public static System.Threading.Tasks.Task LoadAsync(System.IO.Stream stream, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null, System.Threading.CancellationToken cancellationToken = default) { } public static Microsoft.OpenApi.Reader.ReadResult Parse(string input, string? format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } } @@ -1315,32 +1313,28 @@ namespace Microsoft.OpenApi.Reader public class OpenApiJsonReader : Microsoft.OpenApi.Interfaces.IOpenApiReader { public OpenApiJsonReader() { } - public System.Threading.Tasks.Task ReadAsync(System.IO.TextReader input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default) { } - public System.Threading.Tasks.Task ReadAsync(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null, System.Threading.CancellationToken cancellationToken = default) { } - public T ReadFragment(System.IO.TextReader input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) + public Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } + public Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null) { } + public System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default) { } + public T ReadFragment(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } public T ReadFragment(System.Text.Json.Nodes.JsonNode input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } } public static class OpenApiModelFactory { - public static string GetFormat(string url) { } - public static Microsoft.OpenApi.Reader.ReadResult Load(string url, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } - public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.Stream stream, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } - public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.TextReader input, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } - public static T Load(string url, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) + public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.MemoryStream stream, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } + public static T Load(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, string format, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } public static T Load(System.IO.Stream input, Microsoft.OpenApi.OpenApiSpecVersion version, string format, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } - public static T Load(System.IO.TextReader input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) - where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } public static System.Threading.Tasks.Task LoadAsync(string url, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } - public static System.Threading.Tasks.Task LoadAsync(System.IO.Stream input, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default) { } - public static System.Threading.Tasks.Task LoadAsync(System.IO.TextReader input, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.Task LoadAsync(System.IO.Stream input, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.Task LoadAsync(string url, Microsoft.OpenApi.OpenApiSpecVersion version, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) + where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } public static Microsoft.OpenApi.Reader.ReadResult Parse(string input, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } public static T Parse(string input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } - public static System.Threading.Tasks.Task ParseAsync(string input, System.IO.StringReader reader, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } } public static class OpenApiReaderRegistry { From a2f70aea67df13cdb3121bdb30929d06fbab7b81 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 28 Nov 2024 18:54:06 +0300 Subject: [PATCH 041/127] Leave stream open if specified in settings --- src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index 08a9190f6..1ee22e8b2 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -48,7 +48,7 @@ public ReadResult Read(MemoryStream input, // Parse the YAML text in the TextReader into a sequence of JsonNodes try { - using var stream = new StreamReader(input); + using var stream = new StreamReader(input, default, true, -1, settings.LeaveStreamOpen); jsonNode = LoadJsonNodesFromYamlDocument(stream); } catch (JsonException ex) From 8bbb3dd9abde2fce6b3a14a4f31967e2dacbbf3c Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 28 Nov 2024 19:01:14 +0300 Subject: [PATCH 042/127] Guard against null references --- src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs | 2 +- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index 1ee22e8b2..db7482f44 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -48,7 +48,7 @@ public ReadResult Read(MemoryStream input, // Parse the YAML text in the TextReader into a sequence of JsonNodes try { - using var stream = new StreamReader(input, default, true, -1, settings.LeaveStreamOpen); + using var stream = new StreamReader(input, default, true, -1, settings?.LeaveStreamOpen); jsonNode = LoadJsonNodesFromYamlDocument(stream); } catch (JsonException ex) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 2884dd803..e1db00832 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -210,7 +210,7 @@ private static async Task InternalLoadAsync(Stream input, string for var reader = OpenApiReaderRegistry.GetReader(format); var readResult = await reader.ReadAsync(input, settings, cancellationToken); - if (settings.LoadExternalRefs) + if (settings is not null && settings.LoadExternalRefs) { var diagnosticExternalRefs = await LoadExternalRefsAsync(readResult.OpenApiDocument, cancellationToken, settings, format); // Merge diagnostics of external reference @@ -239,7 +239,7 @@ private static async Task LoadExternalRefsAsync(OpenApiDocume private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings = null) { Utils.CheckArgumentNull(format, nameof(format)); - if (settings.LoadExternalRefs) + if (settings is not null && settings.LoadExternalRefs) { throw new InvalidOperationException("Loading external references are not supported when using synchronous methods."); } From cecf011bf3b0e1f69d8b808eeda8e3a6e0e7bd54 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 28 Nov 2024 19:10:45 +0300 Subject: [PATCH 043/127] code cleanup --- .../OpenApiYamlReader.cs | 6 ++--- .../Interfaces/IOpenApiReader.cs | 4 ++-- .../Reader/OpenApiJsonReader.cs | 6 ++--- .../Reader/OpenApiModelFactory.cs | 24 ++++++++----------- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index db7482f44..8639798d6 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -23,7 +23,7 @@ public class OpenApiYamlReader : IOpenApiReader /// public async Task ReadAsync(Stream input, - OpenApiReaderSettings settings = null, + OpenApiReaderSettings settings, CancellationToken cancellationToken = default) { if (input is MemoryStream memoryStream) @@ -41,14 +41,14 @@ public async Task ReadAsync(Stream input, /// public ReadResult Read(MemoryStream input, - OpenApiReaderSettings settings = null) + OpenApiReaderSettings settings) { JsonNode jsonNode; // Parse the YAML text in the TextReader into a sequence of JsonNodes try { - using var stream = new StreamReader(input, default, true, -1, settings?.LeaveStreamOpen); + using var stream = new StreamReader(input, default, true, -1, settings.LeaveStreamOpen); jsonNode = LoadJsonNodesFromYamlDocument(stream); } catch (JsonException ex) diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs index b746b857b..642572985 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs @@ -21,7 +21,7 @@ public interface IOpenApiReader /// The OpenApi reader settings. /// Propagates notification that an operation should be cancelled. /// - Task ReadAsync(Stream input, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default); + Task ReadAsync(Stream input, OpenApiReaderSettings settings, CancellationToken cancellationToken = default); /// /// Provides a synchronous method to read the input memory stream and parse it into an Open API document. @@ -29,7 +29,7 @@ public interface IOpenApiReader /// /// /// - ReadResult Read(MemoryStream input, OpenApiReaderSettings settings = null); + ReadResult Read(MemoryStream input, OpenApiReaderSettings settings); /// /// Parses the JsonNode input into an Open API document. diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 25add6e39..ec696abd5 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -61,7 +61,7 @@ public ReadResult Read(MemoryStream input, /// Propagates notifications that operations should be cancelled. /// public async Task ReadAsync(Stream input, - OpenApiReaderSettings settings = null, + OpenApiReaderSettings settings, CancellationToken cancellationToken = default) { JsonNode jsonNode; @@ -94,8 +94,8 @@ public async Task ReadAsync(Stream input, /// The OpenAPI format. /// public ReadResult Read(JsonNode jsonNode, - OpenApiReaderSettings settings, - string format = null) + OpenApiReaderSettings settings, + string format = null) { var diagnostic = new OpenApiDiagnostic(); var context = new ParsingContext(diagnostic) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index e1db00832..b9abca5ab 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -149,18 +149,14 @@ public static async Task LoadAsync(Stream input, string format = nul preparedStream.Position = 0; } - try + // Use StreamReader to process the prepared stream (buffered for YAML, direct for JSON) + var result = await InternalLoadAsync(preparedStream, format, settings, cancellationToken); + if (!settings.LeaveStreamOpen) { - // Use StreamReader to process the prepared stream (buffered for YAML, direct for JSON) - return await InternalLoadAsync(preparedStream, format, settings, cancellationToken); - } - finally - { - if (!settings.LeaveStreamOpen) - { - input.Dispose(); - } + input.Dispose(); } + + return result; } /// @@ -204,13 +200,13 @@ public static T Parse(string input, return Load(stream, version, format, out diagnostic, settings); } - private static async Task InternalLoadAsync(Stream input, string format, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) + private static async Task InternalLoadAsync(Stream input, string format, OpenApiReaderSettings settings, CancellationToken cancellationToken = default) { Utils.CheckArgumentNull(format, nameof(format)); var reader = OpenApiReaderRegistry.GetReader(format); var readResult = await reader.ReadAsync(input, settings, cancellationToken); - if (settings is not null && settings.LoadExternalRefs) + if (settings.LoadExternalRefs) { var diagnosticExternalRefs = await LoadExternalRefsAsync(readResult.OpenApiDocument, cancellationToken, settings, format); // Merge diagnostics of external reference @@ -236,10 +232,10 @@ private static async Task LoadExternalRefsAsync(OpenApiDocume return await workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource = "/" }, document, format ?? OpenApiConstants.Json, null, cancellationToken); } - private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings = null) + private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings) { Utils.CheckArgumentNull(format, nameof(format)); - if (settings is not null && settings.LoadExternalRefs) + if (settings.LoadExternalRefs) { throw new InvalidOperationException("Loading external references are not supported when using synchronous methods."); } From fe77796702e82a0339f778d8959cd094c1eeddb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Nov 2024 21:12:38 +0000 Subject: [PATCH 044/127] chore(deps): bump Verify.Xunit from 28.3.2 to 28.4.0 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 28.3.2 to 28.4.0. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/28.3.2...28.4.0) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 68ed9fa2c..7a75e9e17 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -14,7 +14,7 @@ - + From be3bbf51c56a6994e383ffa067eabce4e14ad101 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 2 Dec 2024 11:07:53 +0300 Subject: [PATCH 045/127] Update public API --- .../PublicApi/PublicApi.approved.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 822b3048a..3200dfb65 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -219,9 +219,9 @@ namespace Microsoft.OpenApi.Interfaces } public interface IOpenApiReader { - Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null); + Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings); Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null); - System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default); + System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, System.Threading.CancellationToken cancellationToken = default); T ReadFragment(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement; T ReadFragment(System.Text.Json.Nodes.JsonNode input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) @@ -1315,7 +1315,7 @@ namespace Microsoft.OpenApi.Reader public OpenApiJsonReader() { } public Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } public Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null) { } - public System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default) { } + public System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, System.Threading.CancellationToken cancellationToken = default) { } public T ReadFragment(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } public T ReadFragment(System.Text.Json.Nodes.JsonNode input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) From 408e793cfe1fcf76c5a89f1e5af2122e4c7881a9 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 2 Dec 2024 12:00:33 +0300 Subject: [PATCH 046/127] remove extra semi-colon and commented out code --- src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index ec696abd5..61290e48d 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -71,7 +71,7 @@ public async Task ReadAsync(Stream input, // Parse the JSON text in the TextReader into JsonNodes try { - jsonNode = await JsonNode.ParseAsync(input);; + jsonNode = await JsonNode.ParseAsync(input); } catch (JsonException ex) { @@ -110,18 +110,6 @@ public ReadResult Read(JsonNode jsonNode, { // Parse the OpenAPI Document document = context.Parse(jsonNode); - - // if (settings.LoadExternalRefs) - // { - // var diagnosticExternalRefs = await LoadExternalRefsAsync(document, cancellationToken, settings, format); - // // Merge diagnostics of external reference - // if (diagnosticExternalRefs != null) - // { - // diagnostic.Errors.AddRange(diagnosticExternalRefs.Errors); - // diagnostic.Warnings.AddRange(diagnosticExternalRefs.Warnings); - // } - // } - document.SetReferenceHostDocument(); } catch (OpenApiException ex) From 7acdf9b7fcca2e5285cf9ee6231ff69a1f4db38b Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 2 Dec 2024 12:12:16 +0300 Subject: [PATCH 047/127] Remove unnecessary using --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index b9abca5ab..69d0de388 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. using System; -using System.Buffers.Text; using System.IO; using System.Linq; using System.Net.Http; From 36df13d07d57f65815d968f7698b052e9ce0f021 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Dec 2024 22:18:04 +0000 Subject: [PATCH 048/127] chore(deps): bump docker/build-push-action from 6.9.0 to 6.10.0 Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6.9.0 to 6.10.0. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6.9.0...v6.10.0) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a2a2bb104..e01c89f0f 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,13 +30,13 @@ jobs: id: getversion - name: Push to GitHub Packages - Nightly if: ${{ github.ref == 'refs/heads/vnext' }} - uses: docker/build-push-action@v6.9.0 + uses: docker/build-push-action@v6.10.0 with: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly - name: Push to GitHub Packages - Release if: ${{ github.ref == 'refs/heads/master' }} - uses: docker/build-push-action@v6.9.0 + uses: docker/build-push-action@v6.10.0 with: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest,${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.getversion.outputs.version }} From dc25f9ec7658a8c6aaaf76afa03094bed813ea22 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 3 Dec 2024 11:00:53 +0300 Subject: [PATCH 049/127] Inspect string input's format if not explicitly provided --- .../Reader/OpenApiModelFactory.cs | 10 +++++++--- .../V3Tests/OpenApiDocumentTests.cs | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 69d0de388..71dfbbb2c 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -169,7 +169,7 @@ public static ReadResult Parse(string input, string format = null, OpenApiReaderSettings settings = null) { - format ??= OpenApiConstants.Json; + format ??= InspectInputFormat(input); settings ??= new OpenApiReaderSettings(); // Copy string into MemoryStream @@ -193,7 +193,7 @@ public static T Parse(string input, string format = null, OpenApiReaderSettings settings = null) where T : IOpenApiElement { - format ??= OpenApiConstants.Json; + format ??= InspectInputFormat(input); settings ??= new OpenApiReaderSettings(); var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); return Load(stream, version, format, out diagnostic, settings); @@ -201,7 +201,6 @@ public static T Parse(string input, private static async Task InternalLoadAsync(Stream input, string format, OpenApiReaderSettings settings, CancellationToken cancellationToken = default) { - Utils.CheckArgumentNull(format, nameof(format)); var reader = OpenApiReaderRegistry.GetReader(format); var readResult = await reader.ReadAsync(input, settings, cancellationToken); @@ -289,5 +288,10 @@ SecurityException or } return (null, null); } + + private static string InspectInputFormat(string input) + { + return input.StartsWith("{", StringComparison.OrdinalIgnoreCase) || input.StartsWith("[", StringComparison.OrdinalIgnoreCase) ? OpenApiConstants.Json : OpenApiConstants.Yaml; + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index fa6a4dee4..daf253af3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -106,6 +106,21 @@ public void ParseDocumentFromInlineStringShouldSucceed() }); } + [Fact] + public void ParseInlineStringWithoutProvidingFormatSucceeds() + { + var stringOpenApiDoc = """ +openapi: 3.1.0 +info: + title: Sample API + version: 1.0.0 +paths: {} +"""; + + var readResult = OpenApiDocument.Parse(stringOpenApiDoc); + readResult.OpenApiDocument.Info.Title.Should().Be("Sample API"); + } + [Fact] public async Task ParseBasicDocumentWithMultipleServersShouldSucceed() { From 76d581bc94e86f7d412e9d2d240764a44e3bf388 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 3 Dec 2024 11:31:25 +0300 Subject: [PATCH 050/127] Adds required pipeline metadata --- .azure-pipelines/ci-build.yml | 36 ++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index f381a4303..28d442b3a 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -210,6 +210,13 @@ extends: dependsOn: build jobs: - deployment: deploy_hidi + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + artifactName: Nugets + targetPath: '$(Pipeline.Workspace)' dependsOn: [] environment: nuget-org strategy: @@ -218,11 +225,6 @@ extends: pool: vmImage: ubuntu-latest steps: - - task: DownloadPipelineArtifact@2 - displayName: Download nupkg from artifacts - inputs: - artifact: Nugets - source: current - task: DownloadPipelineArtifact@2 displayName: Download hidi executable from artifacts inputs: @@ -264,6 +266,13 @@ extends: ]' - deployment: deploy_lib + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + artifactName: Nugets + targetPath: '$(Pipeline.Workspace)' dependsOn: [] environment: nuget-org strategy: @@ -272,11 +281,6 @@ extends: pool: vmImage: ubuntu-latest steps: - - task: DownloadPipelineArtifact@2 - displayName: Download nupkg from artifacts - inputs: - artifact: Nugets - source: current - powershell: | $fileNames = "$(Pipeline.Workspace)/Nugets/Microsoft.OpenApi.Hidi.*.nupkg", "$(Pipeline.Workspace)/Nugets/Microsoft.OpenApi.Readers.*.nupkg", "$(Pipeline.Workspace)/Nugets/Microsoft.OpenApi.Workbench.*.nupkg" foreach($fileName in $fileNames) { @@ -294,6 +298,13 @@ extends: publishFeedCredentials: 'OpenAPI Nuget Connection' - deployment: deploy_readers + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + artifactName: Nugets + targetPath: '$(Pipeline.Workspace)' dependsOn: deploy_lib environment: nuget-org strategy: @@ -302,11 +313,6 @@ extends: pool: vmImage: ubuntu-latest steps: - - task: DownloadPipelineArtifact@2 - displayName: Download nupkg from artifacts - inputs: - artifact: Nugets - source: current - task: 1ES.PublishNuget@1 displayName: 'NuGet push' inputs: From 63ab53f3125b2ad729d77c9689a8fbc6931ebd19 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 3 Dec 2024 12:40:44 +0300 Subject: [PATCH 051/127] Remove unnecessary using and whitespace --- src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs | 1 - src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 61290e48d..0494bc1e1 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -20,7 +20,6 @@ namespace Microsoft.OpenApi.Reader /// public class OpenApiJsonReader : IOpenApiReader { - /// /// Reads the memory stream input and parses it into an Open API document. /// diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 71dfbbb2c..e2c95c687 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -1,10 +1,11 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using System.IO; using System.Linq; using System.Net.Http; +using System.Runtime.InteropServices.ComTypes; using System.Security; using System.Text; using System.Threading; From ef765f109bd42506d8485ec228291aafbf63b404 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 21:16:52 +0000 Subject: [PATCH 052/127] chore(deps): bump FluentAssertions from 6.12.2 to 7.0.0 Bumps [FluentAssertions](https://github.com/fluentassertions/fluentassertions) from 6.12.2 to 7.0.0. - [Release notes](https://github.com/fluentassertions/fluentassertions/releases) - [Changelog](https://github.com/fluentassertions/fluentassertions/blob/develop/AcceptApiChanges.ps1) - [Commits](https://github.com/fluentassertions/fluentassertions/compare/6.12.2...7.0.0) --- updated-dependencies: - dependency-name: FluentAssertions dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .../Microsoft.OpenApi.Readers.Tests.csproj | 2 +- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index eeac984a0..44f01df94 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -18,7 +18,7 @@ - + diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 7a75e9e17..49653747d 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -10,7 +10,7 @@ - + From d022fa4bdd25dee8a246497ff11b636076ae9c69 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 5 Dec 2024 15:28:32 +0300 Subject: [PATCH 053/127] Remove unnecessary using --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index e2c95c687..7f3857089 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Net.Http; -using System.Runtime.InteropServices.ComTypes; using System.Security; using System.Text; using System.Threading; From 04af1a6f90b82c7dc7ad2ccac68b6f13668c6baa Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 5 Dec 2024 16:10:57 +0300 Subject: [PATCH 054/127] Make format optional; add logic for inspecting stream format --- .../Models/OpenApiDocument.cs | 4 +- .../Reader/OpenApiModelFactory.cs | 100 +++++++++++++++--- .../OpenApiStreamReaderTests.cs | 8 +- .../V3Tests/OpenApiDocumentTests.cs | 7 +- .../V3Tests/OpenApiEncodingTests.cs | 2 +- .../V3Tests/OpenApiInfoTests.cs | 2 +- .../V3Tests/OpenApiParameterTests.cs | 8 +- .../V3Tests/OpenApiXmlTests.cs | 2 +- .../PublicApi/PublicApi.approved.txt | 8 +- 9 files changed, 107 insertions(+), 34 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 13de5f7f8..25b605d6d 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -543,7 +543,7 @@ private static string ConvertByteArrayToString(byte[] hash) /// The OpenApi reader settings. /// public static ReadResult Load(MemoryStream stream, - string format, + string? format = null, OpenApiReaderSettings? settings = null) { return OpenApiModelFactory.Load(stream, format, settings); @@ -568,7 +568,7 @@ public static async Task LoadAsync(string url, OpenApiReaderSettings /// The OpenApi reader settings. /// Propagates information about operation cancelling. /// - public static async Task LoadAsync(Stream stream, string format, OpenApiReaderSettings? settings = null, CancellationToken cancellationToken = default) + public static async Task LoadAsync(Stream stream, string? format = null, OpenApiReaderSettings? settings = null, CancellationToken cancellationToken = default) { return await OpenApiModelFactory.LoadAsync(stream, format, settings, cancellationToken); } diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 7f3857089..2bb3cb8a3 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -36,11 +36,13 @@ static OpenApiModelFactory() /// The OpenAPI format. /// An OpenAPI document instance. public static ReadResult Load(MemoryStream stream, - string format, + string format = null, OpenApiReaderSettings settings = null) { settings ??= new OpenApiReaderSettings(); + // Get the format of the stream if not provided + format ??= InspectStreamFormat(stream); var result = InternalLoad(stream, format, settings); if (!settings.LeaveStreamOpen) @@ -61,7 +63,11 @@ public static ReadResult Load(MemoryStream stream, /// /// /// - public static T Load(Stream input, OpenApiSpecVersion version, string format, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement + public static T Load(Stream input, + OpenApiSpecVersion version, + out OpenApiDiagnostic diagnostic, + string format = null, + OpenApiReaderSettings settings = null) where T : IOpenApiElement { if (input is MemoryStream memoryStream) { @@ -89,7 +95,7 @@ public static T Load(Stream input, OpenApiSpecVersion version, string format, /// The OpenAPI element. public static T Load(MemoryStream input, OpenApiSpecVersion version, string format, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement { - format ??= OpenApiConstants.Json; + format ??= InspectStreamFormat(input); return OpenApiReaderRegistry.GetReader(format).ReadFragment(input, version, out diagnostic, settings); } @@ -117,7 +123,7 @@ public static async Task LoadAsync(string url, OpenApiReaderSettings public static async Task LoadAsync(string url, OpenApiSpecVersion version, OpenApiReaderSettings settings = null) where T : IOpenApiElement { var result = await RetrieveStreamAndFormatAsync(url); - return Load(result.Item1, version, result.Item2, out var diagnostic, settings); + return Load(result.Item1, version, out var diagnostic, result.Item2, settings); } /// @@ -130,22 +136,17 @@ public static async Task LoadAsync(string url, OpenApiSpecVersion version, /// public static async Task LoadAsync(Stream input, string format = null, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) { - Utils.CheckArgumentNull(format, nameof(format)); settings ??= new OpenApiReaderSettings(); - Stream preparedStream; - - // Avoid buffering for JSON documents - if (input is MemoryStream || format.Equals(OpenApiConstants.Json, StringComparison.OrdinalIgnoreCase)) + if (format is null) { - preparedStream = input; + var readResult = await PrepareStreamForReadingAsync(input, format, cancellationToken); + preparedStream = readResult.Item1; + format = readResult.Item2; } else { - // Buffer stream for non-JSON formats (e.g., YAML) since they require synchronous reading - preparedStream = new MemoryStream(); - await input.CopyToAsync(preparedStream, 81920, cancellationToken); - preparedStream.Position = 0; + preparedStream = input; } // Use StreamReader to process the prepared stream (buffered for YAML, direct for JSON) @@ -232,7 +233,6 @@ private static async Task LoadExternalRefsAsync(OpenApiDocume private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings) { - Utils.CheckArgumentNull(format, nameof(format)); if (settings.LoadExternalRefs) { throw new InvalidOperationException("Loading external references are not supported when using synchronous methods."); @@ -293,5 +293,73 @@ private static string InspectInputFormat(string input) { return input.StartsWith("{", StringComparison.OrdinalIgnoreCase) || input.StartsWith("[", StringComparison.OrdinalIgnoreCase) ? OpenApiConstants.Json : OpenApiConstants.Yaml; } + + private static string InspectStreamFormat(Stream stream) + { + if (stream == null) throw new ArgumentNullException(nameof(stream)); + + long initialPosition = stream.Position; + int firstByte = stream.ReadByte(); + + // Skip whitespace if present and read the next non-whitespace byte + if (char.IsWhiteSpace((char)firstByte)) + { + firstByte = stream.ReadByte(); + } + + stream.Position = initialPosition; // Reset the stream position to the beginning + + char firstChar = (char)firstByte; + return firstChar switch + { + '{' or '[' => OpenApiConstants.Json, // If the first character is '{' or '[', assume JSON + _ => OpenApiConstants.Yaml // Otherwise assume YAML + }; + } + + private static async Task<(Stream, string)> PrepareStreamForReadingAsync(Stream input, string format, CancellationToken token = default) + { + Stream preparedStream = input; + + if (!input.CanSeek) + { + // Use a temporary buffer to read a small portion for format detection + using var bufferStream = new MemoryStream(); + await input.CopyToAsync(bufferStream, 1024, token); + bufferStream.Position = 0; + + // Inspect the format from the buffered portion + format ??= InspectStreamFormat(bufferStream); + + // If format is JSON, no need to buffer further — use the original stream. + if (format.Equals(OpenApiConstants.Json, StringComparison.OrdinalIgnoreCase)) + { + preparedStream = input; + } + else + { + // YAML or other non-JSON format; copy remaining input to a new stream. + preparedStream = new MemoryStream(); + bufferStream.Position = 0; + await bufferStream.CopyToAsync(preparedStream, 81920, token); // Copy buffered portion + await input.CopyToAsync(preparedStream, 81920, token); // Copy remaining data + preparedStream.Position = 0; + } + } + else + { + format ??= InspectStreamFormat(input); + + if (!format.Equals(OpenApiConstants.Json, StringComparison.OrdinalIgnoreCase)) + { + // Buffer stream for non-JSON formats (e.g., YAML) since they require synchronous reading + preparedStream = new MemoryStream(); + await input.CopyToAsync(preparedStream, 81920, token); + preparedStream.Position = 0; + } + } + + return (preparedStream, format); + } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs index 91407f0b7..9ce10d22e 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs @@ -25,7 +25,7 @@ public async Task StreamShouldCloseIfLeaveStreamOpenSettingEqualsFalse() { using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "petStore.yaml")); var settings = new OpenApiReaderSettings { LeaveStreamOpen = false }; - _ = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + _ = await OpenApiDocument.LoadAsync(stream, settings: settings); Assert.False(stream.CanRead); } @@ -34,7 +34,7 @@ public async Task StreamShouldNotCloseIfLeaveStreamOpenSettingEqualsTrue() { using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "petStore.yaml")); var settings = new OpenApiReaderSettings { LeaveStreamOpen = true }; - _ = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + _ = await OpenApiDocument.LoadAsync(stream, settings: settings); Assert.True(stream.CanRead); } @@ -48,7 +48,7 @@ public async Task StreamShouldNotBeDisposedIfLeaveStreamOpenSettingIsTrueAsync() memoryStream.Position = 0; var stream = memoryStream; - _ = await OpenApiDocument.LoadAsync(stream, "yaml", new OpenApiReaderSettings { LeaveStreamOpen = true }); + _ = await OpenApiDocument.LoadAsync(stream, settings: new OpenApiReaderSettings { LeaveStreamOpen = true }); stream.Seek(0, SeekOrigin.Begin); // does not throw an object disposed exception Assert.True(stream.CanRead); } @@ -64,7 +64,7 @@ public async Task StreamShouldReadWhenInitializedAsync() var stream = await httpClient.GetStreamAsync("20fe7a7b720a0e48e5842d002ac418b12a8201df/tests/v3.0/pass/petstore.yaml"); // Read V3 as YAML - var result = await OpenApiDocument.LoadAsync(stream, "yaml"); + var result = await OpenApiDocument.LoadAsync(stream); Assert.NotNull(result.OpenApiDocument); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index daf253af3..aeb0a301f 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -156,7 +156,12 @@ public async Task ParseBasicDocumentWithMultipleServersShouldSucceed() public async Task ParseBrokenMinimalDocumentShouldYieldExpectedDiagnostic() { using var stream = Resources.GetStream(System.IO.Path.Combine(SampleFolderPath, "brokenMinimalDocument.yaml")); - var result = await OpenApiDocument.LoadAsync(stream, OpenApiConstants.Yaml); + // Copy stream to MemoryStream + using var memoryStream = new MemoryStream(); + await stream.CopyToAsync(memoryStream); + memoryStream.Position = 0; + + var result = OpenApiDocument.Load(memoryStream); result.OpenApiDocument.Should().BeEquivalentTo( new OpenApiDocument diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs index 2d214c9dc..c2d34493b 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs @@ -40,7 +40,7 @@ public void ParseAdvancedEncodingShouldSucceed() using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "advancedEncoding.yaml")); // Act - var encoding = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, OpenApiConstants.Yaml, out _); + var encoding = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _); // Assert encoding.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs index ffe4b9896..25da65e9d 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs @@ -114,7 +114,7 @@ public void ParseMinimalInfoShouldSucceed() using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "minimalInfo.yaml")); // Act - var openApiInfo = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, "yaml", out _); + var openApiInfo = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _, "yaml"); // Assert openApiInfo.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs index 837edd165..638c47c4a 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs @@ -32,7 +32,7 @@ public void ParsePathParameterShouldSucceed() using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "pathParameter.yaml")); // Act - var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, "yaml", out _); + var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _, "yaml"); // Assert parameter.Should().BeEquivalentTo( @@ -107,7 +107,7 @@ public void ParseQueryParameterWithObjectTypeAndContentShouldSucceed() using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "queryParameterWithObjectTypeAndContent.yaml")); // Act - var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, "yaml", out _); + var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _, "yaml"); // Assert parameter.Should().BeEquivalentTo( @@ -200,7 +200,7 @@ public void ParseParameterWithNoLocationShouldSucceed() using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "parameterWithNoLocation.yaml")); // Act - var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, "yaml", out _); + var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _); // Assert parameter.Should().BeEquivalentTo( @@ -224,7 +224,7 @@ public void ParseParameterWithUnknownLocationShouldSucceed() using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "parameterWithUnknownLocation.yaml")); // Act - var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, "yaml", out _); + var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _); // Assert parameter.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs index c0d99793e..aab130202 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs @@ -24,7 +24,7 @@ public OpenApiXmlTests() public void ParseBasicXmlShouldSucceed() { // Act - var xml = OpenApiModelFactory.Load(Resources.GetStream(Path.Combine(SampleFolderPath, "basicXml.yaml")), OpenApiSpecVersion.OpenApi3_0, "yaml", out _); + var xml = OpenApiModelFactory.Load(Resources.GetStream(Path.Combine(SampleFolderPath, "basicXml.yaml")), OpenApiSpecVersion.OpenApi3_0, out _); // Assert xml.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 3200dfb65..9405b04d3 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -578,9 +578,9 @@ namespace Microsoft.OpenApi.Models public void SerializeAsV31(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SetReferenceHostDocument() { } public static string GenerateHashValue(Microsoft.OpenApi.Models.OpenApiDocument doc) { } - public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.MemoryStream stream, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } + public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.MemoryStream stream, string? format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } public static System.Threading.Tasks.Task LoadAsync(string url, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } - public static System.Threading.Tasks.Task LoadAsync(System.IO.Stream stream, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null, System.Threading.CancellationToken cancellationToken = default) { } + public static System.Threading.Tasks.Task LoadAsync(System.IO.Stream stream, string? format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null, System.Threading.CancellationToken cancellationToken = default) { } public static Microsoft.OpenApi.Reader.ReadResult Parse(string input, string? format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings? settings = null) { } } public class OpenApiEncoding : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiExtensible, Microsoft.OpenApi.Interfaces.IOpenApiSerializable @@ -1323,10 +1323,10 @@ namespace Microsoft.OpenApi.Reader } public static class OpenApiModelFactory { - public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.MemoryStream stream, string format, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } + public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.MemoryStream stream, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } public static T Load(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, string format, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } - public static T Load(System.IO.Stream input, Microsoft.OpenApi.OpenApiSpecVersion version, string format, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) + public static T Load(System.IO.Stream input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } public static System.Threading.Tasks.Task LoadAsync(string url, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } public static System.Threading.Tasks.Task LoadAsync(System.IO.Stream input, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default) { } From 86b70c941d764857ca07026d0b46ce70477be3c7 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 5 Dec 2024 16:53:30 +0300 Subject: [PATCH 055/127] code cleanup --- .../OpenApiYamlReader.cs | 26 +++---- .../Reader/OpenApiJsonReader.cs | 69 +++++++++---------- 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index 8639798d6..4d4289b81 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -65,6 +65,12 @@ public ReadResult Read(MemoryStream input, return Read(jsonNode, settings); } + /// + public ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null) + { + return OpenApiReaderRegistry.DefaultReader.Read(jsonNode, settings, OpenApiConstants.Yaml); + } + /// public T ReadFragment(MemoryStream input, OpenApiSpecVersion version, @@ -89,6 +95,12 @@ public T ReadFragment(MemoryStream input, return ReadFragment(jsonNode, version, out diagnostic); } + /// + public T ReadFragment(JsonNode input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement + { + return OpenApiReaderRegistry.DefaultReader.ReadFragment(input, version, out diagnostic); + } + /// /// Helper method to turn streams into a sequence of JsonNodes /// @@ -98,20 +110,8 @@ static JsonNode LoadJsonNodesFromYamlDocument(TextReader input) { var yamlStream = new YamlStream(); yamlStream.Load(input); - var yamlDocument = yamlStream.Documents.First(); + var yamlDocument = yamlStream.Documents[0]; return yamlDocument.ToJsonNode(); } - - /// - public ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null) - { - return OpenApiReaderRegistry.DefaultReader.Read(jsonNode, settings, OpenApiConstants.Yaml); - } - - /// - public T ReadFragment(JsonNode input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement - { - return OpenApiReaderRegistry.DefaultReader.ReadFragment(input, version, out diagnostic); - } } } diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 0494bc1e1..862cccf39 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -27,7 +27,7 @@ public class OpenApiJsonReader : IOpenApiReader /// The Reader settings to be used during parsing. /// public ReadResult Read(MemoryStream input, - OpenApiReaderSettings settings = null) + OpenApiReaderSettings settings) { JsonNode jsonNode; var diagnostic = new OpenApiDiagnostic(); @@ -51,40 +51,6 @@ public ReadResult Read(MemoryStream input, return Read(jsonNode, settings); } - - /// - /// Reads the stream input asynchronously and parses it into an Open API document. - /// - /// TextReader containing OpenAPI description to parse. - /// The Reader settings to be used during parsing. - /// Propagates notifications that operations should be cancelled. - /// - public async Task ReadAsync(Stream input, - OpenApiReaderSettings settings, - CancellationToken cancellationToken = default) - { - JsonNode jsonNode; - var diagnostic = new OpenApiDiagnostic(); - settings ??= new OpenApiReaderSettings(); - - // Parse the JSON text in the TextReader into JsonNodes - try - { - jsonNode = await JsonNode.ParseAsync(input); - } - catch (JsonException ex) - { - diagnostic.Errors.Add(new OpenApiError($"#line={ex.LineNumber}", $"Please provide the correct format, {ex.Message}")); - return new ReadResult - { - OpenApiDocument = null, - OpenApiDiagnostic = diagnostic - }; - } - - return Read(jsonNode, settings); - } - /// /// Parses the JsonNode input into an Open API document. /// @@ -137,6 +103,39 @@ public ReadResult Read(JsonNode jsonNode, }; } + /// + /// Reads the stream input asynchronously and parses it into an Open API document. + /// + /// TextReader containing OpenAPI description to parse. + /// The Reader settings to be used during parsing. + /// Propagates notifications that operations should be cancelled. + /// + public async Task ReadAsync(Stream input, + OpenApiReaderSettings settings, + CancellationToken cancellationToken = default) + { + JsonNode jsonNode; + var diagnostic = new OpenApiDiagnostic(); + settings ??= new OpenApiReaderSettings(); + + // Parse the JSON text in the TextReader into JsonNodes + try + { + jsonNode = await JsonNode.ParseAsync(input); + } + catch (JsonException ex) + { + diagnostic.Errors.Add(new OpenApiError($"#line={ex.LineNumber}", $"Please provide the correct format, {ex.Message}")); + return new ReadResult + { + OpenApiDocument = null, + OpenApiDiagnostic = diagnostic + }; + } + + return Read(jsonNode, settings); + } + /// public T ReadFragment(MemoryStream input, OpenApiSpecVersion version, From f1ec8130b84d756230d33866abe9b0455d162450 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Mon, 9 Dec 2024 10:34:05 +0300 Subject: [PATCH 056/127] Rename Read Result properties --- src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 10 +-- .../OpenApiYamlReader.cs | 4 +- src/Microsoft.OpenApi.Workbench/MainModel.cs | 4 +- .../Reader/OpenApiJsonReader.cs | 8 +-- src/Microsoft.OpenApi/Reader/ReadResult.cs | 4 +- .../Reader/Services/OpenApiWorkspaceLoader.cs | 8 +-- .../Services/OpenApiFilterServiceTests.cs | 2 +- .../OpenApiDiagnosticTests.cs | 12 ++-- .../OpenApiStreamReaderTests.cs | 2 +- .../OpenApiWorkspaceStreamTests.cs | 10 +-- .../ParseNodeTests.cs | 4 +- .../TryLoadReferenceV2Tests.cs | 10 +-- .../TestCustomExtension.cs | 2 +- .../V2Tests/ComparisonTests.cs | 6 +- .../V2Tests/OpenApiDocumentTests.cs | 21 +++--- .../V2Tests/OpenApiServerTests.cs | 50 +++++++------- .../V31Tests/OpenApiDocumentTests.cs | 49 ++++++------- .../V3Tests/OpenApiCallbackTests.cs | 12 ++-- .../V3Tests/OpenApiDocumentTests.cs | 69 +++++++++---------- .../V3Tests/OpenApiExampleTests.cs | 2 +- .../V3Tests/OpenApiOperationTests.cs | 4 +- .../V3Tests/OpenApiResponseTests.cs | 4 +- .../V3Tests/OpenApiSchemaTests.cs | 12 ++-- .../Models/OpenApiDocumentTests.cs | 6 +- .../OpenApiCallbackReferenceTests.cs | 4 +- .../OpenApiExampleReferenceTests.cs | 4 +- .../References/OpenApiHeaderReferenceTests.cs | 4 +- .../References/OpenApiLinkReferenceTests.cs | 4 +- .../OpenApiParameterReferenceTests.cs | 4 +- .../OpenApiPathItemReferenceTests.cs | 4 +- .../OpenApiRequestBodyReferenceTests.cs | 4 +- .../OpenApiResponseReferenceTest.cs | 4 +- .../OpenApiSecuritySchemeReferenceTests.cs | 2 +- .../References/OpenApiTagReferenceTest.cs | 2 +- .../PublicApi/PublicApi.approved.txt | 4 +- 35 files changed, 174 insertions(+), 181 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs index 7dfb5d797..8a121f7ad 100644 --- a/src/Microsoft.OpenApi.Hidi/OpenApiService.cs +++ b/src/Microsoft.OpenApi.Hidi/OpenApiService.cs @@ -255,7 +255,7 @@ private static async Task GetOpenApiAsync(HidiOptions options, { stream = await GetStreamAsync(options.OpenApi, logger, cancellationToken).ConfigureAwait(false); var result = await ParseOpenApiAsync(options.OpenApi, options.InlineExternal, logger, stream, cancellationToken).ConfigureAwait(false); - document = result.OpenApiDocument; + document = result.Document; } else throw new InvalidOperationException("No input file path or URL provided"); @@ -358,7 +358,7 @@ private static MemoryStream ApplyFilterToCsdl(Stream csdlStream, string entitySe { var statsVisitor = new StatsVisitor(); var walker = new OpenApiWalker(statsVisitor); - walker.Walk(result.OpenApiDocument); + walker.Walk(result.Document); logger.LogTrace("Finished walking through the OpenApi document. Generating a statistics report.."); #pragma warning disable CA2254 @@ -377,7 +377,7 @@ private static MemoryStream ApplyFilterToCsdl(Stream csdlStream, string entitySe if (result is null) return null; - return result.OpenApiDiagnostic.Errors.Count == 0; + return result.Diagnostic.Errors.Count == 0; } private static async Task ParseOpenApiAsync(string openApiFile, bool inlineExternal, ILogger logger, Stream stream, CancellationToken cancellationToken = default) @@ -439,7 +439,7 @@ public static OpenApiDocument FixReferences(OpenApiDocument document, string for var sb = new StringBuilder(); document.SerializeAsV3(new OpenApiYamlWriter(new StringWriter(sb))); - var doc = OpenApiDocument.Parse(sb.ToString(), format).OpenApiDocument; + var doc = OpenApiDocument.Parse(sb.ToString(), format).Document; return doc; } @@ -649,7 +649,7 @@ private static string GetInputPathExtension(string? openapi = null, string? csdl private static void LogErrors(ILogger logger, ReadResult result) { - var context = result.OpenApiDiagnostic; + var context = result.Diagnostic; if (context.Errors.Count != 0) { using (logger.BeginScope("Detected errors")) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index cff6dd1da..947495b96 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -37,8 +37,8 @@ public async Task ReadAsync(TextReader input, diagnostic.Errors.Add(new($"#line={ex.LineNumber}", ex.Message)); return new() { - OpenApiDocument = null, - OpenApiDiagnostic = diagnostic + Document = null, + Diagnostic = diagnostic }; } diff --git a/src/Microsoft.OpenApi.Workbench/MainModel.cs b/src/Microsoft.OpenApi.Workbench/MainModel.cs index 2fdaf0e1c..1cd4f24ac 100644 --- a/src/Microsoft.OpenApi.Workbench/MainModel.cs +++ b/src/Microsoft.OpenApi.Workbench/MainModel.cs @@ -246,8 +246,8 @@ internal async Task ParseDocumentAsync() } var readResult = await OpenApiDocument.LoadAsync(stream, Format.GetDisplayName()); - var document = readResult.OpenApiDocument; - var context = readResult.OpenApiDiagnostic; + var document = readResult.Document; + var context = readResult.Diagnostic; stopwatch.Stop(); ParseTime = $"{stopwatch.ElapsedMilliseconds} ms"; diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 27aad722e..35f4fa6f6 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -49,8 +49,8 @@ public async Task ReadAsync(TextReader input, diagnostic.Errors.Add(new OpenApiError($"#line={ex.LineNumber}", $"Please provide the correct format, {ex.Message}")); return new ReadResult { - OpenApiDocument = null, - OpenApiDiagnostic = diagnostic + Document = null, + Diagnostic = diagnostic }; } @@ -118,8 +118,8 @@ public async Task ReadAsync(JsonNode jsonNode, return new() { - OpenApiDocument = document, - OpenApiDiagnostic = diagnostic + Document = document, + Diagnostic = diagnostic }; } diff --git a/src/Microsoft.OpenApi/Reader/ReadResult.cs b/src/Microsoft.OpenApi/Reader/ReadResult.cs index 77a18ff78..a0013b249 100644 --- a/src/Microsoft.OpenApi/Reader/ReadResult.cs +++ b/src/Microsoft.OpenApi/Reader/ReadResult.cs @@ -13,10 +13,10 @@ public class ReadResult /// /// The parsed OpenApiDocument. Null will be returned if the document could not be parsed. /// - public OpenApiDocument OpenApiDocument { set; get; } + public OpenApiDocument Document { get; set; } /// /// OpenApiDiagnostic contains the Errors reported while parsing /// - public OpenApiDiagnostic OpenApiDiagnostic { set; get; } + public OpenApiDiagnostic Diagnostic { get; set; } } } diff --git a/src/Microsoft.OpenApi/Reader/Services/OpenApiWorkspaceLoader.cs b/src/Microsoft.OpenApi/Reader/Services/OpenApiWorkspaceLoader.cs index a3462da70..06231e75c 100644 --- a/src/Microsoft.OpenApi/Reader/Services/OpenApiWorkspaceLoader.cs +++ b/src/Microsoft.OpenApi/Reader/Services/OpenApiWorkspaceLoader.cs @@ -48,13 +48,13 @@ internal async Task LoadAsync(OpenApiReference reference, var input = await _loader.LoadAsync(new(item.ExternalResource, UriKind.RelativeOrAbsolute)); var result = await OpenApiDocument.LoadAsync(input, format, _readerSettings, cancellationToken); // Merge diagnostics - if (result.OpenApiDiagnostic != null) + if (result.Diagnostic != null) { - diagnostic.AppendDiagnostic(result.OpenApiDiagnostic, item.ExternalResource); + diagnostic.AppendDiagnostic(result.Diagnostic, item.ExternalResource); } - if (result.OpenApiDocument != null) + if (result.Document != null) { - var loadDiagnostic = await LoadAsync(item, result.OpenApiDocument, format, diagnostic, cancellationToken); + var loadDiagnostic = await LoadAsync(item, result.Document, format, diagnostic, cancellationToken); diagnostic = loadDiagnostic; } } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs index 3bd9efd2a..01c4c59fa 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs @@ -232,7 +232,7 @@ public void CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly() // Act using var stream = File.OpenRead(filePath); - var doc = OpenApiDocument.Load(stream, "yaml").OpenApiDocument; + var doc = OpenApiDocument.Load(stream, "yaml").Document; var predicate = OpenApiFilterService.CreatePredicate(operationIds: operationIds); var subsetOpenApiDocument = OpenApiFilterService.CreateFilteredDocument(doc, predicate); diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs index c99cc6fa9..988b42a7c 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiDiagnosticTests.cs @@ -27,8 +27,8 @@ public void DetectedSpecificationVersionShouldBeV2_0() { var actual = OpenApiDocument.Load("V2Tests/Samples/basic.v2.yaml"); - actual.OpenApiDiagnostic.Should().NotBeNull(); - actual.OpenApiDiagnostic.SpecificationVersion.Should().Be(OpenApiSpecVersion.OpenApi2_0); + actual.Diagnostic.Should().NotBeNull(); + actual.Diagnostic.SpecificationVersion.Should().Be(OpenApiSpecVersion.OpenApi2_0); } [Fact] @@ -36,8 +36,8 @@ public void DetectedSpecificationVersionShouldBeV3_0() { var actual = OpenApiDocument.Load("V3Tests/Samples/OpenApiDocument/minimalDocument.yaml"); - actual.OpenApiDiagnostic.Should().NotBeNull(); - actual.OpenApiDiagnostic.SpecificationVersion.Should().Be(OpenApiSpecVersion.OpenApi3_0); + actual.Diagnostic.Should().NotBeNull(); + actual.Diagnostic.SpecificationVersion.Should().Be(OpenApiSpecVersion.OpenApi3_0); } [Fact] @@ -55,8 +55,8 @@ public async Task DiagnosticReportMergedForExternalReferenceAsync() result = await OpenApiDocument.LoadAsync("OpenApiReaderTests/Samples/OpenApiDiagnosticReportMerged/TodoMain.yaml", settings); Assert.NotNull(result); - Assert.NotNull(result.OpenApiDocument.Workspace); - result.OpenApiDiagnostic.Errors.Should().BeEmpty(); + Assert.NotNull(result.Document.Workspace); + result.Diagnostic.Errors.Should().BeEmpty(); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs index 82a410946..da5ed0226 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiReaderTests/OpenApiStreamReaderTests.cs @@ -65,7 +65,7 @@ public async Task StreamShouldReadWhenInitializedAsync() // Read V3 as YAML var result = OpenApiDocument.Load(stream, "yaml"); - Assert.NotNull(result.OpenApiDocument); + Assert.NotNull(result.Document); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs b/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs index 4aca9b54e..2b079ffb8 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/OpenApiWorkspaceTests/OpenApiWorkspaceStreamTests.cs @@ -46,7 +46,7 @@ public async Task LoadingDocumentWithResolveAllReferencesShouldLoadDocumentIntoW var result = await OpenApiDocument.LoadAsync(stream, OpenApiConstants.Yaml, settings: settings); - Assert.NotNull(result.OpenApiDocument.Workspace); + Assert.NotNull(result.Document.Workspace); } [Fact] @@ -63,14 +63,14 @@ public async Task LoadDocumentWithExternalReferenceShouldLoadBothDocumentsIntoWo ReadResult result; result = await OpenApiDocument.LoadAsync("V3Tests/Samples/OpenApiWorkspace/TodoMain.yaml", settings); - var externalDocBaseUri = result.OpenApiDocument.Workspace.GetDocumentId("./TodoComponents.yaml"); + var externalDocBaseUri = result.Document.Workspace.GetDocumentId("./TodoComponents.yaml"); var schemasPath = "/components/schemas/"; var parametersPath = "/components/parameters/"; Assert.NotNull(externalDocBaseUri); - Assert.True(result.OpenApiDocument.Workspace.Contains(externalDocBaseUri + schemasPath + "todo")); - Assert.True(result.OpenApiDocument.Workspace.Contains(externalDocBaseUri + schemasPath + "entity")); - Assert.True(result.OpenApiDocument.Workspace.Contains(externalDocBaseUri + parametersPath + "filter")); + Assert.True(result.Document.Workspace.Contains(externalDocBaseUri + schemasPath + "todo")); + Assert.True(result.Document.Workspace.Contains(externalDocBaseUri + schemasPath + "entity")); + Assert.True(result.Document.Workspace.Contains(externalDocBaseUri + parametersPath + "filter")); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/ParseNodeTests.cs b/test/Microsoft.OpenApi.Readers.Tests/ParseNodeTests.cs index 7c43ed124..0e5eae1c8 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/ParseNodeTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/ParseNodeTests.cs @@ -33,7 +33,7 @@ public void BrokenSimpleList() var result = OpenApiDocument.Parse(input, "yaml"); - result.OpenApiDiagnostic.Errors.Should().BeEquivalentTo(new List() { + result.Diagnostic.Errors.Should().BeEquivalentTo(new List() { new OpenApiError(new OpenApiReaderException("Expected a value.")) }); } @@ -59,7 +59,7 @@ public void BadSchema() var res= OpenApiDocument.Parse(input, "yaml"); - res.OpenApiDiagnostic.Errors.Should().BeEquivalentTo(new List + res.Diagnostic.Errors.Should().BeEquivalentTo(new List { new(new OpenApiReaderException("schema must be a map/object") { Pointer = "#/paths/~1foo/get/responses/200/content/application~1json/schema" diff --git a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs index d6fb3b8ba..815f2cfbe 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/ReferenceService/TryLoadReferenceV2Tests.cs @@ -26,7 +26,7 @@ public void LoadParameterReference() { // Arrange var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); - var reference = new OpenApiParameterReference("skipParam", result.OpenApiDocument); + var reference = new OpenApiParameterReference("skipParam", result.Document); // Assert reference.Should().BeEquivalentTo( @@ -51,7 +51,7 @@ public void LoadSecuritySchemeReference() { var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); - var reference = new OpenApiSecuritySchemeReference("api_key_sample", result.OpenApiDocument); + var reference = new OpenApiSecuritySchemeReference("api_key_sample", result.Document); // Assert reference.Should().BeEquivalentTo( @@ -69,7 +69,7 @@ public void LoadResponseReference() { var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); - var reference = new OpenApiResponseReference("NotFound", result.OpenApiDocument); + var reference = new OpenApiResponseReference("NotFound", result.Document); // Assert reference.Should().BeEquivalentTo( @@ -88,7 +88,7 @@ public void LoadResponseReference() public void LoadResponseAndSchemaReference() { var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "multipleReferences.v2.yaml")); - var reference = new OpenApiResponseReference("GeneralError", result.OpenApiDocument); + var reference = new OpenApiResponseReference("GeneralError", result.Document); // Assert reference.Should().BeEquivalentTo( @@ -118,7 +118,7 @@ public void LoadResponseAndSchemaReference() { Type = ReferenceType.Schema, Id = "SampleObject2", - HostDocument = result.OpenApiDocument + HostDocument = result.Document } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/TestCustomExtension.cs b/test/Microsoft.OpenApi.Readers.Tests/TestCustomExtension.cs index 9d7727aae..9e7d19c7f 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/TestCustomExtension.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/TestCustomExtension.cs @@ -42,7 +42,7 @@ public void ParseCustomExtension() var diag = new OpenApiDiagnostic(); var actual = OpenApiDocument.Parse(description, "yaml", settings: settings); - var fooExtension = actual.OpenApiDocument.Info.Extensions["x-foo"] as FooExtension; + var fooExtension = actual.Document.Info.Extensions["x-foo"] as FooExtension; fooExtension.Should().NotBeNull(); fooExtension.Bar.Should().Be("hey"); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/ComparisonTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/ComparisonTests.cs index b3e30c672..83e14118c 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/ComparisonTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/ComparisonTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System.IO; @@ -26,10 +26,10 @@ public void EquivalentV2AndV3DocumentsShouldProduceEquivalentObjects(string file var result1 = OpenApiDocument.Load(Path.Combine(SampleFolderPath, $"{fileName}.v2.yaml")); var result2 = OpenApiDocument.Load(Path.Combine(SampleFolderPath, $"{fileName}.v3.yaml")); - result2.OpenApiDocument.Should().BeEquivalentTo(result1.OpenApiDocument, + result2.Document.Should().BeEquivalentTo(result1.Document, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); - result1.OpenApiDiagnostic.Errors.Should().BeEquivalentTo(result2.OpenApiDiagnostic.Errors); + result1.Diagnostic.Errors.Should().BeEquivalentTo(result2.Diagnostic.Errors); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs index c97fd1aee..7cf03661c 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs @@ -57,7 +57,7 @@ public void ParseDocumentWithDifferentCultureShouldSucceed(string culture) """, "yaml"); - result.OpenApiDocument.Should().BeEquivalentTo( + result.Document.Should().BeEquivalentTo( new OpenApiDocument { Info = new() @@ -145,16 +145,16 @@ public void ShouldParseProducesInAnyOrder() Schema = new() { Type = JsonSchemaType.Array, - Items = new OpenApiSchemaReference("Item", result.OpenApiDocument) + Items = new OpenApiSchemaReference("Item", result.Document) } }; var errorMediaType = new OpenApiMediaType { - Schema = new OpenApiSchemaReference("Error", result.OpenApiDocument) + Schema = new OpenApiSchemaReference("Error", result.Document) }; - result.OpenApiDocument.Should().BeEquivalentTo(new OpenApiDocument + result.Document.Should().BeEquivalentTo(new OpenApiDocument { Info = new() { @@ -264,16 +264,16 @@ public void ShouldAssignSchemaToAllResponses() using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "multipleProduces.json")); var result = OpenApiDocument.Load(stream, OpenApiConstants.Json); - Assert.Equal(OpenApiSpecVersion.OpenApi2_0, result.OpenApiDiagnostic.SpecificationVersion); + Assert.Equal(OpenApiSpecVersion.OpenApi2_0, result.Diagnostic.SpecificationVersion); var successSchema = new OpenApiSchema { Type = JsonSchemaType.Array, - Items = new OpenApiSchemaReference("Item", result.OpenApiDocument) + Items = new OpenApiSchemaReference("Item", result.Document) }; - var errorSchema = new OpenApiSchemaReference("Error", result.OpenApiDocument); + var errorSchema = new OpenApiSchemaReference("Error", result.Document); - var responses = result.OpenApiDocument.Paths["/items"].Operations[OperationType.Get].Responses; + var responses = result.Document.Paths["/items"].Operations[OperationType.Get].Responses; foreach (var response in responses) { var targetSchema = response.Key == "200" ? successSchema : errorSchema; @@ -292,7 +292,7 @@ public void ShouldAssignSchemaToAllResponses() public void ShouldAllowComponentsThatJustContainAReference() { // Act - var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "ComponentRootReference.json")).OpenApiDocument; + var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "ComponentRootReference.json")).Document; var schema1 = actual.Components.Schemas["AllPets"]; Assert.False(schema1.UnresolvedReference); var schema2 = actual.ResolveReferenceTo(schema1.Reference); @@ -312,7 +312,7 @@ public void ParseDocumentWithDefaultContentTypeSettingShouldSucceed() }; var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "docWithEmptyProduces.yaml"), settings); - var mediaType = actual.OpenApiDocument.Paths["/example"].Operations[OperationType.Get].Responses["200"].Content; + var mediaType = actual.Document.Paths["/example"].Operations[OperationType.Get].Responses["200"].Content; Assert.Contains("application/json", mediaType); } @@ -321,7 +321,6 @@ public void testContentType() { var contentType = "application/json; charset = utf-8"; var res = contentType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).First(); - var expected = res.Split('/').LastOrDefault(); Assert.Equal("application/json", res); } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs index 775145794..e0c076ee3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiServerTests.cs @@ -27,7 +27,7 @@ public void NoServer() var result = OpenApiDocument.Parse(input, "yaml"); - Assert.Empty(result.OpenApiDocument.Servers); + Assert.Empty(result.Document.Servers); } [Fact] @@ -45,7 +45,7 @@ public void JustSchemeNoDefault() """; var result = OpenApiDocument.Parse(input, "yaml"); - Assert.Empty(result.OpenApiDocument.Servers); + Assert.Empty(result.Document.Servers); } [Fact] @@ -62,8 +62,8 @@ public void JustHostNoDefault() """; var result = OpenApiDocument.Parse(input, "yaml"); - var server = result.OpenApiDocument.Servers.First(); - Assert.Single(result.OpenApiDocument.Servers); + var server = result.Document.Servers.First(); + Assert.Single(result.Document.Servers); Assert.Equal("//www.foo.com", server.Url); } @@ -87,8 +87,8 @@ public void NoBasePath() }; var result = OpenApiDocument.Parse(input, "yaml", settings); - var server = result.OpenApiDocument.Servers.First(); - Assert.Single(result.OpenApiDocument.Servers); + var server = result.Document.Servers.First(); + Assert.Single(result.Document.Servers); Assert.Equal("http://www.foo.com", server.Url); } @@ -106,8 +106,8 @@ public void JustBasePathNoDefault() """; var result = OpenApiDocument.Parse(input, "yaml"); - var server = result.OpenApiDocument.Servers.First(); - Assert.Single(result.OpenApiDocument.Servers); + var server = result.Document.Servers.First(); + Assert.Single(result.Document.Servers); Assert.Equal("/baz", server.Url); } @@ -131,8 +131,8 @@ public void JustSchemeWithCustomHost() var result = OpenApiDocument.Parse(input, "yaml", settings); - var server = result.OpenApiDocument.Servers.First(); - Assert.Single(result.OpenApiDocument.Servers); + var server = result.Document.Servers.First(); + Assert.Single(result.Document.Servers); Assert.Equal("http://bing.com/foo", server.Url); } @@ -156,8 +156,8 @@ public void JustSchemeWithCustomHostWithEmptyPath() var result = OpenApiDocument.Parse(input, "yaml", settings); - var server = result.OpenApiDocument.Servers.First(); - Assert.Single(result.OpenApiDocument.Servers); + var server = result.Document.Servers.First(); + Assert.Single(result.Document.Servers); Assert.Equal("http://bing.com", server.Url); } @@ -180,8 +180,8 @@ public void JustBasePathWithCustomHost() var result = OpenApiDocument.Parse(input, "yaml", settings); - var server = result.OpenApiDocument.Servers.First(); - Assert.Single(result.OpenApiDocument.Servers); + var server = result.Document.Servers.First(); + Assert.Single(result.Document.Servers); Assert.Equal("https://bing.com/api", server.Url); } @@ -204,8 +204,8 @@ public void JustHostWithCustomHost() var result = OpenApiDocument.Parse(input, "yaml", settings); - var server = result.OpenApiDocument.Servers.First(); - Assert.Single(result.OpenApiDocument.Servers); + var server = result.Document.Servers.First(); + Assert.Single(result.Document.Servers); Assert.Equal("https://www.example.com", server.Url); } @@ -228,8 +228,8 @@ public void JustHostWithCustomHostWithApi() }; var result = OpenApiDocument.Parse(input, "yaml", settings); - var server = result.OpenApiDocument.Servers.First(); - Assert.Single(result.OpenApiDocument.Servers); + var server = result.Document.Servers.First(); + Assert.Single(result.Document.Servers); Assert.Equal("https://prod.bing.com", server.Url); } @@ -254,10 +254,10 @@ public void MultipleServers() }; var result = OpenApiDocument.Parse(input, "yaml", settings); - var server = result.OpenApiDocument.Servers.First(); - Assert.Equal(2, result.OpenApiDocument.Servers.Count); + var server = result.Document.Servers.First(); + Assert.Equal(2, result.Document.Servers.Count); Assert.Equal("http://dev.bing.com/api", server.Url); - Assert.Equal("https://dev.bing.com/api", result.OpenApiDocument.Servers.Last().Url); + Assert.Equal("https://dev.bing.com/api", result.Document.Servers.Last().Url); } [Fact] @@ -280,8 +280,8 @@ public void LocalHostWithCustomHost() var result = OpenApiDocument.Parse(input, "yaml", settings); - var server = result.OpenApiDocument.Servers.First(); - Assert.Single(result.OpenApiDocument.Servers); + var server = result.Document.Servers.First(); + Assert.Single(result.Document.Servers); Assert.Equal("https://localhost:23232", server.Url); } @@ -304,8 +304,8 @@ public void InvalidHostShouldYieldError() }; var result = OpenApiDocument.Parse(input, "yaml", settings); - result.OpenApiDocument.Servers.Count.Should().Be(0); - result.OpenApiDiagnostic.Should().BeEquivalentTo( + result.Document.Servers.Count.Should().Be(0); + result.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic { Errors = diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs index 638d69667..de5471a44 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiDocumentTests.cs @@ -30,9 +30,9 @@ public void ParseDocumentWithWebhooksShouldSucceed() { // Arrange and Act var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "documentWithWebhooks.yaml")); - var petSchema = new OpenApiSchemaReference("petSchema", actual.OpenApiDocument); + var petSchema = new OpenApiSchemaReference("petSchema", actual.Document); - var newPetSchema = new OpenApiSchemaReference("newPetSchema", actual.OpenApiDocument); + var newPetSchema = new OpenApiSchemaReference("newPetSchema", actual.Document); var components = new OpenApiComponents { @@ -200,8 +200,8 @@ public void ParseDocumentWithWebhooksShouldSucceed() }; // Assert - actual.OpenApiDiagnostic.Should().BeEquivalentTo(new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_1 }); - actual.OpenApiDocument.Should().BeEquivalentTo(expected, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); + actual.Diagnostic.Should().BeEquivalentTo(new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_1 }); + actual.Document.Should().BeEquivalentTo(expected, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); } [Fact] @@ -267,9 +267,9 @@ public void ParseDocumentsWithReusablePathItemInWebhooksSucceeds() }; // Create a clone of the schema to avoid modifying things in components. - var petSchema = new OpenApiSchemaReference("petSchema", actual.OpenApiDocument); + var petSchema = new OpenApiSchemaReference("petSchema", actual.Document); - var newPetSchema = new OpenApiSchemaReference("newPetSchema", actual.OpenApiDocument); + var newPetSchema = new OpenApiSchemaReference("newPetSchema", actual.Document); components.PathItems = new Dictionary { @@ -387,17 +387,12 @@ public void ParseDocumentsWithReusablePathItemInWebhooksSucceeds() }; // Assert - actual.OpenApiDocument.Should().BeEquivalentTo(expected, options => options + actual.Document.Should().BeEquivalentTo(expected, options => options .Excluding(x => x.Webhooks["pets"].Reference) .Excluding(x => x.Workspace) .Excluding(y => y.BaseUri)); - actual.OpenApiDiagnostic.Should().BeEquivalentTo( - new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_1 }); - - var outputWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputWriter, new() { InlineLocalReferences = true }); - actual.OpenApiDocument.SerializeAsV31(writer); - var serialized = outputWriter.ToString(); + actual.Diagnostic.Should().BeEquivalentTo( + new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_1 }); } [Fact] @@ -409,7 +404,7 @@ public void ParseDocumentWithExampleInSchemaShouldSucceed() // Act var actual = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "docWithExample.yaml")); - actual.OpenApiDocument.SerializeAsV31(writer); + actual.Document.SerializeAsV31(writer); // Assert Assert.NotNull(actual); @@ -420,7 +415,7 @@ public void ParseDocumentWithPatternPropertiesInSchemaWorks() { // Arrange and Act var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "docWithPatternPropertiesInSchema.yaml")); - var actualSchema = result.OpenApiDocument.Paths["/example"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; + var actualSchema = result.Document.Paths["/example"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; var expectedSchema = new OpenApiSchema { @@ -450,7 +445,7 @@ public void ParseDocumentWithPatternPropertiesInSchemaWorks() }; // Serialization - var mediaType = result.OpenApiDocument.Paths["/example"].Operations[OperationType.Get].Responses["200"].Content["application/json"]; + var mediaType = result.Document.Paths["/example"].Operations[OperationType.Get].Responses["200"].Content["application/json"]; var expectedMediaType = @"schema: patternProperties: @@ -478,9 +473,9 @@ public void ParseDocumentWithReferenceByIdGetsResolved() // Arrange and Act var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "docWithReferenceById.yaml")); - var responseSchema = result.OpenApiDocument.Paths["/resource"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; - var requestBodySchema = result.OpenApiDocument.Paths["/resource"].Operations[OperationType.Post].RequestBody.Content["application/json"].Schema; - var parameterSchema = result.OpenApiDocument.Paths["/resource"].Operations[OperationType.Get].Parameters[0].Schema; + var responseSchema = result.Document.Paths["/resource"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; + var requestBodySchema = result.Document.Paths["/resource"].Operations[OperationType.Post].RequestBody.Content["application/json"].Schema; + var parameterSchema = result.Document.Paths["/resource"].Operations[OperationType.Get].Parameters[0].Schema; // Assert Assert.Equal(JsonSchemaType.Object, responseSchema.Type); @@ -502,10 +497,10 @@ public async Task ExternalDocumentDereferenceToOpenApiDocumentUsingJsonPointerWo // Act var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "externalRefByJsonPointer.yaml"), settings); - var responseSchema = result.OpenApiDocument.Paths["/resource"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; + var responseSchema = result.Document.Paths["/resource"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; // Assert - result.OpenApiDocument.Workspace.Contains("./externalResource.yaml"); + result.Document.Workspace.Contains("./externalResource.yaml"); responseSchema.Properties.Count.Should().Be(2); // reference has been resolved } @@ -523,10 +518,10 @@ public async Task ParseExternalDocumentDereferenceToOpenApiDocumentByIdWorks() // Act var result = await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "externalRefById.yaml"), settings); - var doc2 = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "externalResource.yaml")).OpenApiDocument; + var doc2 = (await OpenApiDocument.LoadAsync(Path.Combine(SampleFolderPath, "externalResource.yaml"))).Document; - var requestBodySchema = result.OpenApiDocument.Paths["/resource"].Operations[OperationType.Get].Parameters.First().Schema; - result.OpenApiDocument.Workspace.RegisterComponents(doc2); + var requestBodySchema = result.Document.Paths["/resource"].Operations[OperationType.Get].Parameters[0].Schema; + result.Document.Workspace.RegisterComponents(doc2); // Assert requestBodySchema.Properties.Count.Should().Be(2); // reference has been resolved @@ -536,10 +531,10 @@ public async Task ParseExternalDocumentDereferenceToOpenApiDocumentByIdWorks() public async Task ParseDocumentWith31PropertiesWorks() { var path = Path.Combine(SampleFolderPath, "documentWith31Properties.yaml"); - var doc = OpenApiDocument.Load(path).OpenApiDocument; + var doc = (await OpenApiDocument.LoadAsync(path)).Document; var outputStringWriter = new StringWriter(); doc.SerializeAsV31(new OpenApiYamlWriter(outputStringWriter)); - outputStringWriter.Flush(); + await outputStringWriter.FlushAsync(); var actual = outputStringWriter.GetStringBuilder().ToString(); // Assert diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs index cab621c14..0cf804f80 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiCallbackTests.cs @@ -72,12 +72,12 @@ public void ParseCallbackWithReferenceShouldSucceed() var result = OpenApiModelFactory.Load(stream, OpenApiConstants.Yaml); // Assert - var path = result.OpenApiDocument.Paths.First().Value; + var path = result.Document.Paths.First().Value; var subscribeOperation = path.Operations[OperationType.Post]; var callback = subscribeOperation.Callbacks["simpleHook"]; - result.OpenApiDiagnostic.Should().BeEquivalentTo( + result.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); callback.Should().BeEquivalentTo( @@ -116,7 +116,7 @@ public void ParseCallbackWithReferenceShouldSucceed() { Type = ReferenceType.Callback, Id = "simpleHook", - HostDocument = result.OpenApiDocument + HostDocument = result.Document } }); } @@ -128,10 +128,10 @@ public void ParseMultipleCallbacksWithReferenceShouldSucceed() var result = OpenApiModelFactory.Load(Path.Combine(SampleFolderPath, "multipleCallbacksWithReference.yaml")); // Assert - var path = result.OpenApiDocument.Paths.First().Value; + var path = result.Document.Paths.First().Value; var subscribeOperation = path.Operations[OperationType.Post]; - result.OpenApiDiagnostic.Should().BeEquivalentTo( + result.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); var callback1 = subscribeOperation.Callbacks["simpleHook"]; @@ -172,7 +172,7 @@ public void ParseMultipleCallbacksWithReferenceShouldSucceed() { Type = ReferenceType.Callback, Id = "simpleHook", - HostDocument = result.OpenApiDocument + HostDocument = result.Document } }); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 2d3b02820..461df1642 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -87,7 +87,7 @@ public void ParseDocumentFromInlineStringShouldSucceed() paths: {}", OpenApiConstants.Yaml); - result.OpenApiDocument.Should().BeEquivalentTo( + result.Document.Should().BeEquivalentTo( new OpenApiDocument { Info = new OpenApiInfo @@ -98,7 +98,7 @@ public void ParseDocumentFromInlineStringShouldSucceed() Paths = new OpenApiPaths() }, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); - result.OpenApiDiagnostic.Should().BeEquivalentTo( + result.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 @@ -111,8 +111,8 @@ public void ParseBasicDocumentWithMultipleServersShouldSucceed() var path = System.IO.Path.Combine(SampleFolderPath, "basicDocumentWithMultipleServers.yaml"); var result = OpenApiDocument.Load(path); - result.OpenApiDiagnostic.Errors.Should().BeEmpty(); - result.OpenApiDocument.Should().BeEquivalentTo( + result.Diagnostic.Errors.Should().BeEmpty(); + result.Document.Should().BeEquivalentTo( new OpenApiDocument { Info = new OpenApiInfo @@ -142,7 +142,7 @@ public void ParseBrokenMinimalDocumentShouldYieldExpectedDiagnostic() using var stream = Resources.GetStream(System.IO.Path.Combine(SampleFolderPath, "brokenMinimalDocument.yaml")); var result = OpenApiDocument.Load(stream, OpenApiConstants.Yaml); - result.OpenApiDocument.Should().BeEquivalentTo( + result.Document.Should().BeEquivalentTo( new OpenApiDocument { Info = new OpenApiInfo @@ -152,7 +152,7 @@ public void ParseBrokenMinimalDocumentShouldYieldExpectedDiagnostic() Paths = new OpenApiPaths() }, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); - result.OpenApiDiagnostic.Should().BeEquivalentTo( + result.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic { Errors = @@ -168,7 +168,7 @@ public void ParseMinimalDocumentShouldSucceed() { var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "minimalDocument.yaml")); - result.OpenApiDocument.Should().BeEquivalentTo( + result.Document.Should().BeEquivalentTo( new OpenApiDocument { Info = new OpenApiInfo @@ -179,7 +179,7 @@ public void ParseMinimalDocumentShouldSucceed() Paths = new OpenApiPaths() }, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); - result.OpenApiDiagnostic.Should().BeEquivalentTo( + result.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 @@ -269,10 +269,10 @@ public void ParseStandardPetStoreDocumentShouldSucceed() } }; - var petSchema = new OpenApiSchemaReference("pet1", actual.OpenApiDocument); - var newPetSchema = new OpenApiSchemaReference("newPet", actual.OpenApiDocument); + var petSchema = new OpenApiSchemaReference("pet1", actual.Document); + var newPetSchema = new OpenApiSchemaReference("newPet", actual.Document); - var errorModelSchema = new OpenApiSchemaReference("errorModel", actual.OpenApiDocument); + var errorModelSchema = new OpenApiSchemaReference("errorModel", actual.Document); var expectedDoc = new OpenApiDocument { @@ -566,9 +566,9 @@ public void ParseStandardPetStoreDocumentShouldSucceed() Components = components }; - actual.OpenApiDocument.Should().BeEquivalentTo(expectedDoc, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); + actual.Document.Should().BeEquivalentTo(expectedDoc, options => options.Excluding(x => x.Workspace).Excluding(y => y.BaseUri)); - actual.OpenApiDiagnostic.Should().BeEquivalentTo( + actual.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); } @@ -675,7 +675,7 @@ public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { Id = "pet1", Type = ReferenceType.Schema, - HostDocument = actual.OpenApiDocument + HostDocument = actual.Document }; var newPetSchema = Clone(components.Schemas["newPet"]); @@ -684,7 +684,7 @@ public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { Id = "newPet", Type = ReferenceType.Schema, - HostDocument = actual.OpenApiDocument + HostDocument = actual.Document }; var errorModelSchema = Clone(components.Schemas["errorModel"]); @@ -693,7 +693,7 @@ public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() { Id = "errorModel", Type = ReferenceType.Schema, - HostDocument = actual.OpenApiDocument + HostDocument = actual.Document }; var tag1 = new OpenApiTag @@ -1069,7 +1069,7 @@ public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() } }; - actual.OpenApiDocument.Should().BeEquivalentTo(expected, options => options + actual.Document.Should().BeEquivalentTo(expected, options => options .Excluding(x => x.HashCode) .Excluding(m => m.Tags[0].Reference) .Excluding(x => x.Paths["/pets"].Operations[OperationType.Get].Tags[0].Reference) @@ -1080,7 +1080,7 @@ public void ParseModifiedPetStoreDocumentWithTagAndSecurityShouldSucceed() .Excluding(x => x.Workspace) .Excluding(y => y.BaseUri)); - actual.OpenApiDiagnostic.Should().BeEquivalentTo( + actual.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); } @@ -1091,7 +1091,7 @@ public void ParsePetStoreExpandedShouldSucceed() // TODO: Create the object in memory and compare with the one read from YAML file. - actual.OpenApiDiagnostic.Should().BeEquivalentTo( + actual.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); } @@ -1100,9 +1100,9 @@ public void GlobalSecurityRequirementShouldReferenceSecurityScheme() { var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "securedApi.yaml")); - var securityRequirement = result.OpenApiDocument.SecurityRequirements.First(); + var securityRequirement = result.Document.SecurityRequirements[0]; - securityRequirement.Keys.First().Should().BeEquivalentTo(result.OpenApiDocument.Components.SecuritySchemes.First().Value, + securityRequirement.Keys.First().Should().BeEquivalentTo(result.Document.Components.SecuritySchemes.First().Value, options => options.Excluding(x => x.Reference)); } @@ -1111,7 +1111,7 @@ public void HeaderParameterShouldAllowExample() { var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "apiWithFullHeaderComponent.yaml")); - var exampleHeader = result.OpenApiDocument.Components?.Headers?["example-header"]; + var exampleHeader = result.Document.Components?.Headers?["example-header"]; Assert.NotNull(exampleHeader); exampleHeader.Should().BeEquivalentTo( new OpenApiHeader() @@ -1133,7 +1133,7 @@ public void HeaderParameterShouldAllowExample() .Excluding(e => e.Example.Parent) .Excluding(x => x.Reference)); - var examplesHeader = result.OpenApiDocument.Components?.Headers?["examples-header"]; + var examplesHeader = result.Document.Components?.Headers?["examples-header"]; Assert.NotNull(examplesHeader); examplesHeader.Should().BeEquivalentTo( new OpenApiHeader() @@ -1178,7 +1178,7 @@ public void ParseDocumentWithReferencedSecuritySchemeWorks() }; var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "docWithSecuritySchemeReference.yaml"), settings); - var securityScheme = result.OpenApiDocument.Components.SecuritySchemes["OAuth2"]; + var securityScheme = result.Document.Components.SecuritySchemes["OAuth2"]; // Assert Assert.False(securityScheme.UnresolvedReference); @@ -1198,9 +1198,9 @@ public void ParseDocumentWithJsonSchemaReferencesWorks() }; var result = OpenApiDocument.Load(stream, OpenApiConstants.Yaml, settings); - var actualSchema = result.OpenApiDocument.Paths["/users/{userId}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; + var actualSchema = result.Document.Paths["/users/{userId}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema; - var expectedSchema = new OpenApiSchemaReference("User", result.OpenApiDocument); + var expectedSchema = new OpenApiSchemaReference("User", result.Document); // Assert actualSchema.Should().BeEquivalentTo(expectedSchema); } @@ -1216,7 +1216,7 @@ public void ValidateExampleShouldNotHaveDataTypeMismatch() }); // Assert - var warnings = result.OpenApiDiagnostic.Warnings; + var warnings = result.Diagnostic.Warnings; Assert.False(warnings.Any()); } @@ -1312,11 +1312,10 @@ public void ParseDocWithRefsUsingProxyReferencesSucceeds() using var stream = Resources.GetStream(System.IO.Path.Combine(SampleFolderPath, "minifiedPetStore.yaml")); // Act - var doc = OpenApiDocument.Load(stream, "yaml").OpenApiDocument; - var actualParam = doc.Paths["/pets"].Operations[OperationType.Get].Parameters.First(); + var doc = OpenApiDocument.Load(stream, "yaml").Document; + var actualParam = doc.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; var outputDoc = doc.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0).MakeLineBreaksEnvironmentNeutral(); - var output = actualParam.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0); - var expectedParam = expected.Paths["/pets"].Operations[OperationType.Get].Parameters.First(); + var expectedParam = expected.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; // Assert actualParam.Should().BeEquivalentTo(expectedParam, options => options @@ -1367,13 +1366,13 @@ public void ParseBasicDocumentWithServerVariableShouldSucceed() Paths = new() }; - result.OpenApiDiagnostic.Should().BeEquivalentTo( + result.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 }); - result.OpenApiDocument.Should().BeEquivalentTo(expected, options => options.Excluding(x => x.BaseUri)); + result.Document.Should().BeEquivalentTo(expected, options => options.Excluding(x => x.BaseUri)); } [Fact] @@ -1393,14 +1392,14 @@ public void ParseBasicDocumentWithServerVariableAndNoDefaultShouldFail() paths: {} """, "yaml"); - result.OpenApiDiagnostic.Errors.Should().NotBeEmpty(); + result.Diagnostic.Errors.Should().NotBeEmpty(); } [Fact] public void ParseDocumentWithEmptyPathsSucceeds() { var result = OpenApiDocument.Load(System.IO.Path.Combine(SampleFolderPath, "docWithEmptyPaths.yaml")); - result.OpenApiDiagnostic.Errors.Should().BeEmpty(); + result.Diagnostic.Errors.Should().BeEmpty(); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiExampleTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiExampleTests.cs index 84f028f6b..18007d112 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiExampleTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiExampleTests.cs @@ -82,7 +82,7 @@ public void ParseAdvancedExampleShouldSucceed() public void ParseExampleForcedStringSucceed() { var result= OpenApiDocument.Load(Path.Combine(SampleFolderPath, "explicitString.yaml")); - result.OpenApiDiagnostic.Errors.Should().BeEmpty(); + result.Diagnostic.Errors.Should().BeEmpty(); } } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs index 9ba96bbda..4c8af2aeb 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiOperationTests.cs @@ -25,9 +25,9 @@ public void OperationWithSecurityRequirementShouldReferenceSecurityScheme() { var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "securedOperation.yaml")); - var securityScheme = result.OpenApiDocument.Paths["/"].Operations[OperationType.Get].Security.First().Keys.First(); + var securityScheme = result.Document.Paths["/"].Operations[OperationType.Get].Security.First().Keys.First(); - securityScheme.Should().BeEquivalentTo(result.OpenApiDocument.Components.SecuritySchemes.First().Value, + securityScheme.Should().BeEquivalentTo(result.Document.Components.SecuritySchemes.First().Value, options => options.Excluding(x => x.Reference)); } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiResponseTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiResponseTests.cs index 09a1d00a1..f14b89514 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiResponseTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiResponseTests.cs @@ -25,9 +25,9 @@ public void ResponseWithReferencedHeaderShouldReferenceComponent() { var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "responseWithHeaderReference.yaml")); - var response = result.OpenApiDocument.Components.Responses["Test"]; + var response = result.Document.Components.Responses["Test"]; var expected = response.Headers.First().Value; - var actual = result.OpenApiDocument.Components.Headers.First().Value; + var actual = result.Document.Components.Headers.First().Value; actual.Description.Should().BeEquivalentTo(expected.Description); } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs index 6c1370626..d751c89d0 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiSchemaTests.cs @@ -236,9 +236,9 @@ public void ParseBasicSchemaWithReferenceShouldSucceed() var result = OpenApiDocument.Load(Path.Combine(SampleFolderPath, "basicSchemaWithReference.yaml")); // Assert - var components = result.OpenApiDocument.Components; + var components = result.Document.Components; - result.OpenApiDiagnostic.Should().BeEquivalentTo( + result.Diagnostic.Should().BeEquivalentTo( new OpenApiDiagnostic() { SpecificationVersion = OpenApiSpecVersion.OpenApi3_0 @@ -274,7 +274,7 @@ public void ParseBasicSchemaWithReferenceShouldSucceed() { AllOf = { - new OpenApiSchemaReference("ErrorModel", result.OpenApiDocument), + new OpenApiSchemaReference("ErrorModel", result.Document), new OpenApiSchema { Type = JsonSchemaType.Object, @@ -334,7 +334,7 @@ public void ParseAdvancedSchemaWithReferenceShouldSucceed() Description = "A representation of a cat", AllOf = { - new OpenApiSchemaReference("Pet", result.OpenApiDocument), + new OpenApiSchemaReference("Pet", result.Document), new OpenApiSchema { Type = JsonSchemaType.Object, @@ -362,7 +362,7 @@ public void ParseAdvancedSchemaWithReferenceShouldSucceed() Description = "A representation of a dog", AllOf = { - new OpenApiSchemaReference("Pet", result.OpenApiDocument), + new OpenApiSchemaReference("Pet", result.Document), new OpenApiSchema { Type = JsonSchemaType.Object, @@ -385,7 +385,7 @@ public void ParseAdvancedSchemaWithReferenceShouldSucceed() }; // We serialize so that we can get rid of the schema BaseUri properties which show up as diffs - var actual = result.OpenApiDocument.Components.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0); + var actual = result.Document.Components.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0); var expected = expectedComponents.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0); // Assert diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index 884ffa68c..e87e5148c 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -1707,7 +1707,7 @@ private static OpenApiDocument ParseInputFile(string filePath) // Read in the input yaml file using FileStream stream = File.OpenRead(filePath); var format = OpenApiModelFactory.GetFormat(filePath); - var openApiDoc = OpenApiDocument.Load(stream, format).OpenApiDocument; + var openApiDoc = OpenApiDocument.Load(stream, format).Document; return openApiDoc; } @@ -2013,7 +2013,7 @@ public void SerializeV31DocumentWithRefsInWebhooksWorks() items: type: object"; - var doc = OpenApiDocument.Load("Models/Samples/docWithReusableWebhooks.yaml").OpenApiDocument; + var doc = OpenApiDocument.Load("Models/Samples/docWithReusableWebhooks.yaml").Document; var stringWriter = new StringWriter(); var writer = new OpenApiYamlWriter(stringWriter, new OpenApiWriterSettings { InlineLocalReferences = true }); @@ -2067,7 +2067,7 @@ public void SerializeDocWithDollarIdInDollarRefSucceeds() radius: type: number "; - var doc = OpenApiDocument.Load("Models/Samples/docWithDollarId.yaml").OpenApiDocument; + var doc = OpenApiDocument.Load("Models/Samples/docWithDollarId.yaml").Document; var actual = doc.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_1); actual.MakeLineBreaksEnvironmentNeutral().Should().BeEquivalentTo(expected.MakeLineBreaksEnvironmentNeutral()); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.cs index 3a16f4d2a..8942e692c 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiCallbackReferenceTests.cs @@ -134,8 +134,8 @@ public class OpenApiCallbackReferenceTests public OpenApiCallbackReferenceTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); - OpenApiDocument openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).OpenApiDocument; - OpenApiDocument openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).OpenApiDocument; + OpenApiDocument openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).Document; + OpenApiDocument openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).Document; openApiDoc.Workspace.AddDocumentId("https://myserver.com/beta", openApiDoc_2.BaseUri); openApiDoc.Workspace.RegisterComponents(openApiDoc_2); _externalCallbackReference = new("callbackEvent", openApiDoc, "https://myserver.com/beta"); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.cs index 4ea8cdef9..a3342ade6 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiExampleReferenceTests.cs @@ -113,8 +113,8 @@ public class OpenApiExampleReferenceTests public OpenApiExampleReferenceTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); - _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).OpenApiDocument; - _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).OpenApiDocument; + _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).Document; + _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).Document; _openApiDoc.Workspace.AddDocumentId("https://myserver.com/beta", _openApiDoc_2.BaseUri); _openApiDoc.Workspace.RegisterComponents(_openApiDoc_2); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs index cfdf4ab1c..c979e1eb0 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiHeaderReferenceTests.cs @@ -82,8 +82,8 @@ public class OpenApiHeaderReferenceTests public OpenApiHeaderReferenceTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); - _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).OpenApiDocument; - _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).OpenApiDocument; + _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).Document; + _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).Document; _openApiDoc.Workspace.AddDocumentId("https://myserver.com/beta", _openApiDoc_2.BaseUri); _openApiDoc.Workspace.RegisterComponents(_openApiDoc_2); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.cs index 87d2db06e..3587a83d9 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiLinkReferenceTests.cs @@ -125,8 +125,8 @@ public class OpenApiLinkReferenceTests public OpenApiLinkReferenceTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); - _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).OpenApiDocument; - _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).OpenApiDocument; + _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).Document; + _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).Document; _openApiDoc.Workspace.AddDocumentId("https://myserver.com/beta", _openApiDoc_2.BaseUri); _openApiDoc.Workspace.RegisterComponents(_openApiDoc_2); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.cs index c00db94f5..8745da455 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiParameterReferenceTests.cs @@ -83,8 +83,8 @@ public class OpenApiParameterReferenceTests public OpenApiParameterReferenceTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); - _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).OpenApiDocument; - _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).OpenApiDocument; + _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).Document; + _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).Document; _openApiDoc.Workspace.AddDocumentId("https://myserver.com/beta", _openApiDoc_2.BaseUri); _openApiDoc.Workspace.RegisterComponents(_openApiDoc_2); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.cs index a2d9b525d..c23d564d5 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiPathItemReferenceTests.cs @@ -80,8 +80,8 @@ public class OpenApiPathItemReferenceTests public OpenApiPathItemReferenceTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); - _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).OpenApiDocument; - _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).OpenApiDocument; + _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).Document; + _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).Document; _openApiDoc.Workspace.AddDocumentId("https://myserver.com/beta", _openApiDoc_2.BaseUri); _openApiDoc.Workspace.RegisterComponents(_openApiDoc_2); _openApiDoc_2.Workspace.RegisterComponents(_openApiDoc_2); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs index 54521e83c..7bd9ab35b 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiRequestBodyReferenceTests.cs @@ -88,8 +88,8 @@ public class OpenApiRequestBodyReferenceTests public OpenApiRequestBodyReferenceTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); - _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).OpenApiDocument; - _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).OpenApiDocument; + _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).Document; + _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).Document; _openApiDoc.Workspace.AddDocumentId("https://myserver.com/beta", _openApiDoc_2.BaseUri); _openApiDoc.Workspace.RegisterComponents(_openApiDoc_2); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs index 4b6b25564..361006b64 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiResponseReferenceTest.cs @@ -71,8 +71,8 @@ public class OpenApiResponseReferenceTest public OpenApiResponseReferenceTest() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); - _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).OpenApiDocument; - _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).OpenApiDocument; + _openApiDoc = OpenApiDocument.Parse(OpenApi, OpenApiConstants.Yaml).Document; + _openApiDoc_2 = OpenApiDocument.Parse(OpenApi_2, OpenApiConstants.Yaml).Document; _openApiDoc.Workspace.AddDocumentId("https://myserver.com/beta", _openApiDoc_2.BaseUri); _openApiDoc.Workspace.RegisterComponents(_openApiDoc_2); diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs index 7fcd7dfd8..af9ab3c23 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiSecuritySchemeReferenceTests.cs @@ -45,7 +45,7 @@ public OpenApiSecuritySchemeReferenceTests() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); var result = OpenApiDocument.Parse(OpenApi, "yaml"); - _openApiSecuritySchemeReference = new("mySecurityScheme", result.OpenApiDocument); + _openApiSecuritySchemeReference = new("mySecurityScheme", result.Document); } [Fact] diff --git a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs index 82f1b27a2..8ec0e1373 100644 --- a/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs +++ b/test/Microsoft.OpenApi.Tests/Models/References/OpenApiTagReferenceTest.cs @@ -64,7 +64,7 @@ public OpenApiTagReferenceTest() { OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); var result = OpenApiDocument.Parse(OpenApi, "yaml"); - _openApiTagReference = new("user", result.OpenApiDocument) + _openApiTagReference = new("user", result.Document) { Description = "Users operations" }; diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 8f9f8ed41..af1ed8948 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -1388,8 +1388,8 @@ namespace Microsoft.OpenApi.Reader public class ReadResult { public ReadResult() { } - public Microsoft.OpenApi.Reader.OpenApiDiagnostic OpenApiDiagnostic { get; set; } - public Microsoft.OpenApi.Models.OpenApiDocument OpenApiDocument { get; set; } + public Microsoft.OpenApi.Reader.OpenApiDiagnostic Diagnostic { get; set; } + public Microsoft.OpenApi.Models.OpenApiDocument Document { get; set; } } public enum ReferenceResolutionSetting { From 07237af37d92ea66f855ec9739f55203a3e8971f Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 10 Dec 2024 11:15:39 +0300 Subject: [PATCH 057/127] Implement serialization and deserialization logic for unrecognized JSON schema keywords --- .../Models/OpenApiConstants.cs | 5 +++++ src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 14 ++++++++++++- .../Reader/V31/OpenApiSchemaDeserializer.cs | 14 ++++++++++++- .../Writers/OpenApiWriterExtensions.cs | 20 +++++++++++++++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs index 8877faac8..1c016f4c4 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiConstants.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiConstants.cs @@ -480,6 +480,11 @@ public static class OpenApiConstants /// public const string Properties = "properties"; + /// + /// Field: UnrecognizedKeywords + /// + public const string UnrecognizedKeywords = "unrecognizedKeywords"; + /// /// Field: Pattern Properties /// diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 0215ac522..4acca3f1d 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -327,6 +327,11 @@ public virtual IList Examples /// public virtual IDictionary Extensions { get; set; } = new Dictionary(); + /// + /// This object stores any unrecognized keywords found in the schema. + /// + public virtual IDictionary UnrecognizedKeywords { get; set; } = new Dictionary(); + /// /// Indicates object is a placeholder reference to an actual object and does not contain valid data. /// @@ -403,6 +408,7 @@ public OpenApiSchema(OpenApiSchema schema) UnresolvedReference = schema?.UnresolvedReference ?? UnresolvedReference; Reference = schema?.Reference != null ? new(schema?.Reference) : null; Annotations = schema?.Annotations != null ? new Dictionary(schema?.Annotations) : null; + UnrecognizedKeywords = schema?.UnrecognizedKeywords != null ? new Dictionary(schema?.UnrecognizedKeywords) : null; } /// @@ -554,6 +560,12 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, // extensions writer.WriteExtensions(Extensions, version); + // Unrecognized keywords + if (UnrecognizedKeywords.Any()) + { + writer.WriteOptionalMap(OpenApiConstants.UnrecognizedProperties, UnrecognizedKeywords, (w,s) => w.WriteAny(s)); + } + writer.WriteEndObject(); } diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs index 9c035da0d..ad943dce4 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs @@ -7,6 +7,8 @@ using Microsoft.OpenApi.Reader.ParseNodes; using System.Collections.Generic; using System.Globalization; +using System.Linq; +using System.Text.Json.Nodes; namespace Microsoft.OpenApi.Reader.V31 { @@ -254,7 +256,17 @@ public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocum foreach (var propertyNode in mapNode) { - propertyNode.ParseField(schema, _openApiSchemaFixedFields, _openApiSchemaPatternFields); + bool isRecognized = _openApiSchemaFixedFields.ContainsKey(propertyNode.Name) || + _openApiSchemaPatternFields.Any(p => p.Key(propertyNode.Name)); + + if (isRecognized) + { + propertyNode.ParseField(schema, _openApiSchemaFixedFields, _openApiSchemaPatternFields); + } + else + { + schema.UnrecognizedKeywords[propertyNode.Name] = propertyNode.JsonNode; + } } if (schema.Extensions.ContainsKey(OpenApiConstants.NullableExtension)) diff --git a/src/Microsoft.OpenApi/Writers/OpenApiWriterExtensions.cs b/src/Microsoft.OpenApi/Writers/OpenApiWriterExtensions.cs index a1a74e815..8c49a2960 100644 --- a/src/Microsoft.OpenApi/Writers/OpenApiWriterExtensions.cs +++ b/src/Microsoft.OpenApi/Writers/OpenApiWriterExtensions.cs @@ -5,6 +5,7 @@ using System.Collections; using System.Collections.Generic; using System.Linq; +using System.Text.Json.Nodes; using Microsoft.OpenApi.Interfaces; namespace Microsoft.OpenApi.Writers @@ -253,6 +254,25 @@ public static void WriteRequiredMap( writer.WriteMapInternal(name, elements, action); } + /// + /// Write the optional Open API element map (string to string mapping). + /// + /// The Open API writer. + /// The property name. + /// The map values. + /// The map element writer action. + public static void WriteOptionalMap( + this IOpenApiWriter writer, + string name, + IDictionary elements, + Action action) + { + if (elements != null && elements.Any()) + { + writer.WriteMapInternal(name, elements, action); + } + } + /// /// Write the optional Open API element map (string to string mapping). /// From e3310f5d29e667171a17f305aa29d6fa8ba13b41 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 10 Dec 2024 11:16:44 +0300 Subject: [PATCH 058/127] Rename method --- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 4acca3f1d..5eef32696 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -436,7 +436,7 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, if (version == OpenApiSpecVersion.OpenApi3_1) { - WriteV31Properties(writer); + WriteJsonSchemaKeywords(writer); } // title @@ -576,7 +576,7 @@ public virtual void SerializeAsV2(IOpenApiWriter writer) SerializeAsV2(writer: writer, parentRequiredProperties: new HashSet(), propertyName: null); } - internal void WriteV31Properties(IOpenApiWriter writer) + internal void WriteJsonSchemaKeywords(IOpenApiWriter writer) { writer.WriteProperty(OpenApiConstants.Id, Id); writer.WriteProperty(OpenApiConstants.DollarSchema, Schema); From 208d0fd2a1fb6c6bd5e258c1e458fd32e42a1a27 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 10 Dec 2024 11:17:17 +0300 Subject: [PATCH 059/127] Add tests to validate --- .../V31Tests/OpenApiSchemaTests.cs | 16 ++++++++ .../schemaWithJsonSchemaKeywords.yaml | 11 ------ .../Models/OpenApiSchemaTests.cs | 39 ++++++++++++++++--- .../PublicApi/PublicApi.approved.txt | 3 ++ 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs index 5f149b021..4a6fdac50 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/OpenApiSchemaTests.cs @@ -495,5 +495,21 @@ public void ParseSchemaWithConstWorks() var schemaString = writer.ToString(); schemaString.MakeLineBreaksEnvironmentNeutral().Should().Be(expected.MakeLineBreaksEnvironmentNeutral()); } + + [Fact] + public void ParseSchemaWithUnrecognizedKeywordsWorks() + { + var input = @"{ + ""type"": ""string"", + ""format"": ""date-time"", + ""customKeyword"": ""customValue"", + ""anotherKeyword"": 42, + ""x-test"": ""test"" +} +"; + var schema = OpenApiModelFactory.Parse(input, OpenApiSpecVersion.OpenApi3_1, out _, "json"); + schema.UnrecognizedKeywords.Should().HaveCount(2); + } + } } diff --git a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithJsonSchemaKeywords.yaml b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithJsonSchemaKeywords.yaml index 3d88cffcd..8c4fb1c1b 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithJsonSchemaKeywords.yaml +++ b/test/Microsoft.OpenApi.Readers.Tests/V31Tests/Samples/OpenApiSchema/schemaWithJsonSchemaKeywords.yaml @@ -28,14 +28,3 @@ required: - name $dynamicAnchor: "addressDef" -definitions: - address: - $dynamicAnchor: "addressDef" - type: "object" - properties: - street: - type: "string" - city: - type: "string" - postalCode: - type: "string" diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index 408173e6e..44a996573 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -602,15 +602,42 @@ public void OpenApiWalkerVisitsOpenApiSchemaNot() // Assert visitor.Titles.Count.Should().Be(2); } - } - internal class SchemaVisitor : OpenApiVisitorBase - { - public List Titles = new(); + [Fact] + public void SerializeSchemaWithUnrecognizedPropertiesWorks() + { + // Arrange + var schema = new OpenApiSchema + { + UnrecognizedKeywords = new Dictionary() + { + ["customKeyWord"] = "bar", + ["anotherKeyword"] = 42 + } + }; - public override void Visit(OpenApiSchema schema) + var expected = @"{ + ""unrecognizedProperties"": { + ""customKeyWord"": ""bar"", + ""anotherKeyword"": 42 + } +}"; + + // Act + var actual = schema.SerializeAsJson(OpenApiSpecVersion.OpenApi3_1); + + // Assert + actual.MakeLineBreaksEnvironmentNeutral().Should().Be(expected.MakeLineBreaksEnvironmentNeutral()); + } + + internal class SchemaVisitor : OpenApiVisitorBase { - Titles.Add(schema.Title); + public List Titles = new(); + + public override void Visit(OpenApiSchema schema) + { + Titles.Add(schema.Title); + } } } } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 8f9f8ed41..98fdd33a5 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -512,6 +512,7 @@ namespace Microsoft.OpenApi.Models public const string Type = "type"; public const string UnevaluatedProperties = "unevaluatedProperties"; public const string UniqueItems = "uniqueItems"; + public const string UnrecognizedKeywords = "unrecognizedKeywords"; public const string Url = "url"; public const string V2ReferenceUri = "https://registry/definitions/"; public const string V31ExclusiveMaximum = "exclusiveMaximum"; @@ -925,6 +926,7 @@ namespace Microsoft.OpenApi.Models public virtual bool UnEvaluatedProperties { get; set; } public virtual bool UnevaluatedProperties { get; set; } public virtual bool? UniqueItems { get; set; } + public virtual System.Collections.Generic.IDictionary UnrecognizedKeywords { get; set; } public virtual bool UnresolvedReference { get; set; } public virtual decimal? V31ExclusiveMaximum { get; set; } public virtual decimal? V31ExclusiveMinimum { get; set; } @@ -1859,6 +1861,7 @@ namespace Microsoft.OpenApi.Writers public static void WriteOptionalCollection(this Microsoft.OpenApi.Writers.IOpenApiWriter writer, string name, System.Collections.Generic.IEnumerable elements, System.Action action) { } public static void WriteOptionalMap(this Microsoft.OpenApi.Writers.IOpenApiWriter writer, string name, System.Collections.Generic.IDictionary elements, System.Action action) { } public static void WriteOptionalMap(this Microsoft.OpenApi.Writers.IOpenApiWriter writer, string name, System.Collections.Generic.IDictionary elements, System.Action action) { } + public static void WriteOptionalMap(this Microsoft.OpenApi.Writers.IOpenApiWriter writer, string name, System.Collections.Generic.IDictionary elements, System.Action action) { } public static void WriteOptionalMap(this Microsoft.OpenApi.Writers.IOpenApiWriter writer, string name, System.Collections.Generic.IDictionary elements, System.Action action) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } public static void WriteOptionalMap(this Microsoft.OpenApi.Writers.IOpenApiWriter writer, string name, System.Collections.Generic.IDictionary elements, System.Action action) From b91c13ed1caf7b5d58d4b3439d966bb430992c8f Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Tue, 10 Dec 2024 11:22:40 +0300 Subject: [PATCH 060/127] Clean up --- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 2 +- test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 5eef32696..dd7daabb3 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -563,7 +563,7 @@ public void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version, // Unrecognized keywords if (UnrecognizedKeywords.Any()) { - writer.WriteOptionalMap(OpenApiConstants.UnrecognizedProperties, UnrecognizedKeywords, (w,s) => w.WriteAny(s)); + writer.WriteOptionalMap(OpenApiConstants.UnrecognizedKeywords, UnrecognizedKeywords, (w,s) => w.WriteAny(s)); } writer.WriteEndObject(); diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index 44a996573..ebabc9d53 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -617,7 +617,7 @@ public void SerializeSchemaWithUnrecognizedPropertiesWorks() }; var expected = @"{ - ""unrecognizedProperties"": { + ""unrecognizedKeywords"": { ""customKeyWord"": ""bar"", ""anotherKeyword"": 42 } From dd80ab7464495af86c1bc0b92ac38aecedb8368d Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 11 Dec 2024 00:36:39 +0300 Subject: [PATCH 061/127] Update public API --- test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 9405b04d3..418673906 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -1313,7 +1313,7 @@ namespace Microsoft.OpenApi.Reader public class OpenApiJsonReader : Microsoft.OpenApi.Interfaces.IOpenApiReader { public OpenApiJsonReader() { } - public Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } + public Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings) { } public Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null) { } public System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, System.Threading.CancellationToken cancellationToken = default) { } public T ReadFragment(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) From 2c2bbe672eae87b4d3a6f3d68daf3e300b4b0ce8 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 11 Dec 2024 07:35:14 -0500 Subject: [PATCH 062/127] chore: code fixes recommended by sonarqube Signed-off-by: Vincent Biret --- .../Models/OpenApiDocument.cs | 2 +- .../Reader/OpenApiModelFactory.cs | 2 +- .../V3Tests/OpenApiDocumentTests.cs | 54 ++++++++----------- 3 files changed, 24 insertions(+), 34 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index 25b605d6d..b90f1b203 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -371,7 +371,7 @@ private static void WriteHostInfoV2(IOpenApiWriter writer, IList? // Arbitrarily choose the first server given that V2 only allows // one host, port, and base path. - var serverUrl = ParseServerUrl(servers.First()); + var serverUrl = ParseServerUrl(servers[0]); // Divide the URL in the Url property into host and basePath required in OpenAPI V2 // The Url property cannot contain path templating to be valid for V2 serialization. diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 2bb3cb8a3..d60e067e0 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -123,7 +123,7 @@ public static async Task LoadAsync(string url, OpenApiReaderSettings public static async Task LoadAsync(string url, OpenApiSpecVersion version, OpenApiReaderSettings settings = null) where T : IOpenApiElement { var result = await RetrieveStreamAndFormatAsync(url); - return Load(result.Item1, version, out var diagnostic, result.Item2, settings); + return Load(result.Item1, version, out var _, result.Item2, settings); } /// diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index aeb0a301f..a0ffc90c1 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -34,46 +34,36 @@ public OpenApiDocumentTests() public T Clone(T element) where T : IOpenApiSerializable { - using (var stream = new MemoryStream()) + using var stream = new MemoryStream(); + var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); + var writer = new OpenApiJsonWriter(streamWriter, new OpenApiJsonWriterSettings() { - IOpenApiWriter writer; - var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); - writer = new OpenApiJsonWriter(streamWriter, new OpenApiJsonWriterSettings() - { - InlineLocalReferences = true - }); - element.SerializeAsV3(writer); - writer.Flush(); - stream.Position = 0; + InlineLocalReferences = true + }); + element.SerializeAsV3(writer); + writer.Flush(); + stream.Position = 0; - using (var streamReader = new StreamReader(stream)) - { - var result = streamReader.ReadToEnd(); - return OpenApiModelFactory.Parse(result, OpenApiSpecVersion.OpenApi3_0, out OpenApiDiagnostic diagnostic4); - } - } + using var streamReader = new StreamReader(stream); + var result = streamReader.ReadToEnd(); + return OpenApiModelFactory.Parse(result, OpenApiSpecVersion.OpenApi3_0, out var _); } public OpenApiSecurityScheme CloneSecurityScheme(OpenApiSecurityScheme element) { - using (var stream = new MemoryStream()) + using var stream = new MemoryStream(); + var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); + var writer = new OpenApiJsonWriter(streamWriter, new OpenApiJsonWriterSettings() { - IOpenApiWriter writer; - var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); - writer = new OpenApiJsonWriter(streamWriter, new OpenApiJsonWriterSettings() - { - InlineLocalReferences = true - }); - element.SerializeAsV3(writer); - writer.Flush(); - stream.Position = 0; + InlineLocalReferences = true + }); + element.SerializeAsV3(writer); + writer.Flush(); + stream.Position = 0; - using (var streamReader = new StreamReader(stream)) - { - var result = streamReader.ReadToEnd(); - return OpenApiModelFactory.Parse(result, OpenApiSpecVersion.OpenApi3_0, out OpenApiDiagnostic diagnostic4); - } - } + using var streamReader = new StreamReader(stream); + var result = streamReader.ReadToEnd(); + return OpenApiModelFactory.Parse(result, OpenApiSpecVersion.OpenApi3_0, out var _); } [Fact] From d7064c42a2a85d36cee8212d36b8f078006fa091 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 11 Dec 2024 16:05:33 +0300 Subject: [PATCH 063/127] Remove code smells --- .../OpenApiYamlReader.cs | 2 +- src/Microsoft.OpenApi/Models/OpenApiTag.cs | 4 +- .../Models/OpenApiTagTests.cs | 38 +------------------ 3 files changed, 5 insertions(+), 39 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index cff6dd1da..c7f5834e4 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -77,7 +77,7 @@ static JsonNode LoadJsonNodesFromYamlDocument(TextReader input) { var yamlStream = new YamlStream(); yamlStream.Load(input); - var yamlDocument = yamlStream.Documents.First(); + var yamlDocument = yamlStream.Documents[0]; return yamlDocument.ToJsonNode(); } diff --git a/src/Microsoft.OpenApi/Models/OpenApiTag.cs b/src/Microsoft.OpenApi/Models/OpenApiTag.cs index 51175cd12..8e9321fe8 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiTag.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiTag.cs @@ -55,10 +55,10 @@ public OpenApiTag(OpenApiTag tag) { Name = tag?.Name ?? Name; Description = tag?.Description ?? Description; - ExternalDocs = tag?.ExternalDocs != null ? new(tag?.ExternalDocs) : null; + ExternalDocs = tag?.ExternalDocs != null ? new(tag.ExternalDocs) : null; Extensions = tag?.Extensions != null ? new Dictionary(tag.Extensions) : null; UnresolvedReference = tag?.UnresolvedReference ?? UnresolvedReference; - Reference = tag?.Reference != null ? new(tag?.Reference) : null; + Reference = tag?.Reference != null ? new(tag.Reference) : null; } /// diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs index d685be00d..24c186b0b 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs @@ -18,9 +18,9 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiTagTests { - public static OpenApiTag BasicTag = new(); + public static readonly OpenApiTag BasicTag = new(); - public static OpenApiTag AdvancedTag = new() + public static readonly OpenApiTag AdvancedTag = new() { Name = "pet", Description = "Pets operations", @@ -104,40 +104,6 @@ public void SerializeBasicTagAsV2YamlWithoutReferenceWorks() actual.Should().Be(expected); } - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync(bool produceTerseOutput) - { - // Arrange - var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new() { Terse = produceTerseOutput }); - - // Act - AdvancedTag.SerializeAsV3(writer); - writer.Flush(); - - // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public async Task SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync(bool produceTerseOutput) - { - // Arrange - var outputStringWriter = new StringWriter(CultureInfo.InvariantCulture); - var writer = new OpenApiJsonWriter(outputStringWriter, new() { Terse = produceTerseOutput }); - - // Act - AdvancedTag.SerializeAsV2(writer); - writer.Flush(); - - // Assert - await Verifier.Verify(outputStringWriter).UseParameters(produceTerseOutput); - } - [Fact] public void SerializeAdvancedTagAsV3YamlWithoutReferenceWorks() { From f27415de58d8dd4864e302211567374148ebf252 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Wed, 11 Dec 2024 17:49:25 +0300 Subject: [PATCH 064/127] Reduce redundancy and use LINQ statement --- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index dd7daabb3..8fed2e9e3 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -15,7 +15,7 @@ namespace Microsoft.OpenApi.Models /// /// The Schema Object allows the definition of input and output data types. /// - public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiReferenceable, IOpenApiSerializable + public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiReferenceable { private JsonNode _example; private JsonNode _default; @@ -832,15 +832,9 @@ private void SerializeTypeProperty(JsonSchemaType? type, IOpenApiWriter writer, } else { - var list = new List(); - foreach (JsonSchemaType flag in jsonSchemaTypeValues) - { - if (type.Value.HasFlag(flag)) - { - list.Add(flag); - } - } - + var list = (from JsonSchemaType flag in jsonSchemaTypeValues + where type.Value.HasFlag(flag) + select flag).ToList(); writer.WriteOptionalCollection(OpenApiConstants.Type, list, (w, s) => w.WriteValue(s.ToIdentifier())); } } @@ -862,16 +856,9 @@ private void UpCastSchemaTypeToV31(JsonSchemaType? type, IOpenApiWriter writer) { // create a new array and insert the type and "null" as values Type = type | JsonSchemaType.Null; - var list = new List(); - foreach (JsonSchemaType? flag in jsonSchemaTypeValues) - { - // Check if the flag is set in 'type' using a bitwise AND operation - if (Type.Value.HasFlag(flag)) - { - list.Add(flag.ToIdentifier()); - } - } - + var list = (from JsonSchemaType? flag in jsonSchemaTypeValues// Check if the flag is set in 'type' using a bitwise AND operation + where Type.Value.HasFlag(flag) + select flag.ToIdentifier()).ToList(); writer.WriteOptionalCollection(OpenApiConstants.Type, list, (w, s) => w.WriteValue(s)); } From 3665930fdf6949fa40f7739b2f0d57c247b88a98 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 11 Dec 2024 18:07:09 +0300 Subject: [PATCH 065/127] Update src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index 4d4289b81..e8adb5bd5 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -33,7 +33,7 @@ public async Task ReadAsync(Stream input, else { using var preparedStream = new MemoryStream(); - await input.CopyToAsync(preparedStream, copyBufferSize, cancellationToken); + await input.CopyToAsync(preparedStream, copyBufferSize, cancellationToken).ConfigureAwait(false); preparedStream.Position = 0; return Read(preparedStream, settings); } From 5ca061bb05e35a7325a3de84b95eb59121e687e8 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 11 Dec 2024 18:10:05 +0300 Subject: [PATCH 066/127] Update src/Microsoft.OpenApi/Models/OpenApiDocument.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Models/OpenApiDocument.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs index b90f1b203..268007141 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiDocument.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiDocument.cs @@ -570,7 +570,7 @@ public static async Task LoadAsync(string url, OpenApiReaderSettings /// public static async Task LoadAsync(Stream stream, string? format = null, OpenApiReaderSettings? settings = null, CancellationToken cancellationToken = default) { - return await OpenApiModelFactory.LoadAsync(stream, format, settings, cancellationToken); + return await OpenApiModelFactory.LoadAsync(stream, format, settings, cancellationToken).ConfigureAwait(false); } From e8c76dbdada2c224568c051acb95d83c063ec508 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 11 Dec 2024 18:10:33 +0300 Subject: [PATCH 067/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index d60e067e0..539f15bf1 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -325,7 +325,7 @@ private static string InspectStreamFormat(Stream stream) { // Use a temporary buffer to read a small portion for format detection using var bufferStream = new MemoryStream(); - await input.CopyToAsync(bufferStream, 1024, token); + await input.CopyToAsync(bufferStream, 1024, token).ConfigureAwait(false); bufferStream.Position = 0; // Inspect the format from the buffered portion From a66e21b511071b7af25f95eeb40ec927f89383a3 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 11 Dec 2024 18:10:43 +0300 Subject: [PATCH 068/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 539f15bf1..935196a05 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -341,8 +341,8 @@ private static string InspectStreamFormat(Stream stream) // YAML or other non-JSON format; copy remaining input to a new stream. preparedStream = new MemoryStream(); bufferStream.Position = 0; - await bufferStream.CopyToAsync(preparedStream, 81920, token); // Copy buffered portion - await input.CopyToAsync(preparedStream, 81920, token); // Copy remaining data + await bufferStream.CopyToAsync(preparedStream, 81920, token).ConfigureAwait(false); // Copy buffered portion + await input.CopyToAsync(preparedStream, 81920, token).ConfigureAwait(false); // Copy remaining data preparedStream.Position = 0; } } From 4198c82f3fddb404f4bac5029fda6fda04aa3cd8 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 11 Dec 2024 18:10:52 +0300 Subject: [PATCH 069/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 935196a05..6bdd20454 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -354,7 +354,7 @@ private static string InspectStreamFormat(Stream stream) { // Buffer stream for non-JSON formats (e.g., YAML) since they require synchronous reading preparedStream = new MemoryStream(); - await input.CopyToAsync(preparedStream, 81920, token); + await input.CopyToAsync(preparedStream, 81920, token).ConfigureAwait(false); preparedStream.Position = 0; } } From 0836e97d4b21966ee6aa75278fea812e25cb5e77 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 11 Dec 2024 10:12:32 -0500 Subject: [PATCH 070/127] chore: code linting Signed-off-by: Vincent Biret --- .../V3Tests/OpenApiDocumentTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index a0ffc90c1..e2274efab 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -32,7 +32,7 @@ public OpenApiDocumentTests() OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); } - public T Clone(T element) where T : IOpenApiSerializable + private static T Clone(T element) where T : IOpenApiSerializable { using var stream = new MemoryStream(); var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); @@ -49,7 +49,7 @@ public T Clone(T element) where T : IOpenApiSerializable return OpenApiModelFactory.Parse(result, OpenApiSpecVersion.OpenApi3_0, out var _); } - public OpenApiSecurityScheme CloneSecurityScheme(OpenApiSecurityScheme element) + private static OpenApiSecurityScheme CloneSecurityScheme(OpenApiSecurityScheme element) { using var stream = new MemoryStream(); var streamWriter = new FormattingStreamWriter(stream, CultureInfo.InvariantCulture); From a5e1057c2036b8d8d31346dd93e193905624c6a2 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 11 Dec 2024 18:15:13 +0300 Subject: [PATCH 071/127] Update src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 862cccf39..7f5b2bcd3 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -121,7 +121,7 @@ public async Task ReadAsync(Stream input, // Parse the JSON text in the TextReader into JsonNodes try { - jsonNode = await JsonNode.ParseAsync(input); + jsonNode = await JsonNode.ParseAsync(input, cancellationToken: cancellationToken).ConfigureAwait(false); } catch (JsonException ex) { From 01e4f4940598008dac81d2fc2f288988bbcd65ec Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 11 Dec 2024 10:17:11 -0500 Subject: [PATCH 072/127] chore: adds missing defensive programming and passes settings when required Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index e8adb5bd5..f66276a9b 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -11,6 +11,7 @@ using SharpYaml.Serialization; using System.Linq; using Microsoft.OpenApi.Models; +using System; namespace Microsoft.OpenApi.Readers { @@ -26,6 +27,7 @@ public async Task ReadAsync(Stream input, OpenApiReaderSettings settings, CancellationToken cancellationToken = default) { + if (input is null) throw new ArgumentNullException(nameof(input)); if (input is MemoryStream memoryStream) { return Read(memoryStream, settings); @@ -43,6 +45,8 @@ public async Task ReadAsync(Stream input, public ReadResult Read(MemoryStream input, OpenApiReaderSettings settings) { + if (input is null) throw new ArgumentNullException(nameof(input)); + if (settings is null) throw new ArgumentNullException(nameof(settings)); JsonNode jsonNode; // Parse the YAML text in the TextReader into a sequence of JsonNodes @@ -77,6 +81,7 @@ public T ReadFragment(MemoryStream input, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement { + if (input is null) throw new ArgumentNullException(nameof(input)); JsonNode jsonNode; // Parse the YAML @@ -92,13 +97,13 @@ public T ReadFragment(MemoryStream input, return default; } - return ReadFragment(jsonNode, version, out diagnostic); + return ReadFragment(jsonNode, version, out diagnostic, settings); } /// public T ReadFragment(JsonNode input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement { - return OpenApiReaderRegistry.DefaultReader.ReadFragment(input, version, out diagnostic); + return OpenApiReaderRegistry.DefaultReader.ReadFragment(input, version, out diagnostic, settings); } /// From 07ab67ae0deba3ccb6de97f8b7cb2892efcd12c6 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 11 Dec 2024 18:19:27 +0300 Subject: [PATCH 073/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 6bdd20454..3462f2592 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -228,7 +228,7 @@ private static async Task LoadExternalRefsAsync(OpenApiDocume // Load this root document into the workspace var streamLoader = new DefaultStreamLoader(settings.BaseUrl); var workspaceLoader = new OpenApiWorkspaceLoader(openApiWorkSpace, settings.CustomExternalLoader ?? streamLoader, settings); - return await workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource = "/" }, document, format ?? OpenApiConstants.Json, null, cancellationToken); + return await workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource = "/" }, document, format ?? OpenApiConstants.Json, null, cancellationToken).ConfigureAwait(false); } private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings) From 3123cb76abc3b638e1d287c262906a86b0461544 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Wed, 11 Dec 2024 18:20:36 +0300 Subject: [PATCH 074/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 3462f2592..130ce3c87 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -108,7 +108,7 @@ public static T Load(MemoryStream input, OpenApiSpecVersion version, string f public static async Task LoadAsync(string url, OpenApiReaderSettings settings = null) { var result = await RetrieveStreamAndFormatAsync(url); - return await LoadAsync(result.Item1, result.Item2, settings); + return await LoadAsync(result.Item1, result.Item2, settings).ConfigureAwait(false); } /// From ab2ddf0f264ccaf6efbf127c23be00adec51be1f Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 11 Dec 2024 10:21:45 -0500 Subject: [PATCH 075/127] fix: default settings in case of null value Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 6bdd20454..35c64fd05 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -200,12 +200,14 @@ public static T Parse(string input, return Load(stream, version, format, out diagnostic, settings); } + private static readonly OpenApiReaderSettings DefaultReaderSettings = new(); + private static async Task InternalLoadAsync(Stream input, string format, OpenApiReaderSettings settings, CancellationToken cancellationToken = default) { var reader = OpenApiReaderRegistry.GetReader(format); var readResult = await reader.ReadAsync(input, settings, cancellationToken); - if (settings.LoadExternalRefs) + if (settings?.LoadExternalRefs ?? DefaultReaderSettings.LoadExternalRefs) { var diagnosticExternalRefs = await LoadExternalRefsAsync(readResult.OpenApiDocument, cancellationToken, settings, format); // Merge diagnostics of external reference @@ -233,7 +235,7 @@ private static async Task LoadExternalRefsAsync(OpenApiDocume private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings) { - if (settings.LoadExternalRefs) + if (settings?.LoadExternalRefs ?? DefaultReaderSettings.LoadExternalRefs) { throw new InvalidOperationException("Loading external references are not supported when using synchronous methods."); } From 4bc34b14a31757b95e0cfd4b67f559c24387d5c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Dec 2024 21:08:18 +0000 Subject: [PATCH 076/127] chore(deps): bump PublicApiGenerator from 11.1.0 to 11.2.0 Bumps [PublicApiGenerator](https://github.com/PublicApiGenerator/PublicApiGenerator) from 11.1.0 to 11.2.0. - [Release notes](https://github.com/PublicApiGenerator/PublicApiGenerator/releases) - [Commits](https://github.com/PublicApiGenerator/PublicApiGenerator/compare/11.1.0...11.2.0) --- updated-dependencies: - dependency-name: PublicApiGenerator dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 49653747d..f3afbf4e9 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -18,7 +18,7 @@ - + From 1caaaaa07221d96ed4a363a06738fee5a9814fab Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Dec 2024 21:31:11 +0000 Subject: [PATCH 077/127] chore(deps): bump Microsoft.OData.Edm from 8.2.2 to 8.2.3 Bumps Microsoft.OData.Edm from 8.2.2 to 8.2.3. --- updated-dependencies: - dependency-name: Microsoft.OData.Edm dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 2b0582db7..0a31b1199 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -38,7 +38,7 @@ all - + From 7e9b952d732ac611d5d947e5aa871259d0ebaba5 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 13 Dec 2024 12:47:30 +0300 Subject: [PATCH 078/127] Bump preview versions --- src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj | 2 +- src/Microsoft.OpenApi/Microsoft.OpenApi.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj index 2d4f53610..05e3e52e6 100644 --- a/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj +++ b/src/Microsoft.OpenApi.Readers/Microsoft.OpenApi.Readers.csproj @@ -3,7 +3,7 @@ netstandard2.0 latest true - 2.0.0-preview2 + 2.0.0-preview3 OpenAPI.NET Readers for JSON and YAML documents true diff --git a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj index 070ca8108..5c4e18a29 100644 --- a/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj +++ b/src/Microsoft.OpenApi/Microsoft.OpenApi.csproj @@ -3,7 +3,7 @@ netstandard2.0 Latest true - 2.0.0-preview2 + 2.0.0-preview3 .NET models with JSON and YAML writers for OpenAPI specification true From b1265fca6c231475624489cf08023f7df5af12c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 13 Dec 2024 21:39:51 +0000 Subject: [PATCH 079/127] chore(deps): bump Verify.Xunit from 28.4.0 to 28.5.0 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 28.4.0 to 28.5.0. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/28.4.0...28.5.0) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index f3afbf4e9..5b3abf50c 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -14,7 +14,7 @@ - + From f0ac82de6adf73be8dca3a9a7ce5995f2fac4461 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 21:50:20 +0000 Subject: [PATCH 080/127] chore(deps): bump xunit.runner.visualstudio from 2.8.2 to 3.0.0 Bumps [xunit.runner.visualstudio](https://github.com/xunit/visualstudio.xunit) from 2.8.2 to 3.0.0. - [Release notes](https://github.com/xunit/visualstudio.xunit/releases) - [Commits](https://github.com/xunit/visualstudio.xunit/compare/2.8.2...3.0.0) --- updated-dependencies: - dependency-name: xunit.runner.visualstudio dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .../Microsoft.OpenApi.Hidi.Tests.csproj | 2 +- .../Microsoft.OpenApi.Readers.Tests.csproj | 2 +- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj index 7b214091d..a0cc5337f 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj +++ b/test/Microsoft.OpenApi.Hidi.Tests/Microsoft.OpenApi.Hidi.Tests.csproj @@ -15,7 +15,7 @@ - + diff --git a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj index 44f01df94..5a2e85fed 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj +++ b/test/Microsoft.OpenApi.Readers.Tests/Microsoft.OpenApi.Readers.Tests.csproj @@ -21,7 +21,7 @@ - + diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 5b3abf50c..1e28c726c 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -16,7 +16,7 @@ - + From 5e9bb19f9882f2296106dd28abe5cb8f5a9a863c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 21:50:22 +0000 Subject: [PATCH 081/127] chore(deps): bump Verify.Xunit from 28.5.0 to 28.6.0 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 28.5.0 to 28.6.0. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/28.5.0...28.6.0) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 1e28c726c..2f72c65de 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -14,7 +14,7 @@ - + From 5c958f8a83db0185ffb73946333c0db7ebee25da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 21:50:39 +0000 Subject: [PATCH 082/127] chore(deps): bump PublicApiGenerator from 11.2.0 to 11.3.0 Bumps [PublicApiGenerator](https://github.com/PublicApiGenerator/PublicApiGenerator) from 11.2.0 to 11.3.0. - [Release notes](https://github.com/PublicApiGenerator/PublicApiGenerator/releases) - [Commits](https://github.com/PublicApiGenerator/PublicApiGenerator/compare/11.2.0...11.3.0) --- updated-dependencies: - dependency-name: PublicApiGenerator dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 1e28c726c..cab56c5eb 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -18,7 +18,7 @@ - + From 830598209a8df9e25b46e015a4167437b773eb3b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 06:22:51 -0500 Subject: [PATCH 083/127] chore: adds baywet to code owners --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a61cbd408..5bb7a32bd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @irvinesunday @darrelmiller @gavinbarron @millicentachieng @MaggieKimani1 @andrueastman +* @irvinesunday @darrelmiller @gavinbarron @millicentachieng @MaggieKimani1 @andrueastman @baywet From 09158e2c8ec70f3e4687be3017f8a800c9a7572f Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 07:01:34 -0500 Subject: [PATCH 084/127] chore: uses backing fields Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 28 ++++--------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index 8fed2e9e3..e41f9acbb 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -17,10 +17,6 @@ namespace Microsoft.OpenApi.Models /// public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiReferenceable { - private JsonNode _example; - private JsonNode _default; - private IList _examples; - /// /// Follow JSON Schema definition. Short text providing information about the data. /// @@ -148,11 +144,7 @@ public class OpenApiSchema : IOpenApiAnnotatable, IOpenApiExtensible, IOpenApiRe /// Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. /// For example, if type is string, then default can be "foo" but cannot be 1. /// - public virtual JsonNode Default - { - get => _default; - set => _default = value; - } + public virtual JsonNode Default { get; set; } /// /// Relevant only for Schema "properties" definitions. Declares the property as "read only". @@ -273,22 +265,14 @@ public virtual JsonNode Default /// To represent examples that cannot be naturally represented in JSON or YAML, /// a string value can be used to contain the example with escaping where necessary. /// - public virtual JsonNode Example - { - get => _example; - set => _example = value; - } + public virtual JsonNode Example { get; set; } /// /// A free-form property to include examples of an instance for this schema. /// To represent examples that cannot be naturally represented in JSON or YAML, /// a list of values can be used to contain the examples with escaping where necessary. /// - public virtual IList Examples - { - get => _examples; - set => _examples = value; - } + public virtual IList Examples { get; set; } /// /// Follow JSON Schema definition: https://tools.ietf.org/html/draft-fge-json-schema-validation-00 @@ -378,7 +362,7 @@ public OpenApiSchema(OpenApiSchema schema) MinLength = schema?.MinLength ?? MinLength; Pattern = schema?.Pattern ?? Pattern; MultipleOf = schema?.MultipleOf ?? MultipleOf; - _default = schema?.Default != null ? JsonNodeCloneHelper.Clone(schema?.Default) : null; + Default = schema?.Default != null ? JsonNodeCloneHelper.Clone(schema?.Default) : null; ReadOnly = schema?.ReadOnly ?? ReadOnly; WriteOnly = schema?.WriteOnly ?? WriteOnly; AllOf = schema?.AllOf != null ? new List(schema.AllOf) : null; @@ -397,8 +381,8 @@ public OpenApiSchema(OpenApiSchema schema) AdditionalPropertiesAllowed = schema?.AdditionalPropertiesAllowed ?? AdditionalPropertiesAllowed; AdditionalProperties = schema?.AdditionalProperties != null ? new(schema?.AdditionalProperties) : null; Discriminator = schema?.Discriminator != null ? new(schema?.Discriminator) : null; - _example = schema?.Example != null ? JsonNodeCloneHelper.Clone(schema?.Example) : null; - _examples = schema?.Examples != null ? new List(schema.Examples) : null; + Example = schema?.Example != null ? JsonNodeCloneHelper.Clone(schema?.Example) : null; + Examples = schema?.Examples != null ? new List(schema.Examples) : null; Enum = schema?.Enum != null ? new List(schema.Enum) : null; Nullable = schema?.Nullable ?? Nullable; ExternalDocs = schema?.ExternalDocs != null ? new(schema?.ExternalDocs) : null; From 7d297bed60039c7fb64aaf9b00a49ad3e10dd3ab Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 07:17:14 -0500 Subject: [PATCH 085/127] chore: code linting Signed-off-by: Vincent Biret --- test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs index ebabc9d53..75ea5ca47 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiSchemaTests.cs @@ -22,7 +22,7 @@ namespace Microsoft.OpenApi.Tests.Models [Collection("DefaultSettings")] public class OpenApiSchemaTests { - public static OpenApiSchema BasicSchema = new(); + private static readonly OpenApiSchema BasicSchema = new(); public static readonly OpenApiSchema AdvancedSchemaNumber = new() { From 955f7fbfac065373b11f676c41785bcac6ffb79f Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 19 Dec 2024 15:18:44 +0300 Subject: [PATCH 086/127] Fix issues from resolving merge conflicts --- src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs | 4 ++-- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 6 +++--- .../Services/OpenApiFilterServiceTests.cs | 2 +- .../V3Tests/OpenApiDocumentTests.cs | 4 ++-- test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index a729dc10f..1cdf6bb04 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -128,8 +128,8 @@ public async Task ReadAsync(Stream input, diagnostic.Errors.Add(new OpenApiError($"#line={ex.LineNumber}", $"Please provide the correct format, {ex.Message}")); return new ReadResult { - OpenApiDocument = null, - OpenApiDiagnostic = diagnostic + Document = null, + Diagnostic = diagnostic }; } diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index f9048db17..139e1f80c 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -209,12 +209,12 @@ private static async Task InternalLoadAsync(Stream input, string for if (settings?.LoadExternalRefs ?? DefaultReaderSettings.LoadExternalRefs) { - var diagnosticExternalRefs = await LoadExternalRefsAsync(readResult.OpenApiDocument, cancellationToken, settings, format); + var diagnosticExternalRefs = await LoadExternalRefsAsync(readResult.Document, cancellationToken, settings, format); // Merge diagnostics of external reference if (diagnosticExternalRefs != null) { - readResult.OpenApiDiagnostic.Errors.AddRange(diagnosticExternalRefs.Errors); - readResult.OpenApiDiagnostic.Warnings.AddRange(diagnosticExternalRefs.Warnings); + readResult.Diagnostic.Errors.AddRange(diagnosticExternalRefs.Errors); + readResult.Diagnostic.Warnings.AddRange(diagnosticExternalRefs.Warnings); } } diff --git a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs index f51c1ec9b..12293c4e5 100644 --- a/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs +++ b/test/Microsoft.OpenApi.Hidi.Tests/Services/OpenApiFilterServiceTests.cs @@ -232,7 +232,7 @@ public async Task CopiesOverAllReferencedComponentsToTheSubsetDocumentCorrectly( // Act using var stream = File.OpenRead(filePath); - var doc = OpenApiDocument.Load(stream, "yaml").Document; + var doc = (await OpenApiDocument.LoadAsync(stream, "yaml")).Document; var predicate = OpenApiFilterService.CreatePredicate(operationIds: operationIds); var subsetOpenApiDocument = OpenApiFilterService.CreateFilteredDocument(doc, predicate); diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs index 5c9fd71dc..c281206e3 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiDocumentTests.cs @@ -108,7 +108,7 @@ public void ParseInlineStringWithoutProvidingFormatSucceeds() """; var readResult = OpenApiDocument.Parse(stringOpenApiDoc); - readResult.OpenApiDocument.Info.Title.Should().Be("Sample API"); + readResult.Document.Info.Title.Should().Be("Sample API"); } [Fact] @@ -1323,7 +1323,7 @@ public async Task ParseDocWithRefsUsingProxyReferencesSucceeds() using var stream = Resources.GetStream(System.IO.Path.Combine(SampleFolderPath, "minifiedPetStore.yaml")); // Act - var doc = OpenApiDocument.Load(stream, "yaml").Document; + var doc = (await OpenApiDocument.LoadAsync(stream)).Document; var actualParam = doc.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; var outputDoc = doc.SerializeAsYaml(OpenApiSpecVersion.OpenApi3_0).MakeLineBreaksEnvironmentNeutral(); var expectedParam = expected.Paths["/pets"].Operations[OperationType.Get].Parameters[0]; diff --git a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs index c2e0f192a..5d493fc55 100644 --- a/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs +++ b/test/Microsoft.OpenApi.Tests/Models/OpenApiDocumentTests.cs @@ -1702,7 +1702,7 @@ And reading in similar documents(one has a whitespace) yields the same hash code private static async Task ParseInputFileAsync(string filePath) { - var openApiDoc = (await OpenApiDocument.LoadAsync(filePath)).OpenApiDocument; + var openApiDoc = (await OpenApiDocument.LoadAsync(filePath)).Document; return openApiDoc; } From 146b44ff4b8ee926d2923a64c350c8ab9bc83ebc Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 07:19:49 -0500 Subject: [PATCH 087/127] Update src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs --- src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs index ad943dce4..893ed0a37 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs @@ -257,7 +257,7 @@ public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocum foreach (var propertyNode in mapNode) { bool isRecognized = _openApiSchemaFixedFields.ContainsKey(propertyNode.Name) || - _openApiSchemaPatternFields.Any(p => p.Key(propertyNode.Name)); + _openApiSchemaPatternFields.Any(static p => p.Key(propertyNode.Name)); if (isRecognized) { From 7be32fcdf1e1fa70b98cb67dc1aabf3bbc07ea3f Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 07:21:43 -0500 Subject: [PATCH 088/127] Revert "Update src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs" This reverts commit 146b44ff4b8ee926d2923a64c350c8ab9bc83ebc. --- src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs index 893ed0a37..ad943dce4 100644 --- a/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs +++ b/src/Microsoft.OpenApi/Reader/V31/OpenApiSchemaDeserializer.cs @@ -257,7 +257,7 @@ public static OpenApiSchema LoadSchema(ParseNode node, OpenApiDocument hostDocum foreach (var propertyNode in mapNode) { bool isRecognized = _openApiSchemaFixedFields.ContainsKey(propertyNode.Name) || - _openApiSchemaPatternFields.Any(static p => p.Key(propertyNode.Name)); + _openApiSchemaPatternFields.Any(p => p.Key(propertyNode.Name)); if (isRecognized) { From 2443fa0d3da5ec4ef09d9e6cae2491a117fac77b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 07:22:21 -0500 Subject: [PATCH 089/127] fix: missing property rename Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi/Models/OpenApiSchema.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs index e41f9acbb..c9e5441a9 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiSchema.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiSchema.cs @@ -573,7 +573,7 @@ internal void WriteJsonSchemaKeywords(IOpenApiWriter writer) writer.WriteProperty(OpenApiConstants.V31ExclusiveMaximum, V31ExclusiveMaximum); writer.WriteProperty(OpenApiConstants.V31ExclusiveMinimum, V31ExclusiveMinimum); writer.WriteProperty(OpenApiConstants.UnevaluatedProperties, UnevaluatedProperties, false); - writer.WriteOptionalCollection(OpenApiConstants.Examples, _examples, (nodeWriter, s) => nodeWriter.WriteAny(s)); + writer.WriteOptionalCollection(OpenApiConstants.Examples, Examples, (nodeWriter, s) => nodeWriter.WriteAny(s)); writer.WriteOptionalMap(OpenApiConstants.PatternProperties, PatternProperties, (w, s) => s.SerializeAsV31(w)); } From a4933ef3802cc469fdfa1146d3bcfc9e958696bc Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Thu, 19 Dec 2024 15:43:19 +0300 Subject: [PATCH 090/127] Update input doc comments --- src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs | 2 +- src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs | 2 +- src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs | 10 ++++------ 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index 4abfdbddb..3c5046c96 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -49,7 +49,7 @@ public ReadResult Read(MemoryStream input, if (settings is null) throw new ArgumentNullException(nameof(settings)); JsonNode jsonNode; - // Parse the YAML text in the TextReader into a sequence of JsonNodes + // Parse the YAML text in the stream into a sequence of JsonNodes try { using var stream = new StreamReader(input, default, true, -1, settings.LeaveStreamOpen); diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs index 642572985..42e7e466d 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs @@ -17,7 +17,7 @@ public interface IOpenApiReader /// /// Async method to reads the stream and parse it into an Open API document. /// - /// The TextReader input. + /// The stream input. /// The OpenApi reader settings. /// Propagates notification that an operation should be cancelled. /// diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index 1cdf6bb04..d058596dc 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -23,7 +23,7 @@ public class OpenApiJsonReader : IOpenApiReader /// /// Reads the memory stream input and parses it into an Open API document. /// - /// TextReader containing OpenAPI description to parse. + /// Memory stream containing OpenAPI description to parse. /// The Reader settings to be used during parsing. /// public ReadResult Read(MemoryStream input, @@ -33,7 +33,7 @@ public ReadResult Read(MemoryStream input, var diagnostic = new OpenApiDiagnostic(); settings ??= new OpenApiReaderSettings(); - // Parse the JSON text in the TextReader into JsonNodes + // Parse the JSON text in the stream into JsonNodes try { jsonNode = JsonNode.Parse(input); @@ -106,7 +106,7 @@ public ReadResult Read(JsonNode jsonNode, /// /// Reads the stream input asynchronously and parses it into an Open API document. /// - /// TextReader containing OpenAPI description to parse. + /// Memory stream containing OpenAPI description to parse. /// The Reader settings to be used during parsing. /// Propagates notifications that operations should be cancelled. /// @@ -118,7 +118,7 @@ public async Task ReadAsync(Stream input, var diagnostic = new OpenApiDiagnostic(); settings ??= new OpenApiReaderSettings(); - // Parse the JSON text in the TextReader into JsonNodes + // Parse the JSON text in the stream into JsonNodes try { jsonNode = await JsonNode.ParseAsync(input, cancellationToken: cancellationToken).ConfigureAwait(false); @@ -195,7 +195,5 @@ public T ReadFragment(JsonNode input, return (T)element; } - - } } From 4f55597866e1b5405723c9c98b97da626baeeb8e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 07:55:57 -0500 Subject: [PATCH 091/127] chore: exposes unused property so consumers can read the information Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi/Services/OpenApiReferenceError.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Services/OpenApiReferenceError.cs b/src/Microsoft.OpenApi/Services/OpenApiReferenceError.cs index d9a76368d..6dfd066ff 100644 --- a/src/Microsoft.OpenApi/Services/OpenApiReferenceError.cs +++ b/src/Microsoft.OpenApi/Services/OpenApiReferenceError.cs @@ -11,7 +11,10 @@ namespace Microsoft.OpenApi.Services /// public class OpenApiReferenceError : OpenApiError { - private OpenApiReference _reference; + /// + /// The reference that caused the error. + /// + public readonly OpenApiReference Reference; /// /// Initializes the class using the message and pointer from the given exception. /// @@ -26,7 +29,7 @@ public OpenApiReferenceError(OpenApiException exception) : base(exception.Pointe /// public OpenApiReferenceError(OpenApiReference reference, string message) : base("", message) { - _reference = reference; + Reference = reference; } } } From b00b557f54acfa926b9ead54fff3d7e654440ad5 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 07:56:11 -0500 Subject: [PATCH 092/127] chore: aligns parameter names with base definition Signed-off-by: Vincent Biret --- .../Validations/OpenApiValidator.cs | 259 +++++------------- 1 file changed, 74 insertions(+), 185 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs index 6908e58bf..7281ef258 100644 --- a/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs +++ b/src/Microsoft.OpenApi/Validations/OpenApiValidator.cs @@ -67,219 +67,108 @@ public void AddWarning(OpenApiValidatorWarning warning) _warnings.Add(warning); } - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiDocument item) => Validate(item); + /// + public override void Visit(OpenApiDocument doc) => Validate(doc); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiInfo item) => Validate(item); + /// + public override void Visit(OpenApiInfo info) => Validate(info); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiContact item) => Validate(item); + /// + public override void Visit(OpenApiContact contact) => Validate(contact); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiComponents item) => Validate(item); + /// + public override void Visit(OpenApiComponents components) => Validate(components); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiHeader item) => Validate(item); + /// + public override void Visit(OpenApiHeader header) => Validate(header); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiResponse item) => Validate(item); + /// + public override void Visit(OpenApiResponse response) => Validate(response); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiMediaType item) => Validate(item); + /// + public override void Visit(OpenApiMediaType mediaType) => Validate(mediaType); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiResponses item) => Validate(item); + /// + public override void Visit(OpenApiResponses response) => Validate(response); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiExternalDocs item) => Validate(item); + /// + public override void Visit(OpenApiExternalDocs externalDocs) => Validate(externalDocs); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiLicense item) => Validate(item); + /// + public override void Visit(OpenApiLicense license) => Validate(license); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiOAuthFlow item) => Validate(item); + /// + public override void Visit(OpenApiOAuthFlow openApiOAuthFlow) => Validate(openApiOAuthFlow); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiTag item) => Validate(item); + /// + public override void Visit(OpenApiTag tag) => Validate(tag); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiParameter item) => Validate(item); + /// + public override void Visit(OpenApiParameter parameter) => Validate(parameter); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiSchema item) => Validate(item); + /// + public override void Visit(OpenApiSchema schema) => Validate(schema); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiServer item) => Validate(item); + /// + public override void Visit(OpenApiServer server) => Validate(server); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiEncoding item) => Validate(item); + /// + public override void Visit(OpenApiEncoding encoding) => Validate(encoding); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(OpenApiCallback item) => Validate(item); + /// + public override void Visit(OpenApiCallback callback) => Validate(callback); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(IOpenApiExtensible item) => Validate(item); + /// + public override void Visit(IOpenApiExtensible openApiExtensible) => Validate(openApiExtensible); - /// - /// Execute validation rules against an - /// - /// The object to be validated - public override void Visit(IOpenApiExtension item) => Validate(item, item.GetType()); + /// + public override void Visit(IOpenApiExtension openApiExtension) => Validate(openApiExtension, openApiExtension.GetType()); - /// - /// Execute validation rules against a list of - /// - /// The object to be validated - public override void Visit(IList items) => Validate(items, items.GetType()); + /// + public override void Visit(IList example) => Validate(example, example.GetType()); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(OpenApiPathItem item) => Validate(item); + /// + public override void Visit(OpenApiPathItem pathItem) => Validate(pathItem); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(OpenApiServerVariable item) => Validate(item); + /// + public override void Visit(OpenApiServerVariable serverVariable) => Validate(serverVariable); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(OpenApiSecurityScheme item) => Validate(item); + /// + public override void Visit(OpenApiSecurityScheme securityScheme) => Validate(securityScheme); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(OpenApiSecurityRequirement item) => Validate(item); + /// + public override void Visit(OpenApiSecurityRequirement securityRequirement) => Validate(securityRequirement); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(OpenApiRequestBody item) => Validate(item); + /// + public override void Visit(OpenApiRequestBody requestBody) => Validate(requestBody); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(OpenApiPaths item) => Validate(item); + /// + public override void Visit(OpenApiPaths paths) => Validate(paths); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(OpenApiLink item) => Validate(item); + /// + public override void Visit(OpenApiLink link) => Validate(link); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(OpenApiExample item) => Validate(item); + /// + public override void Visit(OpenApiExample example) => Validate(example); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(OpenApiOperation item) => Validate(item); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(IDictionary item) => Validate(item, item.GetType()); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(IDictionary item) => Validate(item, item.GetType()); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(IDictionary item) => Validate(item, item.GetType()); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(IDictionary item) => Validate(item, item.GetType()); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(IDictionary item) => Validate(item, item.GetType()); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(IDictionary item) => Validate(item, item.GetType()); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(IDictionary item) => Validate(item, item.GetType()); - /// - /// Execute validation rules against a - /// - /// The object to be validated - public override void Visit(IDictionary item) => Validate(item, item.GetType()); + /// + public override void Visit(OpenApiOperation operation) => Validate(operation); + /// + public override void Visit(IDictionary operations) => Validate(operations, operations.GetType()); + /// + public override void Visit(IDictionary headers) => Validate(headers, headers.GetType()); + /// + public override void Visit(IDictionary callbacks) => Validate(callbacks, callbacks.GetType()); + /// + public override void Visit(IDictionary content) => Validate(content, content.GetType()); + /// + public override void Visit(IDictionary examples) => Validate(examples, examples.GetType()); + /// + public override void Visit(IDictionary links) => Validate(links, links.GetType()); + /// + public override void Visit(IDictionary serverVariables) => Validate(serverVariables, serverVariables.GetType()); + /// + public override void Visit(IDictionary encodings) => Validate(encodings, encodings.GetType()); private void Validate(T item) { From f9f77668ec594f2d52381ab40193fcb3a15f5571 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 07:56:20 -0500 Subject: [PATCH 093/127] chore: aligns parameter names Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi.Hidi/StatsVisitor.cs | 2 +- src/Microsoft.OpenApi.Workbench/StatsVisitor.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs index b6af07778..d1f6f7f64 100644 --- a/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Hidi/StatsVisitor.cs @@ -61,7 +61,7 @@ public override void Visit(OpenApiOperation operation) public int LinkCount { get; set; } - public override void Visit(OpenApiLink operation) + public override void Visit(OpenApiLink link) { LinkCount++; } diff --git a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs index ed662d302..fafbc8188 100644 --- a/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs +++ b/src/Microsoft.OpenApi.Workbench/StatsVisitor.cs @@ -61,7 +61,7 @@ public override void Visit(OpenApiOperation operation) public int LinkCount { get; set; } - public override void Visit(OpenApiLink operation) + public override void Visit(OpenApiLink link) { LinkCount++; } From a72c5c216ff86a41298aa65c0325e39674c08df6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 07:57:30 -0500 Subject: [PATCH 094/127] chore: linting Signed-off-by: Vincent Biret --- .../Validations/Rules/OpenApiComponentsRules.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiComponentsRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiComponentsRules.cs index 93eba5c71..053c5391b 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiComponentsRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiComponentsRules.cs @@ -17,7 +17,7 @@ public static class OpenApiComponentsRules /// /// The key regex. /// - public static Regex KeyRegex = new(@"^[a-zA-Z0-9\.\-_]+$"); + public static readonly Regex KeyRegex = new(@"^[a-zA-Z0-9\.\-_]+$"); /// /// All the fixed fields declared above are objects From b9ef21d553bb94b98ff1ea384dca42eecadb0ed3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 08:04:48 -0500 Subject: [PATCH 095/127] chore: removes conflicting overload Signed-off-by: Vincent Biret --- .../Models/OpenApiExtensibleDictionary.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs b/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs index be2e56a73..0c7036dba 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs @@ -17,11 +17,6 @@ public abstract class OpenApiExtensibleDictionary : Dictionary, IOpenApiExtensible where T : IOpenApiSerializable { - /// - /// Parameterless constructor - /// - protected OpenApiExtensibleDictionary() { } - /// /// Initializes a copy of class. /// @@ -29,7 +24,7 @@ protected OpenApiExtensibleDictionary() { } /// The dictionary of . protected OpenApiExtensibleDictionary( Dictionary dictionary = null, - IDictionary extensions = null) : base(dictionary) + IDictionary extensions = null) : base(dictionary is null ? [] : dictionary) { Extensions = extensions != null ? new Dictionary(extensions) : null; } From 84e83f47ac9717ac3944cb2dd61375095c897ba2 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 08:10:23 -0500 Subject: [PATCH 096/127] chore: reduces loops Signed-off-by: Vincent Biret --- .../Validations/Rules/OpenApiExtensionRules.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs index 890be82d7..3509d797f 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiExtensionRules.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. using System; +using System.Linq; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Properties; @@ -21,13 +22,10 @@ public static class OpenApiExtensibleRules (context, item) => { context.Enter("extensions"); - foreach (var extensible in item.Extensions) + foreach (var extensible in item.Extensions.Keys.Where(static x => !x.StartsWith("x-", StringComparison.OrdinalIgnoreCase))) { - if (!extensible.Key.StartsWith("x-")) - { - context.CreateError(nameof(ExtensionNameMustStartWithXDash), - String.Format(SRResource.Validation_ExtensionNameMustBeginWithXDash, extensible.Key, context.PathString)); - } + context.CreateError(nameof(ExtensionNameMustStartWithXDash), + string.Format(SRResource.Validation_ExtensionNameMustBeginWithXDash, extensible, context.PathString)); } context.Exit(); }); From 4f28b657310b90c82a5b5af9f91ef6e097847a97 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 08:16:22 -0500 Subject: [PATCH 097/127] fix: extensions collection initialization Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs b/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs index 0c7036dba..4ffc20361 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs @@ -26,13 +26,13 @@ protected OpenApiExtensibleDictionary( Dictionary dictionary = null, IDictionary extensions = null) : base(dictionary is null ? [] : dictionary) { - Extensions = extensions != null ? new Dictionary(extensions) : null; + Extensions = extensions != null ? new Dictionary(extensions) : []; } /// /// This object MAY be extended with Specification Extensions. /// - public IDictionary Extensions { get; set; } = new Dictionary(); + public IDictionary Extensions { get; set; } /// From 778184ff608cd4172de689684272b2d7a8627339 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 08:29:17 -0500 Subject: [PATCH 098/127] fix: restores default constructor for ISerializable implementation --- .../Models/OpenApiExtensibleDictionary.cs | 6 +- .../PublicApi/PublicApi.approved.txt | 79 ++++++++++--------- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs b/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs index 4ffc20361..86fe7ea73 100644 --- a/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs +++ b/src/Microsoft.OpenApi/Models/OpenApiExtensibleDictionary.cs @@ -17,13 +17,17 @@ public abstract class OpenApiExtensibleDictionary : Dictionary, IOpenApiExtensible where T : IOpenApiSerializable { + /// + /// Parameterless constructor + /// + protected OpenApiExtensibleDictionary():this(null) { } /// /// Initializes a copy of class. /// /// The generic dictionary. /// The dictionary of . protected OpenApiExtensibleDictionary( - Dictionary dictionary = null, + Dictionary dictionary, IDictionary extensions = null) : base(dictionary is null ? [] : dictionary) { Extensions = extensions != null ? new Dictionary(extensions) : []; diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index c25a06688..6798d55c0 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -629,7 +629,7 @@ namespace Microsoft.OpenApi.Models where T : Microsoft.OpenApi.Interfaces.IOpenApiSerializable { protected OpenApiExtensibleDictionary() { } - protected OpenApiExtensibleDictionary(System.Collections.Generic.Dictionary dictionary = null, System.Collections.Generic.IDictionary extensions = null) { } + protected OpenApiExtensibleDictionary(System.Collections.Generic.Dictionary dictionary, System.Collections.Generic.IDictionary extensions = null) { } public System.Collections.Generic.IDictionary Extensions { get; set; } public void SerializeAsV2(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } public void SerializeAsV3(Microsoft.OpenApi.Writers.IOpenApiWriter writer) { } @@ -1452,6 +1452,7 @@ namespace Microsoft.OpenApi.Services } public class OpenApiReferenceError : Microsoft.OpenApi.Models.OpenApiError { + public readonly Microsoft.OpenApi.Models.OpenApiReference Reference; public OpenApiReferenceError(Microsoft.OpenApi.Exceptions.OpenApiException exception) { } public OpenApiReferenceError(Microsoft.OpenApi.Models.OpenApiReference reference, string message) { } } @@ -1577,43 +1578,43 @@ namespace Microsoft.OpenApi.Validations public System.Collections.Generic.IEnumerable Warnings { get; } public void AddError(Microsoft.OpenApi.Validations.OpenApiValidatorError error) { } public void AddWarning(Microsoft.OpenApi.Validations.OpenApiValidatorWarning warning) { } - public override void Visit(Microsoft.OpenApi.Interfaces.IOpenApiExtensible item) { } - public override void Visit(Microsoft.OpenApi.Interfaces.IOpenApiExtension item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiCallback item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiComponents item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiContact item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiDocument item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiEncoding item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiExample item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiExternalDocs item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiHeader item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiInfo item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiLicense item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiLink item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiMediaType item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiOAuthFlow item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiOperation item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiParameter item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiPathItem item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiPaths item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiRequestBody item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiResponse item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiResponses item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiSchema item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityScheme item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiServer item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiServerVariable item) { } - public override void Visit(Microsoft.OpenApi.Models.OpenApiTag item) { } - public override void Visit(System.Collections.Generic.IDictionary item) { } - public override void Visit(System.Collections.Generic.IDictionary item) { } - public override void Visit(System.Collections.Generic.IDictionary item) { } - public override void Visit(System.Collections.Generic.IDictionary item) { } - public override void Visit(System.Collections.Generic.IDictionary item) { } - public override void Visit(System.Collections.Generic.IDictionary item) { } - public override void Visit(System.Collections.Generic.IDictionary item) { } - public override void Visit(System.Collections.Generic.IDictionary item) { } - public override void Visit(System.Collections.Generic.IList items) { } + public override void Visit(Microsoft.OpenApi.Interfaces.IOpenApiExtensible openApiExtensible) { } + public override void Visit(Microsoft.OpenApi.Interfaces.IOpenApiExtension openApiExtension) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiCallback callback) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiComponents components) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiContact contact) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiDocument doc) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiEncoding encoding) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiExample example) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiExternalDocs externalDocs) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiHeader header) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiInfo info) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiLicense license) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiLink link) { } + 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) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiResponse response) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiResponses response) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiSchema schema) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityRequirement securityRequirement) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiSecurityScheme securityScheme) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiServer server) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiServerVariable serverVariable) { } + public override void Visit(Microsoft.OpenApi.Models.OpenApiTag tag) { } + public override void Visit(System.Collections.Generic.IDictionary operations) { } + public override void Visit(System.Collections.Generic.IDictionary callbacks) { } + public override void Visit(System.Collections.Generic.IDictionary encodings) { } + public override void Visit(System.Collections.Generic.IDictionary examples) { } + public override void Visit(System.Collections.Generic.IDictionary headers) { } + public override void Visit(System.Collections.Generic.IDictionary links) { } + public override void Visit(System.Collections.Generic.IDictionary content) { } + public override void Visit(System.Collections.Generic.IDictionary serverVariables) { } + public override void Visit(System.Collections.Generic.IList example) { } } public class OpenApiValidatorError : Microsoft.OpenApi.Models.OpenApiError { @@ -1670,7 +1671,7 @@ namespace Microsoft.OpenApi.Validations.Rules [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiComponentsRules { - public static System.Text.RegularExpressions.Regex KeyRegex; + public static readonly System.Text.RegularExpressions.Regex KeyRegex; public static Microsoft.OpenApi.Validations.ValidationRule KeyMustBeRegularExpression { get; } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] From e86df13fd677ccb018ab592da1c3d41a062aa0a5 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 08:30:46 -0500 Subject: [PATCH 099/127] chore: makes regex internal Signed-off-by: Vincent Biret --- .../Validations/Rules/OpenApiComponentsRules.cs | 2 +- test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Microsoft.OpenApi/Validations/Rules/OpenApiComponentsRules.cs b/src/Microsoft.OpenApi/Validations/Rules/OpenApiComponentsRules.cs index 053c5391b..bd14f93ed 100644 --- a/src/Microsoft.OpenApi/Validations/Rules/OpenApiComponentsRules.cs +++ b/src/Microsoft.OpenApi/Validations/Rules/OpenApiComponentsRules.cs @@ -17,7 +17,7 @@ public static class OpenApiComponentsRules /// /// The key regex. /// - public static readonly Regex KeyRegex = new(@"^[a-zA-Z0-9\.\-_]+$"); + internal static readonly Regex KeyRegex = new(@"^[a-zA-Z0-9\.\-_]+$"); /// /// All the fixed fields declared above are objects diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 6798d55c0..83c6898c0 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -1671,7 +1671,6 @@ namespace Microsoft.OpenApi.Validations.Rules [Microsoft.OpenApi.Validations.Rules.OpenApiRule] public static class OpenApiComponentsRules { - public static readonly System.Text.RegularExpressions.Regex KeyRegex; public static Microsoft.OpenApi.Validations.ValidationRule KeyMustBeRegularExpression { get; } } [Microsoft.OpenApi.Validations.Rules.OpenApiRule] From 538d2ebab86efe39cc2129d967ae293619d70dde Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Thu, 19 Dec 2024 16:54:03 +0300 Subject: [PATCH 100/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 139e1f80c..75388c376 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -122,7 +122,7 @@ public static async Task LoadAsync(string url, OpenApiReaderSettings /// The OpenAPI element. public static async Task LoadAsync(string url, OpenApiSpecVersion version, OpenApiReaderSettings settings = null) where T : IOpenApiElement { - var result = await RetrieveStreamAndFormatAsync(url); + var result = await RetrieveStreamAndFormatAsync(url).ConfigureAwait(false); return Load(result.Item1, version, out var _, result.Item2, settings); } From f879452ca0e7a836eca8950054d12c70d89dc450 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Thu, 19 Dec 2024 16:54:51 +0300 Subject: [PATCH 101/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 75388c376..961a01f71 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -196,7 +196,7 @@ public static T Parse(string input, { format ??= InspectInputFormat(input); settings ??= new OpenApiReaderSettings(); - var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); return Load(stream, version, format, out diagnostic, settings); } From aac99fe98d49d8e8c4ac5c2d381c38e51ab40b45 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Thu, 19 Dec 2024 16:55:18 +0300 Subject: [PATCH 102/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 961a01f71..5889b8222 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -140,7 +140,7 @@ public static async Task LoadAsync(Stream input, string format = nul Stream preparedStream; if (format is null) { - var readResult = await PrepareStreamForReadingAsync(input, format, cancellationToken); + var readResult = await PrepareStreamForReadingAsync(input, format, cancellationToken).ConfigureAwait(false); preparedStream = readResult.Item1; format = readResult.Item2; } From e3049a60cbe95f153544eed476d2b680da32046d Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Thu, 19 Dec 2024 16:55:45 +0300 Subject: [PATCH 103/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 5889b8222..25d6156cf 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -174,7 +174,7 @@ public static ReadResult Parse(string input, settings ??= new OpenApiReaderSettings(); // Copy string into MemoryStream - var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); return InternalLoad(stream, format, settings); } From 8a17bf2bee62a1c1b25d69bade9119182d9ca003 Mon Sep 17 00:00:00 2001 From: Maggie Kimani Date: Thu, 19 Dec 2024 16:56:11 +0300 Subject: [PATCH 104/127] Update src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs Co-authored-by: Vincent Biret --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 25d6156cf..75c41a89f 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -205,7 +205,7 @@ public static T Parse(string input, private static async Task InternalLoadAsync(Stream input, string format, OpenApiReaderSettings settings, CancellationToken cancellationToken = default) { var reader = OpenApiReaderRegistry.GetReader(format); - var readResult = await reader.ReadAsync(input, settings, cancellationToken); + var readResult = await reader.ReadAsync(input, settings, cancellationToken).ConfigureAwait(false); if (settings?.LoadExternalRefs ?? DefaultReaderSettings.LoadExternalRefs) { From 329df70e4068493368d095f3de047b3da7a89233 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 09:16:21 -0500 Subject: [PATCH 105/127] chore: fixes extraneous master references --- .gitignore | 2 +- .vscode/launch.json | 4 ++-- README.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 940794e60..4caae17f4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## -## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore # User-specific files *.suo diff --git a/.vscode/launch.json b/.vscode/launch.json index 2fa4340b3..1ff544a39 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,7 +4,7 @@ { // Use IntelliSense to find out which attributes exist for C# debugging // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/main/debugger-launchjson.md "name": "Launch Hidi", "type": "coreclr", "request": "launch", @@ -22,7 +22,7 @@ { // Use IntelliSense to find out which attributes exist for C# debugging // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/main/debugger-launchjson.md "name": "Launch Workbench", "type": "coreclr", "request": "launch", diff --git a/README.md b/README.md index c804787c1..de069aeda 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ var httpClient = new HttpClient BaseAddress = new Uri("https://raw.githubusercontent.com/OAI/OpenAPI-Specification/") }; -var stream = await httpClient.GetStreamAsync("master/examples/v3.0/petstore.yaml"); +var stream = await httpClient.GetStreamAsync("main/examples/v3.0/petstore.yaml"); // Read V3 as YAML var openApiDocument = new OpenApiStreamReader().Read(stream, out var diagnostic); From 899933636f15991add45e367befd1c30c93bcf2c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 09:22:10 -0500 Subject: [PATCH 106/127] fix: sets hidi version to a preview Signed-off-by: Vincent Biret --- src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index 0a31b1199..a42c91879 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -9,7 +9,7 @@ enable hidi ./../../artifacts - 1.4.16 + 2.0.0-preview3 OpenAPI.NET CLI tool for slicing OpenAPI documents true From 9805b8252b235070b3f6357df09694a4a9944409 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 09:51:16 -0500 Subject: [PATCH 107/127] ci: rename master to main Signed-off-by: Vincent Biret --- .azure-pipelines/ci-build.yml | 6 +++--- .github/workflows/docker.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 28d442b3a..16d12003d 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -5,12 +5,12 @@ name: $(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) trigger: branches: include: - - master + - main - vnext pr: branches: include: - - master + - main - vnext variables: buildPlatform: 'Any CPU' @@ -206,7 +206,7 @@ extends: content: '*.nupkg' - stage: deploy - condition: and(contains(variables['build.sourceBranch'], 'refs/heads/master'), succeeded()) + condition: and(contains(variables['build.sourceBranch'], 'refs/heads/main'), succeeded()) dependsOn: build jobs: - deployment: deploy_hidi diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index e01c89f0f..94d807af1 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Publish Docker image on: workflow_dispatch: push: - branches: [master, vnext] + branches: [main, vnext] paths: ['src/Microsoft.OpenApi.Hidi/**', '.github/workflows/**'] env: REGISTRY: msgraphprod.azurecr.io @@ -35,7 +35,7 @@ jobs: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly - name: Push to GitHub Packages - Release - if: ${{ github.ref == 'refs/heads/master' }} + if: ${{ github.ref == 'refs/heads/main' }} uses: docker/build-push-action@v6.10.0 with: push: true From 1a5352a35b361f352bdc237ed8d5bad2e212bb1e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 09:54:20 -0500 Subject: [PATCH 108/127] ci: renames vnext to dev Signed-off-by: Vincent Biret --- .azure-pipelines/ci-build.yml | 4 ++-- .github/workflows/codeql-analysis.yml | 2 +- .github/workflows/docker.yml | 10 +++++----- Dockerfile | 4 ++-- README.md | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 16d12003d..25fdacd7f 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -6,12 +6,12 @@ trigger: branches: include: - main - - vnext + - dev pr: branches: include: - main - - vnext + - dev variables: buildPlatform: 'Any CPU' buildConfiguration: 'Release' diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 22eb5f8fa..4224ace24 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -2,7 +2,7 @@ name: CodeQL Analysis on: push: - branches: [ vnext ] + branches: [ main, dev ] pull_request: schedule: - cron: '0 8 * * *' diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 94d807af1..1769a7b51 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Publish Docker image on: workflow_dispatch: push: - branches: [main, vnext] + branches: [main, dev] paths: ['src/Microsoft.OpenApi.Hidi/**', '.github/workflows/**'] env: REGISTRY: msgraphprod.azurecr.io @@ -16,7 +16,7 @@ jobs: steps: - name: Check out the repo uses: actions/checkout@v4 - - name: Login to GitHub package feed + - name: Login to registry uses: docker/login-action@v3.3.0 with: username: ${{ secrets.ACR_USERNAME }} @@ -28,13 +28,13 @@ jobs: echo "::set-output name=version::${version}" shell: pwsh id: getversion - - name: Push to GitHub Packages - Nightly - if: ${{ github.ref == 'refs/heads/vnext' }} + - name: Push to registry - Nightly + if: ${{ github.ref == 'refs/heads/dev' }} uses: docker/build-push-action@v6.10.0 with: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly - - name: Push to GitHub Packages - Release + - name: Push to registry - Release if: ${{ github.ref == 'refs/heads/main' }} uses: docker/build-push-action@v6.10.0 with: diff --git a/Dockerfile b/Dockerfile index fd821e3e4..25f1ec589 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,5 +19,5 @@ VOLUME /app/collection.json ENV HIDI_CONTAINER=true DOTNET_TieredPGO=1 DOTNET_TC_QuickJitForLoops=1 ENTRYPOINT ["dotnet", "Microsoft.OpenApi.Hidi.dll"] LABEL description="# Welcome to Hidi \ -To start transforming OpenAPI documents checkout [the getting started documentation](https://github.com/microsoft/OpenAPI.NET/tree/vnext/src/Microsoft.OpenApi.Hidi) \ -[Source dockerfile](https://github.com/microsoft/OpenAPI.NET/blob/vnext/Dockerfile)" +To start transforming OpenAPI documents checkout [the getting started documentation](https://github.com/microsoft/OpenAPI.NET/tree/main/src/Microsoft.OpenApi.Hidi) \ +[Source dockerfile](https://github.com/microsoft/OpenAPI.NET/blob/main/Dockerfile)" diff --git a/README.md b/README.md index de069aeda..3a7702eb3 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ var outputString = openApiDocument.Serialize(OpenApiSpecVersion.OpenApi2_0, Open In order to test the validity of an OpenApi document, we avail the following tools: - [Microsoft.OpenApi.Hidi](https://www.nuget.org/packages/Microsoft.OpenApi.Hidi) - A commandline tool for validating and transforming OpenAPI descriptions. [Installation guidelines and documentation](https://github.com/microsoft/OpenAPI.NET/blob/vnext/src/Microsoft.OpenApi.Hidi/readme.md) + A commandline tool for validating and transforming OpenAPI descriptions. [Installation guidelines and documentation](https://github.com/microsoft/OpenAPI.NET/blob/main/src/Microsoft.OpenApi.Hidi/readme.md) - Microsoft.OpenApi.Workbench From c805f2e952c986e28f831cc58abc848525b3dd88 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 09:56:35 -0500 Subject: [PATCH 109/127] ci: adds support branch for v1 Signed-off-by: Vincent Biret --- .azure-pipelines/ci-build.yml | 4 +++- .github/workflows/docker.yml | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 25fdacd7f..e9aa773a3 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -7,11 +7,13 @@ trigger: include: - main - dev + - support/v1 pr: branches: include: - main - dev + - support/v1 variables: buildPlatform: 'Any CPU' buildConfiguration: 'Release' @@ -206,7 +208,7 @@ extends: content: '*.nupkg' - stage: deploy - condition: and(contains(variables['build.sourceBranch'], 'refs/heads/main'), succeeded()) + condition: and(or(contains(variables['build.sourceBranch'], 'refs/heads/main'),contains(variables['build.sourceBranch'], 'refs/heads/support/v1')), succeeded()) dependsOn: build jobs: - deployment: deploy_hidi diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 1769a7b51..7e81a456d 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -2,7 +2,7 @@ name: Publish Docker image on: workflow_dispatch: push: - branches: [main, dev] + branches: [main, dev, support/v1] paths: ['src/Microsoft.OpenApi.Hidi/**', '.github/workflows/**'] env: REGISTRY: msgraphprod.azurecr.io @@ -35,7 +35,7 @@ jobs: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly - name: Push to registry - Release - if: ${{ github.ref == 'refs/heads/main' }} + if: ${{ github.ref == 'refs/heads/main' || github.ref == 'refs/heads/support/v1' }} uses: docker/build-push-action@v6.10.0 with: push: true From 6a9f845d15e14fb8254cbac3f8a651241d57cc09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 15:24:41 +0000 Subject: [PATCH 110/127] chore(deps): bump Verify.Xunit from 28.2.0 to 28.6.1 Bumps [Verify.Xunit](https://github.com/VerifyTests/Verify) from 28.2.0 to 28.6.1. - [Release notes](https://github.com/VerifyTests/Verify/releases) - [Commits](https://github.com/VerifyTests/Verify/compare/28.2.0...28.6.1) --- updated-dependencies: - dependency-name: Verify.Xunit dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj index 88977a0b9..59f05da32 100644 --- a/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj +++ b/test/Microsoft.OpenApi.Tests/Microsoft.OpenApi.Tests.csproj @@ -14,7 +14,7 @@ - + From 66176311c94c4f3cecb355fa0f2b09a7bd58dc28 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 13:03:30 -0500 Subject: [PATCH 111/127] ci: fixes hidi gh release --- .azure-pipelines/ci-build.yml | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index e9aa773a3..922fde421 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -45,8 +45,8 @@ extends: targetPath: '$(Build.ArtifactStagingDirectory)/Nugets' - output: pipelineArtifact displayName: 'Publish Artifact: Hidi' - artifactName: Microsoft.OpenApi.Hidi-v$(hidiversion) - targetPath: '$(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi-v$(hidiversion)' + artifactName: Hidi + targetPath: '$(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi' steps: - task: UseDotNet@2 displayName: 'Use .NET 6' @@ -179,23 +179,13 @@ extends: MaxConcurrency: '50' MaxRetryAttempts: '5' PendingAnalysisWaitTimeoutMinutes: '5' - - - task: PowerShell@2 - displayName: "Get Hidi's version-number from .csproj" - inputs: - targetType: 'inline' - script: | - $xml = [Xml] (Get-Content .\src\Microsoft.OpenApi.Hidi\Microsoft.OpenApi.Hidi.csproj) - $version = $xml.Project.PropertyGroup.Version - echo $version - echo "##vso[task.setvariable variable=hidiversion]$version" - + # publish hidi as an .exe - task: DotNetCoreCLI@2 displayName: publish Hidi as executable inputs: command: 'publish' - arguments: -c Release --runtime win-x64 /p:PublishSingleFile=true /p:PackAsTool=false --self-contained --output $(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi-v$(hidiversion) + arguments: -c Release --runtime win-x64 /p:PublishSingleFile=true /p:PackAsTool=false --self-contained --output $(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi projects: 'src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj' publishWebProjects: False zipAfterPublish: false @@ -219,6 +209,9 @@ extends: - input: pipelineArtifact artifactName: Nugets targetPath: '$(Pipeline.Workspace)' + - input: pipelineArtifact + artifactName: Hidi + targetPath: '$(Pipeline.Workspace)' dependsOn: [] environment: nuget-org strategy: @@ -227,10 +220,6 @@ extends: pool: vmImage: ubuntu-latest steps: - - task: DownloadPipelineArtifact@2 - displayName: Download hidi executable from artifacts - inputs: - source: current - pwsh: | $artifactName = Get-ChildItem -Path $(Pipeline.Workspace)\Nugets -Filter Microsoft.OpenApi.*.nupkg -recurse | select -First 1 $artifactVersion= $artifactName.Name -replace "Microsoft.OpenApi.", "" -replace ".nupkg", "" From 1f72ebf108467d15771a823f6fec7cac3c9164ad Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 19 Dec 2024 13:39:59 -0500 Subject: [PATCH 112/127] fix: redundant artifact upload Signed-off-by: Vincent Biret --- .azure-pipelines/ci-build.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.azure-pipelines/ci-build.yml b/.azure-pipelines/ci-build.yml index 922fde421..449142a91 100644 --- a/.azure-pipelines/ci-build.yml +++ b/.azure-pipelines/ci-build.yml @@ -43,10 +43,6 @@ extends: displayName: 'Publish Artifact: Nugets' artifactName: Nugets targetPath: '$(Build.ArtifactStagingDirectory)/Nugets' - - output: pipelineArtifact - displayName: 'Publish Artifact: Hidi' - artifactName: Hidi - targetPath: '$(Build.ArtifactStagingDirectory)/Microsoft.OpenApi.Hidi' steps: - task: UseDotNet@2 displayName: 'Use .NET 6' @@ -209,9 +205,6 @@ extends: - input: pipelineArtifact artifactName: Nugets targetPath: '$(Pipeline.Workspace)' - - input: pipelineArtifact - artifactName: Hidi - targetPath: '$(Pipeline.Workspace)' dependsOn: [] environment: nuget-org strategy: From c944a316794651fb705d0f110756dfef5ef684ed Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 20 Dec 2024 11:22:54 +0300 Subject: [PATCH 113/127] Defensive programming; pass cancellation token --- .../Reader/OpenApiJsonReader.cs | 13 ++++++- .../Reader/OpenApiModelFactory.cs | 36 ++++++++++++------- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs index d058596dc..71cf3f8c3 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiJsonReader.cs @@ -12,6 +12,7 @@ using Microsoft.OpenApi.Validations; using System.Linq; using Microsoft.OpenApi.Interfaces; +using System; namespace Microsoft.OpenApi.Reader { @@ -29,6 +30,9 @@ public class OpenApiJsonReader : IOpenApiReader public ReadResult Read(MemoryStream input, OpenApiReaderSettings settings) { + if (input is null) throw new ArgumentNullException(nameof(input)); + if (settings is null) throw new ArgumentNullException(nameof(settings)); + JsonNode jsonNode; var diagnostic = new OpenApiDiagnostic(); settings ??= new OpenApiReaderSettings(); @@ -62,6 +66,9 @@ public ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null) { + if (jsonNode is null) throw new ArgumentNullException(nameof(jsonNode)); + if (settings is null) throw new ArgumentNullException(nameof(settings)); + var diagnostic = new OpenApiDiagnostic(); var context = new ParsingContext(diagnostic) { @@ -114,9 +121,11 @@ public async Task ReadAsync(Stream input, OpenApiReaderSettings settings, CancellationToken cancellationToken = default) { + if (input is null) throw new ArgumentNullException(nameof(input)); + if (settings is null) throw new ArgumentNullException(nameof(settings)); + JsonNode jsonNode; var diagnostic = new OpenApiDiagnostic(); - settings ??= new OpenApiReaderSettings(); // Parse the JSON text in the stream into JsonNodes try @@ -142,6 +151,8 @@ public T ReadFragment(MemoryStream input, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement { + if (input is null) throw new ArgumentNullException(nameof(input)); + JsonNode jsonNode; // Parse the JSON diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 139e1f80c..3080d2849 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -39,6 +39,7 @@ public static ReadResult Load(MemoryStream stream, string format = null, OpenApiReaderSettings settings = null) { + if (stream is null) throw new ArgumentNullException(nameof(stream)); settings ??= new OpenApiReaderSettings(); // Get the format of the stream if not provided @@ -69,6 +70,7 @@ public static T Load(Stream input, string format = null, OpenApiReaderSettings settings = null) where T : IOpenApiElement { + if (input is null) throw new ArgumentNullException(nameof(input)); if (input is MemoryStream memoryStream) { return Load(memoryStream, version, format, out diagnostic, settings); @@ -104,11 +106,12 @@ public static T Load(MemoryStream input, OpenApiSpecVersion version, string f /// /// The path to the OpenAPI file /// The OpenApi reader settings. + /// /// - public static async Task LoadAsync(string url, OpenApiReaderSettings settings = null) + public static async Task LoadAsync(string url, OpenApiReaderSettings settings = null, CancellationToken token = default) { - var result = await RetrieveStreamAndFormatAsync(url); - return await LoadAsync(result.Item1, result.Item2, settings).ConfigureAwait(false); + var result = await RetrieveStreamAndFormatAsync(url, token).ConfigureAwait(false); + return await LoadAsync(result.Item1, result.Item2, settings, token).ConfigureAwait(false); } /// @@ -118,11 +121,12 @@ public static async Task LoadAsync(string url, OpenApiReaderSettings /// The path to the OpenAPI file /// Version of the OpenAPI specification that the fragment conforms to. /// The OpenApiReader settings. + /// /// Instance of newly created IOpenApiElement. /// The OpenAPI element. - public static async Task LoadAsync(string url, OpenApiSpecVersion version, OpenApiReaderSettings settings = null) where T : IOpenApiElement + public static async Task LoadAsync(string url, OpenApiSpecVersion version, OpenApiReaderSettings settings = null, CancellationToken token = default) where T : IOpenApiElement { - var result = await RetrieveStreamAndFormatAsync(url); + var result = await RetrieveStreamAndFormatAsync(url, token).ConfigureAwait(false); return Load(result.Item1, version, out var _, result.Item2, settings); } @@ -136,11 +140,13 @@ public static async Task LoadAsync(string url, OpenApiSpecVersion version, /// public static async Task LoadAsync(Stream input, string format = null, OpenApiReaderSettings settings = null, CancellationToken cancellationToken = default) { + if (input is null) throw new ArgumentNullException(nameof(input)); settings ??= new OpenApiReaderSettings(); + Stream preparedStream; if (format is null) { - var readResult = await PrepareStreamForReadingAsync(input, format, cancellationToken); + var readResult = await PrepareStreamForReadingAsync(input, format, cancellationToken).ConfigureAwait(false); preparedStream = readResult.Item1; format = readResult.Item2; } @@ -150,7 +156,7 @@ public static async Task LoadAsync(Stream input, string format = nul } // Use StreamReader to process the prepared stream (buffered for YAML, direct for JSON) - var result = await InternalLoadAsync(preparedStream, format, settings, cancellationToken); + var result = await InternalLoadAsync(preparedStream, format, settings, cancellationToken).ConfigureAwait(false); if (!settings.LeaveStreamOpen) { input.Dispose(); @@ -170,6 +176,7 @@ public static ReadResult Parse(string input, string format = null, OpenApiReaderSettings settings = null) { + if (input is null) throw new ArgumentNullException(nameof(input)); format ??= InspectInputFormat(input); settings ??= new OpenApiReaderSettings(); @@ -194,6 +201,7 @@ public static T Parse(string input, string format = null, OpenApiReaderSettings settings = null) where T : IOpenApiElement { + if (input is null) throw new ArgumentNullException(nameof(input)); format ??= InspectInputFormat(input); settings ??= new OpenApiReaderSettings(); var stream = new MemoryStream(Encoding.UTF8.GetBytes(input)); @@ -209,7 +217,7 @@ private static async Task InternalLoadAsync(Stream input, string for if (settings?.LoadExternalRefs ?? DefaultReaderSettings.LoadExternalRefs) { - var diagnosticExternalRefs = await LoadExternalRefsAsync(readResult.Document, cancellationToken, settings, format); + var diagnosticExternalRefs = await LoadExternalRefsAsync(readResult.Document, settings, format, cancellationToken).ConfigureAwait(false); // Merge diagnostics of external reference if (diagnosticExternalRefs != null) { @@ -221,7 +229,7 @@ private static async Task InternalLoadAsync(Stream input, string for return readResult; } - private static async Task LoadExternalRefsAsync(OpenApiDocument document, CancellationToken cancellationToken, OpenApiReaderSettings settings, string format = null) + private static async Task LoadExternalRefsAsync(OpenApiDocument document, OpenApiReaderSettings settings, string format = null, CancellationToken token = default) { // Create workspace for all documents to live in. var baseUrl = settings.BaseUrl ?? new Uri(OpenApiConstants.BaseRegistryUri); @@ -230,7 +238,7 @@ private static async Task LoadExternalRefsAsync(OpenApiDocume // Load this root document into the workspace var streamLoader = new DefaultStreamLoader(settings.BaseUrl); var workspaceLoader = new OpenApiWorkspaceLoader(openApiWorkSpace, settings.CustomExternalLoader ?? streamLoader, settings); - return await workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource = "/" }, document, format ?? OpenApiConstants.Json, null, cancellationToken).ConfigureAwait(false); + return await workspaceLoader.LoadAsync(new OpenApiReference() { ExternalResource = "/" }, document, format ?? OpenApiConstants.Json, null, token).ConfigureAwait(false); } private static ReadResult InternalLoad(MemoryStream input, string format, OpenApiReaderSettings settings) @@ -246,7 +254,7 @@ private static ReadResult InternalLoad(MemoryStream input, string format, OpenAp return readResult; } - private static async Task<(Stream, string)> RetrieveStreamAndFormatAsync(string url) + private static async Task<(Stream, string)> RetrieveStreamAndFormatAsync(string url, CancellationToken token = default) { if (!string.IsNullOrEmpty(url)) { @@ -256,11 +264,15 @@ private static ReadResult InternalLoad(MemoryStream input, string format, OpenAp if (url.StartsWith("http", StringComparison.OrdinalIgnoreCase) || url.StartsWith("https", StringComparison.OrdinalIgnoreCase)) { - var response = await _httpClient.GetAsync(url); + var response = await _httpClient.GetAsync(url, token).ConfigureAwait(false); var mediaType = response.Content.Headers.ContentType.MediaType; var contentType = mediaType.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)[0]; format = contentType.Split('/').LastOrDefault(); +#if NETSTANDARD2_0 stream = await response.Content.ReadAsStreamAsync(); +#else + stream = await response.Content.ReadAsStreamAsync(token).ConfigureAwait(false);; +#endif return (stream, format); } else From 47dca99227d1f357a823034c359027f72ee52e09 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 20 Dec 2024 11:49:28 +0300 Subject: [PATCH 114/127] Code cleanup and fix tests --- .../Interfaces/IOpenApiReader.cs | 4 +- .../Reader/OpenApiModelFactory.cs | 62 +++++++++---------- .../V3Tests/OpenApiEncodingTests.cs | 4 +- .../V3Tests/OpenApiInfoTests.cs | 4 +- .../V3Tests/OpenApiParameterTests.cs | 16 ++--- .../V3Tests/OpenApiXmlTests.cs | 5 +- 6 files changed, 47 insertions(+), 48 deletions(-) diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs index 42e7e466d..8f001df0c 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs @@ -43,7 +43,7 @@ public interface IOpenApiReader /// /// Reads the MemoryStream and parses the fragment of an OpenAPI description into an Open API Element. /// - /// TextReader containing OpenAPI description to parse. + /// Memory stream containing OpenAPI description to parse. /// Version of the OpenAPI specification that the fragment conforms to. /// Returns diagnostic object containing errors detected during parsing. /// The OpenApiReader settings. @@ -53,7 +53,7 @@ public interface IOpenApiReader /// /// Reads the JsonNode input and parses the fragment of an OpenAPI description into an Open API Element. /// - /// TextReader containing OpenAPI description to parse. + /// Memory stream containing OpenAPI description to parse. /// Version of the OpenAPI specification that the fragment conforms to. /// Returns diagnostic object containing errors detected during parsing. /// The OpenApiReader settings. diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index f192cae15..b714667a6 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; @@ -54,36 +54,6 @@ public static ReadResult Load(MemoryStream stream, return result; } - /// - /// Reads the stream input and ensures it is buffered before passing it to the Load method. - /// - /// - /// - /// - /// - /// - /// - /// - public static T Load(Stream input, - OpenApiSpecVersion version, - out OpenApiDiagnostic diagnostic, - string format = null, - OpenApiReaderSettings settings = null) where T : IOpenApiElement - { - if (input is null) throw new ArgumentNullException(nameof(input)); - if (input is MemoryStream memoryStream) - { - return Load(memoryStream, version, format, out diagnostic, settings); - } - else - { - memoryStream = new MemoryStream(); - input.CopyTo(memoryStream); - memoryStream.Position = 0; - return Load(memoryStream, version, format, out diagnostic, settings); - } - } - /// /// Reads the stream input and parses the fragment of an OpenAPI description into an Open API Element. /// @@ -127,7 +97,7 @@ public static async Task LoadAsync(string url, OpenApiReaderSettings public static async Task LoadAsync(string url, OpenApiSpecVersion version, OpenApiReaderSettings settings = null, CancellationToken token = default) where T : IOpenApiElement { var result = await RetrieveStreamAndFormatAsync(url, token).ConfigureAwait(false); - return Load(result.Item1, version, out var _, result.Item2, settings); + return await LoadAsync(result.Item1, version, result.Item2, settings); } /// @@ -165,6 +135,34 @@ public static async Task LoadAsync(Stream input, string format = nul return result; } + /// + /// Reads the stream input and ensures it is buffered before passing it to the Load method. + /// + /// + /// + /// + /// + /// + /// + public static async Task LoadAsync(Stream input, + OpenApiSpecVersion version, + string format = null, + OpenApiReaderSettings settings = null) where T : IOpenApiElement + { + if (input is null) throw new ArgumentNullException(nameof(input)); + if (input is MemoryStream memoryStream) + { + return Load(memoryStream, version, format, out var _, settings); + } + else + { + memoryStream = new MemoryStream(); + await input.CopyToAsync(memoryStream).ConfigureAwait(false); + memoryStream.Position = 0; + return Load(memoryStream, version, format, out var _, settings); + } + } + /// /// Reads the input string and parses it into an Open API document. /// diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs index c2d34493b..91e428c49 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiEncodingTests.cs @@ -35,12 +35,12 @@ public async Task ParseBasicEncodingShouldSucceed() } [Fact] - public void ParseAdvancedEncodingShouldSucceed() + public async Task ParseAdvancedEncodingShouldSucceed() { using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "advancedEncoding.yaml")); // Act - var encoding = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _); + var encoding = await OpenApiModelFactory.LoadAsync(stream, OpenApiSpecVersion.OpenApi3_0); // Assert encoding.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs index 25da65e9d..fdd5ae8ee 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiInfoTests.cs @@ -109,12 +109,12 @@ public async Task ParseBasicInfoShouldSucceed() } [Fact] - public void ParseMinimalInfoShouldSucceed() + public async Task ParseMinimalInfoShouldSucceed() { using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "minimalInfo.yaml")); // Act - var openApiInfo = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _, "yaml"); + var openApiInfo = await OpenApiModelFactory.LoadAsync(stream, OpenApiSpecVersion.OpenApi3_0); // Assert openApiInfo.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs index 638c47c4a..a40cb4144 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiParameterTests.cs @@ -26,13 +26,13 @@ public OpenApiParameterTests() } [Fact] - public void ParsePathParameterShouldSucceed() + public async Task ParsePathParameterShouldSucceed() { // Arrange using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "pathParameter.yaml")); // Act - var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _, "yaml"); + var parameter = await OpenApiModelFactory.LoadAsync(stream, OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( @@ -101,13 +101,13 @@ public async Task ParseQueryParameterWithObjectTypeShouldSucceed() } [Fact] - public void ParseQueryParameterWithObjectTypeAndContentShouldSucceed() + public async Task ParseQueryParameterWithObjectTypeAndContentShouldSucceed() { // Arrange using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "queryParameterWithObjectTypeAndContent.yaml")); // Act - var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _, "yaml"); + var parameter = await OpenApiModelFactory.LoadAsync(stream, OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( @@ -194,13 +194,13 @@ public async Task ParseParameterWithNullLocationShouldSucceed() } [Fact] - public void ParseParameterWithNoLocationShouldSucceed() + public async Task ParseParameterWithNoLocationShouldSucceed() { // Arrange using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "parameterWithNoLocation.yaml")); // Act - var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _); + var parameter = await OpenApiModelFactory.LoadAsync(stream, OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( @@ -218,13 +218,13 @@ public void ParseParameterWithNoLocationShouldSucceed() } [Fact] - public void ParseParameterWithUnknownLocationShouldSucceed() + public async Task ParseParameterWithUnknownLocationShouldSucceed() { // Arrange using var stream = Resources.GetStream(Path.Combine(SampleFolderPath, "parameterWithUnknownLocation.yaml")); // Act - var parameter = OpenApiModelFactory.Load(stream, OpenApiSpecVersion.OpenApi3_0, out _); + var parameter = await OpenApiModelFactory.LoadAsync(stream, OpenApiSpecVersion.OpenApi3_0); // Assert parameter.Should().BeEquivalentTo( diff --git a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs index aab130202..fc23865ba 100644 --- a/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs +++ b/test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs @@ -3,6 +3,7 @@ using System; using System.IO; +using System.Threading.Tasks; using FluentAssertions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; @@ -21,10 +22,10 @@ public OpenApiXmlTests() } [Fact] - public void ParseBasicXmlShouldSucceed() + public async Task ParseBasicXmlShouldSucceed() { // Act - var xml = OpenApiModelFactory.Load(Resources.GetStream(Path.Combine(SampleFolderPath, "basicXml.yaml")), OpenApiSpecVersion.OpenApi3_0, out _); + var xml = await OpenApiModelFactory.LoadAsync(Resources.GetStream(Path.Combine(SampleFolderPath, "basicXml.yaml")), OpenApiSpecVersion.OpenApi3_0); // Assert xml.Should().BeEquivalentTo( From e243f4efcb74d489a616962956ae885134d2e3c0 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 20 Dec 2024 12:06:36 +0300 Subject: [PATCH 115/127] simplify tuple variables --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index b714667a6..32bf3dccf 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -80,8 +80,8 @@ public static T Load(MemoryStream input, OpenApiSpecVersion version, string f /// public static async Task LoadAsync(string url, OpenApiReaderSettings settings = null, CancellationToken token = default) { - var result = await RetrieveStreamAndFormatAsync(url, token).ConfigureAwait(false); - return await LoadAsync(result.Item1, result.Item2, settings, token).ConfigureAwait(false); + var (stream, format) = await RetrieveStreamAndFormatAsync(url, token).ConfigureAwait(false); + return await LoadAsync(stream, format, settings, token).ConfigureAwait(false); } /// @@ -96,8 +96,8 @@ public static async Task LoadAsync(string url, OpenApiReaderSettings /// The OpenAPI element. public static async Task LoadAsync(string url, OpenApiSpecVersion version, OpenApiReaderSettings settings = null, CancellationToken token = default) where T : IOpenApiElement { - var result = await RetrieveStreamAndFormatAsync(url, token).ConfigureAwait(false); - return await LoadAsync(result.Item1, version, result.Item2, settings); + var (stream, format) = await RetrieveStreamAndFormatAsync(url, token).ConfigureAwait(false); + return await LoadAsync(stream, version, format, settings); } /// @@ -116,9 +116,7 @@ public static async Task LoadAsync(Stream input, string format = nul Stream preparedStream; if (format is null) { - var readResult = await PrepareStreamForReadingAsync(input, format, cancellationToken).ConfigureAwait(false); - preparedStream = readResult.Item1; - format = readResult.Item2; + (preparedStream, format) = await PrepareStreamForReadingAsync(input, format, cancellationToken).ConfigureAwait(false); } else { From 28e1ecd5d48cd4499d5feda1487815c7dd4a6f77 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 20 Dec 2024 12:07:48 +0300 Subject: [PATCH 116/127] Update public API --- .../PublicApi/PublicApi.approved.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index 986eeb4d6..f3aa38ed4 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -1323,11 +1323,11 @@ namespace Microsoft.OpenApi.Reader public static Microsoft.OpenApi.Reader.ReadResult Load(System.IO.MemoryStream stream, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } public static T Load(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, string format, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } - public static T Load(System.IO.Stream input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) - where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } - public static System.Threading.Tasks.Task LoadAsync(string url, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } + public static System.Threading.Tasks.Task LoadAsync(string url, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken token = default) { } public static System.Threading.Tasks.Task LoadAsync(System.IO.Stream input, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken cancellationToken = default) { } - public static System.Threading.Tasks.Task LoadAsync(string url, Microsoft.OpenApi.OpenApiSpecVersion version, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) + public static System.Threading.Tasks.Task LoadAsync(System.IO.Stream input, Microsoft.OpenApi.OpenApiSpecVersion version, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) + where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } + public static System.Threading.Tasks.Task LoadAsync(string url, Microsoft.OpenApi.OpenApiSpecVersion version, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null, System.Threading.CancellationToken token = default) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement { } public static Microsoft.OpenApi.Reader.ReadResult Parse(string input, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) { } public static T Parse(string input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, string format = null, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) From 56742b996ff73a963fa27b26df1a2e4e34f50da7 Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 20 Dec 2024 12:31:12 +0300 Subject: [PATCH 117/127] Dispose stream in caller method --- src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs index 32bf3dccf..1f1924efb 100644 --- a/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs +++ b/src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs @@ -128,6 +128,7 @@ public static async Task LoadAsync(Stream input, string format = nul if (!settings.LeaveStreamOpen) { input.Dispose(); + preparedStream.Dispose(); } return result; From ee637588a4344dee1d03f0b6006bc1f00330adad Mon Sep 17 00:00:00 2001 From: Maggiekimani1 Date: Fri, 20 Dec 2024 13:27:22 +0300 Subject: [PATCH 118/127] Abstract implementation detail from interface --- .../OpenApiYamlReader.cs | 9 +++++---- .../Interfaces/IOpenApiReader.cs | 19 ------------------- .../PublicApi/PublicApi.approved.txt | 3 --- 3 files changed, 5 insertions(+), 26 deletions(-) diff --git a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs index 3c5046c96..95e58c52f 100644 --- a/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs +++ b/src/Microsoft.OpenApi.Readers/OpenApiYamlReader.cs @@ -21,6 +21,7 @@ namespace Microsoft.OpenApi.Readers public class OpenApiYamlReader : IOpenApiReader { private const int copyBufferSize = 4096; + private static readonly OpenApiJsonReader _jsonReader = new(); /// public async Task ReadAsync(Stream input, @@ -70,9 +71,9 @@ public ReadResult Read(MemoryStream input, } /// - public ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null) + public static ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null) { - return OpenApiReaderRegistry.DefaultReader.Read(jsonNode, settings, OpenApiConstants.Yaml); + return _jsonReader.Read(jsonNode, settings, OpenApiConstants.Yaml); } /// @@ -101,9 +102,9 @@ public T ReadFragment(MemoryStream input, } /// - public T ReadFragment(JsonNode input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement + public static T ReadFragment(JsonNode input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement { - return OpenApiReaderRegistry.DefaultReader.ReadFragment(input, version, out diagnostic, settings); + return _jsonReader.ReadFragment(input, version, out diagnostic, settings); } /// diff --git a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs index 8f001df0c..9398551dd 100644 --- a/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs +++ b/src/Microsoft.OpenApi/Interfaces/IOpenApiReader.cs @@ -31,15 +31,6 @@ public interface IOpenApiReader /// ReadResult Read(MemoryStream input, OpenApiReaderSettings settings); - /// - /// Parses the JsonNode input into an Open API document. - /// - /// The JsonNode input. - /// The Reader settings to be used during parsing. - /// The OpenAPI format. - /// - ReadResult Read(JsonNode jsonNode, OpenApiReaderSettings settings, string format = null); - /// /// Reads the MemoryStream and parses the fragment of an OpenAPI description into an Open API Element. /// @@ -49,15 +40,5 @@ public interface IOpenApiReader /// The OpenApiReader settings. /// Instance of newly created IOpenApiElement. T ReadFragment(MemoryStream input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement; - - /// - /// Reads the JsonNode input and parses the fragment of an OpenAPI description into an Open API Element. - /// - /// Memory stream containing OpenAPI description to parse. - /// Version of the OpenAPI specification that the fragment conforms to. - /// Returns diagnostic object containing errors detected during parsing. - /// The OpenApiReader settings. - /// Instance of newly created IOpenApiElement. - T ReadFragment(JsonNode input, OpenApiSpecVersion version, out OpenApiDiagnostic diagnostic, OpenApiReaderSettings settings = null) where T : IOpenApiElement; } } diff --git a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt index f3aa38ed4..ddcf4f5c2 100644 --- a/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt +++ b/test/Microsoft.OpenApi.Tests/PublicApi/PublicApi.approved.txt @@ -220,12 +220,9 @@ namespace Microsoft.OpenApi.Interfaces public interface IOpenApiReader { Microsoft.OpenApi.Reader.ReadResult Read(System.IO.MemoryStream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings); - Microsoft.OpenApi.Reader.ReadResult Read(System.Text.Json.Nodes.JsonNode jsonNode, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, string format = null); System.Threading.Tasks.Task ReadAsync(System.IO.Stream input, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings, System.Threading.CancellationToken cancellationToken = default); T ReadFragment(System.IO.MemoryStream input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) where T : Microsoft.OpenApi.Interfaces.IOpenApiElement; - T ReadFragment(System.Text.Json.Nodes.JsonNode input, Microsoft.OpenApi.OpenApiSpecVersion version, out Microsoft.OpenApi.Reader.OpenApiDiagnostic diagnostic, Microsoft.OpenApi.Reader.OpenApiReaderSettings settings = null) - where T : Microsoft.OpenApi.Interfaces.IOpenApiElement; } public interface IOpenApiReferenceable : Microsoft.OpenApi.Interfaces.IOpenApiElement, Microsoft.OpenApi.Interfaces.IOpenApiSerializable { From 7c63538b52180645c457227ee79468a48875957d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 08:05:21 -0500 Subject: [PATCH 119/127] chore: updates api manifest dependency Signed-off-by: Vincent Biret --- .../Microsoft.OpenApi.Hidi.csproj | 2 +- src/Microsoft.OpenApi.Hidi/OpenApiService.cs | 17 +++++++---------- .../UtilityFiles/exampleapimanifest.json | 3 ++- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj index a42c91879..04c42ee47 100644 --- a/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj +++ b/src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj @@ -40,7 +40,7 @@ - +