From 85194e4128bc77024f7094bfcccbd07dfec634a2 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 14 Oct 2024 14:53:42 -0400 Subject: [PATCH 01/96] fix: oas extensions parsing Signed-off-by: Vincent Biret --- .../Configuration/LanguagesInformation.cs | 34 +++++------ .../Extensions/OpenApiSettingsExtensions.cs | 2 +- src/Kiota.Builder/LanguageInformation.cs | 57 +++++++++++-------- ...OpenApiAiReasoningInstructionsExtension.cs | 9 +-- ...penApiAiRespondingInstructionsExtension.cs | 9 +-- .../OpenApiDescriptionForModelExtension.cs | 4 +- .../OpenApiKiotaExtension.cs | 8 +-- .../OpenApiLegalInfoUrlExtension.cs | 4 +- .../OpenApiExtensions/OpenApiLogoExtension.cs | 11 ++-- .../OpenApiPrivacyPolicyUrlExtension.cs | 4 +- .../OpenApiSimpleStringExtension.cs | 10 ++-- .../Validation/OpenApiSchemaComparer.cs | 8 +-- 12 files changed, 87 insertions(+), 73 deletions(-) diff --git a/src/Kiota.Builder/Configuration/LanguagesInformation.cs b/src/Kiota.Builder/Configuration/LanguagesInformation.cs index 5dcb41dc59..a80f718faf 100644 --- a/src/Kiota.Builder/Configuration/LanguagesInformation.cs +++ b/src/Kiota.Builder/Configuration/LanguagesInformation.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.OpenApi.Any; +using System.Text.Json.Nodes; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -9,23 +9,14 @@ namespace Kiota.Builder.Configuration; public class LanguagesInformation : Dictionary, IOpenApiSerializable, ICloneable { - public void SerializeAsV2(IOpenApiWriter writer) => SerializeAsV3(writer); - public void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) => SerializeAsV31(writer); + public void SerializeAsV3(IOpenApiWriter writer) => SerializeAsV31(writer); + public static LanguagesInformation Parse(JsonObject jsonNode) { - ArgumentNullException.ThrowIfNull(writer); - writer.WriteStartObject(); - foreach (var entry in this.OrderBy(static x => x.Key, StringComparer.OrdinalIgnoreCase)) - { - writer.WriteRequiredObject(entry.Key, entry.Value, (w, x) => x.SerializeAsV3(w)); - } - writer.WriteEndObject(); - } - public static LanguagesInformation Parse(IOpenApiAny source) - { - if (source is not OpenApiObject rawObject) throw new ArgumentOutOfRangeException(nameof(source)); var extension = new LanguagesInformation(); - foreach (var property in rawObject) - extension.Add(property.Key, LanguageInformation.Parse(property.Value)); + foreach (var property in jsonNode.Where(static property => property.Value is JsonObject)) + extension.Add(property.Key, LanguageInformation.Parse(property.Value!)); + return extension; } @@ -36,4 +27,15 @@ public object Clone() result.Add(entry.Key, entry.Value);// records don't need to be cloned as they are immutable return result; } + + public void SerializeAsV31(IOpenApiWriter writer) + { + ArgumentNullException.ThrowIfNull(writer); + writer.WriteStartObject(); + foreach (var entry in this.OrderBy(static x => x.Key, StringComparer.OrdinalIgnoreCase)) + { + writer.WriteRequiredObject(entry.Key, entry.Value, (w, x) => x.SerializeAsV3(w)); + } + writer.WriteEndObject(); + } } diff --git a/src/Kiota.Builder/Extensions/OpenApiSettingsExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSettingsExtensions.cs index 118ac47698..6546b601cb 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSettingsExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSettingsExtensions.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using Kiota.Builder.OpenApiExtensions; -using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi.Reader; namespace Kiota.Builder.Extensions; public static class OpenApiSettingsExtensions diff --git a/src/Kiota.Builder/LanguageInformation.cs b/src/Kiota.Builder/LanguageInformation.cs index c0b36309aa..9c3f44cf23 100644 --- a/src/Kiota.Builder/LanguageInformation.cs +++ b/src/Kiota.Builder/LanguageInformation.cs @@ -1,9 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; using System.Text.Json.Serialization; using Kiota.Builder.Extensions; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -26,8 +27,9 @@ public LanguageMaturityLevel MaturityLevel #pragma warning disable CA2227 public HashSet StructuredMimeTypes { get; set; } = new(StringComparer.OrdinalIgnoreCase); #pragma warning restore CA2227 - public void SerializeAsV2(IOpenApiWriter writer) => SerializeAsV3(writer); - public void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) => SerializeAsV31(writer); + public void SerializeAsV3(IOpenApiWriter writer) => SerializeAsV31(writer); + public void SerializeAsV31(IOpenApiWriter writer) { ArgumentNullException.ThrowIfNull(writer); writer.WriteStartObject(); @@ -39,32 +41,34 @@ public void SerializeAsV3(IOpenApiWriter writer) writer.WriteOptionalCollection(nameof(StructuredMimeTypes).ToFirstCharacterLowerCase(), StructuredMimeTypes, (w, x) => w.WriteValue(x)); writer.WriteEndObject(); } - public static LanguageInformation Parse(IOpenApiAny source) + public static LanguageInformation Parse(JsonNode source) { - if (source is not OpenApiObject rawObject) throw new ArgumentOutOfRangeException(nameof(source)); + ArgumentNullException.ThrowIfNull(source); + if (source.GetValueKind() is not JsonValueKind.Object || + source.AsObject() is not JsonObject rawObject) throw new ArgumentOutOfRangeException(nameof(source)); var extension = new LanguageInformation(); - if (rawObject.TryGetValue(nameof(Dependencies).ToFirstCharacterLowerCase(), out var dependencies) && dependencies is OpenApiArray arrayValue) + if (rawObject.TryGetPropertyValue(nameof(Dependencies).ToFirstCharacterLowerCase(), out var dependencies) && dependencies is JsonArray arrayValue) { - foreach (var entry in arrayValue) + foreach (var entry in arrayValue.OfType()) extension.Dependencies.Add(LanguageDependency.Parse(entry)); } - if (rawObject.TryGetValue(nameof(DependencyInstallCommand).ToFirstCharacterLowerCase(), out var installCommand) && installCommand is OpenApiString stringValue) + if (rawObject.TryGetPropertyValue(nameof(DependencyInstallCommand).ToFirstCharacterLowerCase(), out var installCommand) && installCommand is JsonValue stringValue) { - extension.DependencyInstallCommand = stringValue.Value; + extension.DependencyInstallCommand = stringValue.GetValue(); } // not parsing the maturity level on purpose, we don't want APIs to be able to change that - if (rawObject.TryGetValue(nameof(ClientClassName).ToFirstCharacterLowerCase(), out var clientClassName) && clientClassName is OpenApiString clientClassNameValue) + if (rawObject.TryGetPropertyValue(nameof(ClientClassName).ToFirstCharacterLowerCase(), out var clientClassName) && clientClassName is JsonValue clientClassNameValue) { - extension.ClientClassName = clientClassNameValue.Value; + extension.ClientClassName = clientClassNameValue.GetValue(); } - if (rawObject.TryGetValue(nameof(ClientNamespaceName).ToFirstCharacterLowerCase(), out var clientNamespaceName) && clientNamespaceName is OpenApiString clientNamespaceNameValue) + if (rawObject.TryGetPropertyValue(nameof(ClientNamespaceName).ToFirstCharacterLowerCase(), out var clientNamespaceName) && clientNamespaceName is JsonValue clientNamespaceNameValue) { - extension.ClientNamespaceName = clientNamespaceNameValue.Value; + extension.ClientNamespaceName = clientNamespaceNameValue.GetValue(); } - if (rawObject.TryGetValue(nameof(StructuredMimeTypes).ToFirstCharacterLowerCase(), out var structuredMimeTypes) && structuredMimeTypes is OpenApiArray structuredMimeTypesValue) + if (rawObject.TryGetPropertyValue(nameof(StructuredMimeTypes).ToFirstCharacterLowerCase(), out var structuredMimeTypes) && structuredMimeTypes is JsonArray structuredMimeTypesValue) { - foreach (var entry in structuredMimeTypesValue.OfType()) - extension.StructuredMimeTypes.Add(entry.Value); + foreach (var entry in structuredMimeTypesValue.OfType()) + extension.StructuredMimeTypes.Add(entry.GetValue()); } return extension; } @@ -79,8 +83,9 @@ public DependencyType? DependencyType get; set; } private const string TypePropertyName = "type"; - public void SerializeAsV2(IOpenApiWriter writer) => SerializeAsV3(writer); - public void SerializeAsV3(IOpenApiWriter writer) + public void SerializeAsV2(IOpenApiWriter writer) => SerializeAsV31(writer); + public void SerializeAsV3(IOpenApiWriter writer) => SerializeAsV31(writer); + public void SerializeAsV31(IOpenApiWriter writer) { ArgumentNullException.ThrowIfNull(writer); writer.WriteStartObject(); @@ -92,19 +97,21 @@ public void SerializeAsV3(IOpenApiWriter writer) } writer.WriteEndObject(); } - public static LanguageDependency Parse(IOpenApiAny source) + public static LanguageDependency Parse(JsonNode source) { - if (source is not OpenApiObject rawObject) throw new ArgumentOutOfRangeException(nameof(source)); + ArgumentNullException.ThrowIfNull(source); + if (source.GetValueKind() is not JsonValueKind.Object || + source.AsObject() is not JsonObject rawObject) throw new ArgumentOutOfRangeException(nameof(source)); var extension = new LanguageDependency(); - if (rawObject.TryGetValue(nameof(Name).ToFirstCharacterLowerCase(), out var name) && name is OpenApiString stringValue) + if (rawObject.TryGetPropertyValue(nameof(Name).ToFirstCharacterLowerCase(), out var nameNode) && nameNode is JsonValue nameJsonValue && nameJsonValue.TryGetValue(out var nameValue)) { - extension.Name = stringValue.Value; + extension.Name = nameValue; } - if (rawObject.TryGetValue(nameof(Version).ToFirstCharacterLowerCase(), out var version) && version is OpenApiString versionValue) + if (rawObject.TryGetPropertyValue(nameof(Version).ToFirstCharacterLowerCase(), out var versionNode) && versionNode is JsonValue versionJsonValue && versionJsonValue.TryGetValue(out var versionValue)) { - extension.Version = versionValue.Value; + extension.Version = versionValue; } - if (rawObject.TryGetValue(TypePropertyName, out var typeValue) && typeValue is OpenApiString typeStringValue && Enum.TryParse(typeStringValue.Value, true, out var parsedTypeValue)) + if (rawObject.TryGetPropertyValue(TypePropertyName, out var typeNode) && typeNode is JsonValue typeJsonValue && typeJsonValue.TryGetValue(out var typeValue) && Enum.TryParse(typeValue, true, out var parsedTypeValue)) { extension.DependencyType = parsedTypeValue; } diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiAiReasoningInstructionsExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiAiReasoningInstructionsExtension.cs index f690e1df81..8cfd72a30e 100644 --- a/src/Kiota.Builder/OpenApiExtensions/OpenApiAiReasoningInstructionsExtension.cs +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiAiReasoningInstructionsExtension.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -28,11 +29,11 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion) writer.WriteEndArray(); } } - public static OpenApiAiReasoningInstructionsExtension Parse(IOpenApiAny source) + public static OpenApiAiReasoningInstructionsExtension Parse(JsonNode source) { - if (source is not OpenApiArray rawArray) throw new ArgumentOutOfRangeException(nameof(source)); + if (source is not JsonArray rawArray) throw new ArgumentOutOfRangeException(nameof(source)); var result = new OpenApiAiReasoningInstructionsExtension(); - result.ReasoningInstructions.AddRange(rawArray.OfType().Select(x => x.Value)); + result.ReasoningInstructions.AddRange(rawArray.OfType().Where(static x => x.GetValueKind() is JsonValueKind.String).Select(static x => x.GetValue())); return result; } } diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiAiRespondingInstructionsExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiAiRespondingInstructionsExtension.cs index b8137ec225..440f90f03b 100644 --- a/src/Kiota.Builder/OpenApiExtensions/OpenApiAiRespondingInstructionsExtension.cs +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiAiRespondingInstructionsExtension.cs @@ -1,8 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; +using System.Text.Json.Nodes; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -28,11 +29,11 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion) writer.WriteEndArray(); } } - public static OpenApiAiRespondingInstructionsExtension Parse(IOpenApiAny source) + public static OpenApiAiRespondingInstructionsExtension Parse(JsonNode source) { - if (source is not OpenApiArray rawArray) throw new ArgumentOutOfRangeException(nameof(source)); + if (source is not JsonArray rawArray) throw new ArgumentOutOfRangeException(nameof(source)); var result = new OpenApiAiRespondingInstructionsExtension(); - result.RespondingInstructions.AddRange(rawArray.OfType().Select(x => x.Value)); + result.RespondingInstructions.AddRange(rawArray.OfType().Where(static x => x.GetValueKind() is JsonValueKind.String).Select(static x => x.GetValue())); return result; } } diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiDescriptionForModelExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiDescriptionForModelExtension.cs index ba198df7c9..0a174f9fa3 100644 --- a/src/Kiota.Builder/OpenApiExtensions/OpenApiDescriptionForModelExtension.cs +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiDescriptionForModelExtension.cs @@ -1,4 +1,4 @@ -using Microsoft.OpenApi.Any; +using System.Text.Json.Nodes; namespace Kiota.Builder.OpenApiExtensions; @@ -10,7 +10,7 @@ public string? Description get; set; } protected override string? ValueSelector => Description; - public static OpenApiDescriptionForModelExtension Parse(IOpenApiAny source) + public static OpenApiDescriptionForModelExtension Parse(JsonNode source) { return new OpenApiDescriptionForModelExtension { diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaExtension.cs index 80a9149f2f..6c7d9398d8 100644 --- a/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaExtension.cs +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaExtension.cs @@ -1,9 +1,9 @@ using System; using System.Linq; +using System.Text.Json.Nodes; using Kiota.Builder.Configuration; using Kiota.Builder.Extensions; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -30,11 +30,11 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion) writer.WriteEndObject(); } } - public static OpenApiKiotaExtension Parse(IOpenApiAny source) + public static OpenApiKiotaExtension Parse(JsonNode source) { - if (source is not OpenApiObject rawObject) throw new ArgumentOutOfRangeException(nameof(source)); + if (source is not JsonObject jsonNode) throw new ArgumentOutOfRangeException(nameof(source)); var extension = new OpenApiKiotaExtension(); - if (rawObject.TryGetValue(nameof(LanguagesInformation).ToFirstCharacterLowerCase(), out var languagesInfo) && languagesInfo is OpenApiObject objectValue) + if (jsonNode.TryGetPropertyValue(nameof(LanguagesInformation).ToFirstCharacterLowerCase(), out var languagesInfo) && languagesInfo is JsonObject objectValue) { extension.LanguagesInformation = LanguagesInformation.Parse(objectValue); } diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiLegalInfoUrlExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiLegalInfoUrlExtension.cs index 3f042fc70c..10a52bce1a 100644 --- a/src/Kiota.Builder/OpenApiExtensions/OpenApiLegalInfoUrlExtension.cs +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiLegalInfoUrlExtension.cs @@ -1,4 +1,4 @@ -using Microsoft.OpenApi.Any; +using System.Text.Json.Nodes; namespace Kiota.Builder.OpenApiExtensions; @@ -10,7 +10,7 @@ public string? Legal get; set; } protected override string? ValueSelector => Legal; - public static OpenApiLegalInfoUrlExtension Parse(IOpenApiAny source) + public static OpenApiLegalInfoUrlExtension Parse(JsonNode source) { return new OpenApiLegalInfoUrlExtension { diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiLogoExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiLogoExtension.cs index edd5a2daf5..6ddab21631 100644 --- a/src/Kiota.Builder/OpenApiExtensions/OpenApiLogoExtension.cs +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiLogoExtension.cs @@ -1,7 +1,8 @@ using System; +using System.Text.Json; +using System.Text.Json.Nodes; using Kiota.Builder.Extensions; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -16,13 +17,13 @@ public string? Url { get; set; } - public static OpenApiLogoExtension Parse(IOpenApiAny source) + public static OpenApiLogoExtension Parse(JsonNode source) { - if (source is not OpenApiObject rawObject) throw new ArgumentOutOfRangeException(nameof(source)); + if (source is not JsonObject rawObject) throw new ArgumentOutOfRangeException(nameof(source)); var extension = new OpenApiLogoExtension(); - if (rawObject.TryGetValue(nameof(Url).ToFirstCharacterLowerCase(), out var url) && url is OpenApiString urlValue) + if (rawObject.TryGetPropertyValue(nameof(Url).ToFirstCharacterLowerCase(), out var url) && url is JsonValue urlValue && urlValue.GetValueKind() is JsonValueKind.String && urlValue.TryGetValue(out var urlStrValue)) { - extension.Url = urlValue.Value; + extension.Url = urlStrValue; } return extension; } diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiPrivacyPolicyUrlExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiPrivacyPolicyUrlExtension.cs index 4cbc47c72a..039b2f54fe 100644 --- a/src/Kiota.Builder/OpenApiExtensions/OpenApiPrivacyPolicyUrlExtension.cs +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiPrivacyPolicyUrlExtension.cs @@ -1,4 +1,4 @@ -using Microsoft.OpenApi.Any; +using System.Text.Json.Nodes; namespace Kiota.Builder.OpenApiExtensions; @@ -10,7 +10,7 @@ public string? Privacy get; set; } protected override string? ValueSelector => Privacy; - public static OpenApiPrivacyPolicyUrlExtension Parse(IOpenApiAny source) + public static OpenApiPrivacyPolicyUrlExtension Parse(JsonNode source) { return new OpenApiPrivacyPolicyUrlExtension { diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiSimpleStringExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiSimpleStringExtension.cs index 9978939205..53ba859256 100644 --- a/src/Kiota.Builder/OpenApiExtensions/OpenApiSimpleStringExtension.cs +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiSimpleStringExtension.cs @@ -1,6 +1,7 @@ using System; +using System.Text.Json; +using System.Text.Json.Nodes; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Writers; @@ -20,9 +21,10 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion) writer.WriteValue(ValueSelector); } } - public static string ParseString(IOpenApiAny source) + public static string ParseString(JsonNode source) { - if (source is not OpenApiString rawString) throw new ArgumentOutOfRangeException(nameof(source)); - return rawString.Value; + if (source is not JsonValue rawString || + rawString.GetValueKind() is not JsonValueKind.String) throw new ArgumentOutOfRangeException(nameof(source)); + return rawString.GetValue(); } } diff --git a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs index 5b145e9daa..4543d3acbb 100644 --- a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs +++ b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs @@ -143,17 +143,17 @@ public int GetHashCode([DisallowNull] OpenApiDiscriminator obj) return hash.ToHashCode(); } } -internal class OpenApiAnyComparer : IEqualityComparer +internal class OpenApiAnyComparer : IEqualityComparer { /// - public bool Equals(IOpenApiAny? x, IOpenApiAny? y) + public bool Equals(OpenApiAny? x, OpenApiAny? y) { if (x is null || y is null) return object.Equals(x, y); // TODO: Can we use the OpenAPI.NET implementation of Equals? - return x.AnyType == y.AnyType && string.Equals(x.ToString(), y.ToString(), StringComparison.OrdinalIgnoreCase); + return x.Node.GetValueKind() == y.Node.GetValueKind() && string.Equals(x.Node.ToString(), y.Node.ToString(), StringComparison.OrdinalIgnoreCase); } /// - public int GetHashCode([DisallowNull] IOpenApiAny obj) + public int GetHashCode([DisallowNull] OpenApiAny obj) { var hash = new HashCode(); if (obj == null) return hash.ToHashCode(); From d83bc2fbe274923175951da633d6b0de2cb646e6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 14 Oct 2024 16:02:06 -0400 Subject: [PATCH 02/96] fix: multiple NRE Signed-off-by: Vincent Biret --- .../OpenApiDeprecationExtensionExtensions.cs | 6 +-- .../Extensions/OpenApiDocumentExtensions.cs | 2 +- .../Extensions/OpenApiOperationExtensions.cs | 3 +- src/Kiota.Builder/KiotaBuilder.cs | 51 +++++++++++-------- .../Validation/MultipleServerEntries.cs | 2 +- 5 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs index 75a2b5921d..8d29cd92ba 100644 --- a/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs @@ -24,15 +24,15 @@ internal static DeprecationInformation GetDeprecationInformation(this OpenApiPar return deprecatedValue.ToDeprecationInformation(); else if (parameter.Schema != null && !parameter.Schema.IsReferencedSchema() && parameter.Schema.Deprecated) return parameter.Schema.GetDeprecationInformation(); - else if (parameter.Content.Values.Select(static x => x.Schema).Where(static x => x != null && !x.IsReferencedSchema() && x.Deprecated).Select(static x => x.GetDeprecationInformation()).FirstOrDefault(static x => x.IsDeprecated) is DeprecationInformation contentDeprecationInformation) + else if (parameter.Content.Values.Select(static x => x.Schema).Where(static x => x != null && !x.IsReferencedSchema() && x.Deprecated).Select(static x => x!.GetDeprecationInformation()).FirstOrDefault(static x => x.IsDeprecated) is DeprecationInformation contentDeprecationInformation) return contentDeprecationInformation; return new(null, null, null, null, parameter.Deprecated); } internal static DeprecationInformation GetDeprecationInformation(this OpenApiOperation operation) { - if (operation.Deprecated && operation.Extensions.TryGetValue(OpenApiDeprecationExtension.Name, out var deprecatedExtension) && deprecatedExtension is OpenApiDeprecationExtension deprecatedValue) + if (operation.Deprecated && operation.Extensions is not null && operation.Extensions.TryGetValue(OpenApiDeprecationExtension.Name, out var deprecatedExtension) && deprecatedExtension is OpenApiDeprecationExtension deprecatedValue) return deprecatedValue.ToDeprecationInformation(); - else if (operation.Responses.Values + else if (operation.Responses?.Values .SelectMany(static x => x.Content.Values) .Select(static x => x?.Schema) .OfType() diff --git a/src/Kiota.Builder/Extensions/OpenApiDocumentExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiDocumentExtensions.cs index dc46ca6807..a655a79f12 100644 --- a/src/Kiota.Builder/Extensions/OpenApiDocumentExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiDocumentExtensions.cs @@ -31,7 +31,7 @@ internal static void InitializeInheritanceIndex(this OpenApiDocument openApiDocu { ArgumentNullException.ThrowIfNull(openApiDocument); var candidateUrl = openApiDocument.Servers - .GroupBy(static x => x, new OpenApiServerComparer()) //group by protocol relative urls + ?.GroupBy(static x => x, new OpenApiServerComparer()) //group by protocol relative urls .FirstOrDefault() ?.OrderByDescending(static x => x.Url, StringComparer.OrdinalIgnoreCase) // prefer https over http ?.FirstOrDefault() diff --git a/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs index 2ca1fd3009..23c7659f88 100644 --- a/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs @@ -30,6 +30,7 @@ private static string vendorSpecificCleanup(string input) } internal static IEnumerable GetResponseSchemas(this OpenApiOperation operation, HashSet successCodesToUse, StructuredMimeTypesCollection structuredMimeTypes) { + if (operation.Responses is null) return []; // Return Schema that represents all the possible success responses! return operation.Responses.Where(r => successCodesToUse.Contains(r.Key)) .OrderBy(static x => x.Key, StringComparer.OrdinalIgnoreCase) @@ -67,7 +68,7 @@ internal static IEnumerable GetValidSchemas(this IDictionary (Key: c.Key.Split(';', StringSplitOptions.RemoveEmptyEntries)[0], c.Value)) .Where(c => structuredMimeTypes.Contains(c.Key) || structuredMimeTypes.Contains(vendorSpecificCleanup(c.Key))) .Select(static co => co.Value.Schema) - .Where(static s => s is not null); + .OfType(); } internal static OpenApiSchema? GetResponseSchema(this OpenApiResponse response, StructuredMimeTypesCollection structuredMimeTypes) { diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 193f336e99..a3fc731565 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -8,7 +8,10 @@ using System.Linq; using System.Net.Http; using System.Runtime.CompilerServices; +using System.Security.Cryptography; using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -224,7 +227,7 @@ private void UpdateConfigurationFromOpenApiDocument() } private LanguagesInformation? GetLanguagesInformationInternal() { - if (openApiDocument == null) + if (openApiDocument is null || openApiDocument.Extensions is null) return null; if (openApiDocument.Extensions.TryGetValue(OpenApiKiotaExtension.Name, out var ext) && ext is OpenApiKiotaExtension kiotaExt) return kiotaExt.LanguagesInformation; @@ -1011,7 +1014,7 @@ private CodeParameter GetIndexerParameter(OpenApiUrlTreeNode currentNode, OpenAp var pathItems = GetPathItems(currentNode); var parameter = pathItems.TryGetValue(Constants.DefaultOpenApiLabel, out var pathItem) ? pathItem.Parameters .Select(static x => new { Parameter = x, IsPathParameter = true }) - .Union(pathItems[Constants.DefaultOpenApiLabel].Operations.SelectMany(static x => x.Value.Parameters).Select(static x => new { Parameter = x, IsPathParameter = false })) + .Union(pathItems[Constants.DefaultOpenApiLabel].Operations.SelectMany(static x => x.Value.Parameters ?? []).Select(static x => new { Parameter = x, IsPathParameter = false })) .OrderBy(static x => x.IsPathParameter) .Select(static x => x.Parameter) .FirstOrDefault(x => x.Name.Equals(parameterName, StringComparison.OrdinalIgnoreCase) && x.In == ParameterLocation.Path) : @@ -1112,9 +1115,10 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten !propertyName.Equals(childIdentifier, StringComparison.Ordinal)) prop.SerializationName = childIdentifier; if (kind == CodePropertyKind.Custom && - propertySchema?.Default is OpenApiString stringDefaultValue && - !string.IsNullOrEmpty(stringDefaultValue.Value)) - prop.DefaultValue = $"\"{stringDefaultValue.Value}\""; + propertySchema?.Default is JsonValue stringDefaultJsonValue && + stringDefaultJsonValue.TryGetValue(out var stringDefaultValue) && + !string.IsNullOrEmpty(stringDefaultValue)) + prop.DefaultValue = $"\"{stringDefaultValue}\""; if (existingType == null) { @@ -1185,6 +1189,7 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten .Concat([CodeMethod.ErrorMappingClientRange, CodeMethod.ErrorMappingServerRange]), StringComparer.OrdinalIgnoreCase); private void AddErrorMappingsForExecutorMethod(OpenApiUrlTreeNode currentNode, OpenApiOperation operation, CodeMethod executorMethod) { + if (operation.Responses is null) return; foreach (var response in operation.Responses.Where(x => errorStatusCodes.Contains(x.Key))) { if (response.Value.GetResponseSchema(config.StructuredMimeTypes) is { } schema) @@ -1281,11 +1286,11 @@ private void AddErrorMappingToExecutorMethod(OpenApiUrlTreeNode currentNode, Ope private static CodeType GetExecutorMethodDefaultReturnType(OpenApiOperation operation) { string returnType; - if (operation.Responses.Any(static x => x.Value.Content.ContainsKey(RequestBodyOctetStreamContentType) && redirectStatusCodes.Contains(x.Key))) + if (operation.Responses?.Any(static x => x.Value.Content.ContainsKey(RequestBodyOctetStreamContentType) && redirectStatusCodes.Contains(x.Key)) is true) returnType = "binary"; - else if (operation.Responses.Any(static x => noContentStatusCodes.Contains(x.Key))) + else if (operation.Responses?.Any(static x => noContentStatusCodes.Contains(x.Key)) is true) returnType = VoidType; - else if (operation.Responses.Any(static x => x.Value.Content.ContainsKey(RequestBodyPlainTextContentType))) + else if (operation.Responses?.Any(static x => x.Value.Content.ContainsKey(RequestBodyPlainTextContentType)) is true) returnType = "string"; else returnType = "binary"; @@ -1329,7 +1334,7 @@ private void CreateOperationMethods(OpenApiUrlTreeNode currentNode, OperationTyp Deprecation = deprecationInformation, }; - if (operation.Extensions.TryGetValue(OpenApiPagingExtension.Name, out var extension) && extension is OpenApiPagingExtension pagingExtension) + if (operation.Extensions is not null && operation.Extensions.TryGetValue(OpenApiPagingExtension.Name, out var extension) && extension is OpenApiPagingExtension pagingExtension) { executorMethod.PagingInformation = new PagingInformation { @@ -1388,19 +1393,20 @@ private void CreateOperationMethods(OpenApiUrlTreeNode currentNode, OperationTyp && currentNode.HasRequiredQueryParametersAcrossOperations())// no need to generate extra strings/templates as optional parameters will have no effect on resolved url. generatorMethod.UrlTemplateOverride = operationUrlTemplate; - var mediaTypes = schema switch + var mediaTypes = (schema, operation.Responses is null) switch { - null => operation.Responses + (_, true) => [], + (null, _) => operation.Responses! .Where(static x => !errorStatusCodes.Contains(x.Key)) .SelectMany(static x => x.Value.Content) .Select(static x => x.Key) //get the successful non structured media types first, with a default 1 priority .Union(config.StructuredMimeTypes.GetAcceptedTypes( - operation.Responses + operation.Responses! .Where(static x => errorStatusCodes.Contains(x.Key)) // get any structured error ones, with the priority from the configuration .SelectMany(static x => x.Value.Content) // we can safely ignore unstructured ones as they won't be used in error mappings anyway and the body won't be read .Select(static x => x.Key))) .Distinct(StringComparer.OrdinalIgnoreCase), - _ => config.StructuredMimeTypes.GetAcceptedTypes(operation.Responses.Values.SelectMany(static x => x.Content).Where(x => schemaReferenceComparer.Equals(schema, x.Value.Schema)).Select(static x => x.Key)), + (_, false) => config.StructuredMimeTypes.GetAcceptedTypes(operation.Responses!.Values.SelectMany(static x => x.Content).Where(x => schemaReferenceComparer.Equals(schema, x.Value.Schema)).Select(static x => x.Key)), }; generatorMethod.AddAcceptedResponsesTypes(mediaTypes); if (config.Language == GenerationLanguage.CLI) @@ -1447,8 +1453,9 @@ private static void SetPathAndQueryParameters(CodeMethod target, OpenApiUrlTreeN .Select(GetCodeParameterFromApiParameter) .Union(operation .Parameters - .Where(ParametersFilter) - .Select(GetCodeParameterFromApiParameter)) + ?.Where(ParametersFilter) + .Select(GetCodeParameterFromApiParameter) ?? + []) .ToArray(); target.AddPathQueryOrHeaderParameter(pathAndQueryParameters); } @@ -1510,14 +1517,15 @@ private static bool IsSupportedMultipartDefault(OpenApiSchema openApiSchema, private void AddRequestBuilderMethodParameters(OpenApiUrlTreeNode currentNode, OperationType operationType, OpenApiOperation operation, CodeClass requestConfigClass, CodeMethod method) { - if (operation.GetRequestSchema(config.StructuredMimeTypes) is OpenApiSchema requestBodySchema) + if (operation.RequestBody is not null && + operation.GetRequestSchema(config.StructuredMimeTypes) is OpenApiSchema requestBodySchema) { CodeTypeBase requestBodyType; if (operation.RequestBody.Content.IsMultipartFormDataSchema(config.StructuredMimeTypes) && operation.RequestBody.Content.IsMultipartTopMimeType(config.StructuredMimeTypes)) { var mediaType = operation.RequestBody.Content.First(x => x.Value.Schema == requestBodySchema).Value; - if (mediaType.Encoding.Any()) + if (mediaType.Encoding is not null && mediaType.Encoding.Any()) { requestBodyType = new CodeType { Name = "MultipartBody", IsExternal = true, }; foreach (var encodingEntry in mediaType.Encoding @@ -1940,9 +1948,10 @@ private static void SetEnumOptions(OpenApiSchema schema, CodeEnum target) OpenApiEnumValuesDescriptionExtension? extensionInformation = null; if (schema.Extensions.TryGetValue(OpenApiEnumValuesDescriptionExtension.Name, out var rawExtension) && rawExtension is OpenApiEnumValuesDescriptionExtension localExtInfo) extensionInformation = localExtInfo; - target.AddOption(schema.Enum.OfType() - .Where(static x => !x.Value.Equals("null", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(x.Value)) - .Select(static x => x.Value) + target.AddOption(schema.Enum.OfType() + .Where(static x => x.GetValueKind() is JsonValueKind.String) + .Select(static x => x.GetValue()) + .Where(static x => !string.IsNullOrEmpty(x)) .Distinct(StringComparer.OrdinalIgnoreCase) .Select((x) => { @@ -2215,7 +2224,7 @@ internal static void AddDiscriminatorMethod(CodeClass newClass, string discrimin private CodeType? GetCodeTypeForMapping(OpenApiUrlTreeNode currentNode, string referenceId, CodeNamespace currentNamespace, CodeClass? baseClass, OpenApiOperation? currentOperation) { var componentKey = referenceId?.Replace("#/components/schemas/", string.Empty, StringComparison.OrdinalIgnoreCase); - if (openApiDocument == null || !openApiDocument.Components.Schemas.TryGetValue(componentKey, out var discriminatorSchema)) + if (openApiDocument == null || string.IsNullOrEmpty(componentKey) || openApiDocument.Components?.Schemas is null || !openApiDocument.Components.Schemas.TryGetValue(componentKey, out var discriminatorSchema)) { logger.LogWarning("Discriminator {ComponentKey} not found in the OpenAPI document.", componentKey); return null; diff --git a/src/Kiota.Builder/Validation/MultipleServerEntries.cs b/src/Kiota.Builder/Validation/MultipleServerEntries.cs index 05ff96e5c5..98b3dd2167 100644 --- a/src/Kiota.Builder/Validation/MultipleServerEntries.cs +++ b/src/Kiota.Builder/Validation/MultipleServerEntries.cs @@ -8,7 +8,7 @@ public class MultipleServerEntries : ValidationRule { public MultipleServerEntries() : base(nameof(MultipleServerEntries), static (context, document) => { - if (document.Servers.GroupBy(static x => x.Url, StringComparer.OrdinalIgnoreCase).Count() > 1) + if (document.Servers?.GroupBy(static x => x.Url, StringComparer.OrdinalIgnoreCase).Count() > 1) context.CreateWarning(nameof(MultipleServerEntries), "Multiple servers entries were found in the OpenAPI description. Only the first one will be used. The root URL can be set manually with the request adapter."); }) From 99623e1a2a646c11d5ed9dbdf9ff52abd2fec3c0 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 14 Oct 2024 16:06:37 -0400 Subject: [PATCH 03/96] fix: additional NRE Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 4 ++-- src/Kiota.Builder/Plugins/PluginsGenerationService.cs | 11 ++++++----- .../Validation/InconsistentTypeFormatPair.cs | 2 +- src/Kiota.Builder/Validation/NoContentWithBody.cs | 2 +- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index c5ed4b24e9..31434963dd 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -53,7 +53,7 @@ public static bool IsReferencedSchema(this OpenApiSchema schema) public static bool IsArray(this OpenApiSchema? schema) { - return "array".Equals(schema?.Type, StringComparison.OrdinalIgnoreCase) && schema.Items != null && + return schema is not null && "array".Equals(schema.Type, StringComparison.OrdinalIgnoreCase) && schema.Items is not null && (schema.Items.IsComposedEnum() || schema.Items.IsEnum() || schema.Items.IsSemanticallyMeaningful() || @@ -62,7 +62,7 @@ public static bool IsArray(this OpenApiSchema? schema) public static bool IsObjectType(this OpenApiSchema? schema) { - return "object".Equals(schema?.Type, StringComparison.OrdinalIgnoreCase); + return schema is not null && "object".Equals(schema.Type, StringComparison.OrdinalIgnoreCase); } public static bool HasAnyProperty(this OpenApiSchema? schema) { diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index ef638601fa..a791b281d4 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -107,7 +107,7 @@ private static OpenApiDocument InlineRequestBodyAllOf(OpenApiDocument openApiDoc if (openApiDocument.Paths is null) return openApiDocument; var contentItems = openApiDocument.Paths.Values.Where(static x => x?.Operations is not null) .SelectMany(static x => x.Operations.Values.Where(static x => x?.RequestBody?.Content is not null) - .SelectMany(static x => x.RequestBody.Content.Values)); + .SelectMany(static x => x.RequestBody!.Content.Values)); foreach (var contentItem in contentItems) { var schema = contentItem.Schema; @@ -351,9 +351,9 @@ private static (OpenApiRuntime[], Function[], ConversationStarter[]) GetRuntimes runtimes.Add(new OpenApiRuntime { // Configuration overrides document information - Auth = configAuth ?? GetAuth(operation.Security ?? document.SecurityRequirements), + Auth = configAuth ?? GetAuth(operation.Security ?? document.SecurityRequirements ?? []), Spec = new OpenApiRuntimeSpec { Url = openApiDocumentPath }, - RunForFunctions = [operation.OperationId] + RunForFunctions = [operation.OperationId!] }); var summary = operation.Summary.CleanupXMLString(); @@ -361,7 +361,7 @@ private static (OpenApiRuntime[], Function[], ConversationStarter[]) GetRuntimes functions.Add(new Function { - Name = operation.OperationId, + Name = operation.OperationId!, Description = !string.IsNullOrEmpty(description) ? description : summary, States = GetStatesFromOperation(operation), @@ -441,7 +441,8 @@ SecuritySchemeType.Http when securityScheme.Scheme.Equals("bearer", StringCompar private static State? GetStateFromExtension(OpenApiOperation openApiOperation, string extensionName, Func> instructionsExtractor) { - if (openApiOperation.Extensions.TryGetValue(extensionName, out var rExtRaw) && + if (openApiOperation.Extensions is not null && + openApiOperation.Extensions.TryGetValue(extensionName, out var rExtRaw) && rExtRaw is T rExt && instructionsExtractor(rExt).Exists(static x => !string.IsNullOrEmpty(x))) { diff --git a/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs b/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs index 636bf96689..437aac2b22 100644 --- a/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs +++ b/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs @@ -51,7 +51,7 @@ public class InconsistentTypeFormatPair : ValidationRule }; public InconsistentTypeFormatPair() : base(nameof(InconsistentTypeFormatPair), static (context, schema) => { - if (string.IsNullOrEmpty(schema?.Type) || string.IsNullOrEmpty(schema.Format) || KnownAndNotSupportedFormats.knownAndUnsupportedFormats.Contains(schema.Format) || escapedTypes.Contains(schema.Type)) + if (schema is null || string.IsNullOrEmpty(schema.Type) || string.IsNullOrEmpty(schema.Format) || KnownAndNotSupportedFormats.knownAndUnsupportedFormats.Contains(schema.Format) || escapedTypes.Contains(schema.Type)) return; if (!validPairs.TryGetValue(schema.Type, out var validFormats) || !validFormats.Contains(schema.Format)) context.CreateWarning(nameof(InconsistentTypeFormatPair), $"The format {schema.Format} is not supported by Kiota for the type {schema.Type} and the string type will be used."); diff --git a/src/Kiota.Builder/Validation/NoContentWithBody.cs b/src/Kiota.Builder/Validation/NoContentWithBody.cs index 539c4430e7..29b1c5b960 100644 --- a/src/Kiota.Builder/Validation/NoContentWithBody.cs +++ b/src/Kiota.Builder/Validation/NoContentWithBody.cs @@ -8,7 +8,7 @@ public class NoContentWithBody : ValidationRule { public NoContentWithBody() : base(nameof(NoContentWithBody), static (context, operation) => { - if (operation.Responses.TryGetValue("204", out var response) && (response?.Content?.Any() ?? false)) + if (operation.Responses is not null && operation.Responses.TryGetValue("204", out var response) && (response?.Content?.Any() ?? false)) context.CreateWarning(nameof(NoContentWithBody), "A 204 response with a body media type was found. The response body will be ignored."); }) { From 839202367fe4e6bbf01c9a9d5da47c833446fc4d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 04:41:16 -0500 Subject: [PATCH 04/96] chore: updates reference to oai.net preview --- src/Kiota.Builder/Kiota.Builder.csproj | 4 ++-- src/kiota/kiota.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index b23ec7bc4f..96e4b9cbf5 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -44,9 +44,9 @@ - + - + diff --git a/src/kiota/kiota.csproj b/src/kiota/kiota.csproj index 57ec4596cc..cffd93d309 100644 --- a/src/kiota/kiota.csproj +++ b/src/kiota/kiota.csproj @@ -47,7 +47,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all From 25e45112782cf04cff868bfda5dabbcf53ab4bef Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 06:50:37 -0500 Subject: [PATCH 05/96] fix: additional 3.1 NRT and type reference fixes --- src/Kiota.Builder/KiotaBuilder.cs | 5 ++-- .../Validation/InconsistentTypeFormatPair.cs | 26 +++++++++---------- .../Validation/MissingDiscriminator.cs | 2 +- src/Kiota.Builder/Validation/NoServerEntry.cs | 2 +- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index a3fc731565..c8ad541d67 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -34,6 +34,7 @@ using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.ApiManifest; +using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.MicrosoftExtensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Services; @@ -2389,7 +2390,7 @@ internal static void AddSerializationMembers(CodeClass model, bool includeAdditi } private CodeClass? CreateOperationParameterClass(OpenApiUrlTreeNode node, OperationType operationType, OpenApiOperation operation, CodeClass parentClass) { - var parameters = node.PathItems[Constants.DefaultOpenApiLabel].Parameters.Union(operation.Parameters).Where(static p => p.In == ParameterLocation.Query).ToArray(); + var parameters = node.PathItems[Constants.DefaultOpenApiLabel].Parameters.Union(operation.Parameters ?? Enumerable.Empty()).Where(static p => p.In == ParameterLocation.Query).ToArray(); if (parameters.Length != 0) { var parameterClass = parentClass.AddInnerClass(new CodeClass @@ -2499,7 +2500,7 @@ private static CodeType GetQueryParameterType(OpenApiSchema schema) var paramType = GetPrimitiveType(schema) ?? new() { IsExternal = true, - Name = schema.Items?.Type ?? schema.Type, + Name = schema.Items is not null && schema.Items.Type.HasValue ? schema.Items.Type.ToIdentifier() : schema.Type.ToIdentifier(), }; paramType.CollectionKind = schema.IsArray() ? CodeTypeBase.CodeTypeCollectionKind.Array : default; diff --git a/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs b/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs index 437aac2b22..ecdd6edc2f 100644 --- a/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs +++ b/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs @@ -7,9 +7,9 @@ namespace Kiota.Builder.Validation; public class InconsistentTypeFormatPair : ValidationRule { - private static readonly Dictionary> validPairs = new(StringComparer.OrdinalIgnoreCase) + private static readonly Dictionary> validPairs = new() { - ["string"] = new(StringComparer.OrdinalIgnoreCase) { + [JsonSchemaType.String] = new(StringComparer.OrdinalIgnoreCase) { "commonmark", "html", "date", @@ -21,7 +21,7 @@ public class InconsistentTypeFormatPair : ValidationRule "binary", "byte", }, - ["integer"] = new(StringComparer.OrdinalIgnoreCase) { + [JsonSchemaType.Integer] = new(StringComparer.OrdinalIgnoreCase) { "int32", "int64", "int8", @@ -29,7 +29,7 @@ public class InconsistentTypeFormatPair : ValidationRule "int16", "uint16", }, - ["number"] = new(StringComparer.OrdinalIgnoreCase) { + [JsonSchemaType.Number] = new(StringComparer.OrdinalIgnoreCase) { "float", "double", "decimal", @@ -41,19 +41,17 @@ public class InconsistentTypeFormatPair : ValidationRule "uint16", }, }; - private static readonly HashSet escapedTypes = new(StringComparer.OrdinalIgnoreCase) { - "array", - "boolean", - "const", - "enum", - "null", - "object", - }; + private static readonly HashSet escapedTypes = [ + JsonSchemaType.Array, + JsonSchemaType.Boolean, + JsonSchemaType.Null, + JsonSchemaType.Object, + ]; public InconsistentTypeFormatPair() : base(nameof(InconsistentTypeFormatPair), static (context, schema) => { - if (schema is null || string.IsNullOrEmpty(schema.Type) || string.IsNullOrEmpty(schema.Format) || KnownAndNotSupportedFormats.knownAndUnsupportedFormats.Contains(schema.Format) || escapedTypes.Contains(schema.Type)) + if (schema is null || !schema.Type.HasValue || string.IsNullOrEmpty(schema.Format) || KnownAndNotSupportedFormats.knownAndUnsupportedFormats.Contains(schema.Format) || escapedTypes.Contains(schema.Type.Value)) return; - if (!validPairs.TryGetValue(schema.Type, out var validFormats) || !validFormats.Contains(schema.Format)) + if (!validPairs.TryGetValue(schema.Type.Value, out var validFormats) || !validFormats.Contains(schema.Format)) context.CreateWarning(nameof(InconsistentTypeFormatPair), $"The format {schema.Format} is not supported by Kiota for the type {schema.Type} and the string type will be used."); }) { diff --git a/src/Kiota.Builder/Validation/MissingDiscriminator.cs b/src/Kiota.Builder/Validation/MissingDiscriminator.cs index c889f5cf5a..4fa5b52064 100644 --- a/src/Kiota.Builder/Validation/MissingDiscriminator.cs +++ b/src/Kiota.Builder/Validation/MissingDiscriminator.cs @@ -14,7 +14,7 @@ public MissingDiscriminator(GenerationConfiguration configuration) : base(nameof { var idx = new ConcurrentDictionary>(StringComparer.OrdinalIgnoreCase); document.InitializeInheritanceIndex(idx); - if (document.Components != null) + if (document.Components is { Schemas.Count: > 0 }) Parallel.ForEach(document.Components.Schemas, entry => { ValidateSchema(entry.Value, context, idx, entry.Key); diff --git a/src/Kiota.Builder/Validation/NoServerEntry.cs b/src/Kiota.Builder/Validation/NoServerEntry.cs index 17513ed4f7..8d51b1e9ef 100644 --- a/src/Kiota.Builder/Validation/NoServerEntry.cs +++ b/src/Kiota.Builder/Validation/NoServerEntry.cs @@ -8,7 +8,7 @@ public class NoServerEntry : ValidationRule { public NoServerEntry() : base(nameof(NoServerEntry), static (context, document) => { - if (!document.Servers.Any() || string.IsNullOrEmpty(document.Servers.First().Url?.TrimEnd('/'))) + if (document.Servers is not { Count: > 1 } || string.IsNullOrEmpty(document.Servers[0].Url?.TrimEnd('/'))) context.CreateWarning(nameof(NoServerEntry), "A servers entry (v3) or host + basePath + schemes properties (v2) was not present in the OpenAPI description. The root URL will need to be set manually with the request adapter."); }) From 99dcbfbf4eb6b2fc22af5dee3f54ae44e1d07510 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 07:03:56 -0500 Subject: [PATCH 06/96] fix: additional 3.1 NRT and type reference fixes --- src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs | 2 +- src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs | 2 ++ src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs | 5 +++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs index 4543d3acbb..aac8f6341f 100644 --- a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs +++ b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs @@ -68,7 +68,7 @@ private void GetHashCodeInternal([DisallowNull] OpenApiSchema obj, HashSet }; public UrlFormEncodedComplex() : base(nameof(UrlFormEncodedComplex), static (context, operation) => { + if (string.IsNullOrEmpty(operation.OperationId)) + return; if (operation.GetRequestSchema(validContentTypes) is OpenApiSchema requestSchema) ValidateSchema(requestSchema, context, operation.OperationId, "request body"); if (operation.GetResponseSchema(validContentTypes) is OpenApiSchema responseSchema) diff --git a/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs b/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs index c54eb22904..95d66e80e8 100644 --- a/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs +++ b/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs @@ -24,7 +24,8 @@ public static void AddKiotaValidationRules(this ValidationRuleSet ruleSet, Gener } private static void AddRuleIfEnabled(this ValidationRuleSet ruleSet, GenerationConfiguration configuration, T instance) where T : ValidationRule { - if (!configuration.DisabledValidationRules.Contains(instance.GetType().Name)) - ruleSet.Add(instance); + var ruleType = instance.GetType(); + if (!configuration.DisabledValidationRules.Contains(ruleType.Name)) + ruleSet.Add(ruleType, instance); } } From 6422b453f84688dc2c0491716f3cb53495353fbd Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 07:07:17 -0500 Subject: [PATCH 07/96] fix: wrong value comparison Signed-off-by: Vincent Biret --- src/Kiota.Builder/Validation/NoServerEntry.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Validation/NoServerEntry.cs b/src/Kiota.Builder/Validation/NoServerEntry.cs index 8d51b1e9ef..291ce7ecb0 100644 --- a/src/Kiota.Builder/Validation/NoServerEntry.cs +++ b/src/Kiota.Builder/Validation/NoServerEntry.cs @@ -8,7 +8,7 @@ public class NoServerEntry : ValidationRule { public NoServerEntry() : base(nameof(NoServerEntry), static (context, document) => { - if (document.Servers is not { Count: > 1 } || string.IsNullOrEmpty(document.Servers[0].Url?.TrimEnd('/'))) + if (document.Servers is not { Count: > 0 } || string.IsNullOrEmpty(document.Servers[0].Url?.TrimEnd('/'))) context.CreateWarning(nameof(NoServerEntry), "A servers entry (v3) or host + basePath + schemes properties (v2) was not present in the OpenAPI description. The root URL will need to be set manually with the request adapter."); }) From 4bff2273983a5259f1b96d5afb6eb079fdb09669 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 08:38:45 -0500 Subject: [PATCH 08/96] fix: additional type and NRT fixes Signed-off-by: Vincent Biret --- .../OpenApiUrlTreeNodeExtensions.cs | 16 ++-- src/Kiota.Builder/KiotaBuilder.cs | 86 +++++++++---------- .../OpenApiDocumentDownloadService.cs | 6 +- .../Plugins/PluginsGenerationService.cs | 4 +- src/Kiota.Builder/Validation/NoServerEntry.cs | 3 +- 5 files changed, 57 insertions(+), 58 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs index a49b82968a..98e4e8a6af 100644 --- a/src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs @@ -69,7 +69,7 @@ internal static string CleanupParametersFromPath(string pathSegment) private static IEnumerable GetParametersForPathItem(OpenApiPathItem pathItem, string nodeSegment) { return pathItem.Parameters - .Union(pathItem.Operations.SelectMany(static x => x.Value.Parameters)) + .Union(pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty())) .Where(static x => x.In == ParameterLocation.Path) .Where(x => nodeSegment.Contains($"{{{x.Name}}}", StringComparison.OrdinalIgnoreCase)); } @@ -193,7 +193,7 @@ public static bool HasRequiredQueryParametersAcrossOperations(this OpenApiUrlTre if (!currentNode.PathItems.TryGetValue(Constants.DefaultOpenApiLabel, out var pathItem)) return false; - var operationQueryParameters = pathItem.Operations.SelectMany(static x => x.Value.Parameters); + var operationQueryParameters = pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty()); return operationQueryParameters.Union(pathItem.Parameters).Where(static x => x.In == ParameterLocation.Query) .Any(static x => x.Required); } @@ -207,9 +207,9 @@ public static string GetUrlTemplate(this OpenApiUrlTreeNode currentNode, Operati var pathItem = currentNode.PathItems[Constants.DefaultOpenApiLabel]; var operationQueryParameters = (operationType, pathItem.Operations.Any()) switch { - (OperationType ot, _) when pathItem.Operations.TryGetValue(ot, out var operation) => operation.Parameters, - (null, true) => pathItem.Operations.SelectMany(static x => x.Value.Parameters).Where(static x => x.In == ParameterLocation.Query), - _ => Enumerable.Empty(), + (OperationType ot, _) when pathItem.Operations.TryGetValue(ot, out var operation) && operation.Parameters is not null => operation.Parameters, + (null, true) => pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty()).Where(static x => x.In == ParameterLocation.Query), + _ => [], }; var parameters = pathItem.Parameters .Union(operationQueryParameters) @@ -234,7 +234,7 @@ public static string GetUrlTemplate(this OpenApiUrlTreeNode currentNode, Operati } var pathReservedPathParametersIds = currentNode.PathItems.TryGetValue(Constants.DefaultOpenApiLabel, out var pItem) ? pItem.Parameters - .Union(pItem.Operations.SelectMany(static x => x.Value.Parameters)) + .Union(pItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty())) .Where(static x => x.In == ParameterLocation.Path && x.Extensions.TryGetValue(OpenApiReservedParameterExtension.Name, out var ext) && ext is OpenApiReservedParameterExtension reserved && reserved.IsReserved.HasValue && reserved.IsReserved.Value) .Select(static x => x.Name) .ToHashSet(StringComparer.OrdinalIgnoreCase) : @@ -356,7 +356,7 @@ private static void ReplaceParameterInPathForAllChildNodes(OpenApiUrlTreeNode no if (node.PathItems.TryGetValue(Constants.DefaultOpenApiLabel, out var pathItem)) { foreach (var pathParameter in pathItem.Parameters - .Union(pathItem.Operations.SelectMany(static x => x.Value.Parameters)) + .Union(pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty())) .Where(x => x.In == ParameterLocation.Path && oldName.Equals(x.Name, StringComparison.Ordinal))) { pathParameter.Name = newParameterName; @@ -386,7 +386,7 @@ private static void CopyNodeIntoOtherNode(OpenApiUrlTreeNode source, OpenApiUrlT pathItem .Value .Operations - .SelectMany(static x => x.Value.Parameters) + .SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty()) .Where(x => x.In == ParameterLocation.Path && pathParameterNameToReplace.Equals(x.Name, StringComparison.Ordinal)) )) { diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index c8ad541d67..c04a01f47e 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1082,7 +1082,7 @@ private CodeIndexer[] CreateIndexer(string childIdentifier, string childType, Co result.Add(backCompatibleValue); } - return result.ToArray(); + return [.. result]; } private static readonly StructuralPropertiesReservedNameProvider structuralPropertiesReservedNameProvider = new(); @@ -1091,7 +1091,9 @@ private CodeIndexer[] CreateIndexer(string childIdentifier, string childType, Co var propertyName = childIdentifier.CleanupSymbolName(); if (structuralPropertiesReservedNameProvider.ReservedNames.Contains(propertyName)) propertyName += "Property"; - var resultType = existingType ?? GetPrimitiveType(propertySchema, childType); + var resultType = existingType ?? GetPrimitiveType(propertySchema); + if ((propertySchema?.Items?.IsEnum() ?? false) && resultType is CodeType codeType) + codeType.Name = childType; if (resultType == null) return null; var prop = new CodeProperty { @@ -1128,57 +1130,55 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten } return prop; } - private static readonly HashSet typeNamesToSkip = new(StringComparer.OrdinalIgnoreCase) { "object", "array" }; - private static CodeType? GetPrimitiveType(OpenApiSchema? typeSchema, string? childType = default) + private static readonly HashSet typeNamesToSkip = [JsonSchemaType.Object, JsonSchemaType.Array]; + private static CodeType? GetPrimitiveType(OpenApiSchema? typeSchema) { - var typeNames = new List { typeSchema?.Items?.Type, childType, typeSchema?.Type }; + var typeNames = new List { typeSchema?.Items?.Type, typeSchema?.Type }; if (typeSchema?.AnyOf?.Any() ?? false) typeNames.AddRange(typeSchema.AnyOf.Select(x => x.Type)); // double is sometimes an anyof string, number and enum if (typeSchema?.OneOf?.Any() ?? false) typeNames.AddRange(typeSchema.OneOf.Select(x => x.Type)); // double is sometimes an oneof string, number and enum // first value that's not null, and not "object" for primitive collections, the items type matters - var typeName = typeNames.Find(static x => !string.IsNullOrEmpty(x) && !typeNamesToSkip.Contains(x)); + var typeName = typeNames.Find(static x => x is not null && !typeNamesToSkip.Contains(x.Value)); var isExternal = false; - if (typeSchema?.Items?.IsEnum() ?? false) - typeName = childType; - else + var format = typeSchema?.Format ?? typeSchema?.Items?.Format; + var primitiveTypeName = (typeName, format?.ToLowerInvariant()) switch + { + (JsonSchemaType.String, "base64url") => "base64url", + (JsonSchemaType.String, "duration") => "TimeSpan", + (JsonSchemaType.String, "time") => "TimeOnly", + (JsonSchemaType.String, "date") => "DateOnly", + (JsonSchemaType.String, "date-time") => "DateTimeOffset", + (JsonSchemaType.String, "uuid") => "Guid", + (JsonSchemaType.String, _) => "string", // covers commonmark and html + (JsonSchemaType.Number, "double" or "float" or "decimal") => format.ToLowerInvariant(), + (JsonSchemaType.Number or JsonSchemaType.Integer, "int8") => "sbyte", + (JsonSchemaType.Number or JsonSchemaType.Integer, "uint8") => "byte", + (JsonSchemaType.Number or JsonSchemaType.Integer, "int64") => "int64", + (JsonSchemaType.Number, "int16") => "integer", + (JsonSchemaType.Number, "int32") => "integer", + (JsonSchemaType.Number, _) => "double", + (JsonSchemaType.Integer, _) => "integer", + (JsonSchemaType.Boolean, _) => "boolean", + (_, "byte") => "base64", + (_, "binary") => "binary", + //TODO handle the case where we have multiple entries + (_, _) => string.Empty, + }; + if (!string.IsNullOrEmpty(primitiveTypeName)) { - var format = typeSchema?.Format ?? typeSchema?.Items?.Format; - var primitiveTypeName = (typeName?.ToLowerInvariant(), format?.ToLowerInvariant()) switch - { - ("string", "base64url") => "base64url", - ("file", _) => "binary", - ("string", "duration") => "TimeSpan", - ("string", "time") => "TimeOnly", - ("string", "date") => "DateOnly", - ("string", "date-time") => "DateTimeOffset", - ("string", "uuid") => "Guid", - ("string", _) => "string", // covers commonmark and html - ("number", "double" or "float" or "decimal") => format.ToLowerInvariant(), - ("number" or "integer", "int8") => "sbyte", - ("number" or "integer", "uint8") => "byte", - ("number" or "integer", "int64") => "int64", - ("number", "int16") => "integer", - ("number", "int32") => "integer", - ("number", _) => "double", - ("integer", _) => "integer", - ("boolean", _) => "boolean", - (_, "byte") => "base64", - (_, "binary") => "binary", - (_, _) => string.Empty, - }; - if (!string.IsNullOrEmpty(primitiveTypeName)) + return new CodeType { - typeName = primitiveTypeName; - isExternal = true; - } + Name = primitiveTypeName, + IsExternal = true, + }; } - if (string.IsNullOrEmpty(typeName)) + if (typeName is null || typeName.ToIdentifier() is not string normalizedTypeName || string.IsNullOrEmpty(normalizedTypeName)) return null; return new CodeType { - Name = typeName, + Name = normalizedTypeName, IsExternal = isExternal, }; } @@ -1842,7 +1842,7 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, Ope return CreateComposedModelDeclaration(currentNode, schema, operation, suffix, codeNamespace, isRequestBody, typeNameForInlineSchema); } - if (schema.IsObjectType() || schema.HasAnyProperty() || schema.IsEnum() || !string.IsNullOrEmpty(schema.AdditionalProperties?.Type)) + if (schema.IsObjectType() || schema.HasAnyProperty() || schema.IsEnum() || schema.AdditionalProperties?.Type is not null) { // no inheritance or union type, often empty definitions with only additional properties are used as property bags. return CreateModelDeclarationAndType(currentNode, schema, operation, codeNamespace, suffix, response: responseValue, typeNameForInlineSchema: typeNameForInlineSchema, isRequestBody); @@ -1855,8 +1855,8 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, Ope return CreateCollectionModelDeclaration(currentNode, schema, operation, codeNamespace, typeNameForInlineSchema, isRequestBody); } - if (!string.IsNullOrEmpty(schema.Type) || !string.IsNullOrEmpty(schema.Format)) - return GetPrimitiveType(schema, string.Empty) ?? new CodeType { Name = UntypedNodeName, IsExternal = true }; + if (schema.Type is not null || !string.IsNullOrEmpty(schema.Format)) + return GetPrimitiveType(schema) ?? new CodeType { Name = UntypedNodeName, IsExternal = true }; if ((schema.AnyOf.Any() || schema.OneOf.Any() || schema.AllOf.Any()) && (schema.AnyOf.FirstOrDefault(static x => x.IsSemanticallyMeaningful(true)) ?? schema.OneOf.FirstOrDefault(static x => x.IsSemanticallyMeaningful(true)) ?? schema.AllOf.FirstOrDefault(static x => x.IsSemanticallyMeaningful(true))) is { } childSchema) // we have an empty node because of some local override for schema properties and need to unwrap it. return CreateModelDeclarations(currentNode, childSchema, operation, parentElement, suffixForInlineSchema, response, typeNameForInlineSchema, isRequestBody); @@ -1864,7 +1864,7 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, Ope } private CodeTypeBase CreateCollectionModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeNamespace codeNamespace, string typeNameForInlineSchema, bool isRequestBody) { - CodeTypeBase? type = GetPrimitiveType(schema.Items, string.Empty); + CodeTypeBase? type = GetPrimitiveType(schema.Items); var isEnumOrComposedCollectionType = schema.Items.IsEnum() //the collection could be an enum type so override with strong type instead of string type. || schema.Items.IsComposedEnum() && string.IsNullOrEmpty(schema.Items.Format);//the collection could be a composed type with an enum type so override with strong type instead of string type. if ((string.IsNullOrEmpty(type?.Name) diff --git a/src/Kiota.Builder/OpenApiDocumentDownloadService.cs b/src/Kiota.Builder/OpenApiDocumentDownloadService.cs index ae586c86a3..9e76322596 100644 --- a/src/Kiota.Builder/OpenApiDocumentDownloadService.cs +++ b/src/Kiota.Builder/OpenApiDocumentDownloadService.cs @@ -16,7 +16,7 @@ using Kiota.Builder.WorkspaceManagement; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Validations; namespace Kiota.Builder; @@ -135,8 +135,8 @@ ex is SecurityException || { // couldn't parse the URL, it's probably a local file } - var reader = new OpenApiStreamReader(settings); - var readResult = await reader.ReadAsync(input, cancellationToken).ConfigureAwait(false); + //TODO update to remove the unknown format when the overload is available + var readResult = await OpenApiDocument.LoadAsync(input, "unknown", settings: settings, cancellationToken: cancellationToken).ConfigureAwait(false); stopwatch.Stop(); if (generating) foreach (var warning in readResult.OpenApiDiagnostic.Warnings) diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index a791b281d4..19392e9dd7 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -144,9 +144,9 @@ private static OpenApiDocument InlineRequestBodyAllOf(OpenApiDocument openApiDoc foreach (var apiSchema in schema.AllOf) { if (apiSchema.Title is not null) newSchema.Title = apiSchema.Title; - if (!string.IsNullOrEmpty(apiSchema.Type)) + if (apiSchema.Type is not null) { - if (!string.IsNullOrEmpty(newSchema.Type) && newSchema.Type != apiSchema.Type) + if (newSchema.Type is not null && newSchema.Type.Value != apiSchema.Type.Value) { throw new InvalidOperationException( $"The schemas in allOf cannot have different types: '{newSchema.Type}' and '{apiSchema.Type}'."); diff --git a/src/Kiota.Builder/Validation/NoServerEntry.cs b/src/Kiota.Builder/Validation/NoServerEntry.cs index 291ce7ecb0..895744b4b5 100644 --- a/src/Kiota.Builder/Validation/NoServerEntry.cs +++ b/src/Kiota.Builder/Validation/NoServerEntry.cs @@ -1,5 +1,4 @@ -using System.Linq; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Validations; namespace Kiota.Builder.Validation; From 229a425b4da6291dc8c524670777b6ef724f2c48 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 13:13:41 -0500 Subject: [PATCH 09/96] fix: main project builds Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 45 ++++++++++--------- .../Validation/OpenApiSchemaComparer.cs | 17 +++---- 2 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index 31434963dd..187c3a49e1 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -2,7 +2,7 @@ using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; -using Microsoft.OpenApi.Any; +using System.Text.Json; using Microsoft.OpenApi.Models; namespace Kiota.Builder.Extensions; @@ -53,7 +53,7 @@ public static bool IsReferencedSchema(this OpenApiSchema schema) public static bool IsArray(this OpenApiSchema? schema) { - return schema is not null && "array".Equals(schema.Type, StringComparison.OrdinalIgnoreCase) && schema.Items is not null && + return schema is { Type: JsonSchemaType.Array or (JsonSchemaType.Array | JsonSchemaType.Null) } && schema.Items is not null && (schema.Items.IsComposedEnum() || schema.Items.IsEnum() || schema.Items.IsSemanticallyMeaningful() || @@ -62,7 +62,7 @@ public static bool IsArray(this OpenApiSchema? schema) public static bool IsObjectType(this OpenApiSchema? schema) { - return schema is not null && "object".Equals(schema.Type, StringComparison.OrdinalIgnoreCase); + return schema is { Type: JsonSchemaType.Object or (JsonSchemaType.Object | JsonSchemaType.Null) }; } public static bool HasAnyProperty(this OpenApiSchema? schema) { @@ -128,45 +128,48 @@ public static bool IsExclusiveUnion(this OpenApiSchema? schema) return schema?.OneOf?.Count(static x => IsSemanticallyMeaningful(x, true)) > 1; // so we don't consider one of object/nullable as a union type } - private static readonly HashSet oDataTypes = new(StringComparer.OrdinalIgnoreCase) { - "number", - "integer", - }; + private static readonly HashSet oDataTypes = [ + JsonSchemaType.Number, + JsonSchemaType.Integer, + ]; + private static readonly Func isODataType = static x => x.Type is not null && oDataTypes.Contains(x.Type.Value); + private static readonly Func isStringType = static x => x is { Type: JsonSchemaType.String or (JsonSchemaType.String | JsonSchemaType.Null) }; private static bool IsODataPrimitiveTypeBackwardCompatible(this OpenApiSchema schema) { return schema.IsExclusiveUnion() && schema.OneOf.Count == 3 && schema.OneOf.Count(static x => x.Enum?.Any() ?? false) == 1 && - schema.OneOf.Count(static x => oDataTypes.Contains(x.Type)) == 1 && - schema.OneOf.Count(static x => "string".Equals(x.Type, StringComparison.OrdinalIgnoreCase)) == 1 + schema.OneOf.Count(isODataType) == 1 && + schema.OneOf.Count(isStringType) == 1 || schema.IsInclusiveUnion() && schema.AnyOf.Count == 3 && schema.AnyOf.Count(static x => x.Enum?.Any() ?? false) == 1 && - schema.AnyOf.Count(static x => oDataTypes.Contains(x.Type)) == 1 && - schema.AnyOf.Count(static x => "string".Equals(x.Type, StringComparison.OrdinalIgnoreCase)) == 1; + schema.AnyOf.Count(isODataType) == 1 && + schema.AnyOf.Count(isStringType) == 1; } public static bool IsODataPrimitiveType(this OpenApiSchema schema) { return schema.IsExclusiveUnion() && schema.OneOf.Count == 3 && - schema.OneOf.Count(static x => "string".Equals(x.Type, StringComparison.OrdinalIgnoreCase) && (x.Enum?.Any() ?? false)) == 1 && - schema.OneOf.Count(static x => oDataTypes.Contains(x.Type)) == 1 && - schema.OneOf.Count(static x => "string".Equals(x.Type, StringComparison.OrdinalIgnoreCase)) == 2 + schema.OneOf.Count(static x => isStringType(x) && (x.Enum?.Any() ?? false)) == 1 && + schema.OneOf.Count(isODataType) == 1 && + schema.OneOf.Count(isStringType) == 2 || schema.IsInclusiveUnion() && schema.AnyOf.Count == 3 && - schema.AnyOf.Count(static x => "string".Equals(x.Type, StringComparison.OrdinalIgnoreCase) && (x.Enum?.Any() ?? false)) == 1 && - schema.AnyOf.Count(static x => oDataTypes.Contains(x.Type)) == 1 && - schema.AnyOf.Count(static x => "string".Equals(x.Type, StringComparison.OrdinalIgnoreCase)) == 2 + schema.AnyOf.Count(static x => isStringType(x) && (x.Enum?.Any() ?? false)) == 1 && + schema.AnyOf.Count(isODataType) == 1 && + schema.AnyOf.Count(isStringType) == 2 || schema.IsODataPrimitiveTypeBackwardCompatible(); } public static bool IsEnum(this OpenApiSchema schema) { if (schema is null) return false; - return schema.Enum.OfType().Any(static x => !string.IsNullOrEmpty(x.Value)) && - (string.IsNullOrEmpty(schema.Type) || "string".Equals(schema.Type, StringComparison.OrdinalIgnoreCase)); // number and boolean enums are not supported + return schema.Enum.Any(static x => x.GetValueKind() is JsonValueKind.String && + x.GetValue() is string value && + !string.IsNullOrEmpty(value)); // number and boolean enums are not supported } public static bool IsComposedEnum(this OpenApiSchema schema) { @@ -180,8 +183,8 @@ public static bool IsSemanticallyMeaningful(this OpenApiSchema schema, bool igno return schema.HasAnyProperty() || (!ignoreEnums && schema.Enum is { Count: > 0 }) || (!ignoreArrays && schema.Items != null) || - (!ignoreType && !string.IsNullOrEmpty(schema.Type) && - ((ignoreNullableObjects && !"object".Equals(schema.Type, StringComparison.OrdinalIgnoreCase)) || + (!ignoreType && schema.Type is not null && + ((ignoreNullableObjects && !schema.IsObjectType()) || !ignoreNullableObjects)) || !string.IsNullOrEmpty(schema.Format) || !string.IsNullOrEmpty(schema.Reference?.Id); diff --git a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs index aac8f6341f..1d7b2c1fcb 100644 --- a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs +++ b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Text.Json.Nodes; using Kiota.Builder.Extensions; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; @@ -11,16 +12,16 @@ namespace Kiota.Builder.Validation; internal class OpenApiSchemaComparer : IEqualityComparer { private readonly OpenApiDiscriminatorComparer discriminatorComparer; - private readonly OpenApiAnyComparer openApiAnyComparer; + private readonly JsonNodeComparer jsonNodeComparer; private readonly KeyValueComparer schemaMapComparer; public OpenApiSchemaComparer( OpenApiDiscriminatorComparer? discriminatorComparer = null, - OpenApiAnyComparer? openApiAnyComparer = null, + JsonNodeComparer? jsonNodeComparer = null, KeyValueComparer? schemaMapComparer = null) { this.discriminatorComparer = discriminatorComparer ?? new OpenApiDiscriminatorComparer(); - this.openApiAnyComparer = openApiAnyComparer ?? new OpenApiAnyComparer(); + this.jsonNodeComparer = jsonNodeComparer ?? new JsonNodeComparer(); this.schemaMapComparer = schemaMapComparer ?? new KeyValueComparer(StringComparer.Ordinal, this); } @@ -53,7 +54,7 @@ private void GetHashCodeInternal([DisallowNull] OpenApiSchema obj, HashSet +internal class JsonNodeComparer : IEqualityComparer { /// - public bool Equals(OpenApiAny? x, OpenApiAny? y) + public bool Equals(JsonNode? x, JsonNode? y) { if (x is null || y is null) return object.Equals(x, y); // TODO: Can we use the OpenAPI.NET implementation of Equals? - return x.Node.GetValueKind() == y.Node.GetValueKind() && string.Equals(x.Node.ToString(), y.Node.ToString(), StringComparison.OrdinalIgnoreCase); + return x.GetValueKind() == y.GetValueKind() && string.Equals(x.GetValue(), y.GetValue(), StringComparison.OrdinalIgnoreCase); } /// - public int GetHashCode([DisallowNull] OpenApiAny obj) + public int GetHashCode([DisallowNull] JsonNode obj) { var hash = new HashCode(); if (obj == null) return hash.ToHashCode(); From 193a7b9b970bf851c2ef3fb99e091e5f50215243 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 14:07:44 -0500 Subject: [PATCH 10/96] fix: all validation tests migrated to the new OAI.net object model Signed-off-by: Vincent Biret --- .../DivergentResponseSchemaTests.cs | 50 ++++------ .../Validation/GetWithBodyTests.cs | 48 ++++----- .../InconsistentTypeFormatPairTests.cs | 50 ++++------ .../KnownAndNotSupportedFormatsTests.cs | 51 ++++------ .../Validation/MissingDiscriminatorTests.cs | 74 +++++--------- .../Validation/MultipleServerEntriesTests.cs | 38 ++++--- .../Validation/NoContentWithBodyTests.cs | 51 ++++------ .../Validation/NoServerEntryTests.cs | 38 ++++--- .../Validation/UrlFormEncodedComplexTests.cs | 98 +++++++------------ .../ValidationRuleSetExtensionsTests.cs | 8 +- 10 files changed, 205 insertions(+), 301 deletions(-) diff --git a/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs b/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs index 6bdc1bd756..c50ae4e9e3 100644 --- a/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs @@ -1,8 +1,9 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Kiota.Builder.Validation; -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Validations; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader; using Xunit; namespace Kiota.Builder.Tests.Validation; @@ -10,9 +11,8 @@ namespace Kiota.Builder.Tests.Validation; public class DivergentResponseSchemaTests { [Fact] - public void DoesntAddAWarningWhenBodyIsSingle() + public async Task DoesntAddAWarningWhenBodyIsSingle() { - var rule = new DivergentResponseSchema(new()); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -28,18 +28,12 @@ public void DoesntAddAWarningWhenBodyIsSingle() schema: type: string format: int32"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); } [Fact] - public void AddsAWarningWhenBodyIsDivergent() + public async Task AddsAWarningWhenBodyIsDivergent() { - var rule = new DivergentResponseSchema(new()); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -61,18 +55,12 @@ public void AddsAWarningWhenBodyIsDivergent() schema: type: string format: int64"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhenUsing2XX() + public async Task DoesntAddAWarningWhenUsing2XX() { - var rule = new DivergentResponseSchema(new()); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -94,12 +82,16 @@ public void DoesntAddAWarningWhenUsing2XX() schema: type: string format: int64"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new DivergentResponseSchema(new()); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(DivergentResponseSchema), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.OpenApiDiagnostic; } } diff --git a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs index 99ba847d8c..e04999b87a 100644 --- a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs @@ -1,6 +1,9 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Kiota.Builder.Validation; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Readers; using Microsoft.OpenApi.Validations; using Xunit; @@ -10,9 +13,8 @@ namespace Kiota.Builder.Tests.Validation; public class GetWithBodyTests { [Fact] - public void AddsAWarningWhenGetWithBody() + public async Task AddsAWarningWhenGetWithBody() { - var rule = new GetWithBody(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -29,18 +31,12 @@ public void AddsAWarningWhenGetWithBody() '200': content: application/json:"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhenGetWithNoBody() + public async Task DoesntAddAWarningWhenGetWithNoBody() { - var rule = new GetWithBody(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -55,18 +51,12 @@ public void DoesntAddAWarningWhenGetWithNoBody() '200': content: application/json:"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhenPostWithBody() + public async Task DoesntAddAWarningWhenPostWithBody() { - var rule = new GetWithBody(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -83,12 +73,16 @@ public void DoesntAddAWarningWhenPostWithBody() '200': content: application/json:"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new GetWithBody(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(GetWithBody), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.OpenApiDiagnostic; } } diff --git a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs index 9b46823c30..34b965b2fe 100644 --- a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs @@ -1,17 +1,17 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Kiota.Builder.Validation; -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Validations; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader; using Xunit; namespace Kiota.Builder.Tests.Validation; public class InconsistentTypeFormatPairTests { [Fact] - public void AddsAWarningWhenKnownInconsistentPair() + public async Task AddsAWarningWhenKnownInconsistentPair() { - var rule = new InconsistentTypeFormatPair(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -27,18 +27,12 @@ public void AddsAWarningWhenKnownInconsistentPair() schema: type: string format: int32"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhenSupportedPair() + public async Task DoesntAddAWarningWhenSupportedPair() { - var rule = new InconsistentTypeFormatPair(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -54,18 +48,12 @@ public void DoesntAddAWarningWhenSupportedPair() schema: type: string format: uuid"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); } [Fact] - public void DoesntFailWhenKnownAlternative() + public async Task DoesntFailWhenKnownAlternative() { - var rule = new InconsistentTypeFormatPair(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -81,12 +69,16 @@ public void DoesntFailWhenKnownAlternative() schema: type: enum format: string"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new InconsistentTypeFormatPair(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(InconsistentTypeFormatPair), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.OpenApiDiagnostic; } } diff --git a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs index 8df9463cf9..2a3dfbe407 100644 --- a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs @@ -1,8 +1,9 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Kiota.Builder.Validation; -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Validations; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader; using Xunit; namespace Kiota.Builder.Tests.Validation; @@ -10,9 +11,8 @@ namespace Kiota.Builder.Tests.Validation; public class KnownAndNotSupportedFormatsTests { [Fact] - public void AddsAWarningWhenKnownUnsupportedFormat() + public async Task AddsAWarningWhenKnownUnsupportedFormat() { - var rule = new KnownAndNotSupportedFormats(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -28,18 +28,12 @@ public void AddsAWarningWhenKnownUnsupportedFormat() schema: type: string format: email"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhenSupportedFormat() + public async Task DoesntAddAWarningWhenSupportedFormat() { - var rule = new KnownAndNotSupportedFormats(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -55,18 +49,12 @@ public void DoesntAddAWarningWhenSupportedFormat() schema: type: string format: uuid"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); } [Fact] - public void DoesntFailWhenNoFormat() + public async Task DoesntFailWhenNoFormat() { - var rule = new KnownAndNotSupportedFormats(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -81,13 +69,16 @@ public void DoesntFailWhenNoFormat() application/json: schema: type: string"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new KnownAndNotSupportedFormats(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(KnownAndNotSupportedFormats), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.OpenApiDiagnostic; } - } diff --git a/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs b/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs index d112997287..58404f74d6 100644 --- a/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs @@ -1,17 +1,17 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Kiota.Builder.Validation; -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Validations; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader; using Xunit; namespace Kiota.Builder.Tests.Validation; public class MissingDiscriminatorTests { [Fact] - public void DoesntAddAWarningWhenBodyIsSimple() + public async Task DoesntAddAWarningWhenBodyIsSimple() { - var rule = new MissingDiscriminator(new()); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -27,18 +27,12 @@ public void DoesntAddAWarningWhenBodyIsSimple() schema: type: string format: int32"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); } [Fact] - public void AddsWarningOnInlineSchemas() + public async Task AddsWarningOnInlineSchemas() { - var rule = new MissingDiscriminator(new()); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -62,18 +56,12 @@ public void AddsWarningOnInlineSchemas() properties: type2: type: string"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void AddsWarningOnComponentSchemas() + public async Task AddsWarningOnComponentSchemas() { - var rule = new MissingDiscriminator(new()); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -105,18 +93,12 @@ public void AddsWarningOnComponentSchemas() application/json: schema: $ref: '#/components/schemas/type3'"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void DoesntAddsWarningOnComponentSchemasWithDiscriminatorInformation() + public async Task DoesntAddsWarningOnComponentSchemasWithDiscriminatorInformation() { - var rule = new MissingDiscriminator(new()); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -150,18 +132,12 @@ public void DoesntAddsWarningOnComponentSchemasWithDiscriminatorInformation() application/json: schema: $ref: '#/components/schemas/type3'"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); } [Fact] - public void DoesntAddsWarningOnComponentSchemasScalars() + public async Task DoesntAddsWarningOnComponentSchemasScalars() { - var rule = new MissingDiscriminator(new()); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -185,12 +161,16 @@ public void DoesntAddsWarningOnComponentSchemasScalars() application/json: schema: $ref: '#/components/schemas/type1'"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new MissingDiscriminator(new()); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(MissingDiscriminator), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.OpenApiDiagnostic; } } diff --git a/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs b/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs index 0bbd417140..a4e0934e8b 100644 --- a/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs @@ -1,8 +1,9 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Kiota.Builder.Validation; -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Validations; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader; using Xunit; namespace Kiota.Builder.Tests.Validation; @@ -10,9 +11,8 @@ namespace Kiota.Builder.Tests.Validation; public class MultipleServerEntriesTests { [Fact] - public void AddsAWarningWhenMultipleServersPresent() + public async Task AddsAWarningWhenMultipleServersPresent() { - var rule = new MultipleServerEntries(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -28,18 +28,12 @@ public void AddsAWarningWhenMultipleServersPresent() '200': content: application/json:"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhenSingleServerPresent() + public async Task DoesntAddAWarningWhenSingleServerPresent() { - var rule = new MultipleServerEntries(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -54,12 +48,16 @@ public void DoesntAddAWarningWhenSingleServerPresent() '200': content: application/json:"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new MultipleServerEntries(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(MultipleServerEntries), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.OpenApiDiagnostic; } } diff --git a/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs b/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs index d0924580c3..900228a339 100644 --- a/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs @@ -1,8 +1,9 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Kiota.Builder.Validation; -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Validations; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader; using Xunit; namespace Kiota.Builder.Tests.Validation; @@ -10,9 +11,8 @@ namespace Kiota.Builder.Tests.Validation; public class NoContentWithBodyTests { [Fact] - public void AddsAWarningWhen204WithBody() + public async Task AddsAWarningWhen204WithBody() { - var rule = new NoContentWithBody(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -25,18 +25,12 @@ public void AddsAWarningWhen204WithBody() '204': content: application/json:"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhen204WithNoBody() + public async Task DoesntAddAWarningWhen204WithNoBody() { - var rule = new NoContentWithBody(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -49,18 +43,12 @@ public void DoesntAddAWarningWhen204WithNoBody() get: responses: '204':"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhen200WithBody() + public async Task DoesntAddAWarningWhen200WithBody() { - var rule = new NoContentWithBody(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -77,13 +65,16 @@ public void DoesntAddAWarningWhen200WithBody() '200': content: application/json:"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new NoContentWithBody(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(NoContentWithBody), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.OpenApiDiagnostic; } - } diff --git a/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs b/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs index acae1bf4b3..beeea627c6 100644 --- a/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs @@ -1,8 +1,9 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Kiota.Builder.Validation; -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Validations; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader; using Xunit; namespace Kiota.Builder.Tests.Validation; @@ -10,9 +11,8 @@ namespace Kiota.Builder.Tests.Validation; public class NoServerEntryTests { [Fact] - public void AddsAWarningWhenNoServersPresent() + public async Task AddsAWarningWhenNoServersPresent() { - var rule = new NoServerEntry(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -25,18 +25,12 @@ public void AddsAWarningWhenNoServersPresent() '200': content: application/json:"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhenServerPresent() + public async Task DoesntAddAWarningWhenServerPresent() { - var rule = new NoServerEntry(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -51,12 +45,16 @@ public void DoesntAddAWarningWhenServerPresent() '200': content: application/json:"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new NoServerEntry(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(NoServerEntry), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.OpenApiDiagnostic; } } diff --git a/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs b/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs index a45f0f9498..f74ecbcd80 100644 --- a/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs @@ -1,17 +1,17 @@ using System.IO; using System.Text; +using System.Threading.Tasks; using Kiota.Builder.Validation; -using Microsoft.OpenApi.Readers; -using Microsoft.OpenApi.Validations; +using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Reader; using Xunit; namespace Kiota.Builder.Tests.Validation; public class UrlFormEncodedComplexTests { [Fact] - public void AddsAWarningWhenUrlEncodedNotObjectRequestBody() + public async Task AddsAWarningWhenUrlEncodedNotObjectRequestBody() { - var rule = new UrlFormEncodedComplex(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -33,18 +33,12 @@ public void AddsAWarningWhenUrlEncodedNotObjectRequestBody() schema: type: string format: int32"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void AddsAWarningWhenUrlEncodedNotObjectResponse() + public async Task AddsAWarningWhenUrlEncodedNotObjectResponse() { - var rule = new UrlFormEncodedComplex(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -60,18 +54,12 @@ public void AddsAWarningWhenUrlEncodedNotObjectResponse() schema: type: string format: int32"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void AddsAWarningWhenUrlEncodedComplexPropertyOnRequestBody() + public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnRequestBody() { - var rule = new UrlFormEncodedComplex(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -98,18 +86,12 @@ public void AddsAWarningWhenUrlEncodedComplexPropertyOnRequestBody() schema: type: string format: int32"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() + public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() { - var rule = new UrlFormEncodedComplex(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -130,18 +112,12 @@ public void AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() properties: prop: type: string"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Single(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhenUrlEncoded() + public async Task DoesntAddAWarningWhenUrlEncoded() { - var rule = new UrlFormEncodedComplex(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -159,18 +135,12 @@ public void DoesntAddAWarningWhenUrlEncoded() properties: prop: type: string"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningOnArrayProperty() + public async Task DoesntAddAWarningOnArrayProperty() { - var rule = new UrlFormEncodedComplex(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -199,18 +169,12 @@ public void DoesntAddAWarningOnArrayProperty() properties: prop: type: string"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); } [Fact] - public void DoesntAddAWarningWhenNotUrlEncoded() + public async Task DoesntAddAWarningWhenNotUrlEncoded() { - var rule = new UrlFormEncodedComplex(); var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph @@ -226,12 +190,16 @@ public void DoesntAddAWarningWhenNotUrlEncoded() schema: type: enum format: string"; - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(documentTxt)); - var reader = new OpenApiStreamReader(new OpenApiReaderSettings - { - RuleSet = new(new ValidationRule[] { rule }), - }); - var doc = reader.Read(stream, out var diag); - Assert.Empty(diag.Warnings); + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new UrlFormEncodedComplex(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(UrlFormEncodedComplex), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.OpenApiDiagnostic; } } diff --git a/tests/Kiota.Builder.Tests/Validation/ValidationRuleSetExtensionsTests.cs b/tests/Kiota.Builder.Tests/Validation/ValidationRuleSetExtensionsTests.cs index 7159d17db0..26800d8df4 100644 --- a/tests/Kiota.Builder.Tests/Validation/ValidationRuleSetExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/ValidationRuleSetExtensionsTests.cs @@ -19,7 +19,7 @@ public void DisablesAllRules() var ruleSet = new ValidationRuleSet(); var configuration = new GenerationConfiguration { DisabledValidationRules = new() { "all" } }; ruleSet.AddKiotaValidationRules(configuration); - Assert.Empty(ruleSet); + Assert.Empty(ruleSet.Rules); } [Fact] public void DisablesNoRule() @@ -27,7 +27,7 @@ public void DisablesNoRule() var ruleSet = new ValidationRuleSet(); var configuration = new GenerationConfiguration { DisabledValidationRules = new() }; ruleSet.AddKiotaValidationRules(configuration); - Assert.NotEmpty(ruleSet); + Assert.NotEmpty(ruleSet.Rules); } [Fact] public void DisablesOneRule() @@ -35,7 +35,7 @@ public void DisablesOneRule() var ruleSet = new ValidationRuleSet(); var configuration = new GenerationConfiguration { DisabledValidationRules = new() { nameof(NoServerEntry) } }; ruleSet.AddKiotaValidationRules(configuration); - Assert.NotEmpty(ruleSet); - Assert.DoesNotContain(ruleSet, static x => x.GetType() == typeof(NoServerEntry)); + Assert.NotEmpty(ruleSet.Rules); + Assert.DoesNotContain(ruleSet.Rules, static x => x.GetType() == typeof(NoServerEntry)); } } From 294d80e9fd398ea66825e89bd26213bf2b5a64d1 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 14:32:36 -0500 Subject: [PATCH 11/96] fix: openapi extension migrated to new OAI.net model Signed-off-by: Vincent Biret --- ...piAiReasoningInstructionsExtensionTests.cs | 16 +++++-- ...iAiRespondingInstructionsExtensionTests.cs | 16 +++++-- ...penApiDescriptionForModelExtensionTests.cs | 4 +- .../OpenApiKiotaExtensionTests.cs | 48 ++++++++++--------- 4 files changed, 49 insertions(+), 35 deletions(-) diff --git a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiReasoningInstructionsExtensionTests.cs b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiReasoningInstructionsExtensionTests.cs index 5b34465903..1c511b92f2 100644 --- a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiReasoningInstructionsExtensionTests.cs +++ b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiReasoningInstructionsExtensionTests.cs @@ -1,12 +1,13 @@ using System; using System.IO; using System.Net.Http; +using System.Text; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Kiota.Builder.Configuration; using Kiota.Builder.OpenApiExtensions; using Microsoft.Extensions.Logging; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Writers; using Moq; using Xunit; @@ -22,10 +23,15 @@ public void Dispose() [Fact] public void Parses() { - var oaiValue = new OpenApiArray { - new OpenApiString("This is a description"), - new OpenApiString("This is a description 2"), - }; + var oaiValueRepresentation = + """ + [ + "This is a description", + "This is a description 2", + ] + """; + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(oaiValueRepresentation)); + var oaiValue = JsonNode.Parse(stream); var value = OpenApiAiReasoningInstructionsExtension.Parse(oaiValue); Assert.NotNull(value); Assert.Equal("This is a description", value.ReasoningInstructions[0]); diff --git a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiRespondingInstructionsExtensionTests.cs b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiRespondingInstructionsExtensionTests.cs index d14f85a70e..158f280ea6 100644 --- a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiRespondingInstructionsExtensionTests.cs +++ b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiRespondingInstructionsExtensionTests.cs @@ -1,12 +1,13 @@ using System; using System.IO; using System.Net.Http; +using System.Text; +using System.Text.Json.Nodes; using System.Threading.Tasks; using Kiota.Builder.Configuration; using Kiota.Builder.OpenApiExtensions; using Microsoft.Extensions.Logging; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Writers; using Moq; using Xunit; @@ -22,10 +23,15 @@ public void Dispose() [Fact] public void Parses() { - var oaiValue = new OpenApiArray { - new OpenApiString("This is a description"), - new OpenApiString("This is a description 2"), - }; + var oaiValueRepresentation = + """ + [ + "This is a description", + "This is a description 2", + ] + """; + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(oaiValueRepresentation)); + var oaiValue = JsonNode.Parse(stream); var value = OpenApiAiRespondingInstructionsExtension.Parse(oaiValue); Assert.NotNull(value); Assert.Equal("This is a description", value.RespondingInstructions[0]); diff --git a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiDescriptionForModelExtensionTests.cs b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiDescriptionForModelExtensionTests.cs index bfcec098c2..c81192394a 100644 --- a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiDescriptionForModelExtensionTests.cs +++ b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiDescriptionForModelExtensionTests.cs @@ -6,7 +6,6 @@ using Kiota.Builder.OpenApiExtensions; using Microsoft.Extensions.Logging; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Writers; using Moq; using Xunit; @@ -22,8 +21,7 @@ public void Dispose() [Fact] public void Parses() { - var oaiValue = new OpenApiString("This is a description"); - var value = OpenApiDescriptionForModelExtension.Parse(oaiValue); + var value = OpenApiDescriptionForModelExtension.Parse("This is a description"); Assert.NotNull(value); Assert.Equal("This is a description", value.Description); } diff --git a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiKiotaExtensionTests.cs b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiKiotaExtensionTests.cs index beb4c3fe4f..e7f9dba6f8 100644 --- a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiKiotaExtensionTests.cs +++ b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiKiotaExtensionTests.cs @@ -1,7 +1,8 @@ using System.IO; +using System.Text; +using System.Text.Json.Nodes; using Kiota.Builder.OpenApiExtensions; using Microsoft.OpenApi; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Writers; using Xunit; @@ -48,29 +49,32 @@ public void Serializes() [Fact] public void Parses() { - var oaiValue = new OpenApiObject + var oaiValueRepresentation = + """ { - { "languagesInformation", new OpenApiObject { - {"CSharp", new OpenApiObject { - {"dependencies", new OpenApiArray { - new OpenApiObject { - {"name", new OpenApiString("Microsoft.Graph.Core")}, - {"version", new OpenApiString("1.0.0") }, - {"type", new OpenApiString("bundle")} - } - }}, - {"dependencyInstallCommand", new OpenApiString("dotnet add package") }, - {"maturityLevel", new OpenApiString("Preview")}, - {"clientClassName", new OpenApiString("GraphServiceClient")}, - {"clientNamespaceName", new OpenApiString("Microsoft.Graph")}, - {"structuredMimeTypes", new OpenApiArray { - new OpenApiString("application/json"), - new OpenApiString("application/xml")} - }, - } + "languagesInformation": { + "CSharp": { + "dependencies": [ + { + "name": "Microsoft.Graph.Core", + "version": "1.0.0", + "type": "bundle" + } + ], + "dependencyInstallCommand": "dotnet add package", + "maturityLevel": "Preview", + "clientClassName": "GraphServiceClient", + "clientNamespaceName": "Microsoft.Graph", + "structuredMimeTypes": [ + "application/json", + "application/xml" + ] } - }} - }; + } + } + """; + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(oaiValueRepresentation)); + var oaiValue = JsonNode.Parse(stream); var value = OpenApiKiotaExtension.Parse(oaiValue); Assert.NotNull(value); Assert.True(value.LanguagesInformation.TryGetValue("CSharp", out var CSEntry)); From 2d879383e5d38d01547d8c8aefee257fcbcdb99c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 12 Nov 2024 14:45:35 -0500 Subject: [PATCH 12/96] fix: main tests build Signed-off-by: Vincent Biret --- .../ContentTypeMappingTests.cs | 24 +- .../OpenApiSchemaExtensionsTests.cs | 98 +-- .../OpenApiUrlTreeNodeExtensionsTests.cs | 98 +-- .../Kiota.Builder.Tests/KiotaBuilderTests.cs | 651 +++++++++--------- .../Plugins/PluginsGenerationServiceTests.cs | 71 +- 5 files changed, 469 insertions(+), 473 deletions(-) diff --git a/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs b/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs index 07cd3bd7c4..1c1c020583 100644 --- a/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs +++ b/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs @@ -83,11 +83,11 @@ public void GeneratesTheRightReturnTypeBasedOnContentAndStatus(string contentTyp { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -177,11 +177,11 @@ public void GeneratesTheRightParameterTypeBasedOnContentAndStatus(string content { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -269,11 +269,11 @@ public void GeneratesTheRightAcceptHeaderBasedOnContentAndStatus(string contentM ["200"] = new OpenApiResponse { Content = contentMediaTypes.Split(',').Select(x => new {Key = x.Trim(), value = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -297,11 +297,11 @@ public void GeneratesTheRightAcceptHeaderBasedOnContentAndStatus(string contentM Schemas = new Dictionary { { "myobject", new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -360,11 +360,11 @@ public void GeneratesTheRightContentTypeHeaderBasedOnContentAndStatus(string con { Content = contentMediaTypes.Split(',').Select(x => new {Key = x.Trim(), value = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -387,11 +387,11 @@ public void GeneratesTheRightContentTypeHeaderBasedOnContentAndStatus(string con Schemas = new Dictionary { { "myobject", new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index d0c7a81f9f..02e3288755 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -1,6 +1,6 @@ using System; using System.Collections.Generic; - +using System.Text.Json.Nodes; using Kiota.Builder.Extensions; using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; @@ -49,8 +49,8 @@ public void Defensive() Assert.Null(OpenApiSchemaExtensions.MergeIntersectionSchemaEntries(null)); Assert.False(new OpenApiSchema { Reference = null }.IsReferencedSchema()); - Assert.False(new OpenApiSchema { Type = null }.IsArray()); - Assert.False(new OpenApiSchema { Type = null }.IsObjectType()); + Assert.False(new OpenApiSchema { Type = JsonSchemaType.Null }.IsArray()); + Assert.False(new OpenApiSchema { Type = JsonSchemaType.Null }.IsObjectType()); Assert.False(new OpenApiSchema { AnyOf = null }.IsInclusiveUnion()); Assert.False(new OpenApiSchema { AllOf = null }.IsInherited()); Assert.False(new OpenApiSchema { AllOf = null }.IsIntersection()); @@ -486,7 +486,7 @@ public void IsInherited() { AllOf = new List { new() { - Type = "object", + Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.entity" }, @@ -495,7 +495,7 @@ public void IsInherited() } }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema() } @@ -512,7 +512,7 @@ public void IsIntersection() { AllOf = new List { new() { - Type = "object", + Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.entity" }, @@ -521,7 +521,7 @@ public void IsIntersection() } }, new() { - Type = "object", + Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.user" }, @@ -538,13 +538,13 @@ public void IsIntersection() { AllOf = new List { new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["id"] = new OpenApiSchema() } }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema() } @@ -558,7 +558,7 @@ public void IsIntersection() { AllOf = new List { new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["id"] = new OpenApiSchema() } @@ -577,7 +577,7 @@ public void MergesIntersection() Deprecated = true, AllOf = new List { new() { - Type = "object", + Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.entity" }, @@ -586,7 +586,7 @@ public void MergesIntersection() } }, new() { - Type = "object", + Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.user" }, @@ -613,23 +613,23 @@ public void MergesIntersectionRecursively() Deprecated = true, AllOf = new List { new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["id"] = new OpenApiSchema() } }, new() { - Type = "object", + Type = JsonSchemaType.Object, AllOf = new List() { new () { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), ["lastName"] = new OpenApiSchema() } }, new () { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["lastName"] = new OpenApiSchema() } @@ -652,7 +652,7 @@ public void IsArrayFalseOnEmptyItems() { var schema = new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema(), }; Assert.False(schema.IsArray()); @@ -662,7 +662,7 @@ public void IsArrayFalseOnNullItems() { var schema = new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, }; Assert.False(schema.IsArray()); } @@ -671,27 +671,27 @@ public void IsEnumFailsOnEmptyMembers() { var schema = new OpenApiSchema { - Type = "string", - Enum = new List(), + Type = JsonSchemaType.String, + Enum = new List(), }; Assert.False(schema.IsEnum()); - schema.Enum.Add(new OpenApiString("")); + schema.Enum.Add(""); Assert.False(schema.IsEnum()); } private static readonly OpenApiSchema enumSchema = new OpenApiSchema { Title = "riskLevel", - Enum = new List + Enum = new List { - new OpenApiString("low"), - new OpenApiString("medium"), - new OpenApiString("high"), - new OpenApiString("hidden"), - new OpenApiString("none"), - new OpenApiString("unknownFutureValue") - }, - Type = "string" + "low", + "medium", + "high", + "hidden", + "none", + "unknownFutureValue" + }, + Type = JsonSchemaType.String }; [Fact] public void IsEnumIgnoresNullableUnions() @@ -703,7 +703,7 @@ public void IsEnumIgnoresNullableUnions() enumSchema, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Nullable = true } } @@ -720,7 +720,7 @@ public void IsEnumFailsOnNullableInheritance() enumSchema, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Nullable = true } } @@ -737,7 +737,7 @@ public void IsEnumIgnoresNullableExclusiveUnions() enumSchema, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Nullable = true } } @@ -746,7 +746,7 @@ public void IsEnumIgnoresNullableExclusiveUnions() } private static readonly OpenApiSchema numberSchema = new OpenApiSchema { - Type = "number", + Type = JsonSchemaType.Number, Format = "double", }; [Fact] @@ -760,7 +760,7 @@ public void IsEnumDoesNotMaskExclusiveUnions() numberSchema, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Nullable = true } } @@ -778,7 +778,7 @@ public void IsEnumDoesNotMaskUnions() numberSchema, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Nullable = true } } @@ -794,24 +794,24 @@ public void IsOdataPrimitive() { new () { - Type = "number", + Type = JsonSchemaType.Number, Format = "double", Nullable = true }, new () { - Type = "string", + Type = JsonSchemaType.String, Nullable = true }, new () { - Enum = new List() + Enum = new List { - new OpenApiString("INF"), - new OpenApiString("INF"), - new OpenApiString("NaN"), + "INF", + "INF", + "NaN", }, - Type = "string", + Type = JsonSchemaType.String, Nullable = true } } @@ -827,20 +827,20 @@ public void IsOdataPrimitiveBackwardCompatible() { new () { - Type = "number", + Type = JsonSchemaType.Number, Format = "double", }, new () { - Type = "string", + Type = JsonSchemaType.String, }, new () { - Enum = new List() + Enum = new List() { - new OpenApiString("INF"), - new OpenApiString("INF"), - new OpenApiString("NaN"), + "INF", + "INF", + "NaN", } } } diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs index 718248ee2f..0a073478b1 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs @@ -145,7 +145,7 @@ public void GetUrlTemplateSelectsDistinctQueryParameters() In = ParameterLocation.Path, Required = true, Schema = new() { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, @@ -153,7 +153,7 @@ public void GetUrlTemplateSelectsDistinctQueryParameters() Name = "$select", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, } @@ -168,7 +168,7 @@ public void GetUrlTemplateSelectsDistinctQueryParameters() In = ParameterLocation.Path, Required = true, Schema = new() { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, @@ -176,7 +176,7 @@ public void GetUrlTemplateSelectsDistinctQueryParameters() Name = "$select", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, } @@ -206,7 +206,7 @@ public void DifferentUrlTemplatesPerOperation() Required = true, Schema = new() { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, @@ -219,7 +219,7 @@ public void DifferentUrlTemplatesPerOperation() Name = "$select", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, } @@ -256,7 +256,7 @@ public void DifferentUrlTemplatesPerOperationWithRequiredParameter() Required = true, Schema = new() { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, @@ -269,7 +269,7 @@ public void DifferentUrlTemplatesPerOperationWithRequiredParameter() Name = "$select", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, } @@ -283,7 +283,7 @@ public void DifferentUrlTemplatesPerOperationWithRequiredParameter() Name = "$expand", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, } @@ -300,7 +300,7 @@ public void DifferentUrlTemplatesPerOperationWithRequiredParameter() Name = "id", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, Required = true @@ -335,7 +335,7 @@ public void GeneratesRequiredQueryParametersAndOptionalMixInPathItem() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { @@ -343,7 +343,7 @@ public void GeneratesRequiredQueryParametersAndOptionalMixInPathItem() In = ParameterLocation.Query, Required = false, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { @@ -351,7 +351,7 @@ public void GeneratesRequiredQueryParametersAndOptionalMixInPathItem() In = ParameterLocation.Query, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -381,7 +381,7 @@ public void GeneratesRequiredQueryParametersAndOptionalMixInOperation() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { @@ -389,7 +389,7 @@ public void GeneratesRequiredQueryParametersAndOptionalMixInOperation() In = ParameterLocation.Query, Required = false, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { @@ -397,7 +397,7 @@ public void GeneratesRequiredQueryParametersAndOptionalMixInOperation() In = ParameterLocation.Query, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -423,7 +423,7 @@ public void GeneratesOnlyOptionalQueryParametersInPathItem() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { @@ -431,14 +431,14 @@ public void GeneratesOnlyOptionalQueryParametersInPathItem() In = ParameterLocation.Query, Required = false, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { Name = "apikey", In = ParameterLocation.Query, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -468,21 +468,21 @@ public void GeneratesOnlyOptionalQueryParametersInOperation() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { Name = "filter", In = ParameterLocation.Query, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { Name = "apikey", In = ParameterLocation.Query, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -508,7 +508,7 @@ public void GeneratesOnlyRequiredQueryParametersInPathItem() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { @@ -516,7 +516,7 @@ public void GeneratesOnlyRequiredQueryParametersInPathItem() In = ParameterLocation.Query, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { @@ -524,7 +524,7 @@ public void GeneratesOnlyRequiredQueryParametersInPathItem() Required = true, In = ParameterLocation.Query, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -554,7 +554,7 @@ public void GeneratesOnlyRequiredQueryParametersInOperation() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { @@ -562,7 +562,7 @@ public void GeneratesOnlyRequiredQueryParametersInOperation() Required = true, In = ParameterLocation.Query, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter { @@ -570,7 +570,7 @@ public void GeneratesOnlyRequiredQueryParametersInOperation() Required = true, In = ParameterLocation.Query, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -599,7 +599,7 @@ public void GetUrlTemplateCleansInvalidParameters() In = ParameterLocation.Path, Required = true, Schema = new() { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, @@ -607,7 +607,7 @@ public void GetUrlTemplateCleansInvalidParameters() Name = "$select", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, @@ -615,7 +615,7 @@ public void GetUrlTemplateCleansInvalidParameters() Name = "api-version", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, @@ -623,7 +623,7 @@ public void GetUrlTemplateCleansInvalidParameters() Name = "api~topic", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, @@ -631,7 +631,7 @@ public void GetUrlTemplateCleansInvalidParameters() Name = "api.encoding", In = ParameterLocation.Query, Schema = new () { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, } @@ -669,7 +669,7 @@ public void GetsClassNameWithIndexerAndExtension() In = ParameterLocation.Path, Required = true, Schema = new() { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, } @@ -679,7 +679,7 @@ public void GetsClassNameWithIndexerAndExtension() Content = new Dictionary() { {"application/json", new() { Schema = new () { - Type = "string" + Type = JsonSchemaType.String } }} } @@ -711,7 +711,7 @@ public void GetsClassNameWithSegmentsToSkipForClassNames() In = ParameterLocation.Path, Required = true, Schema = new() { - Type = "string" + Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, } @@ -728,7 +728,7 @@ public void GetsClassNameWithSegmentsToSkipForClassNames() { Schema = new () { - Type = "object", + Type = JsonSchemaType.Object, Title = "json", Reference = new OpenApiReference() { @@ -763,16 +763,16 @@ public void SinglePathParametersAreDeduplicated() { var userSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "displayName", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -794,7 +794,7 @@ public void SinglePathParametersAreDeduplicated() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, }, @@ -823,7 +823,7 @@ public void SinglePathParametersAreDeduplicated() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, }, @@ -855,7 +855,7 @@ public void SinglePathParametersAreDeduplicated() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, }, @@ -912,11 +912,11 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() { var ownerSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -928,11 +928,11 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() }; var repoSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -1023,7 +1023,7 @@ public void repro4085() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -1044,7 +1044,7 @@ public void repro4085() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 606bbe5c62..d1dbc550d3 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Net.Http; using System.Text; +using System.Text.Json.Nodes; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -1354,10 +1355,10 @@ public void Single_path_with_get_collection() { Schema = new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "int" + Type = JsonSchemaType.Integer } } } @@ -1399,19 +1400,19 @@ public void OData_doubles_as_one_of() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ OneOf = new List{ new OpenApiSchema{ - Type = "number" + Type = JsonSchemaType.Number }, new OpenApiSchema{ - Type = "string" + Type = JsonSchemaType.String }, new OpenApiSchema { - Enum = new List { new OpenApiString("-INF"), new OpenApiString("INF"), new OpenApiString("NaN") } + Enum = new List { "-INF", "INF", "NaN" } } }, Format = "double" @@ -1451,20 +1452,20 @@ public void OData_doubles_as_one_of_format_inside() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ OneOf = new List{ new OpenApiSchema{ - Type = "number", + Type = JsonSchemaType.Number, Format = "double" }, new OpenApiSchema{ - Type = "string" + Type = JsonSchemaType.String }, new OpenApiSchema { - Enum = new List { new OpenApiString("-INF"), new OpenApiString("INF"), new OpenApiString("NaN") } + Enum = new List { "-INF", "INF", "NaN" } } }, } @@ -1503,19 +1504,19 @@ public void OData_doubles_as_any_of() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ AnyOf = new List{ new OpenApiSchema{ - Type = "number" + Type = JsonSchemaType.Number }, new OpenApiSchema{ - Type = "string" + Type = JsonSchemaType.String }, new OpenApiSchema { - Enum = new List { new OpenApiString("-INF"), new OpenApiString("INF"), new OpenApiString("NaN") } + Enum = new List { "-INF", "INF", "NaN" } } }, Format = "double" @@ -1541,15 +1542,15 @@ public void MultiNestedArraysSupportedAsUntypedNodes() { var fooSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "sortBy", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -1609,16 +1610,16 @@ public void Object_Arrays_are_supported() { var userSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "displayName", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -1644,17 +1645,17 @@ public void Object_Arrays_are_supported() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "value", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = userSchema } }, { "unknown", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { } } @@ -1711,7 +1712,7 @@ public void TextPlainEndpointsAreSupported() ["text/plain"] = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "number", + Type = JsonSchemaType.Number, Format = "int32", } } @@ -1740,22 +1741,22 @@ public void Supports_Path_Parameters() { var resourceActionSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Title = "resourceAction", Properties = new Dictionary { { "allowedResourceActions", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, { "notAllowedResourceActions", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -1768,11 +1769,11 @@ public void Supports_Path_Parameters() }; var permissionSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "resourceActions", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { AnyOf = new List { resourceActionSchema, @@ -1800,7 +1801,7 @@ public void Supports_Path_Parameters() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -1814,7 +1815,7 @@ public void Supports_Path_Parameters() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { AnyOf = new List { permissionSchema, @@ -1861,22 +1862,22 @@ public void Supports_Path_Query_And_Header_Parameters() { var resourceActionSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Title = "resourceAction", Properties = new Dictionary { { "allowedResourceActions", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, { "notAllowedResourceActions", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -1889,11 +1890,11 @@ public void Supports_Path_Query_And_Header_Parameters() }; var permissionSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "resourceActions", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { AnyOf = new List { resourceActionSchema, @@ -1921,7 +1922,7 @@ public void Supports_Path_Query_And_Header_Parameters() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter @@ -1930,7 +1931,7 @@ public void Supports_Path_Query_And_Header_Parameters() In = ParameterLocation.Query, Required = false, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }, }, new OpenApiParameter @@ -1940,7 +1941,7 @@ public void Supports_Path_Query_And_Header_Parameters() Description = "ETag", Required = false, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }, }, new OpenApiParameter @@ -1950,7 +1951,7 @@ public void Supports_Path_Query_And_Header_Parameters() Description = "Consistency level", Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }, } }, @@ -1964,7 +1965,7 @@ public void Supports_Path_Query_And_Header_Parameters() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { AnyOf = new List { permissionSchema, @@ -2031,7 +2032,7 @@ public void DeduplicatesConflictingParameterNamesForCLI() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, new OpenApiParameter @@ -2040,7 +2041,7 @@ public void DeduplicatesConflictingParameterNamesForCLI() In = ParameterLocation.Query, Required = false, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }, }, new OpenApiParameter @@ -2049,7 +2050,7 @@ public void DeduplicatesConflictingParameterNamesForCLI() In = ParameterLocation.Header, Required = false, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }, }, }, @@ -2063,10 +2064,10 @@ public void DeduplicatesConflictingParameterNamesForCLI() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { { "foo", new() { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -2105,11 +2106,11 @@ public void Inline_Property_Inheritance_Is_Supported() { var resourceSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "info", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -2135,19 +2136,19 @@ public void Inline_Property_Inheritance_Is_Supported() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "derivedResource", new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "info2", new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "title", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } } @@ -2203,7 +2204,7 @@ public void Inline_Property_Inheritance_Is_Supported2() { var resourceSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Reference = new OpenApiReference { Id = "resource" @@ -2213,7 +2214,7 @@ public void Inline_Property_Inheritance_Is_Supported2() var properties = new Dictionary { - { "info", new OpenApiSchema { Type = "string", } }, + { "info", new OpenApiSchema { Type = JsonSchemaType.String, } }, { "derivedResource", new OpenApiSchema { AllOf = new List { resourceSchema, } } }, }; @@ -2289,11 +2290,11 @@ public void MapsTime() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, Format = "time" } } @@ -2331,11 +2332,11 @@ public void MapsDate() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, Format = "date" } } @@ -2373,11 +2374,11 @@ public void MapsDuration() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, Format = "duration" } } @@ -2415,11 +2416,11 @@ public void AddsErrorMapping() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, } } } @@ -2435,11 +2436,11 @@ public void AddsErrorMapping() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "errorId", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, Extensions = new Dictionary { { OpenApiPrimaryErrorMessageExtension.Name, @@ -2463,11 +2464,11 @@ public void AddsErrorMapping() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "serviceErrorId", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, Extensions = new Dictionary { { OpenApiPrimaryErrorMessageExtension.Name, @@ -2491,7 +2492,7 @@ public void AddsErrorMapping() { Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -2504,11 +2505,11 @@ public void AddsErrorMapping() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "authenticationRealm", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, Extensions = new Dictionary { { OpenApiPrimaryErrorMessageExtension.Name, @@ -2521,7 +2522,7 @@ public void AddsErrorMapping() }, { "authenticationCode", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, } } } @@ -2585,11 +2586,11 @@ public void IgnoresErrorCodesWithNoSchema() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, } } } @@ -2634,11 +2635,11 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() { var errorSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "errorId", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -2684,11 +2685,11 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, } } } @@ -2744,11 +2745,11 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() { var errorSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "errorId", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -2794,11 +2795,11 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() { Schema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "progress", new OpenApiSchema{ - Type = "string", + Type = JsonSchemaType.String, } } } @@ -2853,18 +2854,18 @@ public void DoesntAddPropertyHolderOnNonAdditionalModels() { var weatherForecastSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, Properties = new Dictionary { { "date", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, Format = "date-time" } }, { "temperature", new OpenApiSchema { - Type = "integer", + Type = JsonSchemaType.Integer, Format = "int32" } } @@ -2938,18 +2939,18 @@ public void SquishesLonelyNullables() { var uploadSessionSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, Properties = new Dictionary { { "date", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, Format = "date-time" } }, { "temperature", new OpenApiSchema { - Type = "integer", + Type = JsonSchemaType.Integer, Format = "int32" } } @@ -3022,18 +3023,18 @@ public void SquishesLonelyNullablesBothAnyOf() { var uploadSessionSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, Properties = new Dictionary { { "date", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, Format = "date-time" } }, { "temperature", new OpenApiSchema { - Type = "integer", + Type = JsonSchemaType.Integer, Format = "int32" } } @@ -3108,19 +3109,19 @@ public void SupportsArraysInComposedTypes() { var anyOfSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, Properties = new Dictionary { { "date", new OpenApiSchema { AnyOf = [ new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, }, new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, }, }, ] @@ -3191,18 +3192,18 @@ public void SupportsNullableAnyOf() { var anyOfSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, Properties = new Dictionary { { "date", new OpenApiSchema { AnyOf = [ new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, Nullable = true }, new OpenApiSchema { - Type = "number", + Type = JsonSchemaType.Number, Format = "int64", Nullable = true, } @@ -3275,17 +3276,17 @@ public void AddsDiscriminatorMappings() { var entitySchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("#microsoft.graph.entity") + Type = JsonSchemaType.String, + Default = "#microsoft.graph.entity" } } }, @@ -3310,16 +3311,16 @@ public void AddsDiscriminatorMappings() }; var directoryObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "tenant", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("#microsoft.graph.directoryObject") + Type = JsonSchemaType.String, + Default = "#microsoft.graph.directoryObject" } } }, @@ -3410,17 +3411,17 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() { var entitySchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("#microsoft.graph.entity") + Type = JsonSchemaType.String, + Default = "#microsoft.graph.entity" } } }, @@ -3448,16 +3449,16 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() }; var directoryObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "tenant", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("#microsoft.graph.directoryObject") + Type = JsonSchemaType.String, + Default = "#microsoft.graph.directoryObject" } } }, @@ -3473,16 +3474,16 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() }; var fileSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "tenant", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("#microsoft.graph.file") + Type = JsonSchemaType.String, + Default = "#microsoft.graph.file" } } }, @@ -3562,17 +3563,17 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() { var entitySchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("microsoft.graph.entity") + Type = JsonSchemaType.String, + Default = "microsoft.graph.entity" } } }, @@ -3592,16 +3593,16 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() }; var directoryObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "tenant", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("microsoft.graph.directoryObject") + Type = JsonSchemaType.String, + Default = "microsoft.graph.directoryObject" } } }, @@ -3617,7 +3618,7 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() }; var directoryObjectsResponse = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, OneOf = new List { entitySchema, directoryObjectSchema @@ -3705,17 +3706,17 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() { var entitySchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("#microsoft.graph.entity") + Type = JsonSchemaType.String, + Default = "#microsoft.graph.entity" } } }, @@ -3735,19 +3736,19 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() }; var directoryObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AllOf = new List { entitySchema, new OpenApiSchema { Properties = new Dictionary { { "tenant", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("microsoft.graph.directoryObject") + Type = JsonSchemaType.String, + Default = "microsoft.graph.directoryObject" } } }, @@ -3765,19 +3766,19 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() }; var userSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AllOf = new List { directoryObjectSchema, new OpenApiSchema { Properties = new Dictionary { { "firstName", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("microsoft.graph.firstName") + Type = JsonSchemaType.String, + Default = "microsoft.graph.firstName" } } }, @@ -3883,17 +3884,17 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings { var entitySchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("#microsoft.graph.entity") + Type = JsonSchemaType.String, + Default = "#microsoft.graph.entity" } } }, @@ -3922,7 +3923,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings }; var directoryObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AllOf = [ entitySchema, new OpenApiSchema @@ -3930,12 +3931,12 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings Properties = new Dictionary { { "tenant", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("microsoft.graph.directoryObject") + Type = JsonSchemaType.String, + Default = "microsoft.graph.directoryObject" } } }, @@ -3953,7 +3954,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings }; var userSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AllOf = [ directoryObjectSchema, new OpenApiSchema @@ -3961,12 +3962,12 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings Properties = new Dictionary { { "firstName", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "@odata.type", new OpenApiSchema { - Type = "string", - Default = new OpenApiString("microsoft.graph.firstName") + Type = JsonSchemaType.String, + Default = "microsoft.graph.firstName" } } }, @@ -4064,11 +4065,11 @@ public void UnionOfPrimitiveTypesWorks() { var simpleObjet = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -4097,7 +4098,7 @@ public void UnionOfPrimitiveTypesWorks() OneOf = new List { simpleObjet, new OpenApiSchema { - Type = "number" + Type = JsonSchemaType.Number } } } @@ -4182,11 +4183,11 @@ public void UnionOfInlineSchemasWorks() { var simpleObjet = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -4215,11 +4216,11 @@ public void UnionOfInlineSchemasWorks() OneOf = new List { simpleObjet, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -4265,11 +4266,11 @@ public void IntersectionOfPrimitiveTypesWorks() { var simpleObjet = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -4298,7 +4299,7 @@ public void IntersectionOfPrimitiveTypesWorks() AnyOf = new List { simpleObjet, new OpenApiSchema { - Type = "number" + Type = JsonSchemaType.Number } } } @@ -4341,11 +4342,11 @@ public void IntersectionOfInlineSchemasWorks() { var simpleObjet = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -4374,11 +4375,11 @@ public void IntersectionOfInlineSchemasWorks() AnyOf = new List { simpleObjet, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -4424,16 +4425,16 @@ public void InheritedTypeWithInlineSchemaWorks() { var baseObject = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "kind", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -4455,16 +4456,16 @@ public void InheritedTypeWithInlineSchemaWorks() }; var derivedObject = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AllOf = [ baseObject, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "special", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -4488,16 +4489,16 @@ public void InheritedTypeWithInlineSchemaWorks() }; var secondLevelDerivedObject = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AllOf = [ derivedObject, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "moreSpecial", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -4568,38 +4569,37 @@ public void InheritedTypeWithInlineSchemaWorks() Assert.Equal("kind", derivedObjectClass.DiscriminatorInformation.DiscriminatorPropertyName); Assert.NotEmpty(derivedObjectClass.DiscriminatorInformation.DiscriminatorMappings); } - [InlineData("string", "", "string")]// https://spec.openapis.org/registry/format/ - [InlineData("string", "commonmark", "string")] - [InlineData("string", "html", "string")] - [InlineData("string", "date-time", "DateTimeOffset")] - [InlineData("string", "duration", "TimeSpan")] - [InlineData("string", "date", "DateOnly")] - [InlineData("string", "time", "TimeOnly")] - [InlineData("string", "base64url", "base64url")] - [InlineData("string", "uuid", "Guid")] + [InlineData(JsonSchemaType.String, "", "string")]// https://spec.openapis.org/registry/format/ + [InlineData(JsonSchemaType.String, "commonmark", "string")] + [InlineData(JsonSchemaType.String, "html", "string")] + [InlineData(JsonSchemaType.String, "date-time", "DateTimeOffset")] + [InlineData(JsonSchemaType.String, "duration", "TimeSpan")] + [InlineData(JsonSchemaType.String, "date", "DateOnly")] + [InlineData(JsonSchemaType.String, "time", "TimeOnly")] + [InlineData(JsonSchemaType.String, "base64url", "base64url")] + [InlineData(JsonSchemaType.String, "uuid", "Guid")] // floating points can only be declared as numbers - [InlineData("number", "double", "double")] - [InlineData("number", "float", "float")] - [InlineData("number", "decimal", "decimal")] + [InlineData(JsonSchemaType.Number, "double", "double")] + [InlineData(JsonSchemaType.Number, "float", "float")] + [InlineData(JsonSchemaType.Number, "decimal", "decimal")] // integers can only be declared as numbers or integers - [InlineData("number", "int32", "integer")] - [InlineData("integer", "int32", "integer")] - [InlineData("number", "int64", "int64")] - [InlineData("integer", "int64", "int64")] - [InlineData("number", "int8", "sbyte")] - [InlineData("integer", "int8", "sbyte")] - [InlineData("number", "int16", "integer")] - [InlineData("integer", "int16", "integer")] - [InlineData("number", "uint8", "byte")] - [InlineData("integer", "uint8", "byte")] - [InlineData("number", "", "double")] - [InlineData("integer", "", "integer")] - [InlineData("boolean", "", "boolean")] - [InlineData("", "byte", "base64")] - [InlineData("", "binary", "binary")] - [InlineData("file", null, "binary")] + [InlineData(JsonSchemaType.Number, "int32", "integer")] + [InlineData(JsonSchemaType.Integer, "int32", "integer")] + [InlineData(JsonSchemaType.Number, "int64", "int64")] + [InlineData(JsonSchemaType.Integer, "int64", "int64")] + [InlineData(JsonSchemaType.Number, "int8", "sbyte")] + [InlineData(JsonSchemaType.Integer, "int8", "sbyte")] + [InlineData(JsonSchemaType.Number, "int16", "integer")] + [InlineData(JsonSchemaType.Integer, "int16", "integer")] + [InlineData(JsonSchemaType.Number, "uint8", "byte")] + [InlineData(JsonSchemaType.Integer, "uint8", "byte")] + [InlineData(JsonSchemaType.Number, "", "double")] + [InlineData(JsonSchemaType.Integer, "", "integer")] + [InlineData(JsonSchemaType.Boolean, "", "boolean")] + [InlineData(JsonSchemaType.String, "byte", "base64")] + [InlineData(JsonSchemaType.String, "binary", "binary")] [Theory] - public void MapsPrimitiveFormats(string type, string format, string expected) + public void MapsPrimitiveFormats(JsonSchemaType type, string format, string expected) { var document = new OpenApiDocument { @@ -4639,35 +4639,34 @@ public void MapsPrimitiveFormats(string type, string format, string expected) Assert.Equal(expected, method.ReturnType.Name); Assert.True(method.ReturnType.AllTypes.First().IsExternal); } - [InlineData("string", "", "string")]// https://spec.openapis.org/registry/format/ - [InlineData("string", "commonmark", "string")] - [InlineData("string", "html", "string")] - [InlineData("string", "date-time", "DateTimeOffset")] - [InlineData("string", "duration", "TimeSpan")] - [InlineData("string", "date", "DateOnly")] - [InlineData("string", "time", "TimeOnly")] - [InlineData("string", "base64url", "base64url")] + [InlineData(JsonSchemaType.String, "", "string")]// https://spec.openapis.org/registry/format/ + [InlineData(JsonSchemaType.String, "commonmark", "string")] + [InlineData(JsonSchemaType.String, "html", "string")] + [InlineData(JsonSchemaType.String, "date-time", "DateTimeOffset")] + [InlineData(JsonSchemaType.String, "duration", "TimeSpan")] + [InlineData(JsonSchemaType.String, "date", "DateOnly")] + [InlineData(JsonSchemaType.String, "time", "TimeOnly")] + [InlineData(JsonSchemaType.String, "base64url", "base64url")] // floating points can only be declared as numbers - [InlineData("number", "double", "double")] - [InlineData("number", "float", "float")] - [InlineData("number", "decimal", "decimal")] + [InlineData(JsonSchemaType.Number, "double", "double")] + [InlineData(JsonSchemaType.Number, "float", "float")] + [InlineData(JsonSchemaType.Number, "decimal", "decimal")] // integers can only be declared as numbers or integers - [InlineData("number", "int32", "integer")] - [InlineData("integer", "int32", "integer")] - [InlineData("number", "int64", "int64")] - [InlineData("integer", "int64", "int64")] - [InlineData("number", "int8", "sbyte")] - [InlineData("integer", "int8", "sbyte")] - [InlineData("number", "uint8", "byte")] - [InlineData("integer", "uint8", "byte")] - [InlineData("number", "", "double")] - [InlineData("integer", "", "integer")] - [InlineData("boolean", "", "boolean")] - [InlineData("", "byte", "base64")] - [InlineData("", "binary", "binary")] - [InlineData("file", null, "binary")] + [InlineData(JsonSchemaType.Number, "int32", "integer")] + [InlineData(JsonSchemaType.Integer, "int32", "integer")] + [InlineData(JsonSchemaType.Number, "int64", "int64")] + [InlineData(JsonSchemaType.Integer, "int64", "int64")] + [InlineData(JsonSchemaType.Number, "int8", "sbyte")] + [InlineData(JsonSchemaType.Integer, "int8", "sbyte")] + [InlineData(JsonSchemaType.Number, "uint8", "byte")] + [InlineData(JsonSchemaType.Integer, "uint8", "byte")] + [InlineData(JsonSchemaType.Number, "", "double")] + [InlineData(JsonSchemaType.Integer, "", "integer")] + [InlineData(JsonSchemaType.Boolean, "", "boolean")] + [InlineData(JsonSchemaType.String, "byte", "base64")] + [InlineData(JsonSchemaType.String, "binary", "binary")] [Theory] - public void MapsQueryParameterTypes(string type, string format, string expected) + public void MapsQueryParameterTypes(JsonSchemaType type, string format, string expected) { var document = new OpenApiDocument { @@ -4725,9 +4724,9 @@ public void MapsQueryParameterArrayTypes() Name = "query", In = ParameterLocation.Query, Schema = new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "integer", + Type = JsonSchemaType.Integer, Format = "int64" } } @@ -4773,10 +4772,10 @@ public void MapsEnumQueryParameterType(GenerationLanguage generationLanguage) Name = "query", In = ParameterLocation.Query, Schema = new OpenApiSchema { - Type = "string", - Enum = new List { - new OpenApiString("value1"), - new OpenApiString("value2") + Type = JsonSchemaType.String, + Enum = new List { + "value1", + "value2" } } } @@ -4883,12 +4882,12 @@ public void MapsQueryParameterCollectionKinds(bool isArray) { var baseSchema = new OpenApiSchema { - Type = "number", + Type = JsonSchemaType.Number, Format = "int64" }; var arraySchema = new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = baseSchema }; var document = new OpenApiDocument @@ -4971,11 +4970,11 @@ public void DoesntGenerateNamespacesWhenNotRequired() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -5034,11 +5033,11 @@ public void GeneratesNamesapacesWhenRequired() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -5097,11 +5096,11 @@ public void IdsResultInIndexers() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -5164,25 +5163,25 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() var enumSchema = new OpenApiSchema { Title = "riskLevel", - Enum = new List + Enum = new List { - new OpenApiString("low"), - new OpenApiString("medium"), - new OpenApiString("high"), - new OpenApiString("hidden"), - new OpenApiString("none"), - new OpenApiString("unknownFutureValue") + "low", + "medium", + "high", + "hidden", + "none", + "unknownFutureValue" }, - Type = "string" + Type = JsonSchemaType.String }; var myObjectSchema = new OpenApiSchema { Title = "conditionalAccessConditionSet", - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "signInRiskLevels", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { AnyOf = new List @@ -5190,7 +5189,7 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() enumSchema, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Nullable = true } } @@ -5264,25 +5263,25 @@ public void HandlesCollectionOfEnumSchemas() var enumSchema = new OpenApiSchema { Title = "riskLevel", - Enum = new List + Enum = new List { - new OpenApiString("low"), - new OpenApiString("medium"), - new OpenApiString("high"), - new OpenApiString("hidden"), - new OpenApiString("none"), - new OpenApiString("unknownFutureValue") + "low", + "medium", + "high", + "hidden", + "none", + "unknownFutureValue" }, - Type = "string" + Type = JsonSchemaType.String }; var myObjectSchema = new OpenApiSchema { Title = "conditionalAccessConditionSet", - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "signInRiskLevels", new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = enumSchema } } @@ -5352,13 +5351,13 @@ public void InlinePropertiesGenerateTypes() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "tilleggsinformasjon", new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, AdditionalProperties = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -5419,11 +5418,11 @@ public void ModelsDoesntUsePathDescriptionWhenAvailable() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -5485,11 +5484,11 @@ public void CleansUpInvalidDescriptionCharacters() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -5553,11 +5552,11 @@ public void AcceptVendorsTypes(string contentType) { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -5640,7 +5639,7 @@ public void ModelsUseDescriptionWhenAvailable(bool excludeBackwardCompatible) Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } } @@ -5693,11 +5692,11 @@ public void Considers200WithSchemaOver2XXWithSchema() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -5710,11 +5709,11 @@ public void Considers200WithSchemaOver2XXWithSchema() }; var myOtherObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -5788,11 +5787,11 @@ public void Considers2XXWithSchemaOver204WithNoSchema() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -5861,11 +5860,11 @@ public void Considers204WithNoSchemaOver206WithNoSchema() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -5934,11 +5933,11 @@ public void DoesntGenerateVoidExecutorOnMixedNoContent(int statusCode) { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6006,11 +6005,11 @@ public void GeneratesVoidReturnTypeForNoContent(int statusCode) { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6081,11 +6080,11 @@ public void StripsCommonModelsPrefix(string[] componentNames, string stripPrefix { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6129,11 +6128,11 @@ public void HandlesContentParameters() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6162,9 +6161,9 @@ public void HandlesContentParameters() { "application/json", new OpenApiMediaType { Schema = new OpenApiSchema { - Type = "array", + Type = JsonSchemaType.Array, Items = new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } } @@ -6216,11 +6215,11 @@ public void HandlesPagingExtension() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6285,11 +6284,11 @@ public void SetsReadonlyProperties(bool isReadonly) { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, ReadOnly = isReadonly, } } @@ -6349,11 +6348,11 @@ public void SupportsIncludeFilterOnRootPath(string inputPattern, int expectedPat { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6414,11 +6413,11 @@ public void SupportsIncludeFilter() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6499,11 +6498,11 @@ public void SupportsExcludeFilter() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6584,11 +6583,11 @@ public void SupportsIncludeFilterWithOperation() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6739,11 +6738,11 @@ public void SupportsIndexingParametersInSubPaths() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -6769,7 +6768,7 @@ public void SupportsIndexingParametersInSubPaths() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -7210,16 +7209,16 @@ public void AddReservedPathParameterSymbol() { var userSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "displayName", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -7241,7 +7240,7 @@ public void AddReservedPathParameterSymbol() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }, Extensions = { ["x-ms-reserved-parameter"] = new OpenApiReservedParameterExtension { @@ -7292,16 +7291,16 @@ public void DoesNotAddReservedPathParameterSymbol() { var userSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "id", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } }, { "displayName", new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String } } }, @@ -7323,7 +7322,7 @@ public void DoesNotAddReservedPathParameterSymbol() In = ParameterLocation.Path, Required = true, Schema = new OpenApiSchema { - Type = "string" + Type = JsonSchemaType.String }, Extensions = { ["x-ms-reserved-parameter"] = new OpenApiReservedParameterExtension { @@ -9265,11 +9264,11 @@ public void SupportsIncludeFilterAndExcludeWithOperation() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -9410,11 +9409,11 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -9555,11 +9554,11 @@ public void CleansUpOperationIdAddsMissingOperationId() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, @@ -9657,11 +9656,11 @@ public void CleansUpOperationIdChangesOperationId() { var myObjectSchema = new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { { "name", new OpenApiSchema { - Type = "string", + Type = JsonSchemaType.String, } } }, diff --git a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs index 3f74656037..73dddb3268 100644 --- a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs @@ -9,7 +9,7 @@ using Kiota.Builder.Plugins; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; -using Microsoft.OpenApi.Readers; +using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Services; using Microsoft.Plugins.Manifest; using Moq; @@ -242,38 +242,36 @@ public async Task GeneratesManifestAndCleansUpInputDescriptionAsync() Assert.Equal(2, resultingManifest.Document.Capabilities.ConversationStarters.Count);// conversation starters are generated for each function Assert.Empty(resultingManifest.Problems);// no problems are expected with names - var openApiReader = new OpenApiStreamReader(); - // Validate the original file. - var originalOpenApiFile = File.OpenRead(simpleDescriptionPath); - var originalDocument = openApiReader.Read(originalOpenApiFile, out var originalDiagnostic); - Assert.Empty(originalDiagnostic.Errors); - - Assert.Equal(originalDocument.Paths["/test"].Operations[OperationType.Get].Description, resultingManifest.Document.Functions[0].Description);// pulls from description - Assert.Equal(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Summary, resultingManifest.Document.Functions[1].Description);// pulls from summary - Assert.Single(originalDocument.Components.Schemas);// one schema originally - Assert.Single(originalDocument.Extensions); // single unsupported extension at root - Assert.Equal(2, originalDocument.Paths.Count); // document has only two paths - Assert.Equal(2, originalDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count); // 2 responses originally - Assert.Single(originalDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // 1 UNsupported extension - Assert.Equal(2, originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count); // 2 responses originally - Assert.Single(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension + using var originalOpenApiFile = File.OpenRead(simpleDescriptionPath); + var originalResult = await OpenApiDocument.LoadAsync(originalOpenApiFile, "yaml"); + Assert.Empty(originalResult.OpenApiDiagnostic.Errors); + + Assert.Equal(originalResult.OpenApiDocument.Paths["/test"].Operations[OperationType.Get].Description, resultingManifest.Document.Functions[0].Description);// pulls from description + Assert.Equal(originalResult.OpenApiDocument.Paths["/test/{id}"].Operations[OperationType.Get].Summary, resultingManifest.Document.Functions[1].Description);// pulls from summary + Assert.Single(originalResult.OpenApiDocument.Components.Schemas);// one schema originally + Assert.Single(originalResult.OpenApiDocument.Extensions); // single unsupported extension at root + Assert.Equal(2, originalResult.OpenApiDocument.Paths.Count); // document has only two paths + Assert.Equal(2, originalResult.OpenApiDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count); // 2 responses originally + Assert.Single(originalResult.OpenApiDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // 1 UNsupported extension + Assert.Equal(2, originalResult.OpenApiDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count); // 2 responses originally + Assert.Single(originalResult.OpenApiDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension // Validate the output open api file - var resultOpenApiFile = File.OpenRead(Path.Combine(outputDirectory, OpenApiFileName)); - var resultDocument = openApiReader.Read(resultOpenApiFile, out var diagnostic); - Assert.Empty(diagnostic.Errors); + using var resultOpenApiFile = File.OpenRead(Path.Combine(outputDirectory, OpenApiFileName)); + var resultResult = await OpenApiDocument.LoadAsync(originalOpenApiFile, "yaml"); + Assert.Empty(resultResult.OpenApiDiagnostic.Errors); // Assertions / validations - Assert.Empty(resultDocument.Components.Schemas);// no schema is referenced. so ensure they are all removed - Assert.Empty(resultDocument.Extensions); // no extension at root (unsupported extension is removed) - Assert.Equal(2, resultDocument.Paths.Count); // document has only two paths - Assert.Equal(originalDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count, resultDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count); // Responses are still intact. - Assert.NotEmpty(resultDocument.Paths["/test"].Operations[OperationType.Get].Responses["200"].Description); // response description string is not empty - Assert.Empty(resultDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // NO UNsupported extension - Assert.Equal(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count, resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count); // Responses are still intact. - Assert.NotEmpty(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Description);// response description string is not empty - Assert.Single(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension still present in operation + Assert.Empty(resultResult.OpenApiDocument.Components.Schemas);// no schema is referenced. so ensure they are all removed + Assert.Empty(resultResult.OpenApiDocument.Extensions); // no extension at root (unsupported extension is removed) + Assert.Equal(2, resultResult.OpenApiDocument.Paths.Count); // document has only two paths + Assert.Equal(originalResult.OpenApiDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count, resultResult.OpenApiDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count); // Responses are still intact. + Assert.NotEmpty(resultResult.OpenApiDocument.Paths["/test"].Operations[OperationType.Get].Responses["200"].Description); // response description string is not empty + Assert.Empty(resultResult.OpenApiDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // NO UNsupported extension + Assert.Equal(originalResult.OpenApiDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count, resultResult.OpenApiDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count); // Responses are still intact. + Assert.NotEmpty(resultResult.OpenApiDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Description);// response description string is not empty + Assert.Single(resultResult.OpenApiDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension still present in operation } #region Security @@ -686,7 +684,7 @@ public static TheoryData> Assert.NotEmpty(slicedDocument.Paths); var schema = slicedDocument.Paths["/test"].Operations[OperationType.Post].RequestBody .Content["application/json"].Schema; - Assert.Equal("string", schema.Type); + Assert.Equal(JsonSchemaType.String, schema.Type.Value); Assert.Equal(5, schema.MaxLength); } }, @@ -706,7 +704,7 @@ public static TheoryData> Assert.NotEmpty(slicedDocument.Paths); var schema = slicedDocument.Paths["/test"].Operations[OperationType.Post].RequestBody .Content["application/json"].Schema; - Assert.Equal("object", schema.Type); + Assert.Equal(JsonSchemaType.Object, schema.Type.Value); Assert.Equal(3, schema.Properties.Count); } }, @@ -726,7 +724,7 @@ public static TheoryData> Assert.NotEmpty(slicedDocument.Paths); var schema = slicedDocument.Paths["/test"].Operations[OperationType.Post].RequestBody .Content["application/json"].Schema; - Assert.Equal("object", schema.Type); + Assert.Equal(JsonSchemaType.Object, schema.Type.Value); Assert.Equal(2, schema.Properties.Count); } }, @@ -746,7 +744,7 @@ public static TheoryData> Assert.NotEmpty(slicedDocument.Paths); var schema = slicedDocument.Paths["/test"].Operations[OperationType.Post].RequestBody .Content["application/json"].Schema; - Assert.Equal("object", schema.Type); + Assert.Equal(JsonSchemaType.Object, schema.Type.Value); Assert.Equal(2, schema.Properties.Count); } }, @@ -766,7 +764,7 @@ public static TheoryData> Assert.NotEmpty(slicedDocument.Paths); var schema = slicedDocument.Paths["/test"].Operations[OperationType.Post].RequestBody .Content["application/json"].Schema; - Assert.Equal("object", schema.Type); + Assert.Equal(JsonSchemaType.Object, schema.Type.Value); Assert.Single(schema.Properties); } }, @@ -782,7 +780,7 @@ public static TheoryData> Assert.NotEmpty(slicedDocument.Paths); var schema = slicedDocument.Paths["/test"].Operations[OperationType.Post].RequestBody .Content["application/json"].Schema; - Assert.Equal("object", schema.Type); + Assert.Equal(JsonSchemaType.Object, schema.Type.Value); Assert.Single(schema.Properties); } }, @@ -839,9 +837,8 @@ public async Task MergesAllOfRequestBodyAsync(string content, Action Date: Mon, 25 Nov 2024 09:17:17 -0500 Subject: [PATCH 13/96] fix: parsing of dependencies Signed-off-by: Vincent Biret --- src/Kiota.Builder/LanguageInformation.cs | 9 +++++---- .../OpenApiExtensions/OpenApiKiotaExtensionTests.cs | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Kiota.Builder/LanguageInformation.cs b/src/Kiota.Builder/LanguageInformation.cs index 7ffa6555a6..2966c90f81 100644 --- a/src/Kiota.Builder/LanguageInformation.cs +++ b/src/Kiota.Builder/LanguageInformation.cs @@ -54,8 +54,9 @@ public static LanguageInformation Parse(JsonNode source) var extension = new LanguageInformation(); if (rawObject.TryGetPropertyValue(nameof(Dependencies).ToFirstCharacterLowerCase(), out var dependencies) && dependencies is JsonArray arrayValue) { - foreach (var entry in arrayValue.OfType()) - extension.Dependencies.Add(LanguageDependency.Parse(entry)); + foreach (var entry in arrayValue) + if (entry is not null) + extension.Dependencies.Add(LanguageDependency.Parse(entry)); } if (rawObject.TryGetPropertyValue(nameof(DependencyInstallCommand).ToFirstCharacterLowerCase(), out var installCommand) && installCommand is JsonValue stringValue) { @@ -75,11 +76,11 @@ public static LanguageInformation Parse(JsonNode source) foreach (var entry in structuredMimeTypesValue.OfType()) extension.StructuredMimeTypes.Add(entry.GetValue()); } - if (rawObject.TryGetValue(nameof(MaturityLevel).ToFirstCharacterLowerCase(), out var maturityLevel) && maturityLevel is OpenApiString maturityLevelValue && Enum.TryParse(maturityLevelValue.Value, true, out var parsedMaturityLevelValue)) + if (rawObject.TryGetPropertyValue(nameof(MaturityLevel).ToFirstCharacterLowerCase(), out var maturityLevel) && maturityLevel is JsonValue maturityLevelValue && maturityLevelValue.GetValueKind() is JsonValueKind.String && Enum.TryParse(maturityLevelValue.GetValue(), true, out var parsedMaturityLevelValue)) { extension.MaturityLevel = parsedMaturityLevelValue; } - if (rawObject.TryGetValue(nameof(SupportExperience).ToFirstCharacterLowerCase(), out var supportExperience) && supportExperience is OpenApiString supportExperienceValue && Enum.TryParse(supportExperienceValue.Value, true, out var parsedSupportExperienceValue)) + if (rawObject.TryGetPropertyValue(nameof(SupportExperience).ToFirstCharacterLowerCase(), out var supportExperience) && supportExperience is JsonValue supportExperienceValue && supportExperienceValue.GetValueKind() is JsonValueKind.String && Enum.TryParse(supportExperienceValue.GetValue(), true, out var parsedSupportExperienceValue)) { extension.SupportExperience = parsedSupportExperienceValue; } diff --git a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiKiotaExtensionTests.cs b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiKiotaExtensionTests.cs index 762bdb1422..50d598a883 100644 --- a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiKiotaExtensionTests.cs +++ b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiKiotaExtensionTests.cs @@ -64,7 +64,7 @@ public void Parses() ], "dependencyInstallCommand": "dotnet add package", "maturityLevel": "Preview", - "supportExperience", "Microsoft", + "supportExperience": "Microsoft", "clientClassName": "GraphServiceClient", "clientNamespaceName": "Microsoft.Graph", "structuredMimeTypes": [ From 5db7ad0a15c1ff4677fe4b5d5671ea4419655c93 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 25 Nov 2024 12:12:37 -0500 Subject: [PATCH 14/96] fix: aligns dependencies versions Signed-off-by: Vincent Biret --- src/kiota/kiota.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kiota/kiota.csproj b/src/kiota/kiota.csproj index f6e4a627db..ae577ae8b1 100644 --- a/src/kiota/kiota.csproj +++ b/src/kiota/kiota.csproj @@ -46,7 +46,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive From 4c1866df5e26f41a69a5a2fa58434f6675ea987b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 27 Nov 2024 12:05:30 -0500 Subject: [PATCH 15/96] chore: upgrades additional code --- .../Extensions/OpenApiSchemaExtensionsTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index adc6104cc6..77a6fa8f0a 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -878,7 +878,7 @@ public void ReturnsEmptyPropertyNameOnCircularReferences() entitySchema, new OpenApiSchema { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary { ["firstName"] = new OpenApiSchema From 4daed721bfa62b8b0d20f428928f730ad4c6ff6d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 12:33:54 -0500 Subject: [PATCH 16/96] chore: upgrades to OAI.net preview3 Signed-off-by: Vincent Biret --- src/Kiota.Builder/Kiota.Builder.csproj | 4 +- src/Kiota.Builder/KiotaBuilder.cs | 2 +- .../OpenApiDocumentDownloadService.cs | 15 ++- src/kiota/kiota.csproj | 2 +- .../Plugins/PluginsGenerationServiceTests.cs | 10 +- .../DivergentResponseSchemaTests.cs | 2 +- .../Validation/GetWithBodyTests.cs | 60 ++++----- .../InconsistentTypeFormatPairTests.cs | 60 ++++----- .../KnownAndNotSupportedFormatsTests.cs | 60 ++++----- .../Validation/MissingDiscriminatorTests.cs | 88 ++++++------- .../Validation/MultipleServerEntriesTests.cs | 46 +++---- .../Validation/NoContentWithBodyTests.cs | 60 ++++----- .../Validation/NoServerEntryTests.cs | 46 +++---- .../Validation/UrlFormEncodedComplexTests.cs | 116 +++++++++--------- 14 files changed, 285 insertions(+), 286 deletions(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index 6e020eeb8b..f49a92aa8a 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -44,9 +44,9 @@ - + - + diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 104afea1b5..0e84fd70f0 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -2510,7 +2510,7 @@ private static CodeType GetQueryParameterType(OpenApiSchema schema) var paramType = GetPrimitiveType(schema) ?? new() { IsExternal = true, - Name = schema.Items is not null && schema.Items.Type.HasValue ? schema.Items.Type.ToIdentifier() : schema.Type.ToIdentifier(), + Name = schema.Items is not null && schema.Items.Type.ToIdentifier() is string name ? name : "null", }; paramType.CollectionKind = schema.IsArray() ? CodeTypeBase.CodeTypeCollectionKind.Array : default; diff --git a/src/Kiota.Builder/OpenApiDocumentDownloadService.cs b/src/Kiota.Builder/OpenApiDocumentDownloadService.cs index 9e76322596..4b4f3376a1 100644 --- a/src/Kiota.Builder/OpenApiDocumentDownloadService.cs +++ b/src/Kiota.Builder/OpenApiDocumentDownloadService.cs @@ -135,25 +135,24 @@ ex is SecurityException || { // couldn't parse the URL, it's probably a local file } - //TODO update to remove the unknown format when the overload is available - var readResult = await OpenApiDocument.LoadAsync(input, "unknown", settings: settings, cancellationToken: cancellationToken).ConfigureAwait(false); + var readResult = await OpenApiDocument.LoadAsync(input, settings: settings, cancellationToken: cancellationToken).ConfigureAwait(false); stopwatch.Stop(); if (generating) - foreach (var warning in readResult.OpenApiDiagnostic.Warnings) + foreach (var warning in readResult.Diagnostic.Warnings) Logger.LogWarning("OpenAPI warning: {Pointer} - {Warning}", warning.Pointer, warning.Message); - if (readResult.OpenApiDiagnostic.Errors.Any()) + if (readResult.Diagnostic.Errors.Any()) { - Logger.LogTrace("{Timestamp}ms: Parsed OpenAPI with errors. {Count} paths found.", stopwatch.ElapsedMilliseconds, readResult.OpenApiDocument?.Paths?.Count ?? 0); - foreach (var parsingError in readResult.OpenApiDiagnostic.Errors) + Logger.LogTrace("{Timestamp}ms: Parsed OpenAPI with errors. {Count} paths found.", stopwatch.ElapsedMilliseconds, readResult.Document?.Paths?.Count ?? 0); + foreach (var parsingError in readResult.Diagnostic.Errors) { Logger.LogError("OpenAPI error: {Pointer} - {Message}", parsingError.Pointer, parsingError.Message); } } else { - Logger.LogTrace("{Timestamp}ms: Parsed OpenAPI successfully. {Count} paths found.", stopwatch.ElapsedMilliseconds, readResult.OpenApiDocument?.Paths?.Count ?? 0); + Logger.LogTrace("{Timestamp}ms: Parsed OpenAPI successfully. {Count} paths found.", stopwatch.ElapsedMilliseconds, readResult.Document?.Paths?.Count ?? 0); } - return readResult.OpenApiDocument; + return readResult.Document; } } diff --git a/src/kiota/kiota.csproj b/src/kiota/kiota.csproj index da67751739..3a39216ede 100644 --- a/src/kiota/kiota.csproj +++ b/src/kiota/kiota.csproj @@ -47,7 +47,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs index 83b327fc5b..7c95108189 100644 --- a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs @@ -263,8 +263,8 @@ public async Task GeneratesManifestAndCleansUpInputDescriptionAsync() // Validate the original file. using var originalOpenApiFile = File.OpenRead(simpleDescriptionPath); var originalResult = await OpenApiDocument.LoadAsync(originalOpenApiFile, "yaml"); - var originalDocument = originalResult.OpenApiDocument; - Assert.Empty(originalResult.OpenApiDiagnostic.Errors); + var originalDocument = originalResult.Document; + Assert.Empty(originalResult.Diagnostic.Errors); Assert.Equal(originalDocument.Paths["/test"].Operations[OperationType.Get].Description, resultingManifest.Document.Functions[0].Description);// pulls from description Assert.Equal(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Summary, resultingManifest.Document.Functions[1].Description);// pulls from summary @@ -281,8 +281,8 @@ public async Task GeneratesManifestAndCleansUpInputDescriptionAsync() // Validate the output open api file using var resultOpenApiFile = File.OpenRead(Path.Combine(outputDirectory, OpenApiFileName)); var resultResult = await OpenApiDocument.LoadAsync(originalOpenApiFile, "yaml"); - var resultDocument = resultResult.OpenApiDocument; - Assert.Empty(resultResult.OpenApiDiagnostic.Errors); + var resultDocument = resultResult.Document; + Assert.Empty(resultResult.Diagnostic.Errors); // Assertions / validations Assert.Empty(resultDocument.Components.Schemas);// no schema is referenced. so ensure they are all removed @@ -798,7 +798,7 @@ public async Task MergesAllOfRequestBodyAsync(string content, Action GetDiagnosticFromDocumentAsync(stri var settings = new OpenApiReaderSettings(); settings.RuleSet.Add(typeof(DivergentResponseSchema), [rule]); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.OpenApiDiagnostic; + return result.Diagnostic; } } diff --git a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs index e04999b87a..3512b156b0 100644 --- a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs @@ -12,10 +12,10 @@ namespace Kiota.Builder.Tests.Validation; public class GetWithBodyTests { - [Fact] - public async Task AddsAWarningWhenGetWithBody() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenGetWithBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -31,13 +31,13 @@ public async Task AddsAWarningWhenGetWithBody() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenGetWithNoBody() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenGetWithNoBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -51,13 +51,13 @@ public async Task DoesntAddAWarningWhenGetWithNoBody() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenPostWithBody() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenPostWithBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -73,16 +73,16 @@ public async Task DoesntAddAWarningWhenPostWithBody() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new GetWithBody(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(GetWithBody), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.OpenApiDiagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new GetWithBody(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(GetWithBody), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs index 34b965b2fe..070c33da97 100644 --- a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs @@ -9,10 +9,10 @@ namespace Kiota.Builder.Tests.Validation; public class InconsistentTypeFormatPairTests { - [Fact] - public async Task AddsAWarningWhenKnownInconsistentPair() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenKnownInconsistentPair() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -27,13 +27,13 @@ public async Task AddsAWarningWhenKnownInconsistentPair() schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenSupportedPair() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenSupportedPair() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -48,13 +48,13 @@ public async Task DoesntAddAWarningWhenSupportedPair() schema: type: string format: uuid"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntFailWhenKnownAlternative() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntFailWhenKnownAlternative() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -69,16 +69,16 @@ public async Task DoesntFailWhenKnownAlternative() schema: type: enum format: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new InconsistentTypeFormatPair(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(InconsistentTypeFormatPair), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.OpenApiDiagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new InconsistentTypeFormatPair(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(InconsistentTypeFormatPair), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs index 2a3dfbe407..fe4aec47ff 100644 --- a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs @@ -10,10 +10,10 @@ namespace Kiota.Builder.Tests.Validation; public class KnownAndNotSupportedFormatsTests { - [Fact] - public async Task AddsAWarningWhenKnownUnsupportedFormat() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenKnownUnsupportedFormat() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -28,13 +28,13 @@ public async Task AddsAWarningWhenKnownUnsupportedFormat() schema: type: string format: email"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenSupportedFormat() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenSupportedFormat() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -49,13 +49,13 @@ public async Task DoesntAddAWarningWhenSupportedFormat() schema: type: string format: uuid"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntFailWhenNoFormat() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntFailWhenNoFormat() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -69,16 +69,16 @@ public async Task DoesntFailWhenNoFormat() application/json: schema: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new KnownAndNotSupportedFormats(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(KnownAndNotSupportedFormats), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.OpenApiDiagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new KnownAndNotSupportedFormats(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(KnownAndNotSupportedFormats), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs b/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs index 58404f74d6..8ac4e316e3 100644 --- a/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs @@ -9,10 +9,10 @@ namespace Kiota.Builder.Tests.Validation; public class MissingDiscriminatorTests { - [Fact] - public async Task DoesntAddAWarningWhenBodyIsSimple() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task DoesntAddAWarningWhenBodyIsSimple() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -27,13 +27,13 @@ public async Task DoesntAddAWarningWhenBodyIsSimple() schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task AddsWarningOnInlineSchemas() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task AddsWarningOnInlineSchemas() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -56,13 +56,13 @@ public async Task AddsWarningOnInlineSchemas() properties: type2: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task AddsWarningOnComponentSchemas() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task AddsWarningOnComponentSchemas() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -93,13 +93,13 @@ public async Task AddsWarningOnComponentSchemas() application/json: schema: $ref: '#/components/schemas/type3'"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddsWarningOnComponentSchemasWithDiscriminatorInformation() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddsWarningOnComponentSchemasWithDiscriminatorInformation() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -132,13 +132,13 @@ public async Task DoesntAddsWarningOnComponentSchemasWithDiscriminatorInformatio application/json: schema: $ref: '#/components/schemas/type3'"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddsWarningOnComponentSchemasScalars() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddsWarningOnComponentSchemasScalars() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -161,16 +161,16 @@ public async Task DoesntAddsWarningOnComponentSchemasScalars() application/json: schema: $ref: '#/components/schemas/type1'"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new MissingDiscriminator(new()); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(MissingDiscriminator), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.OpenApiDiagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new MissingDiscriminator(new()); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(MissingDiscriminator), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs b/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs index a4e0934e8b..6e195b4a69 100644 --- a/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs @@ -10,10 +10,10 @@ namespace Kiota.Builder.Tests.Validation; public class MultipleServerEntriesTests { - [Fact] - public async Task AddsAWarningWhenMultipleServersPresent() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenMultipleServersPresent() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -28,13 +28,13 @@ public async Task AddsAWarningWhenMultipleServersPresent() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenSingleServerPresent() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenSingleServerPresent() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -48,16 +48,16 @@ public async Task DoesntAddAWarningWhenSingleServerPresent() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new MultipleServerEntries(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(MultipleServerEntries), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.OpenApiDiagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new MultipleServerEntries(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(MultipleServerEntries), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs b/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs index 900228a339..50cc2f9149 100644 --- a/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs @@ -10,10 +10,10 @@ namespace Kiota.Builder.Tests.Validation; public class NoContentWithBodyTests { - [Fact] - public async Task AddsAWarningWhen204WithBody() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhen204WithBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -25,13 +25,13 @@ public async Task AddsAWarningWhen204WithBody() '204': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhen204WithNoBody() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhen204WithNoBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -43,13 +43,13 @@ public async Task DoesntAddAWarningWhen204WithNoBody() get: responses: '204':"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhen200WithBody() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhen200WithBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -65,16 +65,16 @@ public async Task DoesntAddAWarningWhen200WithBody() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new NoContentWithBody(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(NoContentWithBody), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.OpenApiDiagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new NoContentWithBody(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(NoContentWithBody), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs b/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs index beeea627c6..5aecbb914d 100644 --- a/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs @@ -10,10 +10,10 @@ namespace Kiota.Builder.Tests.Validation; public class NoServerEntryTests { - [Fact] - public async Task AddsAWarningWhenNoServersPresent() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenNoServersPresent() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -25,13 +25,13 @@ public async Task AddsAWarningWhenNoServersPresent() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenServerPresent() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenServerPresent() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -45,16 +45,16 @@ public async Task DoesntAddAWarningWhenServerPresent() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new NoServerEntry(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(NoServerEntry), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.OpenApiDiagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new NoServerEntry(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(NoServerEntry), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs b/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs index f74ecbcd80..ce49c615b7 100644 --- a/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs @@ -9,10 +9,10 @@ namespace Kiota.Builder.Tests.Validation; public class UrlFormEncodedComplexTests { - [Fact] - public async Task AddsAWarningWhenUrlEncodedNotObjectRequestBody() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenUrlEncodedNotObjectRequestBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -33,13 +33,13 @@ public async Task AddsAWarningWhenUrlEncodedNotObjectRequestBody() schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task AddsAWarningWhenUrlEncodedNotObjectResponse() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task AddsAWarningWhenUrlEncodedNotObjectResponse() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -54,13 +54,13 @@ public async Task AddsAWarningWhenUrlEncodedNotObjectResponse() schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnRequestBody() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnRequestBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -86,13 +86,13 @@ public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnRequestBody() schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -112,13 +112,13 @@ public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() properties: prop: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenUrlEncoded() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenUrlEncoded() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -135,13 +135,13 @@ public async Task DoesntAddAWarningWhenUrlEncoded() properties: prop: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningOnArrayProperty() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningOnArrayProperty() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -169,13 +169,13 @@ public async Task DoesntAddAWarningOnArrayProperty() properties: prop: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenNotUrlEncoded() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenNotUrlEncoded() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -190,16 +190,16 @@ public async Task DoesntAddAWarningWhenNotUrlEncoded() schema: type: enum format: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new UrlFormEncodedComplex(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(UrlFormEncodedComplex), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.OpenApiDiagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new UrlFormEncodedComplex(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(UrlFormEncodedComplex), [rule]); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } From 9c9f988fe9a7aca9c37110e60c6f5c22025dd00b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 12:47:08 -0500 Subject: [PATCH 17/96] fix: registers missing reader Signed-off-by: Vincent Biret --- src/Kiota.Builder/OpenApiDocumentDownloadService.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Kiota.Builder/OpenApiDocumentDownloadService.cs b/src/Kiota.Builder/OpenApiDocumentDownloadService.cs index 4b4f3376a1..1739f502b5 100644 --- a/src/Kiota.Builder/OpenApiDocumentDownloadService.cs +++ b/src/Kiota.Builder/OpenApiDocumentDownloadService.cs @@ -17,6 +17,7 @@ using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; +using Microsoft.OpenApi.Readers; using Microsoft.OpenApi.Validations; namespace Kiota.Builder; @@ -30,6 +31,8 @@ public OpenApiDocumentDownloadService(HttpClient httpClient, ILogger logger) ArgumentNullException.ThrowIfNull(logger); HttpClient = httpClient; Logger = logger; + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); } private static readonly AsyncKeyedLocker localFilesLock = new(o => { From 9cebd6cacc99771e735bfaff56ce05cc57029a0e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 13:03:39 -0500 Subject: [PATCH 18/96] fix: bad boolean algebra Signed-off-by: Vincent Biret --- src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index 585c1ae2ed..e3bad1ce44 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -80,7 +80,7 @@ public static bool IsInherited(this OpenApiSchema? schema) var meaningfulMemberSchemas = schema.AllOf.FlattenSchemaIfRequired(static x => x.AllOf) .Where(static x => x.IsSemanticallyMeaningful(ignoreEnums: true, ignoreArrays: true, ignoreType: true)) // the next line ensures the meaningful schema are objects as it won't make sense inheriting from a primitive despite it being meaningful. - .Where(static x => string.IsNullOrEmpty(x.Reference?.Id) || x.Type is null || !x.Type.HasValue || (x.Type.Value ^ JsonSchemaType.Object) is JsonSchemaType.Object) + .Where(static x => string.IsNullOrEmpty(x.Reference?.Id) || x.Type is null || !x.Type.HasValue || (x.Type.Value & JsonSchemaType.Object) is JsonSchemaType.Object) .ToArray(); var isRootSchemaMeaningful = schema.IsSemanticallyMeaningful(ignoreEnums: true, ignoreArrays: true, ignoreType: true); return meaningfulMemberSchemas.Count(static x => !string.IsNullOrEmpty(x.Reference?.Id)) == 1 && From 893a5ae791c4b2ae8507ff715abece26255dc403 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 13:20:40 -0500 Subject: [PATCH 19/96] chore: linting Signed-off-by: Vincent Biret --- src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index e3bad1ce44..8c814b0e07 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -309,7 +309,7 @@ internal static string GetDiscriminatorPropertyName(this OpenApiSchema schema, H internal static IEnumerable> GetDiscriminatorMappings(this OpenApiSchema schema, ConcurrentDictionary> inheritanceIndex) { if (schema == null) - return Enumerable.Empty>(); + return []; if (!(schema.Discriminator?.Mapping?.Any() ?? false)) if (schema.OneOf.Any()) return schema.OneOf.SelectMany(x => GetDiscriminatorMappings(x, inheritanceIndex)); @@ -322,9 +322,9 @@ internal static IEnumerable> GetDiscriminatorMappin return GetAllInheritanceSchemaReferences(schema.Reference.Id, inheritanceIndex) .Where(static x => !string.IsNullOrEmpty(x)) .Select(x => KeyValuePair.Create(x, x)) - .Union(new[] { KeyValuePair.Create(schema.Reference.Id, schema.Reference.Id) }); + .Union([KeyValuePair.Create(schema.Reference.Id, schema.Reference.Id)]); else - return Enumerable.Empty>(); + return []; return schema.Discriminator .Mapping; From c1e21aa93af256807e104e51d2ac291627ced9e3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 14:13:06 -0500 Subject: [PATCH 20/96] fix: class naming for discriminator mapping Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 0e84fd70f0..f054297386 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -2240,8 +2240,11 @@ internal static void AddDiscriminatorMethod(CodeClass newClass, string discrimin logger.LogWarning("Discriminator {ComponentKey} not found in the OpenAPI document.", componentKey); return null; } + // the new version of OAI.net does not mutate the source schema anymore when resolving references which is a positive thing but is challenging for naming. + var schemaClone = new OpenApiSchema(discriminatorSchema); + schemaClone.Reference ??= new OpenApiReference { Id = referenceId }; // Call CreateModelDeclarations with isViaDiscriminator=true. This is for a special case where we always generate a base class when types are referenced via a oneOf discriminator. - if (CreateModelDeclarations(currentNode, discriminatorSchema, currentOperation, GetShortestNamespace(currentNamespace, discriminatorSchema), string.Empty, null, string.Empty, false, true) is not CodeType result) + if (CreateModelDeclarations(currentNode, schemaClone, currentOperation, GetShortestNamespace(currentNamespace, schemaClone), string.Empty, null, string.Empty, false, true) is not CodeType result) { logger.LogWarning("Discriminator {ComponentKey} is not a valid model and points to a union type.", componentKey); return null; From 5f7e287319f67ca910e32482f62a32674d52c1f6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 14:24:18 -0500 Subject: [PATCH 21/96] fix: further fix of missing reference ids Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index f054297386..cda9fd26d4 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -2242,7 +2242,7 @@ internal static void AddDiscriminatorMethod(CodeClass newClass, string discrimin } // the new version of OAI.net does not mutate the source schema anymore when resolving references which is a positive thing but is challenging for naming. var schemaClone = new OpenApiSchema(discriminatorSchema); - schemaClone.Reference ??= new OpenApiReference { Id = referenceId }; + schemaClone.Reference ??= new OpenApiReference { Id = componentKey, Type = ReferenceType.Schema }; // Call CreateModelDeclarations with isViaDiscriminator=true. This is for a special case where we always generate a base class when types are referenced via a oneOf discriminator. if (CreateModelDeclarations(currentNode, schemaClone, currentOperation, GetShortestNamespace(currentNamespace, schemaClone), string.Empty, null, string.Empty, false, true) is not CodeType result) { From 77f3a55a74db00f16e3d14a233babdcc68e6eaff Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 14:28:13 -0500 Subject: [PATCH 22/96] fix: wrong method overload use Signed-off-by: Vincent Biret --- .../Plugins/PluginsGenerationServiceTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs index 7c95108189..ddc6a98d9f 100644 --- a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs @@ -796,8 +796,8 @@ public async Task MergesAllOfRequestBodyAsync(string content, Action Date: Fri, 20 Dec 2024 14:31:17 -0500 Subject: [PATCH 23/96] fix: wrong test data Signed-off-by: Vincent Biret --- .../OpenApiAiReasoningInstructionsExtensionTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiReasoningInstructionsExtensionTests.cs b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiReasoningInstructionsExtensionTests.cs index 1c511b92f2..cd7492744f 100644 --- a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiReasoningInstructionsExtensionTests.cs +++ b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiReasoningInstructionsExtensionTests.cs @@ -27,7 +27,7 @@ public void Parses() """ [ "This is a description", - "This is a description 2", + "This is a description 2" ] """; using var stream = new MemoryStream(Encoding.UTF8.GetBytes(oaiValueRepresentation)); From 52ede22a80712d224d502d8583c5c9e6d8fb070b Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 14:54:40 -0500 Subject: [PATCH 24/96] fix: missing readers fix: missing descriptions Signed-off-by: Vincent Biret --- .../DivergentResponseSchemaTests.cs | 8 ++ .../Validation/GetWithBodyTests.cs | 65 ++++----- .../InconsistentTypeFormatPairTests.cs | 66 ++++----- .../KnownAndNotSupportedFormatsTests.cs | 66 ++++----- .../Validation/MissingDiscriminatorTests.cs | 96 +++++++------ .../Validation/MultipleServerEntriesTests.cs | 51 +++---- .../Validation/NoContentWithBodyTests.cs | 68 +++++----- .../Validation/NoServerEntryTests.cs | 49 +++---- .../Validation/UrlFormEncodedComplexTests.cs | 126 ++++++++++-------- 9 files changed, 326 insertions(+), 269 deletions(-) diff --git a/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs b/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs index dc3ecfb1d1..8ea2af1ff7 100644 --- a/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs @@ -4,6 +4,7 @@ using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; +using Microsoft.OpenApi.Readers; using Xunit; namespace Kiota.Builder.Tests.Validation; @@ -23,6 +24,7 @@ public async Task DoesntAddAWarningWhenBodyIsSingle() get: responses: '200': + description: some description content: application/json: schema: @@ -44,12 +46,14 @@ public async Task AddsAWarningWhenBodyIsDivergent() get: responses: '200': + description: some description content: application/json: schema: type: string format: int32 '201': + description: some description content: application/json: schema: @@ -71,12 +75,14 @@ public async Task DoesntAddAWarningWhenUsing2XX() get: responses: '200': + description: some description content: application/json: schema: type: string format: int32 '2XX': + description: some description content: application/json: schema: @@ -91,6 +97,8 @@ private static async Task GetDiagnosticFromDocumentAsync(stri using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); settings.RuleSet.Add(typeof(DivergentResponseSchema), [rule]); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); return result.Diagnostic; } diff --git a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs index 3512b156b0..888c42230c 100644 --- a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs @@ -12,10 +12,10 @@ namespace Kiota.Builder.Tests.Validation; public class GetWithBodyTests { - [Fact] - public async Task AddsAWarningWhenGetWithBody() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenGetWithBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -29,15 +29,16 @@ public async Task AddsAWarningWhenGetWithBody() application/json: responses: '200': + description: some description content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenGetWithNoBody() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenGetWithNoBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -49,15 +50,16 @@ public async Task DoesntAddAWarningWhenGetWithNoBody() get: responses: '200': + description: some description content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenPostWithBody() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenPostWithBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -71,18 +73,21 @@ public async Task DoesntAddAWarningWhenPostWithBody() application/json: responses: '200': + description: some description content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new GetWithBody(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(GetWithBody), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.Diagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new GetWithBody(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(GetWithBody), [rule]); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs index 070c33da97..c71ce5488d 100644 --- a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs @@ -4,15 +4,16 @@ using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; +using Microsoft.OpenApi.Readers; using Xunit; namespace Kiota.Builder.Tests.Validation; public class InconsistentTypeFormatPairTests { - [Fact] - public async Task AddsAWarningWhenKnownInconsistentPair() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenKnownInconsistentPair() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -22,18 +23,19 @@ public async Task AddsAWarningWhenKnownInconsistentPair() get: responses: '200': + description: some description content: application/json: schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenSupportedPair() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenSupportedPair() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -43,18 +45,19 @@ public async Task DoesntAddAWarningWhenSupportedPair() get: responses: '200': + description: some description content: application/json: schema: type: string format: uuid"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntFailWhenKnownAlternative() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntFailWhenKnownAlternative() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -64,21 +67,24 @@ public async Task DoesntFailWhenKnownAlternative() get: responses: '200': + description: some description content: application/json: schema: type: enum format: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new InconsistentTypeFormatPair(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(InconsistentTypeFormatPair), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.Diagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new InconsistentTypeFormatPair(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(InconsistentTypeFormatPair), [rule]); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs index fe4aec47ff..a568470f3c 100644 --- a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs @@ -4,16 +4,17 @@ using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; +using Microsoft.OpenApi.Readers; using Xunit; namespace Kiota.Builder.Tests.Validation; public class KnownAndNotSupportedFormatsTests { - [Fact] - public async Task AddsAWarningWhenKnownUnsupportedFormat() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenKnownUnsupportedFormat() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -23,18 +24,19 @@ public async Task AddsAWarningWhenKnownUnsupportedFormat() get: responses: '200': + description: some description content: application/json: schema: type: string format: email"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenSupportedFormat() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenSupportedFormat() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -44,18 +46,19 @@ public async Task DoesntAddAWarningWhenSupportedFormat() get: responses: '200': + description: some description content: application/json: schema: type: string format: uuid"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntFailWhenNoFormat() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntFailWhenNoFormat() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -65,20 +68,23 @@ public async Task DoesntFailWhenNoFormat() get: responses: '200': + description: some description content: application/json: schema: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new KnownAndNotSupportedFormats(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(KnownAndNotSupportedFormats), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.Diagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new KnownAndNotSupportedFormats(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(KnownAndNotSupportedFormats), [rule]); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs b/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs index 8ac4e316e3..65bdb25849 100644 --- a/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs @@ -4,15 +4,16 @@ using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; +using Microsoft.OpenApi.Readers; using Xunit; namespace Kiota.Builder.Tests.Validation; public class MissingDiscriminatorTests { - [Fact] - public async Task DoesntAddAWarningWhenBodyIsSimple() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task DoesntAddAWarningWhenBodyIsSimple() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -22,18 +23,19 @@ public async Task DoesntAddAWarningWhenBodyIsSimple() get: responses: '200': + description: some description content: application/json: schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task AddsWarningOnInlineSchemas() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task AddsWarningOnInlineSchemas() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -43,6 +45,7 @@ public async Task AddsWarningOnInlineSchemas() get: responses: '200': + description: some description content: application/json: schema: @@ -56,13 +59,13 @@ public async Task AddsWarningOnInlineSchemas() properties: type2: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task AddsWarningOnComponentSchemas() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task AddsWarningOnComponentSchemas() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -89,17 +92,18 @@ public async Task AddsWarningOnComponentSchemas() get: responses: '200': + description: some description content: application/json: schema: $ref: '#/components/schemas/type3'"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddsWarningOnComponentSchemasWithDiscriminatorInformation() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddsWarningOnComponentSchemasWithDiscriminatorInformation() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -128,17 +132,18 @@ public async Task DoesntAddsWarningOnComponentSchemasWithDiscriminatorInformatio get: responses: '200': + description: some description content: application/json: schema: $ref: '#/components/schemas/type3'"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddsWarningOnComponentSchemasScalars() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddsWarningOnComponentSchemasScalars() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -157,20 +162,23 @@ public async Task DoesntAddsWarningOnComponentSchemasScalars() get: responses: '200': + description: some description content: application/json: schema: $ref: '#/components/schemas/type1'"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new MissingDiscriminator(new()); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(MissingDiscriminator), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.Diagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new MissingDiscriminator(new()); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(MissingDiscriminator), [rule]); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs b/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs index 6e195b4a69..f19f86f5be 100644 --- a/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs @@ -4,16 +4,17 @@ using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; +using Microsoft.OpenApi.Readers; using Xunit; namespace Kiota.Builder.Tests.Validation; public class MultipleServerEntriesTests { - [Fact] - public async Task AddsAWarningWhenMultipleServersPresent() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenMultipleServersPresent() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -26,15 +27,16 @@ public async Task AddsAWarningWhenMultipleServersPresent() get: responses: '200': + description: some description content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenSingleServerPresent() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenSingleServerPresent() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -46,18 +48,21 @@ public async Task DoesntAddAWarningWhenSingleServerPresent() get: responses: '200': + description: some description content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new MultipleServerEntries(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(MultipleServerEntries), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.Diagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new MultipleServerEntries(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(MultipleServerEntries), [rule]); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs b/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs index 50cc2f9149..e63de927c3 100644 --- a/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs @@ -4,16 +4,17 @@ using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; +using Microsoft.OpenApi.Readers; using Xunit; namespace Kiota.Builder.Tests.Validation; public class NoContentWithBodyTests { - [Fact] - public async Task AddsAWarningWhen204WithBody() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhen204WithBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -23,15 +24,16 @@ public async Task AddsAWarningWhen204WithBody() get: responses: '204': + description: some description content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhen204WithNoBody() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhen204WithNoBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -42,14 +44,15 @@ public async Task DoesntAddAWarningWhen204WithNoBody() /enumeration: get: responses: - '204':"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhen200WithBody() - { - var documentTxt = @"openapi: 3.0.1 + '204': + description: some description"; + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhen200WithBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -63,18 +66,21 @@ public async Task DoesntAddAWarningWhen200WithBody() application/json: responses: '200': + description: some description content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new NoContentWithBody(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(NoContentWithBody), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.Diagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new NoContentWithBody(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(NoContentWithBody), [rule]); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs b/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs index 5aecbb914d..26ac6d6355 100644 --- a/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs @@ -4,16 +4,17 @@ using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; +using Microsoft.OpenApi.Readers; using Xunit; namespace Kiota.Builder.Tests.Validation; public class NoServerEntryTests { - [Fact] - public async Task AddsAWarningWhenNoServersPresent() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenNoServersPresent() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -25,13 +26,13 @@ public async Task AddsAWarningWhenNoServersPresent() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenServerPresent() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenServerPresent() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -45,16 +46,18 @@ public async Task DoesntAddAWarningWhenServerPresent() '200': content: application/json:"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new NoServerEntry(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(NoServerEntry), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.Diagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new NoServerEntry(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(NoServerEntry), [rule]); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } diff --git a/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs b/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs index ce49c615b7..abef8864cf 100644 --- a/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs @@ -4,15 +4,16 @@ using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; +using Microsoft.OpenApi.Readers; using Xunit; namespace Kiota.Builder.Tests.Validation; public class UrlFormEncodedComplexTests { - [Fact] - public async Task AddsAWarningWhenUrlEncodedNotObjectRequestBody() - { - var documentTxt = @"openapi: 3.0.1 + [Fact] + public async Task AddsAWarningWhenUrlEncodedNotObjectRequestBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -28,18 +29,19 @@ public async Task AddsAWarningWhenUrlEncodedNotObjectRequestBody() format: int32 responses: '200': + description: some description content: application/json: schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task AddsAWarningWhenUrlEncodedNotObjectResponse() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task AddsAWarningWhenUrlEncodedNotObjectResponse() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -49,18 +51,19 @@ public async Task AddsAWarningWhenUrlEncodedNotObjectResponse() get: responses: '200': + description: some description content: application/x-www-form-urlencoded: schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnRequestBody() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnRequestBody() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -81,18 +84,19 @@ public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnRequestBody() type: string responses: '200': + description: some description content: application/json: schema: type: string format: int32"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -102,6 +106,7 @@ public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() get: responses: '200': + description: some description content: application/x-www-form-urlencoded: schema: @@ -112,13 +117,13 @@ public async Task AddsAWarningWhenUrlEncodedComplexPropertyOnResponse() properties: prop: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Single(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenUrlEncoded() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Single(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenUrlEncoded() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -128,6 +133,7 @@ public async Task DoesntAddAWarningWhenUrlEncoded() get: responses: '200': + description: some description content: application/x-www-form-urlencoded: schema: @@ -135,13 +141,13 @@ public async Task DoesntAddAWarningWhenUrlEncoded() properties: prop: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningOnArrayProperty() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningOnArrayProperty() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -162,6 +168,7 @@ public async Task DoesntAddAWarningOnArrayProperty() format: int32 responses: '200': + description: some description content: application/x-www-form-urlencoded: schema: @@ -169,13 +176,13 @@ public async Task DoesntAddAWarningOnArrayProperty() properties: prop: type: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - [Fact] - public async Task DoesntAddAWarningWhenNotUrlEncoded() - { - var documentTxt = @"openapi: 3.0.1 + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + [Fact] + public async Task DoesntAddAWarningWhenNotUrlEncoded() + { + var documentTxt = @"openapi: 3.0.1 info: title: OData Service for namespace microsoft.graph description: This OData service is located at https://graph.microsoft.com/v1.0 @@ -185,21 +192,24 @@ public async Task DoesntAddAWarningWhenNotUrlEncoded() get: responses: '200': + description: some description content: application/json: schema: type: enum format: string"; - var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); - Assert.Empty(diagnostic.Warnings); - } - private static async Task GetDiagnosticFromDocumentAsync(string document) - { - var rule = new UrlFormEncodedComplex(); - using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); - var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(UrlFormEncodedComplex), [rule]); - var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); - return result.Diagnostic; - } + var diagnostic = await GetDiagnosticFromDocumentAsync(documentTxt); + Assert.Empty(diagnostic.Warnings); + } + private static async Task GetDiagnosticFromDocumentAsync(string document) + { + var rule = new UrlFormEncodedComplex(); + using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); + var settings = new OpenApiReaderSettings(); + settings.RuleSet.Add(typeof(UrlFormEncodedComplex), [rule]); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); + OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); + var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); + return result.Diagnostic; + } } From 85c67cd239c5028545d596d81ca7b5f140560807 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 15:23:10 -0500 Subject: [PATCH 25/96] fix: form encoded validation rule Signed-off-by: Vincent Biret --- .../Validation/UrlFormEncodedComplex.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs b/src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs index f36ffb775b..917ba8a289 100644 --- a/src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs +++ b/src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs @@ -13,21 +13,19 @@ public class UrlFormEncodedComplex : ValidationRule }; public UrlFormEncodedComplex() : base(nameof(UrlFormEncodedComplex), static (context, operation) => { - if (string.IsNullOrEmpty(operation.OperationId)) - return; if (operation.GetRequestSchema(validContentTypes) is OpenApiSchema requestSchema) - ValidateSchema(requestSchema, context, operation.OperationId, "request body"); + ValidateSchema(requestSchema, context, "request body"); if (operation.GetResponseSchema(validContentTypes) is OpenApiSchema responseSchema) - ValidateSchema(responseSchema, context, operation.OperationId, "response body"); + ValidateSchema(responseSchema, context, "response body"); }) { } - private static void ValidateSchema(OpenApiSchema schema, IValidationContext context, string operationId, string schemaName) + private static void ValidateSchema(OpenApiSchema schema, IValidationContext context, string schemaName) { if (schema == null) return; if (!schema.IsObjectType()) - context.CreateWarning(nameof(UrlFormEncodedComplex), $"The operation {operationId} has a {schemaName} which is not an object type. This is not supported by Kiota and serialization will fail."); + context.CreateWarning(nameof(UrlFormEncodedComplex), $"The operation {context.PathString} has a {schemaName} which is not an object type. This is not supported by Kiota and serialization will fail."); if (schema.Properties.Any(static x => x.Value.IsObjectType())) - context.CreateWarning(nameof(UrlFormEncodedComplex), $"The operation {operationId} has a {schemaName} with a complex properties and the url form encoded content type. This is not supported by Kiota and serialization of complex properties will fail."); + context.CreateWarning(nameof(UrlFormEncodedComplex), $"The operation {context.PathString} has a {schemaName} with a complex properties and the url form encoded content type. This is not supported by Kiota and serialization of complex properties will fail."); } } From bc64b834d7ed2fd4beccf209531328c92928b833 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 20 Dec 2024 15:34:41 -0500 Subject: [PATCH 26/96] fix: validation rules registration Signed-off-by: Vincent Biret --- .../Validation/ValidationRuleSetExtensions.cs | 20 +++++++++---------- .../DivergentResponseSchemaTests.cs | 2 +- .../Validation/GetWithBodyTests.cs | 2 +- .../InconsistentTypeFormatPairTests.cs | 2 +- .../KnownAndNotSupportedFormatsTests.cs | 2 +- .../Validation/MissingDiscriminatorTests.cs | 2 +- .../Validation/MultipleServerEntriesTests.cs | 2 +- .../Validation/NoContentWithBodyTests.cs | 2 +- .../Validation/NoServerEntryTests.cs | 2 +- .../Validation/UrlFormEncodedComplexTests.cs | 2 +- 10 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs b/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs index 95d66e80e8..e80f6c2005 100644 --- a/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs +++ b/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs @@ -1,5 +1,6 @@ using System; using Kiota.Builder.Configuration; +using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Validations; namespace Kiota.Builder.Validation; @@ -13,18 +14,17 @@ public static void AddKiotaValidationRules(this ValidationRuleSet ruleSet, Gener configuration ??= new(); if (configuration.DisabledValidationRules.Contains(AllValidationRule)) return; - ruleSet.AddRuleIfEnabled(configuration, new NoServerEntry()); - ruleSet.AddRuleIfEnabled(configuration, new MultipleServerEntries()); - ruleSet.AddRuleIfEnabled(configuration, new GetWithBody()); - ruleSet.AddRuleIfEnabled(configuration, new KnownAndNotSupportedFormats()); - ruleSet.AddRuleIfEnabled(configuration, new InconsistentTypeFormatPair()); - ruleSet.AddRuleIfEnabled(configuration, new UrlFormEncodedComplex()); - ruleSet.AddRuleIfEnabled(configuration, new DivergentResponseSchema(configuration)); - ruleSet.AddRuleIfEnabled(configuration, new MissingDiscriminator(configuration)); + ruleSet.AddRuleIfEnabled(configuration, new NoServerEntry(), typeof(OpenApiDocument)); + ruleSet.AddRuleIfEnabled(configuration, new MultipleServerEntries(), typeof(OpenApiDocument)); + ruleSet.AddRuleIfEnabled(configuration, new GetWithBody(), typeof(OpenApiPathItem)); + ruleSet.AddRuleIfEnabled(configuration, new KnownAndNotSupportedFormats(), typeof(OpenApiSchema)); + ruleSet.AddRuleIfEnabled(configuration, new InconsistentTypeFormatPair(), typeof(OpenApiSchema)); + ruleSet.AddRuleIfEnabled(configuration, new UrlFormEncodedComplex(), typeof(OpenApiOperation)); + ruleSet.AddRuleIfEnabled(configuration, new DivergentResponseSchema(configuration), typeof(OpenApiOperation)); + ruleSet.AddRuleIfEnabled(configuration, new MissingDiscriminator(configuration), typeof(OpenApiDocument)); } - private static void AddRuleIfEnabled(this ValidationRuleSet ruleSet, GenerationConfiguration configuration, T instance) where T : ValidationRule + private static void AddRuleIfEnabled(this ValidationRuleSet ruleSet, GenerationConfiguration configuration, T instance, Type ruleType) where T : ValidationRule { - var ruleType = instance.GetType(); if (!configuration.DisabledValidationRules.Contains(ruleType.Name)) ruleSet.Add(ruleType, instance); } diff --git a/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs b/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs index 8ea2af1ff7..596fb20e7e 100644 --- a/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/DivergentResponseSchemaTests.cs @@ -96,7 +96,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new DivergentResponseSchema(new()); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(DivergentResponseSchema), [rule]); + settings.RuleSet.Add(typeof(OpenApiOperation), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs index 888c42230c..89ea47f7b1 100644 --- a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs @@ -84,7 +84,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new GetWithBody(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(GetWithBody), [rule]); + settings.RuleSet.Add(typeof(OpenApiPathItem), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs index c71ce5488d..4c3d61f8f3 100644 --- a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs @@ -81,7 +81,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new InconsistentTypeFormatPair(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(InconsistentTypeFormatPair), [rule]); + settings.RuleSet.Add(typeof(OpenApiSchema), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs index a568470f3c..abc24f3ac3 100644 --- a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs @@ -81,7 +81,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new KnownAndNotSupportedFormats(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(KnownAndNotSupportedFormats), [rule]); + settings.RuleSet.Add(typeof(OpenApiSchema), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs b/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs index 65bdb25849..efd89a1c2b 100644 --- a/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/MissingDiscriminatorTests.cs @@ -175,7 +175,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new MissingDiscriminator(new()); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(MissingDiscriminator), [rule]); + settings.RuleSet.Add(typeof(OpenApiDocument), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs b/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs index f19f86f5be..d6585196e9 100644 --- a/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/MultipleServerEntriesTests.cs @@ -59,7 +59,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new MultipleServerEntries(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(MultipleServerEntries), [rule]); + settings.RuleSet.Add(typeof(OpenApiDocument), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs b/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs index e63de927c3..ce59591fff 100644 --- a/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/NoContentWithBodyTests.cs @@ -77,7 +77,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new NoContentWithBody(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(NoContentWithBody), [rule]); + settings.RuleSet.Add(typeof(OpenApiOperation), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs b/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs index 26ac6d6355..cc488df6db 100644 --- a/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/NoServerEntryTests.cs @@ -54,7 +54,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new NoServerEntry(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(NoServerEntry), [rule]); + settings.RuleSet.Add(typeof(OpenApiDocument), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs b/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs index abef8864cf..3482735a3e 100644 --- a/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/UrlFormEncodedComplexTests.cs @@ -206,7 +206,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new UrlFormEncodedComplex(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(UrlFormEncodedComplex), [rule]); + settings.RuleSet.Add(typeof(OpenApiOperation), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); From f5b95b71abd4647aac63e111ba709129afb1bae3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 23 Dec 2024 08:25:42 -0500 Subject: [PATCH 27/96] fix: rules disablement did not work anymore Signed-off-by: Vincent Biret --- src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs | 2 +- .../Validation/ValidationRuleSetExtensionsTests.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs b/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs index e80f6c2005..523bbcfc3a 100644 --- a/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs +++ b/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs @@ -25,7 +25,7 @@ public static void AddKiotaValidationRules(this ValidationRuleSet ruleSet, Gener } private static void AddRuleIfEnabled(this ValidationRuleSet ruleSet, GenerationConfiguration configuration, T instance, Type ruleType) where T : ValidationRule { - if (!configuration.DisabledValidationRules.Contains(ruleType.Name)) + if (!configuration.DisabledValidationRules.Contains(typeof(T).Name)) ruleSet.Add(ruleType, instance); } } diff --git a/tests/Kiota.Builder.Tests/Validation/ValidationRuleSetExtensionsTests.cs b/tests/Kiota.Builder.Tests/Validation/ValidationRuleSetExtensionsTests.cs index 26800d8df4..1bba9f1448 100644 --- a/tests/Kiota.Builder.Tests/Validation/ValidationRuleSetExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/ValidationRuleSetExtensionsTests.cs @@ -33,7 +33,7 @@ public void DisablesNoRule() public void DisablesOneRule() { var ruleSet = new ValidationRuleSet(); - var configuration = new GenerationConfiguration { DisabledValidationRules = new() { nameof(NoServerEntry) } }; + var configuration = new GenerationConfiguration { DisabledValidationRules = [nameof(NoServerEntry)] }; ruleSet.AddKiotaValidationRules(configuration); Assert.NotEmpty(ruleSet.Rules); Assert.DoesNotContain(ruleSet.Rules, static x => x.GetType() == typeof(NoServerEntry)); From c539330cad9554b2f873ef1d877974e2ed46608f Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 23 Dec 2024 08:28:01 -0500 Subject: [PATCH 28/96] fix: invalid payload for unit test Signed-off-by: Vincent Biret --- .../OpenApiAiRespondingInstructionsExtensionTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiRespondingInstructionsExtensionTests.cs b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiRespondingInstructionsExtensionTests.cs index 158f280ea6..e900673fbc 100644 --- a/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiRespondingInstructionsExtensionTests.cs +++ b/tests/Kiota.Builder.Tests/OpenApiExtensions/OpenApiAiRespondingInstructionsExtensionTests.cs @@ -27,7 +27,7 @@ public void Parses() """ [ "This is a description", - "This is a description 2", + "This is a description 2" ] """; using var stream = new MemoryStream(Encoding.UTF8.GetBytes(oaiValueRepresentation)); From c1cbea987d29eb99f4a2135a823f9528aee48bae Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 23 Dec 2024 08:35:53 -0500 Subject: [PATCH 29/96] chore: improves validation tests performance for API export Signed-off-by: Vincent Biret --- .../Export/PublicAPIExportServiceTests.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/Kiota.Builder.Tests/Export/PublicAPIExportServiceTests.cs b/tests/Kiota.Builder.Tests/Export/PublicAPIExportServiceTests.cs index 51b4306f49..13465008e5 100644 --- a/tests/Kiota.Builder.Tests/Export/PublicAPIExportServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Export/PublicAPIExportServiceTests.cs @@ -73,7 +73,7 @@ public void Defensive() Assert.Throws(() => new PublicApiExportService(null)); } - private static readonly Dictionary> Validators = new() + private static readonly Dictionary>> Validators = new() { { GenerationLanguage.CSharp, ValidateExportCSharp }, { GenerationLanguage.Go, ValidateExportGo }, @@ -122,7 +122,7 @@ public async Task GeneratesExportsAndFileHasExpectedAssertionsAsync(GenerationLa Assert.NotEqual(0, outputStream.Length); // output is not empty using var streamReader = new StreamReader(outputStream); - var contents = (await streamReader.ReadToEndAsync()).Split(Environment.NewLine); + var contents = new HashSet((await streamReader.ReadToEndAsync()).Split(Environment.NewLine), StringComparer.Ordinal); if (!Validators.TryGetValue(generationLanguage, out var validator)) { @@ -132,7 +132,7 @@ public async Task GeneratesExportsAndFileHasExpectedAssertionsAsync(GenerationLa validator.Invoke(contents); } - private static void ValidateExportCSharp(string[] exportContents) + private static void ValidateExportCSharp(HashSet exportContents) { Assert.NotEmpty(exportContents); Assert.Contains("ExportNamespace.Graph-->BaseRequestBuilder", exportContents); // captures class inheritance @@ -145,7 +145,7 @@ private static void ValidateExportCSharp(string[] exportContents) Assert.Contains("ExportNamespace.Models.Microsoft.Graph.user::|public|OtherNames:List", exportContents);// captures collection info in language specific format } - private static void ValidateExportJava(string[] exportContents) + private static void ValidateExportJava(HashSet exportContents) { Assert.NotEmpty(exportContents); Assert.Contains("exportnamespace.Graph-->BaseRequestBuilder", exportContents); // captures class inheritance @@ -160,7 +160,7 @@ private static void ValidateExportJava(string[] exportContents) Assert.Contains("exportnamespace.models.microsoft.graph.User::|public|setOtherNames(value?:java.util.List):void", exportContents);// captures collection info in language specific format } - private static void ValidateExportGo(string[] exportContents) + private static void ValidateExportGo(HashSet exportContents) { Assert.NotEmpty(exportContents); Assert.Contains("exportNamespace.Graph-->*i2ae4187f7daee263371cb1c977df639813ab50ffa529013b7437480d1ec0158f.BaseRequestBuilder", exportContents); // captures class inheritance @@ -178,7 +178,7 @@ private static void ValidateExportGo(string[] exportContents) Assert.Contains("exportNamespace.models.microsoft.graph.user::|public|SetOtherNames(value:[]string):void", exportContents);// captures collection info in language specific format } - private static void ValidateExportPython(string[] exportContents) + private static void ValidateExportPython(HashSet exportContents) { Assert.NotEmpty(exportContents); Assert.Contains("exportNamespace.Graph-->BaseRequestBuilder", exportContents); // captures class inheritance @@ -193,7 +193,7 @@ private static void ValidateExportPython(string[] exportContents) Assert.Contains("exportNamespace.models.microsoft.graph.User::|public|other_names(value:List[str]):None", exportContents);// captures collection info in language specific format } - private static void ValidateExportTypeScript(string[] exportContents) + private static void ValidateExportTypeScript(HashSet exportContents) { Assert.NotEmpty(exportContents); Assert.Contains("exportNamespace.Graph~~>BaseRequestBuilder", exportContents); // captures class inheritance. TS does not do inheritance due to interfaces. @@ -210,7 +210,7 @@ private static void ValidateExportTypeScript(string[] exportContents) Assert.Contains("exportNamespace.models.microsoft.graph.User::|public|otherNames:string[]", exportContents);// captures collection info in language specific format } - private static void ValidateExportPhp(string[] exportContents) + private static void ValidateExportPhp(HashSet exportContents) { Assert.NotEmpty(exportContents); Assert.Contains("exportNamespace.Graph-->BaseRequestBuilder", exportContents); // captures class inheritance From 3cdd3d4a932fcf277e3e3bb9ec5b54e2d91b53e5 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 23 Dec 2024 08:48:35 -0500 Subject: [PATCH 30/96] fix: document path for manifest generation tests Signed-off-by: Vincent Biret --- .../Plugins/PluginsGenerationServiceTests.cs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs index ddc6a98d9f..15d39158c0 100644 --- a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs @@ -75,13 +75,12 @@ public async Task GeneratesManifestAsync(string inputPluginName, string expected var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; await File.WriteAllTextAsync(simpleDescriptionPath, simpleDescriptionContent); - var mockLogger = new Mock>(); var openAPIDocumentDS = new OpenApiDocumentDownloadService(_httpClient, _logger); var outputDirectory = Path.Combine(workingDirectory, "output"); var generationConfiguration = new GenerationConfiguration { OutputPath = outputDirectory, - OpenAPIFilePath = "openapiPath", + OpenAPIFilePath = simpleDescriptionPath, PluginTypes = [PluginType.APIPlugin, PluginType.APIManifest, PluginType.OpenAI], ClientClassName = inputPluginName, ApiRootUrl = "http://localhost/", //Kiota builder would set this for us @@ -234,7 +233,7 @@ public async Task GeneratesManifestAndCleansUpInputDescriptionAsync() var generationConfiguration = new GenerationConfiguration { OutputPath = outputDirectory, - OpenAPIFilePath = "openapiPath", + OpenAPIFilePath = simpleDescriptionPath, PluginTypes = [PluginType.APIPlugin], ClientClassName = "client", ApiRootUrl = "http://localhost/", //Kiota builder would set this for us @@ -487,13 +486,12 @@ public async Task GeneratesManifestWithAuthAsync(string securitySchemesComponent var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; await File.WriteAllTextAsync(simpleDescriptionPath, apiDescription); - var mockLogger = new Mock>(); var openApiDocumentDs = new OpenApiDocumentDownloadService(_httpClient, _logger); var outputDirectory = Path.Combine(workingDirectory, "output"); var generationConfiguration = new GenerationConfiguration { OutputPath = outputDirectory, - OpenAPIFilePath = "openapiPath", + OpenAPIFilePath = simpleDescriptionPath, PluginTypes = [PluginType.APIPlugin], ClientClassName = "client", ApiRootUrl = "http://localhost/", //Kiota builder would set this for us @@ -566,13 +564,12 @@ public async Task GeneratesManifestWithMultipleSecuritySchemesAsync() var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; await File.WriteAllTextAsync(simpleDescriptionPath, apiDescription); - var mockLogger = new Mock>(); var openApiDocumentDs = new OpenApiDocumentDownloadService(_httpClient, _logger); var outputDirectory = Path.Combine(workingDirectory, "output"); var generationConfiguration = new GenerationConfiguration { OutputPath = outputDirectory, - OpenAPIFilePath = "openapiPath", + OpenAPIFilePath = simpleDescriptionPath, PluginTypes = [PluginType.APIPlugin], ClientClassName = "client", ApiRootUrl = "http://localhost/", //Kiota builder would set this for us @@ -777,7 +774,7 @@ public async Task MergesAllOfRequestBodyAsync(string content, Action Date: Mon, 23 Dec 2024 08:50:26 -0500 Subject: [PATCH 31/96] fix: invalid type for test data Signed-off-by: Vincent Biret --- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 0bfb1abd3d..8f5c549c47 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -7717,7 +7717,8 @@ public async Task CleanupSymbolNameDoesNotCauseNameConflictsInQueryParametersAsy - name: select in: query schema: - type: int64 + type: number + format: int64 responses: '200': content: From 1886d77a23316cb05000cbe06dbe711edd483269 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 23 Dec 2024 08:58:07 -0500 Subject: [PATCH 32/96] chore: linting removes unnecessary string interpolation Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index cda9fd26d4..9317f30fe4 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -539,18 +539,18 @@ public CodeNamespace CreateSourceModel(OpenApiUrlTreeNode? root) var codeNamespace = rootNamespace.AddNamespace(config.ClientNamespaceName); modelsNamespace = rootNamespace.AddNamespace(config.ModelsNamespaceName); InitializeInheritanceIndex(); - StopLogAndReset(stopwatch, $"{nameof(InitializeInheritanceIndex)}"); + StopLogAndReset(stopwatch, nameof(InitializeInheritanceIndex)); if (root != null) { CreateRequestBuilderClass(codeNamespace, root, root); - StopLogAndReset(stopwatch, $"{nameof(CreateRequestBuilderClass)}"); + StopLogAndReset(stopwatch, nameof(CreateRequestBuilderClass)); stopwatch.Start(); MapTypeDefinitions(codeNamespace); - StopLogAndReset(stopwatch, $"{nameof(MapTypeDefinitions)}"); + StopLogAndReset(stopwatch, nameof(MapTypeDefinitions)); TrimInheritedModels(); - StopLogAndReset(stopwatch, $"{nameof(TrimInheritedModels)}"); + StopLogAndReset(stopwatch, nameof(TrimInheritedModels)); CleanUpInternalState(); - StopLogAndReset(stopwatch, $"{nameof(CleanUpInternalState)}"); + StopLogAndReset(stopwatch, nameof(CleanUpInternalState)); logger.LogTrace("{Timestamp}ms: Created source model with {Count} classes", stopwatch.ElapsedMilliseconds, codeNamespace.GetChildElements(true).Count()); } From 7f16e6b781a929ce737c3594e993d5a5c94d51ca Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 23 Dec 2024 09:46:08 -0500 Subject: [PATCH 33/96] fix: navigation properties type generation Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 63 ++++++++++++------------------- 1 file changed, 24 insertions(+), 39 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 9317f30fe4..c466d3ed4b 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1091,7 +1091,7 @@ private CodeIndexer[] CreateIndexer(string childIdentifier, string childType, Co var propertyName = childIdentifier.CleanupSymbolName(); if (structuralPropertiesReservedNameProvider.ReservedNames.Contains(propertyName)) propertyName += "Property"; - var resultType = existingType ?? GetPrimitiveType(propertySchema); + var resultType = existingType ?? GetPrimitiveType(propertySchema, childType); if ((propertySchema?.Items?.IsEnum() ?? false) && resultType is CodeType codeType) codeType.Name = childType; if (resultType == null) return null; @@ -1131,7 +1131,7 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten return prop; } private static readonly HashSet typeNamesToSkip = [JsonSchemaType.Object, JsonSchemaType.Array]; - private static CodeType? GetPrimitiveType(OpenApiSchema? typeSchema) + private static CodeType? GetPrimitiveType(OpenApiSchema? typeSchema, string? childType = default) { var typeNames = new List { typeSchema?.Items?.Type, typeSchema?.Type }; if (typeSchema?.AnyOf?.Any() ?? false) @@ -1141,45 +1141,30 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten // first value that's not null, and not "object" for primitive collections, the items type matters var typeName = typeNames.Find(static x => x is not null && !typeNamesToSkip.Contains(x.Value)); - var isExternal = false; var format = typeSchema?.Format ?? typeSchema?.Items?.Format; - var primitiveTypeName = (typeName, format?.ToLowerInvariant()) switch - { - (JsonSchemaType.String, "base64url") => "base64url", - (JsonSchemaType.String, "duration") => "TimeSpan", - (JsonSchemaType.String, "time") => "TimeOnly", - (JsonSchemaType.String, "date") => "DateOnly", - (JsonSchemaType.String, "date-time") => "DateTimeOffset", - (JsonSchemaType.String, "uuid") => "Guid", - (JsonSchemaType.String, _) => "string", // covers commonmark and html - (JsonSchemaType.Number, "double" or "float" or "decimal") => format.ToLowerInvariant(), - (JsonSchemaType.Number or JsonSchemaType.Integer, "int8") => "sbyte", - (JsonSchemaType.Number or JsonSchemaType.Integer, "uint8") => "byte", - (JsonSchemaType.Number or JsonSchemaType.Integer, "int64") => "int64", - (JsonSchemaType.Number, "int16") => "integer", - (JsonSchemaType.Number, "int32") => "integer", - (JsonSchemaType.Number, _) => "double", - (JsonSchemaType.Integer, _) => "integer", - (JsonSchemaType.Boolean, _) => "boolean", - (_, "byte") => "base64", - (_, "binary") => "binary", + return (typeName, format?.ToLowerInvariant()) switch + { + (JsonSchemaType.String, "base64url") => new CodeType { Name = "base64url", IsExternal = true }, + (JsonSchemaType.String, "duration") => new CodeType { Name = "TimeSpan", IsExternal = true }, + (JsonSchemaType.String, "time") => new CodeType { Name = "TimeOnly", IsExternal = true }, + (JsonSchemaType.String, "date") => new CodeType { Name = "DateOnly", IsExternal = true }, + (JsonSchemaType.String, "date-time") => new CodeType { Name = "DateTimeOffset", IsExternal = true }, + (JsonSchemaType.String, "uuid") => new CodeType { Name = "Guid", IsExternal = true }, + (JsonSchemaType.String, _) => new CodeType { Name = "string", IsExternal = true }, // covers commonmark and html + (JsonSchemaType.Number, "double" or "float" or "decimal") => new CodeType { Name = format.ToLowerInvariant(), IsExternal = true }, + (JsonSchemaType.Number or JsonSchemaType.Integer, "int8") => new CodeType { Name = "sbyte", IsExternal = true }, + (JsonSchemaType.Number or JsonSchemaType.Integer, "uint8") => new CodeType { Name = "byte", IsExternal = true }, + (JsonSchemaType.Number or JsonSchemaType.Integer, "int64") => new CodeType { Name = "int64", IsExternal = true }, + (JsonSchemaType.Number, "int16") => new CodeType { Name = "integer", IsExternal = true }, + (JsonSchemaType.Number, "int32") => new CodeType { Name = "integer", IsExternal = true }, + (JsonSchemaType.Number, _) => new CodeType { Name = "double", IsExternal = true }, + (JsonSchemaType.Integer, _) => new CodeType { Name = "integer", IsExternal = true }, + (JsonSchemaType.Boolean, _) => new CodeType { Name = "boolean", IsExternal = true }, + (_, "byte") => new CodeType { Name = "base64", IsExternal = true }, + (_, "binary") => new CodeType { Name = "binary", IsExternal = true }, //TODO handle the case where we have multiple entries - (_, _) => string.Empty, - }; - if (!string.IsNullOrEmpty(primitiveTypeName)) - { - return new CodeType - { - Name = primitiveTypeName, - IsExternal = true, - }; - } - if (typeName is null || typeName.ToIdentifier() is not string normalizedTypeName || string.IsNullOrEmpty(normalizedTypeName)) - return null; - return new CodeType - { - Name = normalizedTypeName, - IsExternal = isExternal, + (_, _) when !string.IsNullOrEmpty(childType) => new CodeType { Name = childType, IsExternal = false, }, + (_, _) => null, }; } private const string RequestBodyPlainTextContentType = "text/plain"; From 118e5242a2d98c020e7983e29dafd8c833294f79 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 23 Dec 2024 10:13:04 -0500 Subject: [PATCH 34/96] fix: binary and byte format mapping Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 4 ++-- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index c466d3ed4b..9e6c72eb5e 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1144,6 +1144,8 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten var format = typeSchema?.Format ?? typeSchema?.Items?.Format; return (typeName, format?.ToLowerInvariant()) switch { + (_, "byte") => new CodeType { Name = "base64", IsExternal = true }, + (_, "binary") => new CodeType { Name = "binary", IsExternal = true }, (JsonSchemaType.String, "base64url") => new CodeType { Name = "base64url", IsExternal = true }, (JsonSchemaType.String, "duration") => new CodeType { Name = "TimeSpan", IsExternal = true }, (JsonSchemaType.String, "time") => new CodeType { Name = "TimeOnly", IsExternal = true }, @@ -1160,8 +1162,6 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten (JsonSchemaType.Number, _) => new CodeType { Name = "double", IsExternal = true }, (JsonSchemaType.Integer, _) => new CodeType { Name = "integer", IsExternal = true }, (JsonSchemaType.Boolean, _) => new CodeType { Name = "boolean", IsExternal = true }, - (_, "byte") => new CodeType { Name = "base64", IsExternal = true }, - (_, "binary") => new CodeType { Name = "binary", IsExternal = true }, //TODO handle the case where we have multiple entries (_, _) when !string.IsNullOrEmpty(childType) => new CodeType { Name = childType, IsExternal = false, }, (_, _) => null, diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 8f5c549c47..6a2c929781 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -7871,7 +7871,7 @@ public async Task SupportsMultiPartFormAsRequestBodyWithoutEncodingWithDefaultMi var bodyParameter = postMethod.Parameters.FirstOrDefault(static x => x.IsOfKind(CodeParameterKind.RequestBody)); Assert.NotNull(bodyParameter); Assert.Equal("MultipartBody", bodyParameter.Type.Name, StringComparer.OrdinalIgnoreCase); - var addressClass = codeModel.FindChildByName("Address"); + var addressClass = codeModel.FindChildByName("Address"); // json is structured, we generated a model Assert.NotNull(addressClass); } [Fact] @@ -7929,9 +7929,8 @@ public async Task SupportsMultiPartFormAsRequestBodyWithoutEncodingWithDefaultMi Assert.NotNull(postMethod); var bodyParameter = postMethod.Parameters.FirstOrDefault(static x => x.IsOfKind(CodeParameterKind.RequestBody)); Assert.NotNull(bodyParameter); - Assert.Equal("DirectoryObjectPostRequestBody", bodyParameter.Type.Name, StringComparer.OrdinalIgnoreCase); //generate the model type as we do not have the serializer for the schema registered. - var addressClass = codeModel.FindChildByName("Address"); - Assert.NotNull(addressClass); + Assert.Equal("MultipartBody", bodyParameter.Type.Name, StringComparer.OrdinalIgnoreCase); + Assert.Null(codeModel.FindChildByName("Address")); // json is not structured so we didn't generate a model for the address } [Fact] public async Task SupportsMultipleContentTypesAsRequestBodyWithDefaultMimeTypesAsync() From 8782bd6a6054b57f7f11735bdb64a8bbd35e7b8d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 23 Dec 2024 10:35:32 -0500 Subject: [PATCH 35/96] fix: enum values number parsing Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 4 ++-- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 9e6c72eb5e..8a47e6a4d9 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1945,8 +1945,8 @@ private static void SetEnumOptions(OpenApiSchema schema, CodeEnum target) if (schema.Extensions.TryGetValue(OpenApiEnumValuesDescriptionExtension.Name, out var rawExtension) && rawExtension is OpenApiEnumValuesDescriptionExtension localExtInfo) extensionInformation = localExtInfo; target.AddOption(schema.Enum.OfType() - .Where(static x => x.GetValueKind() is JsonValueKind.String) - .Select(static x => x.GetValue()) + .Where(static x => x.GetValueKind() is JsonValueKind.String or JsonValueKind.Number) + .Select(static x => x.GetValueKind() is JsonValueKind.String ? x.GetValue() : x.GetValue().ToString(CultureInfo.InvariantCulture)) .Where(static x => !string.IsNullOrEmpty(x)) .Distinct(StringComparer.OrdinalIgnoreCase) .Select((x) => diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 6a2c929781..88b05cd08c 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -427,7 +427,7 @@ public async Task ParsesEnumDescriptionsAsync() StorageAccountType: type: string enum: - - +1 + - '+1' - -1 - Standard_LRS - Standard_ZRS @@ -439,7 +439,7 @@ public async Task ParsesEnumDescriptionsAsync() name: AccountType modelAsString: false values: - - value: +1 + - value: '+1' - value: -1 - value: Standard_LRS description: Locally redundant storage. From 1ca8341f93d88e3963acd226dab00f53bd1bf53c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 24 Dec 2024 10:12:15 -0500 Subject: [PATCH 36/96] chore: bumps oai.net preview version --- src/Kiota.Builder/Kiota.Builder.csproj | 4 ++-- src/kiota/kiota.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index 711f420863..6fcc1b6710 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -44,9 +44,9 @@ - + - + diff --git a/src/kiota/kiota.csproj b/src/kiota/kiota.csproj index 3a39216ede..2e2cb8fef4 100644 --- a/src/kiota/kiota.csproj +++ b/src/kiota/kiota.csproj @@ -47,7 +47,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all From 7a7ca1a3dc28677e02cb12adab90db16ac1cabae Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 2 Jan 2025 08:32:04 -0500 Subject: [PATCH 37/96] fix: tolerate more than strings for comparisons --- src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs index 1d7b2c1fcb..2505515d5f 100644 --- a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs +++ b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs @@ -151,7 +151,7 @@ public bool Equals(JsonNode? x, JsonNode? y) { if (x is null || y is null) return object.Equals(x, y); // TODO: Can we use the OpenAPI.NET implementation of Equals? - return x.GetValueKind() == y.GetValueKind() && string.Equals(x.GetValue(), y.GetValue(), StringComparison.OrdinalIgnoreCase); + return x.GetValueKind() == y.GetValueKind() && string.Equals(x.ToJsonString(), y.ToJsonString(), StringComparison.OrdinalIgnoreCase); } /// public int GetHashCode([DisallowNull] JsonNode obj) From f54ee9e37cec9b1c5836e302954a9fed62743173 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 2 Jan 2025 09:24:34 -0500 Subject: [PATCH 38/96] chore: updates api manifest reference Signed-off-by: Vincent Biret --- src/Kiota.Builder/Kiota.Builder.csproj | 2 +- src/kiota/kiota.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index 6fcc1b6710..65a9f42abb 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -45,7 +45,7 @@ - + diff --git a/src/kiota/kiota.csproj b/src/kiota/kiota.csproj index 2e2cb8fef4..cd1499a732 100644 --- a/src/kiota/kiota.csproj +++ b/src/kiota/kiota.csproj @@ -46,7 +46,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive From 3fe029434aef07aa377f04271c7b3984355b0cd3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 2 Jan 2025 09:26:29 -0500 Subject: [PATCH 39/96] fix: references to schema type after merge Signed-off-by: Vincent Biret --- .../OpenApiSchemaExtensionsTests.cs | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index 360aae6822..e34351bc89 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -681,7 +681,7 @@ public void DoesMergeWithInheritance() { var schema = new OpenApiSchema() { - Type = "object", + Type = JsonSchemaType.Object, AnyOf = [ new() @@ -701,7 +701,7 @@ public void DoesMergeWithInheritance() }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), @@ -726,7 +726,7 @@ public void DoesMergeWithIntersection() { var schema = new OpenApiSchema() { - Type = "object", + Type = JsonSchemaType.Object, AnyOf = [ new() @@ -739,7 +739,7 @@ public void DoesMergeWithIntersection() [ new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["first"] = new OpenApiSchema(), @@ -747,7 +747,7 @@ public void DoesMergeWithIntersection() }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["second"] = new OpenApiSchema(), @@ -755,7 +755,7 @@ public void DoesMergeWithIntersection() }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["third"] = new OpenApiSchema(), @@ -779,7 +779,7 @@ public void DoesNotMergeWithMoreThanOneInclusiveEntry() { var schema = new OpenApiSchema() { - Type = "object", + Type = JsonSchemaType.Object, AnyOf = [ new() @@ -799,7 +799,7 @@ public void DoesNotMergeWithMoreThanOneInclusiveEntry() }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), @@ -808,7 +808,7 @@ public void DoesNotMergeWithMoreThanOneInclusiveEntry() }, ] }, - new() { Type = "object" }, + new() { Type = JsonSchemaType.Object }, ], }; @@ -820,7 +820,7 @@ public void DoesNotMergeWithoutInheritanceOrIntersection() { var schema = new OpenApiSchema() { - Type = "object", + Type = JsonSchemaType.Object, AnyOf = [ new() @@ -829,7 +829,7 @@ public void DoesNotMergeWithoutInheritanceOrIntersection() [ new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), @@ -853,7 +853,7 @@ public void DoesMergeWithInheritance() { var schema = new OpenApiSchema() { - Type = "object", + Type = JsonSchemaType.Object, OneOf = [ new() @@ -873,7 +873,7 @@ public void DoesMergeWithInheritance() }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), @@ -898,7 +898,7 @@ public void DoesMergeWithIntersection() { var schema = new OpenApiSchema() { - Type = "object", + Type = JsonSchemaType.Object, OneOf = [ new() @@ -911,7 +911,7 @@ public void DoesMergeWithIntersection() [ new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["first"] = new OpenApiSchema(), @@ -919,7 +919,7 @@ public void DoesMergeWithIntersection() }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["second"] = new OpenApiSchema(), @@ -927,7 +927,7 @@ public void DoesMergeWithIntersection() }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["third"] = new OpenApiSchema(), @@ -951,7 +951,7 @@ public void DoesNotMergeWithMoreThanOneExclusiveEntry() { var schema = new OpenApiSchema() { - Type = "object", + Type = JsonSchemaType.Object, OneOf = [ new() @@ -971,7 +971,7 @@ public void DoesNotMergeWithMoreThanOneExclusiveEntry() }, new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), @@ -980,7 +980,7 @@ public void DoesNotMergeWithMoreThanOneExclusiveEntry() }, ] }, - new() { Type = "object" }, + new() { Type = JsonSchemaType.Object }, ], }; @@ -992,7 +992,7 @@ public void DoesNotMergeWithoutInheritanceOrIntersection() { var schema = new OpenApiSchema() { - Type = "object", + Type = JsonSchemaType.Object, OneOf = [ new() @@ -1001,7 +1001,7 @@ public void DoesNotMergeWithoutInheritanceOrIntersection() [ new() { - Type = "object", + Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), From fbfd05da80811d903a4a4210c2eb01ac1daf127f Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 8 Jan 2025 09:43:38 -0500 Subject: [PATCH 40/96] chore; upgrades plugin manifest lib to align oai.net versions Signed-off-by: Vincent Biret --- src/Kiota.Builder/Kiota.Builder.csproj | 2 +- .../Plugins/PluginsGenerationServiceTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index d4208ba545..4d19956f95 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -47,7 +47,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs index 15d39158c0..db7d7b1072 100644 --- a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs @@ -279,7 +279,7 @@ public async Task GeneratesManifestAndCleansUpInputDescriptionAsync() // Validate the output open api file using var resultOpenApiFile = File.OpenRead(Path.Combine(outputDirectory, OpenApiFileName)); - var resultResult = await OpenApiDocument.LoadAsync(originalOpenApiFile, "yaml"); + var resultResult = await OpenApiDocument.LoadAsync(resultOpenApiFile, "yaml"); var resultDocument = resultResult.Document; Assert.Empty(resultResult.Diagnostic.Errors); @@ -521,7 +521,7 @@ public async Task GeneratesManifestWithAuthAsync(string securitySchemesComponent // Cleanup try { - Directory.Delete(outputDirectory); + Directory.Delete(outputDirectory, true); } catch (Exception) { From e2a6e20ddcd3b3b1e7ac04bf42c86ad8c2a68a9a Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 8 Jan 2025 10:54:54 -0500 Subject: [PATCH 41/96] fix: adds missing serialization settings to get schemas inlined Signed-off-by: Vincent Biret --- src/Kiota.Builder/Plugins/PluginsGenerationService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index 58a3458cbc..abdcb36495 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -59,7 +59,7 @@ public async Task GenerateManifestAsync(CancellationToken cancellationToken = de await using var descriptionStream = File.Create(descriptionFullPath, 4096); await using var fileWriter = new StreamWriter(descriptionStream); #pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task - var descriptionWriter = new OpenApiYamlWriter(fileWriter); + var descriptionWriter = new OpenApiYamlWriter(fileWriter, new() { InlineLocalReferences = true, InlineExternalReferences = true }); var trimmedPluginDocument = GetDocumentWithTrimmedComponentsAndResponses(OAIDocument); PrepareDescriptionForCopilot(trimmedPluginDocument); // trimming a second time to remove any components that are no longer used after the inlining From f50764500f2d4589606d9735e848ceffc47dd8fb Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 8 Jan 2025 17:45:22 -0500 Subject: [PATCH 42/96] fix: updates to latest OAI.net async changes --- src/Kiota.Builder/KiotaBuilder.cs | 10 ++++++++-- src/Kiota.Builder/Plugins/PluginsGenerationService.cs | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 3ffedba64e..fc01a0045e 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -190,7 +190,8 @@ private static string NormalizeApiManifestPath(RequestInfo request, string? base // Should Generate sw.Start(); - shouldGenerate &= await workspaceManagementService.ShouldGenerateAsync(config, openApiDocument.HashCode, cancellationToken).ConfigureAwait(false); + var hashCode = await openApiDocument.GetHashCodeAsync(cancellationToken).ConfigureAwait(false); + shouldGenerate &= await workspaceManagementService.ShouldGenerateAsync(config, hashCode, cancellationToken).ConfigureAwait(false); StopLogAndReset(sw, $"step {++stepId} - checking whether the output should be updated - took"); if (shouldGenerate && generating) @@ -343,7 +344,12 @@ private async Task FinalizeWorkspaceAsync(Stopwatch sw, int stepId, OpenApiUrlTr // Write lock file sw.Start(); using var descriptionStream = !isDescriptionFromWorkspaceCopy ? await LoadStreamAsync(inputPath, cancellationToken).ConfigureAwait(false) : Stream.Null; - await workspaceManagementService.UpdateStateFromConfigurationAsync(config, openApiDocument?.HashCode ?? string.Empty, openApiTree?.GetRequestInfo().ToDictionary(static x => x.Key, static x => x.Value) ?? [], descriptionStream, cancellationToken).ConfigureAwait(false); + var hashCode = openApiDocument switch + { + null => string.Empty, + _ => await openApiDocument.GetHashCodeAsync(cancellationToken).ConfigureAwait(false), + }; + await workspaceManagementService.UpdateStateFromConfigurationAsync(config, hashCode, openApiTree?.GetRequestInfo().ToDictionary(static x => x.Key, static x => x.Value) ?? [], descriptionStream, cancellationToken).ConfigureAwait(false); StopLogAndReset(sw, $"step {++stepId} - writing lock file - took"); } private readonly WorkspaceManagementService workspaceManagementService; diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index abdcb36495..bb7107cdc5 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -66,7 +66,7 @@ public async Task GenerateManifestAsync(CancellationToken cancellationToken = de trimmedPluginDocument = GetDocumentWithTrimmedComponentsAndResponses(trimmedPluginDocument); trimmedPluginDocument.Info.Title = trimmedPluginDocument.Info.Title[..^9]; // removing the second ` - Subset` suffix from the title trimmedPluginDocument.SerializeAsV3(descriptionWriter); - descriptionWriter.Flush(); + await descriptionWriter.FlushAsync(cancellationToken).ConfigureAwait(false); // 3. write the plugins From a4e0a0ff90b65f55956a496b1704838d21372095 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 20 Jan 2025 15:40:28 -0500 Subject: [PATCH 43/96] fix: defensive programming Signed-off-by: Vincent Biret --- src/Kiota.Builder/Plugins/OpenApiPluginWalker.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Kiota.Builder/Plugins/OpenApiPluginWalker.cs b/src/Kiota.Builder/Plugins/OpenApiPluginWalker.cs index 245dd014ac..4ce8bf152f 100644 --- a/src/Kiota.Builder/Plugins/OpenApiPluginWalker.cs +++ b/src/Kiota.Builder/Plugins/OpenApiPluginWalker.cs @@ -18,6 +18,9 @@ public class OpenApiPluginWalker : OpenApiVisitorBase public override void Visit(IOpenApiExtensible openApiExtensible) { ArgumentNullException.ThrowIfNull(openApiExtensible); + if (openApiExtensible.Extensions is not { Count: > 0 }) + return; + // remove any extensions we do not support foreach (var extension in openApiExtensible.Extensions.Where(static extension => !SupportedExtensions.Contains(extension.Key))) { @@ -31,6 +34,9 @@ public override void Visit(OpenApiResponses response) { ArgumentNullException.ThrowIfNull(response); + if (response.Count < 1) + return; + // Ensure description strings are not empty strings. foreach (var responseItem in response.Where(static res => string.IsNullOrEmpty(res.Value.Description))) { From 3010bf2c5372d16b87f3f5b0b0eddbcf2765678c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 21 Jan 2025 08:06:11 -0500 Subject: [PATCH 44/96] chore: bumps to latest oai.net preview --- src/Kiota.Builder/Kiota.Builder.csproj | 4 ++-- src/kiota/kiota.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index 197261b3f7..4546b4df31 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -44,9 +44,9 @@ - + - + diff --git a/src/kiota/kiota.csproj b/src/kiota/kiota.csproj index c63e2928dc..9d6b53b387 100644 --- a/src/kiota/kiota.csproj +++ b/src/kiota/kiota.csproj @@ -47,7 +47,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all From 0a548090f0ec04f65625e42c137200f227362aac Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 3 Feb 2025 13:33:07 -0500 Subject: [PATCH 45/96] fix: updates reference code for preview6 in main projects --- .../OpenApiSchemaReferenceComparer.cs | 20 ++- .../OpenApiDeprecationExtensionExtensions.cs | 5 +- .../Extensions/OpenApiDocumentExtensions.cs | 3 +- .../Extensions/OpenApiOperationExtensions.cs | 13 +- .../Extensions/OpenApiReferenceExtensions.cs | 12 -- .../Extensions/OpenApiSchemaExtensions.cs | 159 ++++++++++-------- .../OpenApiUrlTreeNodeExtensions.cs | 52 ++++-- src/Kiota.Builder/KiotaBuilder.cs | 102 +++++------ .../Plugins/PluginsGenerationService.cs | 151 +++++++++-------- .../Validation/MissingDiscriminator.cs | 7 +- .../Validation/OpenApiSchemaComparer.cs | 15 +- 11 files changed, 289 insertions(+), 250 deletions(-) delete mode 100644 src/Kiota.Builder/Extensions/OpenApiReferenceExtensions.cs diff --git a/src/Kiota.Builder/EqualityComparers/OpenApiSchemaReferenceComparer.cs b/src/Kiota.Builder/EqualityComparers/OpenApiSchemaReferenceComparer.cs index 588bfde78c..ceb2097b2c 100644 --- a/src/Kiota.Builder/EqualityComparers/OpenApiSchemaReferenceComparer.cs +++ b/src/Kiota.Builder/EqualityComparers/OpenApiSchemaReferenceComparer.cs @@ -1,28 +1,30 @@ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; namespace Kiota.Builder.EqualityComparers; -internal class OpenApiSchemaReferenceComparer(StringComparer? stringComparer = null) : IEqualityComparer +internal class OpenApiSchemaReferenceComparer(StringComparer? stringComparer = null) : IEqualityComparer { private readonly StringComparer _stringComparer = stringComparer ?? StringComparer.OrdinalIgnoreCase; - public bool Equals(OpenApiSchema? x, OpenApiSchema? y) + public bool Equals(IOpenApiSchema? x, IOpenApiSchema? y) { - if (string.IsNullOrEmpty(x?.Reference?.Id) || string.IsNullOrEmpty(y?.Reference?.Id)) return object.Equals(x, y); - return _stringComparer.Equals(x.Reference.Id, y.Reference.Id); + if (x is not OpenApiSchemaReference xRef || y is not OpenApiSchemaReference yRef) return object.Equals(x, y); + return _stringComparer.Equals(xRef.Reference.Id, yRef.Reference.Id); } - public int GetHashCode([DisallowNull] OpenApiSchema obj) + public int GetHashCode([DisallowNull] IOpenApiSchema obj) { + if (obj is not OpenApiSchemaReference objRef) return obj.GetHashCode(); var hash = new HashCode(); - if (!string.IsNullOrEmpty(obj.Reference?.Id)) + if (!string.IsNullOrEmpty(objRef.Reference?.Id)) { - hash.Add(obj.Reference.Id, _stringComparer); + hash.Add(objRef.Reference.Id, _stringComparer); } else { - hash.Add(obj); + hash.Add(objRef); } return hash.ToHashCode(); diff --git a/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs index 8d29cd92ba..b4fbd3f267 100644 --- a/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs @@ -3,6 +3,7 @@ using Kiota.Builder.CodeDOM; using Microsoft.OpenApi.MicrosoftExtensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; namespace Kiota.Builder.Extensions; @@ -12,13 +13,13 @@ internal static DeprecationInformation ToDeprecationInformation(this OpenApiDepr { return new DeprecationInformation(value.Description.CleanupDescription().CleanupXMLString(), value.Date, value.RemovalDate, value.Version.CleanupDescription().CleanupXMLString(), true); } - internal static DeprecationInformation GetDeprecationInformation(this OpenApiSchema schema) + internal static DeprecationInformation GetDeprecationInformation(this IOpenApiSchema schema) { if (schema.Deprecated && schema.Extensions.TryGetValue(OpenApiDeprecationExtension.Name, out var deprecatedExtension) && deprecatedExtension is OpenApiDeprecationExtension deprecatedValue) return deprecatedValue.ToDeprecationInformation(); return new(null, null, null, null, schema.Deprecated); } - internal static DeprecationInformation GetDeprecationInformation(this OpenApiParameter parameter) + internal static DeprecationInformation GetDeprecationInformation(this IOpenApiParameter parameter) { if (parameter.Deprecated && parameter.Extensions.TryGetValue(OpenApiDeprecationExtension.Name, out var deprecatedExtension) && deprecatedExtension is OpenApiDeprecationExtension deprecatedValue) return deprecatedValue.ToDeprecationInformation(); diff --git a/src/Kiota.Builder/Extensions/OpenApiDocumentExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiDocumentExtensions.cs index a655a79f12..04fd3d6e9f 100644 --- a/src/Kiota.Builder/Extensions/OpenApiDocumentExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiDocumentExtensions.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Kiota.Builder.EqualityComparers; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; namespace Kiota.Builder.Extensions; @@ -19,7 +20,7 @@ internal static void InitializeInheritanceIndex(this OpenApiDocument openApiDocu { inheritanceIndex.TryAdd(entry.Key, new(StringComparer.OrdinalIgnoreCase)); if (entry.Value.AllOf != null) - foreach (var allOfEntry in entry.Value.AllOf.Where(static x => !string.IsNullOrEmpty(x.Reference?.Id))) + foreach (var allOfEntry in entry.Value.AllOf.OfType()) { var dependents = inheritanceIndex.GetOrAdd(allOfEntry.Reference.Id, new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase)); dependents.TryAdd(entry.Key, false); diff --git a/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs index 23c7659f88..194683e0cd 100644 --- a/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs @@ -3,6 +3,7 @@ using System.Linq; using Kiota.Builder.Configuration; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Kiota.Builder.Extensions; public static class OpenApiOperationExtensions @@ -21,14 +22,14 @@ private static string vendorSpecificCleanup(string input) /// /// cleans application/vnd.github.mercy-preview+json to application/json /// - internal static OpenApiSchema? GetResponseSchema(this OpenApiOperation operation, StructuredMimeTypesCollection structuredMimeTypes) + internal static IOpenApiSchema? GetResponseSchema(this OpenApiOperation operation, StructuredMimeTypesCollection structuredMimeTypes) { ArgumentNullException.ThrowIfNull(operation); // Return Schema that represents all the possible success responses! return operation.GetResponseSchemas(SuccessCodes, structuredMimeTypes) .FirstOrDefault(); } - internal static IEnumerable GetResponseSchemas(this OpenApiOperation operation, HashSet successCodesToUse, StructuredMimeTypesCollection structuredMimeTypes) + internal static IEnumerable GetResponseSchemas(this OpenApiOperation operation, HashSet successCodesToUse, StructuredMimeTypesCollection structuredMimeTypes) { if (operation.Responses is null) return []; // Return Schema that represents all the possible success responses! @@ -36,7 +37,7 @@ internal static IEnumerable GetResponseSchemas(this OpenApiOperat .OrderBy(static x => x.Key, StringComparer.OrdinalIgnoreCase) .SelectMany(re => re.Value.Content.GetValidSchemas(structuredMimeTypes)); } - internal static OpenApiSchema? GetRequestSchema(this OpenApiOperation operation, StructuredMimeTypesCollection structuredMimeTypes) + internal static IOpenApiSchema? GetRequestSchema(this OpenApiOperation operation, StructuredMimeTypesCollection structuredMimeTypes) { ArgumentNullException.ThrowIfNull(operation); return operation.RequestBody?.Content @@ -57,7 +58,7 @@ internal static bool IsMultipartTopMimeType(this IDictionary !multipartMimeTypes.Contains(x)).Any(structuredMimeTypes.Contains)) return true; return structuredMimeTypes.First() == multipartMimeTypes.First(); } - internal static IEnumerable GetValidSchemas(this IDictionary source, StructuredMimeTypesCollection structuredMimeTypes) + internal static IEnumerable GetValidSchemas(this IDictionary source, StructuredMimeTypesCollection structuredMimeTypes) { ArgumentNullException.ThrowIfNull(source); ArgumentNullException.ThrowIfNull(structuredMimeTypes); @@ -68,9 +69,9 @@ internal static IEnumerable GetValidSchemas(this IDictionary (Key: c.Key.Split(';', StringSplitOptions.RemoveEmptyEntries)[0], c.Value)) .Where(c => structuredMimeTypes.Contains(c.Key) || structuredMimeTypes.Contains(vendorSpecificCleanup(c.Key))) .Select(static co => co.Value.Schema) - .OfType(); + .OfType(); } - internal static OpenApiSchema? GetResponseSchema(this OpenApiResponse response, StructuredMimeTypesCollection structuredMimeTypes) + internal static IOpenApiSchema? GetResponseSchema(this IOpenApiResponse response, StructuredMimeTypesCollection structuredMimeTypes) { ArgumentNullException.ThrowIfNull(response); return response.Content.GetValidSchemas(structuredMimeTypes).FirstOrDefault(); diff --git a/src/Kiota.Builder/Extensions/OpenApiReferenceExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiReferenceExtensions.cs deleted file mode 100644 index c1c556ee35..0000000000 --- a/src/Kiota.Builder/Extensions/OpenApiReferenceExtensions.cs +++ /dev/null @@ -1,12 +0,0 @@ -using Microsoft.OpenApi.Models; - -namespace Kiota.Builder.Extensions; -public static class OpenApiReferenceExtensions -{ - public static string GetClassName(this OpenApiReference? reference) - { - if (reference?.Id is string referenceId && !string.IsNullOrEmpty(referenceId)) - return referenceId[(referenceId.LastIndexOf('.') + 1)..]; - return string.Empty; - } -} diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index a98d4bfd06..4ee83928bb 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -4,20 +4,22 @@ using System.Linq; using System.Text.Json; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; namespace Kiota.Builder.Extensions; public static class OpenApiSchemaExtensions { - private static readonly Func> classNamesFlattener = x => - (x.AnyOf ?? Enumerable.Empty()).Union(x.AllOf).Union(x.OneOf).ToList(); - public static IEnumerable GetSchemaNames(this OpenApiSchema schema, bool directOnly = false) + private static readonly Func> classNamesFlattener = x => + (x.AnyOf ?? Enumerable.Empty()).Union(x.AllOf).Union(x.OneOf).ToList(); + public static IEnumerable GetSchemaNames(this IOpenApiSchema schema, bool directOnly = false) { if (schema == null) return []; if (!directOnly && schema.Items != null) return schema.Items.GetSchemaNames(); - if (!string.IsNullOrEmpty(schema.Reference?.Id)) - return [schema.Reference.Id.Split('/')[^1].Split('.')[^1]]; + if (schema.GetReferenceId() is string refId && !string.IsNullOrEmpty(refId)) + return [refId.Split('/')[^1].Split('.')[^1]]; if (!directOnly && schema.AnyOf.Any()) return schema.AnyOf.FlattenIfRequired(classNamesFlattener); if (!directOnly && schema.AllOf.Any()) @@ -26,32 +28,44 @@ public static IEnumerable GetSchemaNames(this OpenApiSchema schema, bool return schema.OneOf.FlattenIfRequired(classNamesFlattener); return []; } - internal static IEnumerable FlattenSchemaIfRequired(this IList schemas, Func> subsequentGetter) + internal static string? GetReferenceId(this IOpenApiSchema schema) + { + return schema switch + { + OpenApiSchemaReference reference => reference.Reference?.Id, + _ => null, + }; + } + internal static IEnumerable FlattenSchemaIfRequired(this IList schemas, Func> subsequentGetter) { if (schemas is null) return []; - return schemas.Count == 1 && !schemas[0].HasAnyProperty() && string.IsNullOrEmpty(schemas[0].Reference?.Id) ? + return schemas.Count == 1 && !schemas[0].HasAnyProperty() && string.IsNullOrEmpty(schemas[0].GetReferenceId()) ? schemas.FlattenEmptyEntries(subsequentGetter, 1) : schemas; } - private static IEnumerable FlattenIfRequired(this IList schemas, Func> subsequentGetter) + private static IEnumerable FlattenIfRequired(this IList schemas, Func> subsequentGetter) { return schemas.FlattenSchemaIfRequired(subsequentGetter).SelectMany(static x => x.GetSchemaNames()); } - public static string GetSchemaName(this OpenApiSchema schema, bool directOnly = false) + public static string GetSchemaName(this IOpenApiSchema schema, bool directOnly = false) { return schema.GetSchemaNames(directOnly).LastOrDefault()?.TrimStart('$') ?? string.Empty;// OData $ref } - public static bool IsReferencedSchema(this OpenApiSchema schema) + public static bool IsReferencedSchema(this IOpenApiSchema schema) { - var isReference = schema?.Reference != null; - if (isReference && schema!.Reference.IsExternal) - throw new NotSupportedException("External references are not supported in this version of Kiota. While Kiota awaits on OpenAPI.Net to support inlining external references, you can use https://www.nuget.org/packages/Microsoft.OpenApi.Hidi to generate an OpenAPI description with inlined external references and then use this new reference with Kiota."); - return isReference; + return schema switch + { + OpenApiSchemaReference reference => reference.Reference.IsExternal ? + // TODO remove this failsafe once we have a test with external documents. + throw new NotSupportedException("External references are not supported in this version of Kiota. While Kiota awaits on OpenAPI.Net to support inlining external references, you can use https://www.nuget.org/packages/Microsoft.OpenApi.Hidi to generate an OpenAPI description with inlined external references and then use this new reference with Kiota.") : + true, + _ => false, + }; } - public static bool IsArray(this OpenApiSchema? schema) + public static bool IsArray(this IOpenApiSchema? schema) { return schema is { Type: JsonSchemaType.Array or (JsonSchemaType.Array | JsonSchemaType.Null) } && schema.Items is not null && (schema.Items.IsComposedEnum() || @@ -60,65 +74,65 @@ public static bool IsArray(this OpenApiSchema? schema) FlattenEmptyEntries([schema.Items], static x => x.AnyOf.Union(x.AllOf).Union(x.OneOf).ToList(), 1).FirstOrDefault() is OpenApiSchema flat && flat.IsSemanticallyMeaningful()); } - public static bool IsObjectType(this OpenApiSchema? schema) + public static bool IsObjectType(this IOpenApiSchema? schema) { return schema is { Type: JsonSchemaType.Object or (JsonSchemaType.Object | JsonSchemaType.Null) }; } - public static bool HasAnyProperty(this OpenApiSchema? schema) + public static bool HasAnyProperty(this IOpenApiSchema? schema) { return schema?.Properties is { Count: > 0 }; } - public static bool IsInclusiveUnion(this OpenApiSchema? schema, uint exclusiveMinimumNumberOfEntries = 1) + public static bool IsInclusiveUnion(this IOpenApiSchema? schema, uint exclusiveMinimumNumberOfEntries = 1) { return schema?.AnyOf?.Count(static x => IsSemanticallyMeaningful(x, true)) > exclusiveMinimumNumberOfEntries; // so we don't consider any of object/nullable as a union type } - public static bool IsInherited(this OpenApiSchema? schema) + public static bool IsInherited(this IOpenApiSchema? schema) { if (schema is null) return false; var meaningfulMemberSchemas = schema.AllOf.FlattenSchemaIfRequired(static x => x.AllOf) .Where(static x => x.IsSemanticallyMeaningful(ignoreEnums: true, ignoreArrays: true, ignoreType: true)) // the next line ensures the meaningful schema are objects as it won't make sense inheriting from a primitive despite it being meaningful. - .Where(static x => string.IsNullOrEmpty(x.Reference?.Id) || x.Type is null || !x.Type.HasValue || (x.Type.Value & JsonSchemaType.Object) is JsonSchemaType.Object) + .Where(static x => string.IsNullOrEmpty(x.GetReferenceId()) || x.Type is null || !x.Type.HasValue || (x.Type.Value & JsonSchemaType.Object) is JsonSchemaType.Object) .ToArray(); var isRootSchemaMeaningful = schema.IsSemanticallyMeaningful(ignoreEnums: true, ignoreArrays: true, ignoreType: true); - return meaningfulMemberSchemas.Count(static x => !string.IsNullOrEmpty(x.Reference?.Id)) == 1 && - (meaningfulMemberSchemas.Count(static x => string.IsNullOrEmpty(x.Reference?.Id)) == 1 || + return meaningfulMemberSchemas.Count(static x => !string.IsNullOrEmpty(x.GetReferenceId())) == 1 && + (meaningfulMemberSchemas.Count(static x => string.IsNullOrEmpty(x.GetReferenceId())) == 1 || isRootSchemaMeaningful); } - internal static OpenApiSchema? MergeAllOfSchemaEntries(this OpenApiSchema? schema, HashSet? schemasToExclude = default, Func? filter = default) + internal static IOpenApiSchema? MergeAllOfSchemaEntries(this IOpenApiSchema? schema, HashSet? schemasToExclude = default, Func? filter = default) { return schema.MergeIntersectionSchemaEntries(schemasToExclude, true, filter); } - internal static OpenApiSchema? MergeInclusiveUnionSchemaEntries(this OpenApiSchema? schema) + internal static IOpenApiSchema? MergeInclusiveUnionSchemaEntries(this IOpenApiSchema? schema) { if (schema is null || !schema.IsInclusiveUnion(0)) return null; - var result = new OpenApiSchema(schema); + var result = schema.CreateShallowCopy(); result.AnyOf.Clear(); result.TryAddProperties(schema.AnyOf.SelectMany(static x => x.Properties)); return result; } - internal static OpenApiSchema? MergeExclusiveUnionSchemaEntries(this OpenApiSchema? schema) + internal static IOpenApiSchema? MergeExclusiveUnionSchemaEntries(this IOpenApiSchema? schema) { if (schema is null || !schema.IsExclusiveUnion(0)) return null; - var result = new OpenApiSchema(schema); + var result = schema.CreateShallowCopy(); result.OneOf.Clear(); result.TryAddProperties(schema.OneOf.SelectMany(static x => x.Properties)); return result; } - internal static OpenApiSchema? MergeSingleInclusiveUnionInheritanceOrIntersectionSchemaEntries(this OpenApiSchema? schema) + internal static IOpenApiSchema? MergeSingleInclusiveUnionInheritanceOrIntersectionSchemaEntries(this IOpenApiSchema? schema) { if (schema is not null && schema.IsInclusiveUnion(0) && schema.AnyOf.OnlyOneOrDefault() is OpenApiSchema subSchema && (subSchema.IsInherited() || subSchema.IsIntersection())) { - var result = new OpenApiSchema(schema); + var result = schema.CreateShallowCopy(); result.AnyOf.Clear(); result.TryAddProperties(subSchema.Properties); result.AllOf.AddRange(subSchema.AllOf); @@ -128,14 +142,14 @@ public static bool IsInherited(this OpenApiSchema? schema) return null; } - internal static OpenApiSchema? MergeSingleExclusiveUnionInheritanceOrIntersectionSchemaEntries(this OpenApiSchema? schema) + internal static IOpenApiSchema? MergeSingleExclusiveUnionInheritanceOrIntersectionSchemaEntries(this IOpenApiSchema? schema) { if (schema is not null && schema.IsExclusiveUnion(0) && schema.OneOf.OnlyOneOrDefault() is OpenApiSchema subSchema && (subSchema.IsInherited() || subSchema.IsIntersection())) { - var result = new OpenApiSchema(schema); + var result = schema.CreateShallowCopy(); result.OneOf.Clear(); result.TryAddProperties(subSchema.Properties); result.AllOf.AddRange(subSchema.AllOf); @@ -145,33 +159,34 @@ public static bool IsInherited(this OpenApiSchema? schema) return null; } - internal static OpenApiSchema? MergeIntersectionSchemaEntries(this OpenApiSchema? schema, HashSet? schemasToExclude = default, bool overrideIntersection = false, Func? filter = default) + internal static IOpenApiSchema? MergeIntersectionSchemaEntries(this IOpenApiSchema? schema, HashSet? schemasToExclude = default, bool overrideIntersection = false, Func? filter = default) { if (schema is null) return null; if (!schema.IsIntersection() && !overrideIntersection) return schema; - var result = new OpenApiSchema(schema); + var result = schema.CreateShallowCopy(); result.AllOf.Clear(); var meaningfulSchemas = schema.AllOf .Where(x => (x.IsSemanticallyMeaningful() || x.AllOf.Any()) && (filter == null || filter(x))) .Select(x => MergeIntersectionSchemaEntries(x, schemasToExclude, overrideIntersection, filter)) .Where(x => x is not null && (schemasToExclude is null || !schemasToExclude.Contains(x))) - .OfType() + .OfType() .ToArray(); var entriesToMerge = meaningfulSchemas.FlattenEmptyEntries(static x => x.AllOf).Union(meaningfulSchemas).ToArray(); - if (entriesToMerge.Select(static x => x.Discriminator).OfType().FirstOrDefault() is OpenApiDiscriminator discriminator) - if (result.Discriminator is null) - result.Discriminator = discriminator; - else if (string.IsNullOrEmpty(result.Discriminator.PropertyName) && !string.IsNullOrEmpty(discriminator.PropertyName)) - result.Discriminator.PropertyName = discriminator.PropertyName; + if (entriesToMerge.Select(static x => x.Discriminator).OfType().FirstOrDefault() is OpenApiDiscriminator discriminator && + result is OpenApiSchema resultSchema) + if (resultSchema.Discriminator is null) + resultSchema.Discriminator = discriminator; + else if (string.IsNullOrEmpty(resultSchema.Discriminator.PropertyName) && !string.IsNullOrEmpty(discriminator.PropertyName)) + resultSchema.Discriminator.PropertyName = discriminator.PropertyName; else if (discriminator.Mapping?.Any() ?? false) - result.Discriminator.Mapping = discriminator.Mapping.ToDictionary(static x => x.Key, static x => x.Value); + resultSchema.Discriminator.Mapping = discriminator.Mapping.ToDictionary(static x => x.Key, static x => x.Value); result.TryAddProperties(entriesToMerge.SelectMany(static x => x.Properties)); return result; } - internal static void TryAddProperties(this OpenApiSchema schema, IEnumerable> properties) + internal static void TryAddProperties(this IOpenApiSchema schema, IEnumerable> properties) { foreach (var property in properties) { @@ -179,13 +194,13 @@ internal static void TryAddProperties(this OpenApiSchema schema, IEnumerable x.IsSemanticallyMeaningful()).ToArray(); - return meaningfulSchemas?.Count(static x => !string.IsNullOrEmpty(x.Reference?.Id)) > 1 || meaningfulSchemas?.Count(static x => string.IsNullOrEmpty(x.Reference?.Id)) > 1; + return meaningfulSchemas?.Count(static x => !string.IsNullOrEmpty(x.GetReferenceId())) > 1 || meaningfulSchemas?.Count(static x => string.IsNullOrEmpty(x.GetReferenceId())) > 1; } - public static bool IsExclusiveUnion(this OpenApiSchema? schema, uint exclusiveMinimumNumberOfEntries = 1) + public static bool IsExclusiveUnion(this IOpenApiSchema? schema, uint exclusiveMinimumNumberOfEntries = 1) { return schema?.OneOf?.Count(static x => IsSemanticallyMeaningful(x, true)) > exclusiveMinimumNumberOfEntries; // so we don't consider one of object/nullable as a union type @@ -194,9 +209,9 @@ public static bool IsExclusiveUnion(this OpenApiSchema? schema, uint exclusiveMi JsonSchemaType.Number, JsonSchemaType.Integer, ]; - private static readonly Func isODataType = static x => x.Type is not null && oDataTypes.Contains(x.Type.Value); - private static readonly Func isStringType = static x => x is { Type: JsonSchemaType.String or (JsonSchemaType.String | JsonSchemaType.Null) }; - private static bool IsODataPrimitiveTypeBackwardCompatible(this OpenApiSchema schema) + private static readonly Func isODataType = static x => x.Type is not null && oDataTypes.Contains(x.Type.Value); + private static readonly Func isStringType = static x => x is { Type: JsonSchemaType.String or (JsonSchemaType.String | JsonSchemaType.Null) }; + private static bool IsODataPrimitiveTypeBackwardCompatible(this IOpenApiSchema schema) { return schema.IsExclusiveUnion() && schema.OneOf.Count == 3 && @@ -210,7 +225,7 @@ private static bool IsODataPrimitiveTypeBackwardCompatible(this OpenApiSchema sc schema.AnyOf.Count(isODataType) == 1 && schema.AnyOf.Count(isStringType) == 1; } - public static bool IsODataPrimitiveType(this OpenApiSchema schema) + public static bool IsODataPrimitiveType(this IOpenApiSchema schema) { return schema.IsExclusiveUnion() && schema.OneOf.Count == 3 && @@ -226,20 +241,20 @@ public static bool IsODataPrimitiveType(this OpenApiSchema schema) || schema.IsODataPrimitiveTypeBackwardCompatible(); } - public static bool IsEnum(this OpenApiSchema schema) + public static bool IsEnum(this IOpenApiSchema schema) { if (schema is null) return false; return schema.Enum.Any(static x => x.GetValueKind() is JsonValueKind.String && x.GetValue() is string value && !string.IsNullOrEmpty(value)); // number and boolean enums are not supported } - public static bool IsComposedEnum(this OpenApiSchema schema) + public static bool IsComposedEnum(this IOpenApiSchema schema) { if (schema is null) return false; return schema.AnyOf.Count(static x => !x.IsSemanticallyMeaningful(true)) == 1 && schema.AnyOf.Count(static x => x.IsEnum()) == 1 || schema.OneOf.Count(static x => !x.IsSemanticallyMeaningful(true)) == 1 && schema.OneOf.Count(static x => x.IsEnum()) == 1; } - public static bool IsSemanticallyMeaningful(this OpenApiSchema schema, bool ignoreNullableObjects = false, bool ignoreEnums = false, bool ignoreArrays = false, bool ignoreType = false) + public static bool IsSemanticallyMeaningful(this IOpenApiSchema schema, bool ignoreNullableObjects = false, bool ignoreEnums = false, bool ignoreArrays = false, bool ignoreType = false) { if (schema is null) return false; return schema.HasAnyProperty() || @@ -249,27 +264,27 @@ public static bool IsSemanticallyMeaningful(this OpenApiSchema schema, bool igno ((ignoreNullableObjects && !schema.IsObjectType()) || !ignoreNullableObjects)) || !string.IsNullOrEmpty(schema.Format) || - !string.IsNullOrEmpty(schema.Reference?.Id); + !string.IsNullOrEmpty(schema.GetReferenceId()); } - public static IEnumerable GetSchemaReferenceIds(this OpenApiSchema schema, HashSet? visitedSchemas = null) + public static IEnumerable GetSchemaReferenceIds(this IOpenApiSchema schema, HashSet? visitedSchemas = null) { visitedSchemas ??= new(); if (schema != null && !visitedSchemas.Contains(schema)) { visitedSchemas.Add(schema); var result = new List(); - if (!string.IsNullOrEmpty(schema.Reference?.Id)) - result.Add(schema.Reference.Id); + if (schema.GetReferenceId() is string refId && !string.IsNullOrEmpty(refId)) + result.Add(refId); if (schema.Items != null) { - if (!string.IsNullOrEmpty(schema.Items.Reference?.Id)) - result.Add(schema.Items.Reference.Id); + if (schema.Items.GetReferenceId() is string itemsRefId && !string.IsNullOrEmpty(itemsRefId)) + result.Add(itemsRefId); result.AddRange(schema.Items.GetSchemaReferenceIds(visitedSchemas)); } - var subSchemaReferences = (schema.Properties?.Values ?? Enumerable.Empty()) - .Union(schema.AnyOf ?? Enumerable.Empty()) - .Union(schema.AllOf ?? Enumerable.Empty()) - .Union(schema.OneOf ?? Enumerable.Empty()) + var subSchemaReferences = (schema.Properties?.Values ?? Enumerable.Empty()) + .Union(schema.AnyOf ?? Enumerable.Empty()) + .Union(schema.AllOf ?? Enumerable.Empty()) + .Union(schema.OneOf ?? Enumerable.Empty()) .SelectMany(x => x.GetSchemaReferenceIds(visitedSchemas)) .ToList();// this to list is important otherwise the any marks the schemas as visited and add range doesn't find anything if (subSchemaReferences.Count != 0) @@ -279,7 +294,7 @@ public static IEnumerable GetSchemaReferenceIds(this OpenApiSchema schem return []; } - private static IEnumerable FlattenEmptyEntries(this IEnumerable schemas, Func> subsequentGetter, int? maxDepth = default) + private static IEnumerable FlattenEmptyEntries(this IEnumerable schemas, Func> subsequentGetter, int? maxDepth = default) { if (schemas == null) return []; ArgumentNullException.ThrowIfNull(subsequentGetter); @@ -288,7 +303,7 @@ private static IEnumerable FlattenEmptyEntries(this IEnumerable>(); + var permutations = new Dictionary>(); foreach (var item in result) { var subsequentItems = subsequentGetter(item); @@ -311,7 +326,7 @@ private static IEnumerable FlattenEmptyEntries(this IEnumerable? visitedSchemas = default) + internal static string GetDiscriminatorPropertyName(this IOpenApiSchema schema, HashSet? visitedSchemas = default) { if (schema == null) @@ -334,7 +349,7 @@ internal static string GetDiscriminatorPropertyName(this OpenApiSchema schema, H return string.Empty; } - internal static IEnumerable> GetDiscriminatorMappings(this OpenApiSchema schema, ConcurrentDictionary> inheritanceIndex) + internal static IEnumerable> GetDiscriminatorMappings(this IOpenApiSchema schema, ConcurrentDictionary> inheritanceIndex) { if (schema == null) return []; @@ -346,18 +361,18 @@ internal static IEnumerable> GetDiscriminatorMappin else if (schema.AllOf.Any(allOfEvaluatorForMappings) && schema.AllOf[^1].Equals(schema.AllOf.Last(allOfEvaluatorForMappings))) // ensure the matched AllOf entry is the last in the list return GetDiscriminatorMappings(schema.AllOf.Last(allOfEvaluatorForMappings), inheritanceIndex); - else if (!string.IsNullOrEmpty(schema.Reference?.Id)) - return GetAllInheritanceSchemaReferences(schema.Reference.Id, inheritanceIndex) + else if (schema.GetReferenceId() is string refId && !string.IsNullOrEmpty(refId)) + return GetAllInheritanceSchemaReferences(refId, inheritanceIndex) .Where(static x => !string.IsNullOrEmpty(x)) .Select(x => KeyValuePair.Create(x, x)) - .Union([KeyValuePair.Create(schema.Reference.Id, schema.Reference.Id)]); + .Union([KeyValuePair.Create(refId, refId)]); else return []; return schema.Discriminator .Mapping; } - private static readonly Func allOfEvaluatorForMappings = static x => x.Discriminator?.Mapping.Any() ?? false; + private static readonly Func allOfEvaluatorForMappings = static x => x.Discriminator?.Mapping.Any() ?? false; private static IEnumerable GetAllInheritanceSchemaReferences(string currentReferenceId, ConcurrentDictionary> inheritanceIndex) { ArgumentException.ThrowIfNullOrEmpty(currentReferenceId); @@ -366,5 +381,11 @@ private static IEnumerable GetAllInheritanceSchemaReferences(string curr return dependents.Keys.Union(dependents.Keys.SelectMany(x => GetAllInheritanceSchemaReferences(x, inheritanceIndex))).Distinct(StringComparer.OrdinalIgnoreCase); return []; } + internal static string GetClassName(this IOpenApiSchema? schema) + { + if (schema?.GetReferenceId() is string referenceId && !string.IsNullOrEmpty(referenceId)) + return referenceId[(referenceId.LastIndexOf('.') + 1)..]; + return string.Empty; + } } diff --git a/src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs index 98e4e8a6af..a7869fdf05 100644 --- a/src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiUrlTreeNodeExtensions.cs @@ -6,6 +6,8 @@ using Microsoft.Extensions.Logging; using Microsoft.OpenApi.MicrosoftExtensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; namespace Kiota.Builder.Extensions; @@ -66,14 +68,14 @@ internal static string CleanupParametersFromPath(string pathSegment) .Replace(RequestParametersSectionEndChar, string.Empty, StringComparison.OrdinalIgnoreCase) .Replace(RequestParametersSectionChar, string.Empty, StringComparison.OrdinalIgnoreCase); } - private static IEnumerable GetParametersForPathItem(OpenApiPathItem pathItem, string nodeSegment) + private static IEnumerable GetParametersForPathItem(IOpenApiPathItem pathItem, string nodeSegment) { return pathItem.Parameters - .Union(pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty())) + .Union(pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty())) .Where(static x => x.In == ParameterLocation.Path) .Where(x => nodeSegment.Contains($"{{{x.Name}}}", StringComparison.OrdinalIgnoreCase)); } - public static IEnumerable GetPathParametersForCurrentSegment(this OpenApiUrlTreeNode node) + public static IEnumerable GetPathParametersForCurrentSegment(this OpenApiUrlTreeNode node) { if (node != null && node.IsComplexPathMultipleParameters()) @@ -92,7 +94,7 @@ public static IEnumerable GetPathParametersForCurrentSegment(t /// /// Returns the class name for the node with more or less precision depending on the provided arguments /// - internal static string GetClassName(this OpenApiUrlTreeNode currentNode, StructuredMimeTypesCollection structuredMimeTypes, string? suffix = default, string? prefix = default, OpenApiOperation? operation = default, OpenApiResponse? response = default, OpenApiSchema? schema = default, bool requestBody = false) + internal static string GetClassName(this OpenApiUrlTreeNode currentNode, StructuredMimeTypesCollection structuredMimeTypes, string? suffix = default, string? prefix = default, OpenApiOperation? operation = default, IOpenApiResponse? response = default, IOpenApiSchema? schema = default, bool requestBody = false) { ArgumentNullException.ThrowIfNull(currentNode); return currentNode.GetSegmentName(structuredMimeTypes, suffix, prefix, operation, response, schema, requestBody, static x => x.LastOrDefault() ?? string.Empty); @@ -106,14 +108,14 @@ internal static string GetNavigationPropertyName(this OpenApiUrlTreeNode current return result; } private static readonly HashSet httpVerbs = new(8, StringComparer.OrdinalIgnoreCase) { "get", "post", "put", "patch", "delete", "head", "options", "trace" }; - private static string GetSegmentName(this OpenApiUrlTreeNode currentNode, StructuredMimeTypesCollection structuredMimeTypes, string? suffix, string? prefix, OpenApiOperation? operation, OpenApiResponse? response, OpenApiSchema? schema, bool requestBody, Func, string> segmentsReducer, bool skipExtension = true) + private static string GetSegmentName(this OpenApiUrlTreeNode currentNode, StructuredMimeTypesCollection structuredMimeTypes, string? suffix, string? prefix, OpenApiOperation? operation, IOpenApiResponse? response, IOpenApiSchema? schema, bool requestBody, Func, string> segmentsReducer, bool skipExtension = true) { - var referenceName = schema?.Reference?.GetClassName(); + var referenceName = schema?.GetClassName(); var rawClassName = referenceName is not null && !string.IsNullOrEmpty(referenceName) ? referenceName : - ((requestBody ? null : response?.GetResponseSchema(structuredMimeTypes)?.Reference?.GetClassName()) is string responseClassName && !string.IsNullOrEmpty(responseClassName) ? + ((requestBody ? null : response?.GetResponseSchema(structuredMimeTypes)?.GetClassName()) is string responseClassName && !string.IsNullOrEmpty(responseClassName) ? responseClassName : - ((requestBody ? operation?.GetRequestSchema(structuredMimeTypes) : operation?.GetResponseSchema(structuredMimeTypes))?.Reference?.GetClassName() is string requestClassName && !string.IsNullOrEmpty(requestClassName) ? + ((requestBody ? operation?.GetRequestSchema(structuredMimeTypes) : operation?.GetResponseSchema(structuredMimeTypes))?.GetClassName() is string requestClassName && !string.IsNullOrEmpty(requestClassName) ? requestClassName : CleanupParametersFromPath(currentNode.DeduplicatedSegment())?.ReplaceValueIdentifier())); if (!string.IsNullOrEmpty(rawClassName) && string.IsNullOrEmpty(referenceName)) @@ -193,7 +195,7 @@ public static bool HasRequiredQueryParametersAcrossOperations(this OpenApiUrlTre if (!currentNode.PathItems.TryGetValue(Constants.DefaultOpenApiLabel, out var pathItem)) return false; - var operationQueryParameters = pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty()); + var operationQueryParameters = pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty()); return operationQueryParameters.Union(pathItem.Parameters).Where(static x => x.In == ParameterLocation.Query) .Any(static x => x.Required); } @@ -208,7 +210,7 @@ public static string GetUrlTemplate(this OpenApiUrlTreeNode currentNode, Operati var operationQueryParameters = (operationType, pathItem.Operations.Any()) switch { (OperationType ot, _) when pathItem.Operations.TryGetValue(ot, out var operation) && operation.Parameters is not null => operation.Parameters, - (null, true) => pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty()).Where(static x => x.In == ParameterLocation.Query), + (null, true) => pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty()).Where(static x => x.In == ParameterLocation.Query), _ => [], }; var parameters = pathItem.Parameters @@ -234,7 +236,7 @@ public static string GetUrlTemplate(this OpenApiUrlTreeNode currentNode, Operati } var pathReservedPathParametersIds = currentNode.PathItems.TryGetValue(Constants.DefaultOpenApiLabel, out var pItem) ? pItem.Parameters - .Union(pItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty())) + .Union(pItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty())) .Where(static x => x.In == ParameterLocation.Path && x.Extensions.TryGetValue(OpenApiReservedParameterExtension.Name, out var ext) && ext is OpenApiReservedParameterExtension reserved && reserved.IsReserved.HasValue && reserved.IsReserved.Value) .Select(static x => x.Name) .ToHashSet(StringComparer.OrdinalIgnoreCase) : @@ -356,10 +358,20 @@ private static void ReplaceParameterInPathForAllChildNodes(OpenApiUrlTreeNode no if (node.PathItems.TryGetValue(Constants.DefaultOpenApiLabel, out var pathItem)) { foreach (var pathParameter in pathItem.Parameters - .Union(pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty())) + .Union(pathItem.Operations.SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty())) .Where(x => x.In == ParameterLocation.Path && oldName.Equals(x.Name, StringComparison.Ordinal))) { - pathParameter.Name = newParameterName; + switch (pathParameter) + { + case OpenApiParameter openApiParameter: + openApiParameter.Name = newParameterName; + break; + case OpenApiParameterReference openApiReference: + openApiReference.Target.Name = newParameterName; + break; + default: + throw new InvalidOperationException("Unexpected parameter type"); + } } } } @@ -386,11 +398,21 @@ private static void CopyNodeIntoOtherNode(OpenApiUrlTreeNode source, OpenApiUrlT pathItem .Value .Operations - .SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty()) + .SelectMany(static x => x.Value.Parameters ?? Enumerable.Empty()) .Where(x => x.In == ParameterLocation.Path && pathParameterNameToReplace.Equals(x.Name, StringComparison.Ordinal)) )) { - pathParameter.Name = pathParameterNameReplacement; + switch (pathParameter) + { + case OpenApiParameter openApiParameter: + openApiParameter.Name = pathParameterNameReplacement; + break; + case OpenApiParameterReference openApiReference: + openApiReference.Target.Name = pathParameterNameReplacement; + break; + default: + throw new InvalidOperationException("Unexpected parameter type"); + } } if (source != destination && !destination.PathItems.TryAdd(pathItem.Key, pathItem.Value)) { diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 3a732b1f9e..127dfcd8e9 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -8,7 +8,6 @@ using System.Linq; using System.Net.Http; using System.Runtime.CompilerServices; -using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Text.Json.Nodes; @@ -38,6 +37,8 @@ using Microsoft.OpenApi.Extensions; using Microsoft.OpenApi.MicrosoftExtensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using HttpMethod = Kiota.Builder.CodeDOM.HttpMethod; [assembly: InternalsVisibleTo("Kiota.Builder.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100957cb48387b2a5f54f5ce39255f18f26d32a39990db27cf48737afc6bc62759ba996b8a2bfb675d4e39f3d06ecb55a178b1b4031dcb2a767e29977d88cce864a0d16bfc1b3bebb0edf9fe285f10fffc0a85f93d664fa05af07faa3aad2e545182dbf787e3fd32b56aca95df1a3c4e75dec164a3f1a4c653d971b01ffc39eb3c4")] @@ -582,7 +583,7 @@ private void AddOperationSecurityRequirementToDOM(OpenApiOperation operation, Co return; } - if (operation.Security == null || !operation.Security.Any()) + if (operation.Security == null || !operation.Security.Any() || openApiDocument.Components?.SecuritySchemes is null) return; var securitySchemes = openApiDocument.Components.SecuritySchemes; @@ -598,15 +599,16 @@ private void AddOperationSecurityRequirementToDOM(OpenApiOperation operation, Co } } - private void AddSecurity(CodeClass codeClass, OpenApiSecurityScheme openApiSecurityScheme) + private void AddSecurity(CodeClass codeClass, IOpenApiSecurityScheme openApiSecurityScheme) { - codeClass.AddProperty( - new CodeProperty - { - Type = new CodeType { Name = openApiSecurityScheme.Type.ToString(), IsExternal = true }, - Kind = CodePropertyKind.Headers - } - ); + if (openApiSecurityScheme.Type is not null) + codeClass.AddProperty( + new CodeProperty + { + Type = new CodeType { Name = openApiSecurityScheme.Type.Value.ToString(), IsExternal = true }, + Kind = CodePropertyKind.Headers + } + ); } /// @@ -1097,7 +1099,7 @@ private CodeParameter GetIndexerParameter(OpenApiUrlTreeNode currentNode, OpenAp }; return result; } - private static IDictionary GetPathItems(OpenApiUrlTreeNode currentNode, bool validateIsParameterNode = true) + private static IDictionary GetPathItems(OpenApiUrlTreeNode currentNode, bool validateIsParameterNode = true) { if ((!validateIsParameterNode || currentNode.IsParameter) && currentNode.PathItems.Any()) { @@ -1112,7 +1114,7 @@ private static IDictionary GetPathItems(OpenApiUrlTreeN .ToDictionary(static x => x.Key, static x => x.Value, StringComparer.Ordinal); } - return ImmutableDictionary.Empty; + return ImmutableDictionary.Empty; } private CodeIndexer[] CreateIndexer(string childIdentifier, string childType, CodeParameter parameter, OpenApiUrlTreeNode currentNode, OpenApiUrlTreeNode parentNode) { @@ -1144,7 +1146,7 @@ private CodeIndexer[] CreateIndexer(string childIdentifier, string childType, Co } private static readonly StructuralPropertiesReservedNameProvider structuralPropertiesReservedNameProvider = new(); - private CodeProperty? CreateProperty(string childIdentifier, string childType, OpenApiSchema? propertySchema = null, CodeTypeBase? existingType = null, CodePropertyKind kind = CodePropertyKind.Custom) + private CodeProperty? CreateProperty(string childIdentifier, string childType, IOpenApiSchema? propertySchema = null, CodeTypeBase? existingType = null, CodePropertyKind kind = CodePropertyKind.Custom) { var propertyName = childIdentifier.CleanupSymbolName(); if (structuralPropertiesReservedNameProvider.ReservedNames.Contains(propertyName)) @@ -1189,7 +1191,7 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten return prop; } private static readonly HashSet typeNamesToSkip = [JsonSchemaType.Object, JsonSchemaType.Array]; - private static CodeType? GetPrimitiveType(OpenApiSchema? typeSchema, string? childType = default) + private static CodeType? GetPrimitiveType(IOpenApiSchema? typeSchema, string? childType = default) { var typeNames = new List { typeSchema?.Items?.Type, typeSchema?.Type }; if (typeSchema?.AnyOf?.Any() ?? false) @@ -1249,11 +1251,11 @@ private void AddErrorMappingsForExecutorMethod(OpenApiUrlTreeNode currentNode, O AddErrorMappingToExecutorMethod(currentNode, operation, executorMethod, errorSchema, defaultResponse, CodeMethod.ErrorMappingServerRange); } } - private void AddErrorMappingToExecutorMethod(OpenApiUrlTreeNode currentNode, OpenApiOperation operation, CodeMethod executorMethod, OpenApiSchema errorSchema, OpenApiResponse response, string errorCode) + private void AddErrorMappingToExecutorMethod(OpenApiUrlTreeNode currentNode, OpenApiOperation operation, CodeMethod executorMethod, IOpenApiSchema errorSchema, IOpenApiResponse response, string errorCode) { if (modelsNamespace != null) { - var parentElement = string.IsNullOrEmpty(response.Reference?.Id) && string.IsNullOrEmpty(errorSchema.Reference?.Id) + var parentElement = response is not OpenApiResponseReference && errorSchema is not OpenApiSchemaReference ? (CodeElement)executorMethod : modelsNamespace; var errorType = CreateModelDeclarations(currentNode, errorSchema, operation, parentElement, $"{errorCode}Error", response: response); @@ -1268,7 +1270,7 @@ private void AddErrorMappingToExecutorMethod(OpenApiUrlTreeNode currentNode, Ope logger.LogWarning("Could not create error type for {Error} in {Operation}", errorCode, operation.OperationId); } } - private (CodeTypeBase?, CodeTypeBase?) GetExecutorMethodReturnType(OpenApiUrlTreeNode currentNode, OpenApiSchema? schema, OpenApiOperation operation, CodeClass parentClass, OperationType operationType) + private (CodeTypeBase?, CodeTypeBase?) GetExecutorMethodReturnType(OpenApiUrlTreeNode currentNode, IOpenApiSchema? schema, OpenApiOperation operation, CodeClass parentClass, OperationType operationType) { if (schema != null) { @@ -1465,7 +1467,7 @@ private void CreateOperationMethods(OpenApiUrlTreeNode currentNode, OperationTyp } } private static readonly OpenApiSchemaReferenceComparer schemaReferenceComparer = new(); - private static readonly Func GetCodeParameterFromApiParameter = x => + private static readonly Func GetCodeParameterFromApiParameter = x => { var codeName = x.Name.SanitizeParameterNameForCodeSymbols(); return new CodeParameter @@ -1487,7 +1489,7 @@ private void CreateOperationMethods(OpenApiUrlTreeNode currentNode, OperationTyp Optional = !x.Required }; }; - private static readonly Func ParametersFilter = x => x.In == ParameterLocation.Path || x.In == ParameterLocation.Query || x.In == ParameterLocation.Header; + private static readonly Func ParametersFilter = x => x.In == ParameterLocation.Path || x.In == ParameterLocation.Query || x.In == ParameterLocation.Header; private static void SetPathAndQueryParameters(CodeMethod target, OpenApiUrlTreeNode currentNode, OpenApiOperation operation) { var pathAndQueryParameters = currentNode @@ -1543,7 +1545,7 @@ private static void AddRequestConfigurationProperties(CodeClass? parameterClass, private readonly ConcurrentDictionary multipartPropertiesModels = new(); - private static bool IsSupportedMultipartDefault(OpenApiSchema openApiSchema, + private static bool IsSupportedMultipartDefault(IOpenApiSchema openApiSchema, StructuredMimeTypesCollection structuredMimeTypes) { // https://spec.openapis.org/oas/v3.0.3.html#special-considerations-for-multipart-content @@ -1691,7 +1693,7 @@ private string GetModelsNamespaceNameFromReferenceId(string? referenceId) var namespaceSuffix = lastDotIndex != -1 ? $".{referenceId[..lastDotIndex]}" : string.Empty; return $"{modelsNamespace?.Name}{string.Join(NsNameSeparator, namespaceSuffix.Split(NsNameSeparator).Select(static x => x.CleanupSymbolName()))}"; } - private CodeType CreateModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeNamespace codeNamespace, string classNameSuffix = "", OpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false) + private CodeType CreateModelDeclarationAndType(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, OpenApiOperation? operation, CodeNamespace codeNamespace, string classNameSuffix = "", IOpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false) { var className = string.IsNullOrEmpty(typeNameForInlineSchema) ? currentNode.GetClassName(config.StructuredMimeTypes, operation: operation, suffix: classNameSuffix, response: response, schema: schema, requestBody: isRequestBody).CleanupSymbolName() : typeNameForInlineSchema; var codeDeclaration = AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, codeNamespace); @@ -1700,17 +1702,17 @@ private CodeType CreateModelDeclarationAndType(OpenApiUrlTreeNode currentNode, O TypeDefinition = codeDeclaration, }; } - private CodeType CreateInheritedModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool isViaDiscriminator = false) + private CodeType CreateInheritedModelDeclarationAndType(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool isViaDiscriminator = false) { return new CodeType { TypeDefinition = CreateInheritedModelDeclaration(currentNode, schema, operation, classNameSuffix, codeNamespace, isRequestBody, typeNameForInlineSchema, isViaDiscriminator), }; } - private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool isViaDiscriminator = false) + private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, OpenApiOperation? operation, string classNameSuffix, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema, bool isViaDiscriminator = false) { var flattenedAllOfs = schema.AllOf.FlattenSchemaIfRequired(static x => x.AllOf).ToArray(); - var referenceId = schema.Reference?.Id; + var referenceId = schema.GetReferenceId(); var shortestNamespaceName = GetModelsNamespaceNameFromReferenceId(referenceId); var codeNamespaceFromParent = GetShortestNamespace(codeNamespace, schema); if (rootNamespace is null) @@ -1735,7 +1737,7 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace), // inline schema + referenced schema (false, { Length: > 0 }, { Length: 1 }, _) => - AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries([.. referencedSchemas], static x => x.Reference is null)!, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), + AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries([.. referencedSchemas], static x => x is OpenApiSchema)!, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // properties + referenced schema (true, { Length: 0 }, { Length: 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), @@ -1777,14 +1779,14 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode if (!currentClass.Documentation.DescriptionAvailable && new string[] { schema.Description } .Union(schema.AllOf - .Where(static x => x.Reference is null) + .OfType() .Select(static x => x.Description)) .FirstOrDefault(static x => !string.IsNullOrEmpty(x)) is string description) currentClass.Documentation.DescriptionTemplate = description.CleanupDescription(); // the last allof entry often is not a reference and doesn't have a description. return currentClass; } - private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, string suffixForInlineSchema, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema) + private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, OpenApiOperation? operation, string suffixForInlineSchema, CodeNamespace codeNamespace, bool isRequestBody, string typeNameForInlineSchema) { var typeName = string.IsNullOrEmpty(typeNameForInlineSchema) ? currentNode.GetClassName(config.StructuredMimeTypes, operation: operation, suffix: suffixForInlineSchema, schema: schema, requestBody: isRequestBody).CleanupSymbolName() : typeNameForInlineSchema; var typesCount = schema.AnyOf?.Count ?? schema.OneOf?.Count ?? 0; @@ -1820,8 +1822,8 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo }, schema.AnyOf), (_, _) => throw new InvalidOperationException("Schema is not oneOf nor anyOf"), }; - if (!string.IsNullOrEmpty(schema.Reference?.Id)) - unionType.TargetNamespace = codeNamespace.GetRootNamespace().FindOrAddNamespace(GetModelsNamespaceNameFromReferenceId(schema.Reference.Id)); + if (schema.GetReferenceId() is string refId && !string.IsNullOrEmpty(refId)) + unionType.TargetNamespace = codeNamespace.GetRootNamespace().FindOrAddNamespace(GetModelsNamespaceNameFromReferenceId(refId)); unionType.DiscriminatorInformation.DiscriminatorPropertyName = schema.GetDiscriminatorPropertyName(); GetDiscriminatorMappings(currentNode, schema, codeNamespace, null, operation) ?.ToList() @@ -1852,7 +1854,7 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo } return unionType; } - private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeElement parentElement, string suffixForInlineSchema, OpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false, bool isViaDiscriminator = false) + private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, OpenApiOperation? operation, CodeElement parentElement, string suffixForInlineSchema, IOpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false, bool isViaDiscriminator = false) { var (codeNamespace, responseValue, suffix) = schema.IsReferencedSchema() switch { @@ -1873,7 +1875,7 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, Ope return CreateInheritedModelDeclarationAndType(currentNode, schema, operation, suffix, codeNamespace, isRequestBody, typeNameForInlineSchema, isViaDiscriminator); } - if (schema.IsIntersection() && schema.MergeIntersectionSchemaEntries() is OpenApiSchema mergedSchema) + if (schema.IsIntersection() && schema.MergeIntersectionSchemaEntries() is IOpenApiSchema mergedSchema) { // multiple allOf entries that do not translate to inheritance return CreateModelDeclarationAndType(currentNode, mergedSchema, operation, codeNamespace, suffix, response: responseValue, typeNameForInlineSchema: typeNameForInlineSchema, isRequestBody); @@ -1917,7 +1919,7 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, Ope return CreateModelDeclarations(currentNode, childSchema, operation, parentElement, suffixForInlineSchema, response, typeNameForInlineSchema, isRequestBody); return new CodeType { Name = UntypedNodeName, IsExternal = true }; } - private CodeTypeBase CreateCollectionModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation? operation, CodeNamespace codeNamespace, string typeNameForInlineSchema, bool isRequestBody) + private CodeTypeBase CreateCollectionModelDeclaration(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, OpenApiOperation? operation, CodeNamespace codeNamespace, string typeNameForInlineSchema, bool isRequestBody) { CodeTypeBase? type = GetPrimitiveType(schema.Items); var isEnumOrComposedCollectionType = schema.Items.IsEnum() //the collection could be an enum type so override with strong type instead of string type. @@ -1946,7 +1948,7 @@ private CodeNamespace GetSearchNamespace(OpenApiUrlTreeNode currentNode, CodeNam return currentNamespace; } private ConcurrentDictionary classLifecycles = new(StringComparer.OrdinalIgnoreCase); - private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null) + private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation? currentOperation, IOpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, CodeClass? inheritsFrom = null) { if (GetExistingDeclaration(currentNamespace, currentNode, declarationName) is not CodeElement existingDeclaration) // we can find it in the components { @@ -1973,7 +1975,7 @@ private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentN } return existingDeclaration; } - private CodeEnum? AddEnumDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace) + private CodeEnum? AddEnumDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, string declarationName, CodeNamespace currentNamespace) { if (GetExistingDeclaration(currentNamespace, currentNode, declarationName) is not CodeEnum existingDeclaration) // we can find it in the components { @@ -1981,7 +1983,7 @@ private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentN } return existingDeclaration; } - private static CodeEnum? AddEnumDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace) + private static CodeEnum? AddEnumDeclaration(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, string declarationName, CodeNamespace currentNamespace) { if (schema.IsEnum()) { @@ -1998,7 +2000,7 @@ private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentN Flags = enumFlagsExtension?.IsFlags ?? false, Documentation = new() { - DescriptionTemplate = !string.IsNullOrEmpty(schemaDescription) || !string.IsNullOrEmpty(schema.Reference?.Id) ? + DescriptionTemplate = !string.IsNullOrEmpty(schemaDescription) || !string.IsNullOrEmpty(schema.GetReferenceId()) ? schemaDescription : // if it's a referenced component, we shouldn't use the path item description as it makes it indeterministic currentNode.GetPathItemDescription(Constants.DefaultOpenApiLabel), }, @@ -2009,7 +2011,7 @@ private CodeElement AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentN } return default; } - private static void SetEnumOptions(OpenApiSchema schema, CodeEnum target) + private static void SetEnumOptions(IOpenApiSchema schema, CodeEnum target) { OpenApiEnumValuesDescriptionExtension? extensionInformation = null; if (schema.Extensions.TryGetValue(OpenApiEnumValuesDescriptionExtension.Name, out var rawExtension) && rawExtension is OpenApiEnumValuesDescriptionExtension localExtInfo) @@ -2037,18 +2039,18 @@ private static void SetEnumOptions(OpenApiSchema schema, CodeEnum target) .Where(static x => !string.IsNullOrEmpty(x.Name)) .ToArray()); } - private CodeNamespace GetShortestNamespace(CodeNamespace currentNamespace, OpenApiSchema currentSchema) + private CodeNamespace GetShortestNamespace(CodeNamespace currentNamespace, IOpenApiSchema currentSchema) { - if (!string.IsNullOrEmpty(currentSchema.Reference?.Id) && rootNamespace != null) + if (currentSchema.GetReferenceId() is string refId && !string.IsNullOrEmpty(refId) && rootNamespace != null) { - var parentClassNamespaceName = GetModelsNamespaceNameFromReferenceId(currentSchema.Reference.Id); + var parentClassNamespaceName = GetModelsNamespaceNameFromReferenceId(refId); return rootNamespace.AddNamespace(parentClassNamespaceName); } return currentNamespace; } - private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null) + private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, string declarationName, CodeNamespace currentNamespace, OpenApiOperation? currentOperation, CodeClass? inheritsFrom = null) { - if (inheritsFrom == null && schema.AllOf.Where(static x => x.Reference != null).ToArray() is { Length: 1 } referencedSchemas) + if (inheritsFrom == null && schema.AllOf.OfType().ToArray() is { Length: 1 } referencedSchemas) {// any non-reference would be the current class in some description styles var parentSchema = referencedSchemas[0]; var parentClassNamespace = GetShortestNamespace(currentNamespace, parentSchema); @@ -2105,7 +2107,7 @@ private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema sc AddDiscriminatorMethod(newClass, schema.GetDiscriminatorPropertyName(), mappings, static s => s); return newClass; } - private IEnumerable> GetDiscriminatorMappings(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, CodeNamespace currentNamespace, CodeClass? baseClass, OpenApiOperation? currentOperation) + private IEnumerable> GetDiscriminatorMappings(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, CodeNamespace currentNamespace, CodeClass? baseClass, OpenApiOperation? currentOperation) { // Generate types that this discriminator references return schema.GetDiscriminatorMappings(inheritanceIndex) @@ -2295,9 +2297,7 @@ internal static void AddDiscriminatorMethod(CodeClass newClass, string discrimin logger.LogWarning("Discriminator {ComponentKey} not found in the OpenAPI document.", componentKey); return null; } - // the new version of OAI.net does not mutate the source schema anymore when resolving references which is a positive thing but is challenging for naming. - var schemaClone = new OpenApiSchema(discriminatorSchema); - schemaClone.Reference ??= new OpenApiReference { Id = componentKey, Type = ReferenceType.Schema }; + var schemaClone = discriminatorSchema.CreateShallowCopy(); // Call CreateModelDeclarations with isViaDiscriminator=true. This is for a special case where we always generate a base class when types are referenced via a oneOf discriminator. if (CreateModelDeclarations(currentNode, schemaClone, currentOperation, GetShortestNamespace(currentNamespace, schemaClone), string.Empty, null, string.Empty, false, true) is not CodeType result) { @@ -2312,14 +2312,14 @@ internal static void AddDiscriminatorMethod(CodeClass newClass, string discrimin } return result; } - private void CreatePropertiesForModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, CodeNamespace ns, CodeClass model) + private void CreatePropertiesForModelClass(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, CodeNamespace ns, CodeClass model) { var propertiesToAdd = schema.Properties .Select(x => { var propertySchema = x.Value; var className = $"{model.Name}_{x.Key.CleanupSymbolName()}"; - var shortestNamespaceName = GetModelsNamespaceNameFromReferenceId(propertySchema.Reference?.Id); + var shortestNamespaceName = GetModelsNamespaceNameFromReferenceId(propertySchema.GetReferenceId()); var targetNamespace = string.IsNullOrEmpty(shortestNamespaceName) ? ns : rootNamespace?.FindOrAddNamespace(shortestNamespaceName) ?? ns; var definition = CreateModelDeclarations(currentNode, propertySchema, default, targetNamespace, string.Empty, typeNameForInlineSchema: className); @@ -2458,7 +2458,7 @@ internal static void AddSerializationMembers(CodeClass model, bool includeAdditi } private CodeClass? CreateOperationParameterClass(OpenApiUrlTreeNode node, OperationType operationType, OpenApiOperation operation, CodeClass parentClass) { - var parameters = node.PathItems[Constants.DefaultOpenApiLabel].Parameters.Union(operation.Parameters ?? Enumerable.Empty()).Where(static p => p.In == ParameterLocation.Query).ToArray(); + var parameters = node.PathItems[Constants.DefaultOpenApiLabel].Parameters.Union(operation.Parameters ?? Enumerable.Empty()).Where(static p => p.In == ParameterLocation.Query).ToArray(); if (parameters.Length != 0) { var parameterClass = parentClass.AddInnerClass(new CodeClass @@ -2480,7 +2480,7 @@ internal static void AddSerializationMembers(CodeClass model, bool includeAdditi return null; } - private void AddPropertyForQueryParameter(OpenApiUrlTreeNode node, OperationType operationType, OpenApiParameter parameter, CodeClass parameterClass) + private void AddPropertyForQueryParameter(OpenApiUrlTreeNode node, OperationType operationType, IOpenApiParameter parameter, CodeClass parameterClass) { CodeType? resultType = default; var addBackwardCompatibleParameter = false; @@ -2563,7 +2563,7 @@ private static CodeType GetDefaultQueryParameterType() Name = "string", }; } - private static CodeType GetQueryParameterType(OpenApiSchema schema) + private static CodeType GetQueryParameterType(IOpenApiSchema schema) { var paramType = GetPrimitiveType(schema) ?? new() { diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index bb7107cdc5..c8ee3c7473 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -13,6 +13,8 @@ using Microsoft.OpenApi.ApiManifest; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Writers; using Microsoft.Plugins.Manifest; @@ -113,7 +115,7 @@ private sealed class MappingCleanupVisitor(OpenApiDocument openApiDocument) : Op { private readonly OpenApiDocument _document = openApiDocument; - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { if (schema.Discriminator?.Mapping is null) return; @@ -126,7 +128,7 @@ public override void Visit(OpenApiSchema schema) private sealed class AllOfPropertiesRetrievalVisitor : OpenApiVisitorBase { - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { if (schema.AllOf is not { Count: > 0 }) return; @@ -139,7 +141,7 @@ public override void Visit(OpenApiSchema schema) base.Visit(schema); } - private static IEnumerable> GetAllProperties(OpenApiSchema schema) + private static IEnumerable> GetAllProperties(IOpenApiSchema schema) { return schema.AllOf is not null ? schema.AllOf.SelectMany(static x => GetAllProperties(x)).Union(schema.Properties) : @@ -149,7 +151,7 @@ private static IEnumerable> GetAllProperties private sealed class SelectFirstAnyOneOfVisitor : OpenApiVisitorBase { - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { if (schema.AnyOf is { Count: > 0 }) { @@ -163,72 +165,75 @@ public override void Visit(OpenApiSchema schema) } base.Visit(schema); } - internal static void CopyRelevantInformation(OpenApiSchema source, OpenApiSchema target, bool includeProperties = true, bool includeReference = true, bool includeDiscriminator = true) + internal static void CopyRelevantInformation(IOpenApiSchema source, IOpenApiSchema target, bool includeProperties = true, bool includeReference = true, bool includeDiscriminator = true) { - if (source.Type is not null && source.Type.HasValue) - target.Type = source.Type; - if (!string.IsNullOrEmpty(source.Format)) - target.Format = source.Format; - if (source.Items is not null) - target.Items = source.Items; - if (source.Properties is not null && includeProperties) - target.Properties = new Dictionary(source.Properties); - if (source.Required is not null) - target.Required = new HashSet(source.Required); - if (source.AdditionalProperties is not null) - target.AdditionalProperties = source.AdditionalProperties; - if (source.Enum is not null) - target.Enum = [.. source.Enum]; - if (source.ExclusiveMaximum is not null) - target.ExclusiveMaximum = source.ExclusiveMaximum; - if (source.ExclusiveMinimum is not null) - target.ExclusiveMinimum = source.ExclusiveMinimum; - if (source.Maximum is not null) - target.Maximum = source.Maximum; - if (source.Minimum is not null) - target.Minimum = source.Minimum; - if (source.MaxItems is not null) - target.MaxItems = source.MaxItems; - if (source.MinItems is not null) - target.MinItems = source.MinItems; - if (source.MaxLength is not null) - target.MaxLength = source.MaxLength; - if (source.MinLength is not null) - target.MinLength = source.MinLength; - if (source.Pattern is not null) - target.Pattern = source.Pattern; - if (source.MaxProperties is not null) - target.MaxProperties = source.MaxProperties; - if (source.MinProperties is not null) - target.MinProperties = source.MinProperties; - if (source.UniqueItems is not null) - target.UniqueItems = source.UniqueItems; - if (source.Nullable) - target.Nullable = true; - if (source.ReadOnly) - target.ReadOnly = true; - if (source.WriteOnly) - target.WriteOnly = true; - if (source.Deprecated) - target.Deprecated = true; - if (source.Xml is not null) - target.Xml = source.Xml; - if (source.ExternalDocs is not null) - target.ExternalDocs = source.ExternalDocs; - if (source.Example is not null) - target.Example = source.Example; - if (source.Extensions is not null) - target.Extensions = new Dictionary(source.Extensions); - if (source.Discriminator is not null && includeDiscriminator) - target.Discriminator = source.Discriminator; - if (!string.IsNullOrEmpty(source.Description)) - target.Description = source.Description; - if (!string.IsNullOrEmpty(source.Title)) - target.Title = source.Title; - if (source.Default is not null) - target.Default = source.Default; - if (source.Reference is not null && includeReference) - target.Reference = source.Reference; + if (target is OpenApiSchema openApiSchema) + { + if (source.Type is not null && source.Type.HasValue) + openApiSchema.Type = source.Type; + if (!string.IsNullOrEmpty(source.Format)) + openApiSchema.Format = source.Format; + if (source.Items is not null) + openApiSchema.Items = source.Items; + if (source.Properties is not null && includeProperties) + openApiSchema.Properties = new Dictionary(source.Properties); + if (source.Required is not null) + openApiSchema.Required = new HashSet(source.Required); + if (source.AdditionalProperties is not null) + openApiSchema.AdditionalProperties = source.AdditionalProperties; + if (source.Enum is not null) + openApiSchema.Enum = [.. source.Enum]; + if (source.ExclusiveMaximum is not null) + openApiSchema.ExclusiveMaximum = source.ExclusiveMaximum; + if (source.ExclusiveMinimum is not null) + openApiSchema.ExclusiveMinimum = source.ExclusiveMinimum; + if (source.Maximum is not null) + openApiSchema.Maximum = source.Maximum; + if (source.Minimum is not null) + openApiSchema.Minimum = source.Minimum; + if (source.MaxItems is not null) + openApiSchema.MaxItems = source.MaxItems; + if (source.MinItems is not null) + openApiSchema.MinItems = source.MinItems; + if (source.MaxLength is not null) + openApiSchema.MaxLength = source.MaxLength; + if (source.MinLength is not null) + openApiSchema.MinLength = source.MinLength; + if (source.Pattern is not null) + openApiSchema.Pattern = source.Pattern; + if (source.MaxProperties is not null) + openApiSchema.MaxProperties = source.MaxProperties; + if (source.MinProperties is not null) + openApiSchema.MinProperties = source.MinProperties; + if (source.UniqueItems is not null) + openApiSchema.UniqueItems = source.UniqueItems; + if (source.Nullable) + openApiSchema.Nullable = true; + if (source.ReadOnly) + openApiSchema.ReadOnly = true; + if (source.WriteOnly) + openApiSchema.WriteOnly = true; + if (source.Deprecated) + openApiSchema.Deprecated = true; + if (source.Xml is not null) + openApiSchema.Xml = source.Xml; + if (source.ExternalDocs is not null) + openApiSchema.ExternalDocs = source.ExternalDocs; + if (source.Example is not null) + openApiSchema.Example = source.Example; + if (source.Extensions is not null) + openApiSchema.Extensions = new Dictionary(source.Extensions); + if (source.Discriminator is not null && includeDiscriminator) + openApiSchema.Discriminator = source.Discriminator; + if (!string.IsNullOrEmpty(source.Description)) + openApiSchema.Description = source.Description; + if (!string.IsNullOrEmpty(source.Title)) + openApiSchema.Title = source.Title; + if (source.Default is not null) + openApiSchema.Default = source.Default; + } + else if (includeReference && source is OpenApiSchemaReference sourceRef && target is OpenApiSchemaReference targetRef) + targetRef.Reference = sourceRef.Reference; } } @@ -259,10 +264,10 @@ public override void Visit(OpenApiOperation operation) operation.ExternalDocs = null; base.Visit(operation); } - public override void Visit(OpenApiSchema schema) + public override void Visit(IOpenApiSchema schema) { - if (schema.ExternalDocs is not null) - schema.ExternalDocs = null; + if (schema.ExternalDocs is not null && schema is OpenApiSchema openApiSchema) + openApiSchema.ExternalDocs = null; base.Visit(schema); } public override void Visit(OpenApiTag tag) @@ -483,7 +488,7 @@ private static Auth GetAuth(IList securityRequiremen return (opSecurity is null || opSecurity.UnresolvedReference) ? new AnonymousAuth() : GetAuthFromSecurityScheme(opSecurity); } - private static Auth GetAuthFromSecurityScheme(OpenApiSecurityScheme securityScheme) + private static Auth GetAuthFromSecurityScheme(OpenApiSecuritySchemeReference securityScheme) { string name = securityScheme.Reference.Id; return securityScheme.Type switch diff --git a/src/Kiota.Builder/Validation/MissingDiscriminator.cs b/src/Kiota.Builder/Validation/MissingDiscriminator.cs index 4fa5b52064..b544cc5eea 100644 --- a/src/Kiota.Builder/Validation/MissingDiscriminator.cs +++ b/src/Kiota.Builder/Validation/MissingDiscriminator.cs @@ -5,6 +5,7 @@ using Kiota.Builder.Configuration; using Kiota.Builder.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Validations; namespace Kiota.Builder.Validation; @@ -22,8 +23,8 @@ public MissingDiscriminator(GenerationConfiguration configuration) : base(nameof var inlineSchemasToValidate = document.Paths ?.SelectMany(static x => x.Value.Operations.Values.Select(y => (x.Key, Operation: y))) .SelectMany(x => x.Operation.GetResponseSchemas(OpenApiOperationExtensions.SuccessCodes, configuration.StructuredMimeTypes).Select(y => (x.Key, Schema: y))) - .Where(static x => string.IsNullOrEmpty(x.Schema.Reference?.Id)) - .ToArray() ?? Array.Empty<(string, OpenApiSchema)>(); + .Where(static x => x.Schema is OpenApiSchema) + .ToArray() ?? []; Parallel.ForEach(inlineSchemasToValidate, entry => { ValidateSchema(entry.Schema, context, idx, entry.Key); @@ -31,7 +32,7 @@ public MissingDiscriminator(GenerationConfiguration configuration) : base(nameof }) { } - private static void ValidateSchema(OpenApiSchema schema, IValidationContext context, ConcurrentDictionary> idx, string address) + private static void ValidateSchema(IOpenApiSchema schema, IValidationContext context, ConcurrentDictionary> idx, string address) { if (!schema.IsInclusiveUnion() && !schema.IsExclusiveUnion()) return; diff --git a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs index 2505515d5f..4a5fec57c8 100644 --- a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs +++ b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs @@ -4,43 +4,40 @@ using System.Linq; using System.Text.Json.Nodes; using Kiota.Builder.Extensions; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; namespace Kiota.Builder.Validation; -internal class OpenApiSchemaComparer : IEqualityComparer +internal class OpenApiSchemaComparer : IEqualityComparer { private readonly OpenApiDiscriminatorComparer discriminatorComparer; private readonly JsonNodeComparer jsonNodeComparer; - private readonly KeyValueComparer schemaMapComparer; public OpenApiSchemaComparer( OpenApiDiscriminatorComparer? discriminatorComparer = null, - JsonNodeComparer? jsonNodeComparer = null, - KeyValueComparer? schemaMapComparer = null) + JsonNodeComparer? jsonNodeComparer = null) { this.discriminatorComparer = discriminatorComparer ?? new OpenApiDiscriminatorComparer(); this.jsonNodeComparer = jsonNodeComparer ?? new JsonNodeComparer(); - this.schemaMapComparer = schemaMapComparer ?? new KeyValueComparer(StringComparer.Ordinal, this); } /// - public bool Equals(OpenApiSchema? x, OpenApiSchema? y) + public bool Equals(IOpenApiSchema? x, IOpenApiSchema? y) { // this workaround might result in collisions, however so far this has not been a problem // implemented this way to avoid stack overflow caused by schemas referencing themselves return x == null && y == null || x != null && y != null && GetHashCode(x) == GetHashCode(y); } /// - public int GetHashCode([DisallowNull] OpenApiSchema obj) + public int GetHashCode([DisallowNull] IOpenApiSchema obj) { var hash = new HashCode(); GetHashCodeInternal(obj, [], ref hash); return hash.ToHashCode(); } - private void GetHashCodeInternal([DisallowNull] OpenApiSchema obj, HashSet visitedSchemas, ref HashCode hash) + private void GetHashCodeInternal([DisallowNull] IOpenApiSchema obj, HashSet visitedSchemas, ref HashCode hash) { if (obj is null) return; if (!visitedSchemas.Add(obj)) return; From eaa16e4fa837ceffecefad9cfd208c4f639b9248 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 3 Feb 2025 14:07:38 -0500 Subject: [PATCH 46/96] fix: first batch of unit test reference fixes --- .../ContentTypeMappingTests.cs | 27 +- .../OpenApiOperationExtensionsTests.cs | 12 +- .../OpenApiReferenceExtensionsTests.cs | 25 - .../OpenApiSchemaExtensionsTests.cs | 270 +++++------ .../OpenApiUrlTreeNodeExtensionsTests.cs | 138 +++--- .../Kiota.Builder.Tests/KiotaBuilderTests.cs | 436 ++++++++---------- .../Validation/OpenApiSchemaComparerTests.cs | 6 +- 7 files changed, 410 insertions(+), 504 deletions(-) delete mode 100644 tests/Kiota.Builder.Tests/Extensions/OpenApiReferenceExtensionsTests.cs diff --git a/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs b/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs index 1c1c020583..a04bc9bfde 100644 --- a/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs +++ b/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs @@ -8,6 +8,7 @@ using Kiota.Builder.Extensions; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Moq; using Xunit; @@ -84,7 +85,7 @@ public void GeneratesTheRightReturnTypeBasedOnContentAndStatus(string contentTyp var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -96,7 +97,6 @@ public void GeneratesTheRightReturnTypeBasedOnContentAndStatus(string contentTyp Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -123,7 +123,7 @@ public void GeneratesTheRightReturnTypeBasedOnContentAndStatus(string contentTyp }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -178,7 +178,7 @@ public void GeneratesTheRightParameterTypeBasedOnContentAndStatus(string content var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -190,7 +190,6 @@ public void GeneratesTheRightParameterTypeBasedOnContentAndStatus(string content Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -218,7 +217,7 @@ public void GeneratesTheRightParameterTypeBasedOnContentAndStatus(string content }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -270,7 +269,7 @@ public void GeneratesTheRightAcceptHeaderBasedOnContentAndStatus(string contentM Content = contentMediaTypes.Split(',').Select(x => new {Key = x.Trim(), value = new OpenApiMediaType { Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -282,7 +281,6 @@ public void GeneratesTheRightAcceptHeaderBasedOnContentAndStatus(string contentM Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false } } }).ToDictionary(x => x.Key, x => x.value) @@ -294,11 +292,11 @@ public void GeneratesTheRightAcceptHeaderBasedOnContentAndStatus(string contentM }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -310,7 +308,6 @@ public void GeneratesTheRightAcceptHeaderBasedOnContentAndStatus(string contentM Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false } } } @@ -361,7 +358,7 @@ public void GeneratesTheRightContentTypeHeaderBasedOnContentAndStatus(string con Content = contentMediaTypes.Split(',').Select(x => new {Key = x.Trim(), value = new OpenApiMediaType { Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -373,7 +370,6 @@ public void GeneratesTheRightContentTypeHeaderBasedOnContentAndStatus(string con Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false } } }).ToDictionary(x => x.Key, x => x.value) @@ -384,11 +380,11 @@ public void GeneratesTheRightContentTypeHeaderBasedOnContentAndStatus(string con }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -400,7 +396,6 @@ public void GeneratesTheRightContentTypeHeaderBasedOnContentAndStatus(string con Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false } } } diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiOperationExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiOperationExtensionsTests.cs index 79114497b6..a1499e0b6e 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiOperationExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiOperationExtensionsTests.cs @@ -16,10 +16,10 @@ public void GetsResponseSchema() var operation = new OpenApiOperation { Responses = new() { - { "200", new() { + { "200", new OpenApiResponse() { Content = new Dictionary { {"application/json", new() { - Schema = new() + Schema = new OpenApiSchema() }} } }} @@ -28,10 +28,10 @@ public void GetsResponseSchema() var operation2 = new OpenApiOperation { Responses = new() { - { "400", new() { + { "400", new OpenApiResponse() { Content = new Dictionary { {"application/json", new() { - Schema = new() + Schema = new OpenApiSchema() }} } }} @@ -40,10 +40,10 @@ public void GetsResponseSchema() var operation3 = new OpenApiOperation { Responses = new() { - { "200", new() { + { "200", new OpenApiResponse() { Content = new Dictionary { {"application/invalid", new() { - Schema = new() + Schema = new OpenApiSchema() }} } }} diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiReferenceExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiReferenceExtensionsTests.cs deleted file mode 100644 index 107cbe325d..0000000000 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiReferenceExtensionsTests.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Kiota.Builder.Extensions; - -using Microsoft.OpenApi.Models; - -using Xunit; - -namespace Kiota.Builder.Tests.Extensions; -public class OpenApiReferenceExtensionsTests -{ - [Fact] - public void GetsClassName() - { - var reference = new OpenApiReference - { - Id = "microsoft.graph.user" - }; - Assert.Equal("user", reference.GetClassName()); - } - [Fact] - public void GetsClassNameDefensive() - { - var reference = new OpenApiReference(); - Assert.Empty(reference.GetClassName()); - } -} diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index e34351bc89..9f73a67887 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Text.Json.Nodes; using Kiota.Builder.Extensions; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Models; - +using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Xunit; namespace Kiota.Builder.Tests.Extensions; @@ -48,7 +48,7 @@ public void Defensive() Assert.False(OpenApiSchemaExtensions.IsReferencedSchema(null)); Assert.Null(OpenApiSchemaExtensions.MergeIntersectionSchemaEntries(null)); - Assert.False(new OpenApiSchema { Reference = null }.IsReferencedSchema()); + Assert.False(new OpenApiSchema { }.IsReferencedSchema()); Assert.False(new OpenApiSchema { Type = JsonSchemaType.Null }.IsArray()); Assert.False(new OpenApiSchema { Type = JsonSchemaType.Null }.IsObjectType()); Assert.False(new OpenApiSchema { AnyOf = null }.IsInclusiveUnion()); @@ -91,11 +91,11 @@ public void GetSchemaNameAllOfTitleEmpty() var schema = new OpenApiSchema { AllOf = [ - new() + new OpenApiSchema() { Title = "microsoft.graph.entity" }, - new() + new OpenApiSchema() { Title = "microsoft.graph.user" } @@ -111,14 +111,14 @@ public void GetSchemaNameAllOfReference() var schema = new OpenApiSchema { AllOf = [ - new() + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.entity" } }, - new() + new OpenApiSchema() { Reference = new() { @@ -138,14 +138,14 @@ public void GetSchemaNameAllOfNestedTitleEmpty() var schema = new OpenApiSchema { AllOf = [ - new() + new OpenApiSchema() { AllOf = [ - new() + new OpenApiSchema() { Title = "microsoft.graph.entity" }, - new() + new OpenApiSchema() { Title = "microsoft.graph.user" } @@ -163,17 +163,17 @@ public void GetSchemaNameAllOfNestedReference() var schema = new OpenApiSchema { AllOf = [ - new() + new OpenApiSchema() { AllOf = [ - new() + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.entity" } }, - new() + new OpenApiSchema() { Reference = new() { @@ -195,11 +195,11 @@ public void GetSchemaNameAnyOfTitleEmpty() var schema = new OpenApiSchema { AnyOf = [ - new() + new OpenApiSchema() { Title = "microsoft.graph.entity" }, - new() + new OpenApiSchema() { Title = "microsoft.graph.user" } @@ -215,14 +215,14 @@ public void GetSchemaNameAnyOfReference() var schema = new OpenApiSchema { AnyOf = [ - new() + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.entity" } }, - new() + new OpenApiSchema() { Reference = new() { @@ -242,11 +242,11 @@ public void GetSchemaNameOneOfTitleEmpty() var schema = new OpenApiSchema { OneOf = [ - new() + new OpenApiSchema() { Title = "microsoft.graph.entity" }, - new() + new OpenApiSchema() { Title = "microsoft.graph.user" } @@ -262,14 +262,14 @@ public void GetSchemaNameOneOfReference() var schema = new OpenApiSchema { OneOf = [ - new() + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.entity" } }, - new() + new OpenApiSchema() { Reference = new() { @@ -288,7 +288,7 @@ public void GetSchemaNameItemsTitleEmpty() { var schema = new OpenApiSchema { - Items = new() + Items = new OpenApiSchema() { Title = "microsoft.graph.entity" }, @@ -302,7 +302,7 @@ public void GetSchemaNameItemsReference() { var schema = new OpenApiSchema { - Items = new() + Items = new OpenApiSchema() { Reference = new() { @@ -354,13 +354,13 @@ public void GetReferenceIdsAllOf() { var schema = new OpenApiSchema { - AllOf = new List { - new() { + AllOf = new List { + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.entity" } }, - new() { + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.user" } @@ -376,15 +376,15 @@ public void GetReferenceIdsAllOfNested() { var schema = new OpenApiSchema { - AllOf = new List { - new() { - AllOf = new List { - new() { + AllOf = new List { + new OpenApiSchema() { + AllOf = new List { + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.entity" } }, - new() { + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.user" } @@ -402,13 +402,13 @@ public void GetReferenceIdsAnyOf() { var schema = new OpenApiSchema { - AnyOf = new List { - new() { + AnyOf = new List { + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.entity" } }, - new() { + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.user" } @@ -424,13 +424,13 @@ public void GetReferenceIdsOneOf() { var schema = new OpenApiSchema { - OneOf = new List { - new() { + OneOf = new List { + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.entity" } }, - new() { + new OpenApiSchema() { Reference = new() { Id = "microsoft.graph.user" } @@ -446,7 +446,7 @@ public void GetReferenceIdsItems() { var schema = new OpenApiSchema { - Items = new() + Items = new OpenApiSchema() { Reference = new() { @@ -484,19 +484,19 @@ public void IsInherited() { var schema = new OpenApiSchema { - AllOf = new List { - new() { + AllOf = new List { + new OpenApiSchema() { Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.entity" }, - Properties = new Dictionary() { + Properties = new Dictionary() { ["id"] = new OpenApiSchema() } }, - new() { + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() { + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema() } } @@ -510,22 +510,22 @@ public void IsIntersection() { var schema = new OpenApiSchema { - AllOf = new List { - new() { + AllOf = new List { + new OpenApiSchema() { Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.entity" }, - Properties = new Dictionary() { + Properties = new Dictionary() { ["id"] = new OpenApiSchema() } }, - new() { + new OpenApiSchema() { Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.user" }, - Properties = new Dictionary() { + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema() } } @@ -536,16 +536,16 @@ public void IsIntersection() schema = new OpenApiSchema { - AllOf = new List { - new() { + AllOf = new List { + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() { + Properties = new Dictionary() { ["id"] = new OpenApiSchema() } }, - new() { + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() { + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema() } } @@ -556,10 +556,10 @@ public void IsIntersection() schema = new OpenApiSchema { - AllOf = new List { - new() { + AllOf = new List { + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() { + Properties = new Dictionary() { ["id"] = new OpenApiSchema() } } @@ -571,8 +571,8 @@ public void IsIntersection() schema = new OpenApiSchema { Title = "Trader Id", - AllOf = new List { - new () + AllOf = new List { + new OpenApiSchema() { Title = "UserId", Description = "unique identifier", @@ -601,22 +601,22 @@ public void MergesIntersection() { Description = "description", Deprecated = true, - AllOf = new List { - new() { + AllOf = new List { + new OpenApiSchema() { Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.entity" }, - Properties = new Dictionary() { + Properties = new Dictionary() { ["id"] = new OpenApiSchema() } }, - new() { + new OpenApiSchema() { Type = JsonSchemaType.Object, Reference = new() { Id = "microsoft.graph.user" }, - Properties = new Dictionary() { + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema() } } @@ -637,26 +637,26 @@ public void MergesIntersectionRecursively() { Description = "description", Deprecated = true, - AllOf = new List { - new() { + AllOf = new List { + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() { + Properties = new Dictionary() { ["id"] = new OpenApiSchema() } }, - new() { + new OpenApiSchema() { Type = JsonSchemaType.Object, - AllOf = new List() { - new () { + AllOf = new List() { + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() { + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), ["lastName"] = new OpenApiSchema() } }, - new () { + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() { + Properties = new Dictionary() { ["lastName"] = new OpenApiSchema() } }, @@ -684,25 +684,25 @@ public void DoesMergeWithInheritance() Type = JsonSchemaType.Object, AnyOf = [ - new() + new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["one"] = new OpenApiSchema(), }, AllOf = [ - new() + new OpenApiSchema() { Reference = new() { Id = "BaseClass" }, }, - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), ["lastName"] = new OpenApiSchema() @@ -729,34 +729,34 @@ public void DoesMergeWithIntersection() Type = JsonSchemaType.Object, AnyOf = [ - new() + new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["one"] = new OpenApiSchema(), }, AllOf = [ - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["first"] = new OpenApiSchema(), } }, - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["second"] = new OpenApiSchema(), } }, - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["third"] = new OpenApiSchema(), } @@ -782,25 +782,25 @@ public void DoesNotMergeWithMoreThanOneInclusiveEntry() Type = JsonSchemaType.Object, AnyOf = [ - new() + new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["one"] = new OpenApiSchema(), }, AllOf = [ - new() + new OpenApiSchema() { Reference = new() { Id = "BaseClass" }, }, - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), ["lastName"] = new OpenApiSchema() @@ -823,14 +823,14 @@ public void DoesNotMergeWithoutInheritanceOrIntersection() Type = JsonSchemaType.Object, AnyOf = [ - new() + new OpenApiSchema() { AllOf = [ - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), ["lastName"] = new OpenApiSchema() @@ -856,25 +856,25 @@ public void DoesMergeWithInheritance() Type = JsonSchemaType.Object, OneOf = [ - new() + new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["one"] = new OpenApiSchema(), }, AllOf = [ - new() + new OpenApiSchema() { Reference = new() { Id = "BaseClass" }, }, - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), ["lastName"] = new OpenApiSchema() @@ -901,34 +901,34 @@ public void DoesMergeWithIntersection() Type = JsonSchemaType.Object, OneOf = [ - new() + new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["one"] = new OpenApiSchema(), }, AllOf = [ - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["first"] = new OpenApiSchema(), } }, - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["second"] = new OpenApiSchema(), } }, - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["third"] = new OpenApiSchema(), } @@ -954,25 +954,25 @@ public void DoesNotMergeWithMoreThanOneExclusiveEntry() Type = JsonSchemaType.Object, OneOf = [ - new() + new OpenApiSchema() { - Properties = new Dictionary() + Properties = new Dictionary() { ["one"] = new OpenApiSchema(), }, AllOf = [ - new() + new OpenApiSchema() { Reference = new() { Id = "BaseClass" }, }, - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), ["lastName"] = new OpenApiSchema() @@ -995,14 +995,14 @@ public void DoesNotMergeWithoutInheritanceOrIntersection() Type = JsonSchemaType.Object, OneOf = [ - new() + new OpenApiSchema() { AllOf = [ - new() + new OpenApiSchema() { Type = JsonSchemaType.Object, - Properties = new Dictionary() + Properties = new Dictionary() { ["firstName"] = new OpenApiSchema(), ["lastName"] = new OpenApiSchema() @@ -1069,7 +1069,7 @@ public void IsEnumIgnoresNullableUnions() { var schema = new OpenApiSchema { - AnyOf = new List + AnyOf = new List { enumSchema, new OpenApiSchema @@ -1086,7 +1086,7 @@ public void IsEnumFailsOnNullableInheritance() { var schema = new OpenApiSchema { - AllOf = new List + AllOf = new List { enumSchema, new OpenApiSchema @@ -1103,7 +1103,7 @@ public void IsEnumIgnoresNullableExclusiveUnions() { var schema = new OpenApiSchema { - OneOf = new List + OneOf = new List { enumSchema, new OpenApiSchema @@ -1125,7 +1125,7 @@ public void IsEnumDoesNotMaskExclusiveUnions() { var schema = new OpenApiSchema { - OneOf = new List + OneOf = new List { enumSchema, numberSchema, @@ -1143,7 +1143,7 @@ public void IsEnumDoesNotMaskUnions() { var schema = new OpenApiSchema { - AnyOf = new List + AnyOf = new List { enumSchema, numberSchema, @@ -1161,20 +1161,20 @@ public void IsOdataPrimitive() { var schema = new OpenApiSchema { - OneOf = new List + OneOf = new List { - new () + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "double", Nullable = true }, - new () + new OpenApiSchema() { Type = JsonSchemaType.String, Nullable = true }, - new () + new OpenApiSchema() { Enum = new List { @@ -1194,18 +1194,18 @@ public void IsOdataPrimitiveBackwardCompatible() { var schema = new OpenApiSchema { - OneOf = new List + OneOf = new List { - new () + new OpenApiSchema() { Type = JsonSchemaType.Number, Format = "double", }, - new () + new OpenApiSchema() { Type = JsonSchemaType.String, }, - new () + new OpenApiSchema() { Enum = new List() { @@ -1227,7 +1227,7 @@ public void ReturnsEmptyPropertyNameOnCircularReferences() { Id = "microsoft.graph.entity" }, - Properties = new Dictionary + Properties = new Dictionary { ["id"] = new OpenApiSchema { @@ -1250,7 +1250,7 @@ public void ReturnsEmptyPropertyNameOnCircularReferences() new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary + Properties = new Dictionary { ["firstName"] = new OpenApiSchema { @@ -1277,4 +1277,16 @@ public void ReturnsEmptyPropertyNameOnCircularReferences() ]; Assert.Empty(userSchema.GetDiscriminatorPropertyName()); } + [Fact] + public void GetsClassName() + { + var reference = new OpenApiSchemaReference("microsoft.graph.user", new()); + Assert.Equal("user", reference.GetClassName()); + } + [Fact] + public void GetsClassNameDefensive() + { + var reference = new OpenApiSchema(); + Assert.Empty(reference.GetClassName()); + } } diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs index 0a073478b1..2b3602b0ee 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs @@ -6,6 +6,7 @@ using Kiota.Builder.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Xunit; @@ -29,7 +30,7 @@ public void Defensive() public void GetsDescription() { var node = OpenApiUrlTreeNode.Create(); - node.PathItems.Add(Label, new() + node.PathItems.Add(Label, new OpenApiPathItem() { Description = "description", Summary = "summary" @@ -46,9 +47,9 @@ public void IsComplexPathWithAnyNumberOfParameters() { Paths = new(), }; - doc.Paths.Add("function()", new()); - doc.Paths.Add("function({param})", new()); - doc.Paths.Add("function({param}, {param2})", new()); + doc.Paths.Add("function()", new OpenApiPathItem()); + doc.Paths.Add("function({param})", new OpenApiPathItem()); + doc.Paths.Add("function({param}, {param2})", new OpenApiPathItem()); var node = OpenApiUrlTreeNode.Create(doc, Label); Assert.False(node.IsComplexPathMultipleParameters()); Assert.False(node.Children.First().Value.IsComplexPathMultipleParameters()); @@ -62,7 +63,7 @@ public void IsPathWithSingleSimpleParameter() { Paths = new(), }; - doc.Paths.Add("{param}", new()); + doc.Paths.Add("{param}", new OpenApiPathItem()); var node = OpenApiUrlTreeNode.Create(doc, Label); Assert.False(node.IsPathSegmentWithSingleSimpleParameter()); Assert.True(node.Children.First().Value.IsPathSegmentWithSingleSimpleParameter()); @@ -74,7 +75,7 @@ public void DoesNodeBelongToItemSubnamespace() { Paths = new(), }; - doc.Paths.Add("{param}", new()); + doc.Paths.Add("{param}", new OpenApiPathItem()); var node = OpenApiUrlTreeNode.Create(doc, Label); Assert.False(node.DoesNodeBelongToItemSubnamespace()); Assert.True(node.Children.First().Value.DoesNodeBelongToItemSubnamespace()); @@ -83,7 +84,7 @@ public void DoesNodeBelongToItemSubnamespace() { Paths = new(), }; - doc.Paths.Add("param}", new()); + doc.Paths.Add("param}", new OpenApiPathItem()); node = OpenApiUrlTreeNode.Create(doc, Label); Assert.False(node.Children.First().Value.DoesNodeBelongToItemSubnamespace()); @@ -91,7 +92,7 @@ public void DoesNodeBelongToItemSubnamespace() { Paths = new(), }; - doc.Paths.Add("{param", new()); + doc.Paths.Add("{param", new OpenApiPathItem()); node = OpenApiUrlTreeNode.Create(doc, Label); Assert.False(node.Children.First().Value.DoesNodeBelongToItemSubnamespace()); } @@ -102,7 +103,7 @@ public void GetNodeNamespaceFromPath() { Paths = new(), }; - doc.Paths.Add("\\users\\messages", new()); + doc.Paths.Add("\\users\\messages", new OpenApiPathItem()); var node = OpenApiUrlTreeNode.Create(doc, Label); Assert.Equal("graph.users.messages", node.Children.First().Value.GetNodeNamespaceFromPath("graph")); Assert.Equal("users.messages", node.Children.First().Value.GetNodeNamespaceFromPath(null)); @@ -114,7 +115,7 @@ public void SanitizesAtSign() { Paths = new(), }; - doc.Paths.Add("\\deviceManagement\\microsoft.graph.getRoleScopeTagsByIds(ids=@ids)", new()); + doc.Paths.Add("\\deviceManagement\\microsoft.graph.getRoleScopeTagsByIds(ids=@ids)", new OpenApiPathItem()); var node = OpenApiUrlTreeNode.Create(doc, Label); Assert.Equal("graph.deviceManagement.microsoftGraphGetRoleScopeTagsByIdsWithIds", node.Children.First().Value.GetNodeNamespaceFromPath("graph")); } @@ -135,24 +136,24 @@ public void GetUrlTemplateSelectsDistinctQueryParameters() { Paths = [], }; - doc.Paths.Add("{param-with-dashes}\\existing-segment", new() + doc.Paths.Add("{param-with-dashes}\\existing-segment", new OpenApiPathItem() { Operations = new Dictionary { { OperationType.Get, new() { Parameters = [ - new() { + new OpenApiParameter() { Name = "param-with-dashes", In = ParameterLocation.Path, Required = true, - Schema = new() { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, - new (){ + new OpenApiParameter (){ Name = "$select", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, @@ -163,19 +164,19 @@ public void GetUrlTemplateSelectsDistinctQueryParameters() { OperationType.Put, new() { Parameters = [ - new() { + new OpenApiParameter() { Name = "param-with-dashes", In = ParameterLocation.Path, Required = true, - Schema = new() { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, - new (){ + new OpenApiParameter(){ Name = "$select", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema () { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, @@ -196,15 +197,15 @@ public void DifferentUrlTemplatesPerOperation() { Paths = [], }; - doc.Paths.Add("{param-with-dashes}\\existing-segment", new() + doc.Paths.Add("{param-with-dashes}\\existing-segment", new OpenApiPathItem() { Parameters = [ - new() + new OpenApiParameter() { Name = "param-with-dashes", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -215,10 +216,10 @@ public void DifferentUrlTemplatesPerOperation() { OperationType.Get, new() { Parameters = [ - new (){ + new OpenApiParameter(){ Name = "$select", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, @@ -246,15 +247,15 @@ public void DifferentUrlTemplatesPerOperationWithRequiredParameter() { Paths = [], }; - doc.Paths.Add("{param-with-dashes}\\existing-segment", new() + doc.Paths.Add("{param-with-dashes}\\existing-segment", new OpenApiPathItem() { Parameters = [ - new() + new OpenApiParameter() { Name = "param-with-dashes", In = ParameterLocation.Path, Required = true, - Schema = new() + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, @@ -265,10 +266,10 @@ public void DifferentUrlTemplatesPerOperationWithRequiredParameter() { OperationType.Get, new() { Parameters = [ - new (){ + new OpenApiParameter(){ Name = "$select", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, @@ -279,10 +280,10 @@ public void DifferentUrlTemplatesPerOperationWithRequiredParameter() { OperationType.Post, new() { Parameters = [ - new (){ + new OpenApiParameter(){ Name = "$expand", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, @@ -296,10 +297,10 @@ public void DifferentUrlTemplatesPerOperationWithRequiredParameter() { OperationType.Delete, new() { Parameters = [ - new (){ + new OpenApiParameter (){ Name = "id", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, @@ -327,7 +328,7 @@ public void GeneratesRequiredQueryParametersAndOptionalMixInPathItem() { Paths = [], }; - doc.Paths.Add("users\\{id}\\manager", new() + doc.Paths.Add("users\\{id}\\manager", new OpenApiPathItem() { Parameters = { new OpenApiParameter { @@ -371,7 +372,7 @@ public void GeneratesRequiredQueryParametersAndOptionalMixInOperation() { Paths = [], }; - doc.Paths.Add("users\\{id}\\manager", new() + doc.Paths.Add("users\\{id}\\manager", new OpenApiPathItem() { Operations = new Dictionary { { OperationType.Get, new() { @@ -415,7 +416,7 @@ public void GeneratesOnlyOptionalQueryParametersInPathItem() { Paths = [], }; - doc.Paths.Add("users\\{id}\\manager", new() + doc.Paths.Add("users\\{id}\\manager", new OpenApiPathItem() { Parameters = { new OpenApiParameter { @@ -458,7 +459,7 @@ public void GeneratesOnlyOptionalQueryParametersInOperation() { Paths = [], }; - doc.Paths.Add("users\\{id}\\manager", new() + doc.Paths.Add("users\\{id}\\manager", new OpenApiPathItem() { Operations = new Dictionary { { OperationType.Get, new() { @@ -500,7 +501,7 @@ public void GeneratesOnlyRequiredQueryParametersInPathItem() { Paths = [], }; - doc.Paths.Add("users\\{id}\\manager", new() + doc.Paths.Add("users\\{id}\\manager", new OpenApiPathItem() { Parameters = { new OpenApiParameter { @@ -544,7 +545,7 @@ public void GeneratesOnlyRequiredQueryParametersInOperation() { Paths = [], }; - doc.Paths.Add("users\\{id}\\manager", new() + doc.Paths.Add("users\\{id}\\manager", new OpenApiPathItem() { Operations = new Dictionary { { OperationType.Get, new() { @@ -589,48 +590,48 @@ public void GetUrlTemplateCleansInvalidParameters() { Paths = [], }; - doc.Paths.Add("{param-with-dashes}\\existing-segment", new() + doc.Paths.Add("{param-with-dashes}\\existing-segment", new OpenApiPathItem() { Operations = new Dictionary { { OperationType.Get, new() { Parameters = [ - new() { + new OpenApiParameter() { Name = "param-with-dashes", In = ParameterLocation.Path, Required = true, - Schema = new() { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, - new (){ + new OpenApiParameter(){ Name = "$select", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, - new (){ + new OpenApiParameter(){ Name = "api-version", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, - new (){ + new OpenApiParameter(){ Name = "api~topic", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, }, - new (){ + new OpenApiParameter(){ Name = "api.encoding", In = ParameterLocation.Query, - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, @@ -659,26 +660,26 @@ public void GetsClassNameWithIndexerAndExtension() { Paths = new(), }; - doc.Paths.Add("/reviews/{resource-type}.json", new() + doc.Paths.Add("/reviews/{resource-type}.json", new OpenApiPathItem() { Operations = new Dictionary { { OperationType.Get, new() { - Parameters = new List { - new() { + Parameters = new List { + new OpenApiParameter() { Name = "resource-type", In = ParameterLocation.Path, Required = true, - Schema = new() { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, } }, Responses = new OpenApiResponses() { - {"200", new() { + {"200", new OpenApiResponse() { Content = new Dictionary() { {"application/json", new() { - Schema = new () { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String } }} @@ -700,17 +701,17 @@ public void GetsClassNameWithSegmentsToSkipForClassNames() { Paths = new(), }; - doc.Paths.Add("/reviews/{resource-type}.json", new() + doc.Paths.Add("/reviews/{resource-type}.json", new OpenApiPathItem() { Operations = new Dictionary { { OperationType.Get, new() { - Parameters = new List { - new() { + Parameters = new List { + new OpenApiParameter() { Name = "resource-type", In = ParameterLocation.Path, Required = true, - Schema = new() { + Schema = new OpenApiSchema() { Type = JsonSchemaType.String }, Style = ParameterStyle.Simple, @@ -719,14 +720,14 @@ public void GetsClassNameWithSegmentsToSkipForClassNames() Responses = new OpenApiResponses() { { - "200", new() + "200", new OpenApiResponse() { Content = new Dictionary() { { "application/json", new() { - Schema = new () + Schema = new OpenApiSchema() { Type = JsonSchemaType.Object, Title = "json", @@ -764,7 +765,7 @@ public void SinglePathParametersAreDeduplicated() var userSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -780,7 +781,6 @@ public void SinglePathParametersAreDeduplicated() { Id = "#/components/schemas/microsoft.graph.user" }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -876,7 +876,7 @@ public void SinglePathParametersAreDeduplicated() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.user", userSchema } @@ -913,7 +913,7 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() var ownerSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -924,12 +924,11 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() { Id = "#/components/schemas/owner" }, - UnresolvedReference = false }; var repoSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -940,7 +939,6 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() { Id = "#/components/schemas/repo" }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -987,7 +985,7 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { {"owner", ownerSchema}, {"repo", repoSchema} } diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 89658bdb0c..92b5d480fb 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -15,10 +15,10 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; -using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.MicrosoftExtensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Services; using Moq; @@ -1401,10 +1401,10 @@ public void OData_doubles_as_one_of() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ - OneOf = new List{ + OneOf = new List{ new OpenApiSchema{ Type = JsonSchemaType.Number }, @@ -1453,10 +1453,10 @@ public void OData_doubles_as_one_of_format_inside() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ - OneOf = new List{ + OneOf = new List{ new OpenApiSchema{ Type = JsonSchemaType.Number, Format = "double" @@ -1505,10 +1505,10 @@ public void OData_doubles_as_any_of() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ - AnyOf = new List{ + AnyOf = new List{ new OpenApiSchema{ Type = JsonSchemaType.Number }, @@ -1543,7 +1543,7 @@ public void MultiNestedArraysSupportedAsUntypedNodes() var fooSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "sortBy", new OpenApiSchema { Type = JsonSchemaType.Array, @@ -1560,7 +1560,6 @@ public void MultiNestedArraysSupportedAsUntypedNodes() { Id = "#/components/schemas/bar.foo" }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -1588,7 +1587,7 @@ public void MultiNestedArraysSupportedAsUntypedNodes() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "bar.foo", fooSchema } @@ -1611,7 +1610,7 @@ public void Object_Arrays_are_supported() var userSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -1627,7 +1626,6 @@ public void Object_Arrays_are_supported() { Id = "#/components/schemas/microsoft.graph.user" }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -1646,7 +1644,7 @@ public void Object_Arrays_are_supported() { Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "value", new OpenApiSchema { Type = JsonSchemaType.Array, @@ -1672,7 +1670,7 @@ public void Object_Arrays_are_supported() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.user", userSchema } @@ -1743,7 +1741,7 @@ public void Supports_Path_Parameters() { Type = JsonSchemaType.Object, Title = "resourceAction", - Properties = new Dictionary { + Properties = new Dictionary { { "allowedResourceActions", new OpenApiSchema { Type = JsonSchemaType.Array, @@ -1765,17 +1763,16 @@ public void Supports_Path_Parameters() { Id = "#/components/schemas/microsoft.graph.resourceAction" }, - UnresolvedReference = false }; var permissionSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "resourceActions", new OpenApiSchema { Type = JsonSchemaType.Array, Items = new OpenApiSchema { - AnyOf = new List { + AnyOf = new List { resourceActionSchema, } } @@ -1786,7 +1783,6 @@ public void Supports_Path_Parameters() { Id = "#/components/schemas/microsoft.graph.rolePermission" }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -1817,7 +1813,7 @@ public void Supports_Path_Parameters() Schema = new OpenApiSchema { Type = JsonSchemaType.Array, Items = new OpenApiSchema { - AnyOf = new List { + AnyOf = new List { permissionSchema, } } @@ -1832,7 +1828,7 @@ public void Supports_Path_Parameters() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.rolePermission", permissionSchema }, { "microsoft.graph.resourceAction", resourceActionSchema }, } @@ -1864,7 +1860,7 @@ public void Supports_Path_Query_And_Header_Parameters() { Type = JsonSchemaType.Object, Title = "resourceAction", - Properties = new Dictionary { + Properties = new Dictionary { { "allowedResourceActions", new OpenApiSchema { Type = JsonSchemaType.Array, @@ -1886,17 +1882,16 @@ public void Supports_Path_Query_And_Header_Parameters() { Id = "#/components/schemas/microsoft.graph.resourceAction" }, - UnresolvedReference = false }; var permissionSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "resourceActions", new OpenApiSchema { Type = JsonSchemaType.Array, Items = new OpenApiSchema { - AnyOf = new List { + AnyOf = new List { resourceActionSchema, } } @@ -1907,7 +1902,6 @@ public void Supports_Path_Query_And_Header_Parameters() { Id = "#/components/schemas/microsoft.graph.rolePermission" }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -1967,7 +1961,7 @@ public void Supports_Path_Query_And_Header_Parameters() Schema = new OpenApiSchema { Type = JsonSchemaType.Array, Items = new OpenApiSchema { - AnyOf = new List { + AnyOf = new List { permissionSchema, } } @@ -1982,7 +1976,7 @@ public void Supports_Path_Query_And_Header_Parameters() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.rolePermission", permissionSchema }, { "microsoft.graph.resourceAction", resourceActionSchema }, } @@ -2065,8 +2059,8 @@ public void DeduplicatesConflictingParameterNamesForCLI() { Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary() { - { "foo", new() { + Properties = new Dictionary() { + { "foo", new OpenApiSchema() { Type = JsonSchemaType.String } } @@ -2107,7 +2101,7 @@ public void Inline_Property_Inheritance_Is_Supported() var resourceSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "info", new OpenApiSchema { Type = JsonSchemaType.String, @@ -2118,7 +2112,6 @@ public void Inline_Property_Inheritance_Is_Supported() { Id = "resource" }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -2137,15 +2130,15 @@ public void Inline_Property_Inheritance_Is_Supported() { Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "derivedResource", new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "info2", new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "title", new OpenApiSchema { Type = JsonSchemaType.String, @@ -2172,7 +2165,7 @@ public void Inline_Property_Inheritance_Is_Supported() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "#/components/resource", resourceSchema } @@ -2209,13 +2202,12 @@ public void Inline_Property_Inheritance_Is_Supported2() { Id = "resource" }, - UnresolvedReference = false }; - var properties = new Dictionary + var properties = new Dictionary { { "info", new OpenApiSchema { Type = JsonSchemaType.String, } }, - { "derivedResource", new OpenApiSchema { AllOf = new List { resourceSchema, } } }, + { "derivedResource", new OpenApiSchema { AllOf = new List { resourceSchema, } } }, }; resourceSchema.Properties = properties; @@ -2236,7 +2228,7 @@ public void Inline_Property_Inheritance_Is_Supported2() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - AllOf = new List() + AllOf = new List() { resourceSchema } @@ -2251,7 +2243,7 @@ public void Inline_Property_Inheritance_Is_Supported2() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "#/components/resource", resourceSchema } @@ -2291,7 +2283,7 @@ public void MapsTime() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2333,7 +2325,7 @@ public void MapsDate() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2375,7 +2367,7 @@ public void MapsDuration() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2417,7 +2409,7 @@ public void AddsErrorMapping() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2437,7 +2429,7 @@ public void AddsErrorMapping() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "errorId", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2465,7 +2457,7 @@ public void AddsErrorMapping() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "serviceErrorId", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2506,7 +2498,7 @@ public void AddsErrorMapping() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "authenticationRealm", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2587,7 +2579,7 @@ public void IgnoresErrorCodesWithNoSchema() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2636,7 +2628,7 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() var errorSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "errorId", new OpenApiSchema { Type = JsonSchemaType.String @@ -2648,7 +2640,6 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() Id = "microsoft.graph.error", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var errorResponse = new OpenApiResponse { @@ -2664,7 +2655,6 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() Id = "microsoft.graph.error", Type = ReferenceType.Response }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -2686,7 +2676,7 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2707,12 +2697,12 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.error", errorSchema } }, - Responses = new Dictionary { + Responses = new Dictionary { { "microsoft.graph.error", errorResponse } @@ -2746,7 +2736,7 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() var errorSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "errorId", new OpenApiSchema { Type = JsonSchemaType.String @@ -2758,7 +2748,6 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() Id = "microsoft.graph.error", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var errorResponse = new OpenApiResponse { @@ -2774,7 +2763,6 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() Id = "microsoft.graph.error", Type = ReferenceType.Response }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -2796,7 +2784,7 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() Schema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "progress", new OpenApiSchema{ Type = JsonSchemaType.String, @@ -2816,12 +2804,12 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.error", errorSchema } }, - Responses = new Dictionary { + Responses = new Dictionary { { "microsoft.graph.error", errorResponse } @@ -2856,7 +2844,7 @@ public void DoesntAddPropertyHolderOnNonAdditionalModels() { Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, - Properties = new Dictionary { + Properties = new Dictionary { { "date", new OpenApiSchema { Type = JsonSchemaType.String, @@ -2875,7 +2863,6 @@ public void DoesntAddPropertyHolderOnNonAdditionalModels() Id = "weatherForecast", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var forecastResponse = new OpenApiResponse { @@ -2891,7 +2878,6 @@ public void DoesntAddPropertyHolderOnNonAdditionalModels() Id = "weatherForecast", Type = ReferenceType.Response }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -2912,12 +2898,12 @@ public void DoesntAddPropertyHolderOnNonAdditionalModels() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "weatherForecast", weatherForecastSchema } }, - Responses = new Dictionary { + Responses = new Dictionary { { "weatherForecast", forecastResponse } @@ -2941,7 +2927,7 @@ public void SquishesLonelyNullables() { Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, - Properties = new Dictionary { + Properties = new Dictionary { { "date", new OpenApiSchema { Type = JsonSchemaType.String, @@ -2960,7 +2946,6 @@ public void SquishesLonelyNullables() Id = "microsoft.graph.uploadSession", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -2981,7 +2966,7 @@ public void SquishesLonelyNullables() Schema = new OpenApiSchema { Nullable = true, - AnyOf = new List { + AnyOf = new List { uploadSessionSchema } } @@ -2995,7 +2980,7 @@ public void SquishesLonelyNullables() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.uploadSession", uploadSessionSchema } @@ -3025,7 +3010,7 @@ public void SquishesLonelyNullablesBothAnyOf() { Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, - Properties = new Dictionary { + Properties = new Dictionary { { "date", new OpenApiSchema { Type = JsonSchemaType.String, @@ -3044,7 +3029,6 @@ public void SquishesLonelyNullablesBothAnyOf() Id = "microsoft.graph.uploadSession", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -3064,7 +3048,7 @@ public void SquishesLonelyNullablesBothAnyOf() { Schema = new OpenApiSchema { - AnyOf = new List { + AnyOf = new List { uploadSessionSchema, new OpenApiSchema { Nullable = true, @@ -3081,7 +3065,7 @@ public void SquishesLonelyNullablesBothAnyOf() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.uploadSession", uploadSessionSchema } @@ -3111,7 +3095,7 @@ public void SupportsArraysInComposedTypes() { Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, - Properties = new Dictionary { + Properties = new Dictionary { { "date", new OpenApiSchema { AnyOf = [ @@ -3133,7 +3117,6 @@ public void SupportsArraysInComposedTypes() Id = "anyOfNullable", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -3162,7 +3145,7 @@ public void SupportsArraysInComposedTypes() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "anyOfNullable", anyOfSchema } @@ -3194,7 +3177,7 @@ public void SupportsNullableAnyOf() { Type = JsonSchemaType.Object, AdditionalPropertiesAllowed = false, - Properties = new Dictionary { + Properties = new Dictionary { { "date", new OpenApiSchema { AnyOf = [ @@ -3216,7 +3199,6 @@ public void SupportsNullableAnyOf() Id = "anyOfNullable", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -3245,7 +3227,7 @@ public void SupportsNullableAnyOf() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "anyOfNullable", anyOfSchema } @@ -3277,7 +3259,7 @@ public void AddsDiscriminatorMappings() var entitySchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -3307,12 +3289,11 @@ public void AddsDiscriminatorMappings() Id = "microsoft.graph.entity", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var directoryObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "tenant", new OpenApiSchema { Type = JsonSchemaType.String @@ -3329,10 +3310,9 @@ public void AddsDiscriminatorMappings() Id = "microsoft.graph.directoryObject", Type = ReferenceType.Schema }, - AllOf = new List { + AllOf = new List { entitySchema }, - UnresolvedReference = false }; var directoryObjects = new OpenApiResponse { @@ -3348,7 +3328,6 @@ public void AddsDiscriminatorMappings() Id = "microsoft.graph.directoryObjects", Type = ReferenceType.Response }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -3369,7 +3348,7 @@ public void AddsDiscriminatorMappings() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.entity", entitySchema }, @@ -3377,7 +3356,7 @@ public void AddsDiscriminatorMappings() "microsoft.graph.directoryObject", directoryObjectSchema } }, - Responses = new Dictionary { + Responses = new Dictionary { { "microsoft.graph.directoryObjects", directoryObjects } @@ -3412,7 +3391,7 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() var entitySchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -3445,12 +3424,11 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() Id = "microsoft.graph.entity", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var directoryObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "tenant", new OpenApiSchema { Type = JsonSchemaType.String @@ -3467,15 +3445,14 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() Id = "microsoft.graph.directoryObject", Type = ReferenceType.Schema }, - AllOf = new List { + AllOf = new List { entitySchema }, - UnresolvedReference = false }; var fileSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "tenant", new OpenApiSchema { Type = JsonSchemaType.String @@ -3492,7 +3469,6 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() Id = "microsoft.graph.file", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var directoryObjects = new OpenApiResponse() { @@ -3508,7 +3484,6 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() Id = "microsoft.graph.directoryObjects", Type = ReferenceType.Response }, - UnresolvedReference = false }; var document = new OpenApiDocument() { @@ -3528,7 +3503,7 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() }, Components = new OpenApiComponents() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.entity", entitySchema }, @@ -3539,7 +3514,7 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() "microsoft.graph.file", fileSchema } }, - Responses = new Dictionary { + Responses = new Dictionary { { "microsoft.graph.directoryObjects", directoryObjects } @@ -3564,7 +3539,7 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() var entitySchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -3589,12 +3564,11 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() Id = "microsoft.graph.entity", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var directoryObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "tenant", new OpenApiSchema { Type = JsonSchemaType.String @@ -3614,12 +3588,11 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() Id = "microsoft.graph.directoryObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var directoryObjectsResponse = new OpenApiSchema { Type = JsonSchemaType.Object, - OneOf = new List { + OneOf = new List { entitySchema, directoryObjectSchema }, @@ -3628,7 +3601,6 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() Id = "microsoft.graph.directoryObjects", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var directoryObjects = new OpenApiResponse { @@ -3644,7 +3616,6 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() Id = "microsoft.graph.directoryObjects", Type = ReferenceType.Response }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -3665,7 +3636,7 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.entity", entitySchema }, @@ -3676,7 +3647,7 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() "microsoft.graph.directoryObjects", directoryObjectsResponse } }, - Responses = new Dictionary { + Responses = new Dictionary { { "microsoft.graph.directoryObjects", directoryObjects } @@ -3707,7 +3678,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() var entitySchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -3732,15 +3703,14 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() Id = "microsoft.graph.entity", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var directoryObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - AllOf = new List { + AllOf = new List { entitySchema, new OpenApiSchema { - Properties = new Dictionary { + Properties = new Dictionary { { "tenant", new OpenApiSchema { Type = JsonSchemaType.String @@ -3762,15 +3732,14 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() Id = "microsoft.graph.directoryObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var userSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - AllOf = new List { + AllOf = new List { directoryObjectSchema, new OpenApiSchema { - Properties = new Dictionary { + Properties = new Dictionary { { "firstName", new OpenApiSchema { Type = JsonSchemaType.String @@ -3792,7 +3761,6 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() Id = "microsoft.graph.user", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var directoryObjects = new OpenApiResponse { @@ -3808,7 +3776,6 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() Id = "microsoft.graph.directoryObjects", Type = ReferenceType.Response }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -3829,7 +3796,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.entity", entitySchema }, @@ -3840,7 +3807,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() "microsoft.graph.user", userSchema } }, - Responses = new Dictionary { + Responses = new Dictionary { { "microsoft.graph.directoryObjects", directoryObjects } @@ -3885,7 +3852,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings var entitySchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -3919,7 +3886,6 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings Id = "microsoft.graph.entity", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var directoryObjectSchema = new OpenApiSchema { @@ -3928,7 +3894,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings entitySchema, new OpenApiSchema { - Properties = new Dictionary { + Properties = new Dictionary { { "tenant", new OpenApiSchema { Type = JsonSchemaType.String @@ -3950,7 +3916,6 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings Id = "microsoft.graph.directoryObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var userSchema = new OpenApiSchema { @@ -3959,7 +3924,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings directoryObjectSchema, new OpenApiSchema { - Properties = new Dictionary { + Properties = new Dictionary { { "firstName", new OpenApiSchema { Type = JsonSchemaType.String @@ -3981,7 +3946,6 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings Id = "microsoft.graph.user", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var directoryObjects = new OpenApiResponse { @@ -3997,7 +3961,6 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings Id = "microsoft.graph.directoryObjects", Type = ReferenceType.Response }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -4018,7 +3981,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.entity", entitySchema }, @@ -4029,7 +3992,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings "microsoft.graph.user", userSchema } }, - Responses = new Dictionary { + Responses = new Dictionary { { "microsoft.graph.directoryObjects", directoryObjects } @@ -4066,7 +4029,7 @@ public void UnionOfPrimitiveTypesWorks() var simpleObjet = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -4078,7 +4041,6 @@ public void UnionOfPrimitiveTypesWorks() Id = "subNS.simpleObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -4095,7 +4057,7 @@ public void UnionOfPrimitiveTypesWorks() Content = { ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - OneOf = new List { + OneOf = new List { simpleObjet, new OpenApiSchema { Type = JsonSchemaType.Number @@ -4112,7 +4074,7 @@ public void UnionOfPrimitiveTypesWorks() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "subNS.simpleObject", simpleObjet } @@ -4184,7 +4146,7 @@ public void UnionOfInlineSchemasWorks() var simpleObjet = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -4196,7 +4158,6 @@ public void UnionOfInlineSchemasWorks() Id = "subNS.simpleObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -4213,11 +4174,11 @@ public void UnionOfInlineSchemasWorks() Content = { ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - OneOf = new List { + OneOf = new List { simpleObjet, new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String @@ -4237,7 +4198,7 @@ public void UnionOfInlineSchemasWorks() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "subNS.simpleObject", simpleObjet } @@ -4267,7 +4228,7 @@ public void IntersectionOfPrimitiveTypesWorks() var simpleObjet = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -4279,7 +4240,6 @@ public void IntersectionOfPrimitiveTypesWorks() Id = "subNS.simpleObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -4296,7 +4256,7 @@ public void IntersectionOfPrimitiveTypesWorks() Content = { ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - AnyOf = new List { + AnyOf = new List { simpleObjet, new OpenApiSchema { Type = JsonSchemaType.Number @@ -4313,7 +4273,7 @@ public void IntersectionOfPrimitiveTypesWorks() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "subNS.simpleObject", simpleObjet } @@ -4343,7 +4303,7 @@ public void IntersectionOfInlineSchemasWorks() var simpleObjet = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -4355,7 +4315,6 @@ public void IntersectionOfInlineSchemasWorks() Id = "subNS.simpleObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -4372,11 +4331,11 @@ public void IntersectionOfInlineSchemasWorks() Content = { ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { - AnyOf = new List { + AnyOf = new List { simpleObjet, new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String @@ -4396,7 +4355,7 @@ public void IntersectionOfInlineSchemasWorks() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "subNS.simpleObject", simpleObjet } @@ -4426,7 +4385,7 @@ public void InheritedTypeWithInlineSchemaWorks() var baseObject = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String @@ -4452,7 +4411,6 @@ public void InheritedTypeWithInlineSchemaWorks() Id = "subNS.baseObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var derivedObject = new OpenApiSchema { @@ -4462,7 +4420,7 @@ public void InheritedTypeWithInlineSchemaWorks() new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "special", new OpenApiSchema { Type = JsonSchemaType.String @@ -4485,7 +4443,6 @@ public void InheritedTypeWithInlineSchemaWorks() Id = "subNS.derivedObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var secondLevelDerivedObject = new OpenApiSchema { @@ -4495,7 +4452,7 @@ public void InheritedTypeWithInlineSchemaWorks() new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "moreSpecial", new OpenApiSchema { Type = JsonSchemaType.String @@ -4509,7 +4466,6 @@ public void InheritedTypeWithInlineSchemaWorks() Id = "subNS.secondLevelDerivedObject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -4536,7 +4492,7 @@ public void InheritedTypeWithInlineSchemaWorks() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "subNS.baseObject", baseObject }, @@ -4677,8 +4633,8 @@ public void MapsQueryParameterTypes(JsonSchemaType type, string format, string e Operations = { [OperationType.Get] = new OpenApiOperation { - Parameters = new List { - new() { + Parameters = new List { + new OpenApiParameter() { Name = "query", In = ParameterLocation.Query, Schema = new OpenApiSchema { @@ -4719,8 +4675,8 @@ public void MapsQueryParameterArrayTypes() Operations = { [OperationType.Get] = new OpenApiOperation { - Parameters = new List { - new() { + Parameters = new List { + new OpenApiParameter() { Name = "query", In = ParameterLocation.Query, Schema = new OpenApiSchema { @@ -4767,8 +4723,8 @@ public void MapsEnumQueryParameterType(GenerationLanguage generationLanguage) Operations = { [OperationType.Get] = new OpenApiOperation { - Parameters = new List { - new() { + Parameters = new List { + new OpenApiParameter() { Name = "query", In = ParameterLocation.Query, Schema = new OpenApiSchema { @@ -4899,7 +4855,7 @@ public void MapsQueryParameterCollectionKinds(bool isArray) Operations = { [OperationType.Get] = new OpenApiOperation { - Parameters = new List { + Parameters = new List { new OpenApiParameter { Name = "query", In = ParameterLocation.Query, @@ -4939,7 +4895,7 @@ public void DefaultsQueryParametersWithNoSchemaToString() Operations = { [OperationType.Get] = new OpenApiOperation { - Parameters = new List { + Parameters = new List { new OpenApiParameter { Name = "query", In = ParameterLocation.Query @@ -4971,7 +4927,7 @@ public void DoesntGenerateNamespacesWhenNotRequired() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String @@ -4983,7 +4939,6 @@ public void DoesntGenerateNamespacesWhenNotRequired() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5010,7 +4965,7 @@ public void DoesntGenerateNamespacesWhenNotRequired() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -5034,7 +4989,7 @@ public void GeneratesNamesapacesWhenRequired() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String @@ -5046,7 +5001,6 @@ public void GeneratesNamesapacesWhenRequired() Id = "subns.myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5073,7 +5027,7 @@ public void GeneratesNamesapacesWhenRequired() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "subns.myobject", myObjectSchema } @@ -5097,7 +5051,7 @@ public void IdsResultInIndexers() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -5109,7 +5063,6 @@ public void IdsResultInIndexers() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5136,7 +5089,7 @@ public void IdsResultInIndexers() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -5178,13 +5131,13 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() { Title = "conditionalAccessConditionSet", Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "signInRiskLevels", new OpenApiSchema { Type = JsonSchemaType.Array, Items = new OpenApiSchema { - AnyOf = new List + AnyOf = new List { enumSchema, new OpenApiSchema @@ -5202,7 +5155,6 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument @@ -5230,7 +5182,7 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema }, @@ -5278,7 +5230,7 @@ public void HandlesCollectionOfEnumSchemas() { Title = "conditionalAccessConditionSet", Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "signInRiskLevels", new OpenApiSchema { Type = JsonSchemaType.Array, @@ -5291,7 +5243,6 @@ public void HandlesCollectionOfEnumSchemas() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument @@ -5319,7 +5270,7 @@ public void HandlesCollectionOfEnumSchemas() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema }, @@ -5352,7 +5303,7 @@ public void InlinePropertiesGenerateTypes() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "tilleggsinformasjon", new OpenApiSchema { Type = JsonSchemaType.Object, @@ -5367,7 +5318,6 @@ public void InlinePropertiesGenerateTypes() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5394,7 +5344,7 @@ public void InlinePropertiesGenerateTypes() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -5419,7 +5369,7 @@ public void ModelsDoesntUsePathDescriptionWhenAvailable() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String @@ -5431,7 +5381,6 @@ public void ModelsDoesntUsePathDescriptionWhenAvailable() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5462,7 +5411,7 @@ public void ModelsDoesntUsePathDescriptionWhenAvailable() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -5485,7 +5434,7 @@ public void CleansUpInvalidDescriptionCharacters() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -5497,7 +5446,6 @@ public void CleansUpInvalidDescriptionCharacters() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, Description = @" some description with invalid characters: ", }; @@ -5526,7 +5474,7 @@ public void CleansUpInvalidDescriptionCharacters() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -5553,7 +5501,7 @@ public void AcceptVendorsTypes(string contentType) var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String @@ -5565,7 +5513,6 @@ public void AcceptVendorsTypes(string contentType) Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5592,7 +5539,7 @@ public void AcceptVendorsTypes(string contentType) }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -5636,7 +5583,7 @@ public void ModelsUseDescriptionWhenAvailable(bool excludeBackwardCompatible) ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { Description = "some description", - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String @@ -5693,7 +5640,7 @@ public void Considers200WithSchemaOver2XXWithSchema() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -5705,12 +5652,11 @@ public void Considers200WithSchemaOver2XXWithSchema() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var myOtherObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -5722,7 +5668,6 @@ public void Considers200WithSchemaOver2XXWithSchema() Id = "myotherobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5756,7 +5701,7 @@ public void Considers200WithSchemaOver2XXWithSchema() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema }, { "myotherobject", myOtherObjectSchema }, } @@ -5788,7 +5733,7 @@ public void Considers2XXWithSchemaOver204WithNoSchema() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -5800,7 +5745,6 @@ public void Considers2XXWithSchemaOver204WithNoSchema() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5828,7 +5772,7 @@ public void Considers2XXWithSchemaOver204WithNoSchema() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -5861,7 +5805,7 @@ public void Considers204WithNoSchemaOver206WithNoSchema() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -5873,7 +5817,6 @@ public void Considers204WithNoSchemaOver206WithNoSchema() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5895,7 +5838,7 @@ public void Considers204WithNoSchemaOver206WithNoSchema() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -5934,7 +5877,7 @@ public void DoesntGenerateVoidExecutorOnMixedNoContent(int statusCode) var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -5946,7 +5889,6 @@ public void DoesntGenerateVoidExecutorOnMixedNoContent(int statusCode) Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -5974,7 +5916,7 @@ public void DoesntGenerateVoidExecutorOnMixedNoContent(int statusCode) }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -6006,7 +5948,7 @@ public void GeneratesVoidReturnTypeForNoContent(int statusCode) var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6018,7 +5960,6 @@ public void GeneratesVoidReturnTypeForNoContent(int statusCode) Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -6045,7 +5986,7 @@ public void GeneratesVoidReturnTypeForNoContent(int statusCode) }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -6074,14 +6015,14 @@ public void StripsCommonModelsPrefix(string[] componentNames, string stripPrefix var paths = new OpenApiPaths(); var components = new OpenApiComponents { - Schemas = new Dictionary() + Schemas = new Dictionary() }; foreach (var componentName in componentNames) { var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6093,7 +6034,6 @@ public void StripsCommonModelsPrefix(string[] componentNames, string stripPrefix Id = componentName, Type = ReferenceType.Schema }, - UnresolvedReference = false }; paths.Add($"answer{componentName}", new OpenApiPathItem { @@ -6129,7 +6069,7 @@ public void HandlesContentParameters() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6141,7 +6081,6 @@ public void HandlesContentParameters() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -6152,7 +6091,7 @@ public void HandlesContentParameters() Operations = { [OperationType.Get] = new OpenApiOperation { - Parameters = new List { + Parameters = new List { new OpenApiParameter { Name = "ids", In = ParameterLocation.Path, @@ -6187,7 +6126,7 @@ public void HandlesContentParameters() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -6216,7 +6155,7 @@ public void HandlesPagingExtension() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6228,7 +6167,6 @@ public void HandlesPagingExtension() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -6258,7 +6196,7 @@ public void HandlesPagingExtension() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -6285,7 +6223,7 @@ public void SetsReadonlyProperties(bool isReadonly) var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6298,7 +6236,6 @@ public void SetsReadonlyProperties(bool isReadonly) Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -6325,7 +6262,7 @@ public void SetsReadonlyProperties(bool isReadonly) }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -6349,7 +6286,7 @@ public void SupportsIncludeFilterOnRootPath(string inputPattern, int expectedPat var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6361,7 +6298,6 @@ public void SupportsIncludeFilterOnRootPath(string inputPattern, int expectedPat Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -6388,7 +6324,7 @@ public void SupportsIncludeFilterOnRootPath(string inputPattern, int expectedPat }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -6414,7 +6350,7 @@ public void SupportsIncludeFilter() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6426,7 +6362,6 @@ public void SupportsIncludeFilter() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -6471,7 +6406,7 @@ public void SupportsIncludeFilter() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -6499,7 +6434,7 @@ public void SupportsExcludeFilter() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6511,7 +6446,6 @@ public void SupportsExcludeFilter() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -6556,7 +6490,7 @@ public void SupportsExcludeFilter() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -6584,7 +6518,7 @@ public void SupportsIncludeFilterWithOperation() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6596,7 +6530,6 @@ public void SupportsIncludeFilterWithOperation() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -6699,7 +6632,7 @@ public void SupportsIncludeFilterWithOperation() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -6739,7 +6672,7 @@ public void SupportsIndexingParametersInSubPaths() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -6751,7 +6684,6 @@ public void SupportsIndexingParametersInSubPaths() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -6762,7 +6694,7 @@ public void SupportsIndexingParametersInSubPaths() Operations = { [OperationType.Get] = new OpenApiOperation { - Parameters = new List { + Parameters = new List { new OpenApiParameter { Name = "userId", In = ParameterLocation.Path, @@ -6788,7 +6720,7 @@ public void SupportsIndexingParametersInSubPaths() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -7210,7 +7142,7 @@ public void AddReservedPathParameterSymbol() var userSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -7226,7 +7158,6 @@ public void AddReservedPathParameterSymbol() { Id = "#/components/schemas/microsoft.graph.user" }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -7234,7 +7165,7 @@ public void AddReservedPathParameterSymbol() { ["users/{id}/manager"] = new OpenApiPathItem { - Parameters = new List { + Parameters = new List { new OpenApiParameter { Name = "id", In = ParameterLocation.Path, @@ -7269,7 +7200,7 @@ public void AddReservedPathParameterSymbol() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.user", userSchema } @@ -7292,7 +7223,7 @@ public void DoesNotAddReservedPathParameterSymbol() var userSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "id", new OpenApiSchema { Type = JsonSchemaType.String @@ -7308,7 +7239,6 @@ public void DoesNotAddReservedPathParameterSymbol() { Id = "#/components/schemas/microsoft.graph.user" }, - UnresolvedReference = false }; var document = new OpenApiDocument { @@ -7316,7 +7246,7 @@ public void DoesNotAddReservedPathParameterSymbol() { ["users/{id}/manager"] = new OpenApiPathItem { - Parameters = new List { + Parameters = new List { new OpenApiParameter { Name = "id", In = ParameterLocation.Path, @@ -7351,7 +7281,7 @@ public void DoesNotAddReservedPathParameterSymbol() }, Components = new OpenApiComponents { - Schemas = new Dictionary { + Schemas = new Dictionary { { "microsoft.graph.user", userSchema } @@ -9951,7 +9881,7 @@ public void SupportsIncludeFilterAndExcludeWithOperation() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -9963,7 +9893,6 @@ public void SupportsIncludeFilterAndExcludeWithOperation() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -10049,7 +9978,7 @@ public void SupportsIncludeFilterAndExcludeWithOperation() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -10096,7 +10025,7 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -10108,7 +10037,6 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -10194,7 +10122,7 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -10241,7 +10169,7 @@ public void CleansUpOperationIdAddsMissingOperationId() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -10253,7 +10181,6 @@ public void CleansUpOperationIdAddsMissingOperationId() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -10300,7 +10227,7 @@ public void CleansUpOperationIdAddsMissingOperationId() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } @@ -10343,7 +10270,7 @@ public void CleansUpOperationIdChangesOperationId() var myObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Properties = new Dictionary { + Properties = new Dictionary { { "name", new OpenApiSchema { Type = JsonSchemaType.String, @@ -10355,7 +10282,6 @@ public void CleansUpOperationIdChangesOperationId() Id = "myobject", Type = ReferenceType.Schema }, - UnresolvedReference = false, }; var document = new OpenApiDocument { @@ -10423,7 +10349,7 @@ public void CleansUpOperationIdChangesOperationId() }, Components = new() { - Schemas = new Dictionary { + Schemas = new Dictionary { { "myobject", myObjectSchema } diff --git a/tests/Kiota.Builder.Tests/Validation/OpenApiSchemaComparerTests.cs b/tests/Kiota.Builder.Tests/Validation/OpenApiSchemaComparerTests.cs index e794eb3f3d..943255bb91 100644 --- a/tests/Kiota.Builder.Tests/Validation/OpenApiSchemaComparerTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/OpenApiSchemaComparerTests.cs @@ -13,14 +13,14 @@ public void Defensive() { Assert.Equal(new HashCode().ToHashCode(), _comparer.GetHashCode(null)); Assert.True(_comparer.Equals(null, null)); - Assert.False(_comparer.Equals(new(), null)); - Assert.False(_comparer.Equals(null, new())); + Assert.False(_comparer.Equals(new OpenApiSchema(), null)); + Assert.False(_comparer.Equals(null, new OpenApiSchema())); } [Fact] public void TestEquals() { - Assert.True(_comparer.Equals(new(), new())); + Assert.True(_comparer.Equals(new OpenApiSchema(), new OpenApiSchema())); } [Fact] public void DoesNotStackOverFlowOnCircularReferencesForEquals() From 18722f309a0e52c58b4a5cc1a6bcf9033c3239f7 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 3 Feb 2025 15:40:26 -0500 Subject: [PATCH 47/96] fix: removes nullable references Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 4 ++-- src/Kiota.Builder/Plugins/PluginsGenerationService.cs | 2 -- src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs | 1 - .../Extensions/OpenApiSchemaExtensionsTests.cs | 8 -------- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 5 ----- 5 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 127dfcd8e9..fd4a812be4 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1790,9 +1790,9 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo { var typeName = string.IsNullOrEmpty(typeNameForInlineSchema) ? currentNode.GetClassName(config.StructuredMimeTypes, operation: operation, suffix: suffixForInlineSchema, schema: schema, requestBody: isRequestBody).CleanupSymbolName() : typeNameForInlineSchema; var typesCount = schema.AnyOf?.Count ?? schema.OneOf?.Count ?? 0; - if ((typesCount == 1 && schema.Nullable && schema.IsInclusiveUnion() || // nullable on the root schema outside of anyOf + if ((typesCount == 1 && (schema.Type & JsonSchemaType.Null) is JsonSchemaType.Null && schema.IsInclusiveUnion() || // nullable on the root schema outside of anyOf typesCount == 2 && (schema.AnyOf?.Any(static x => // nullable on a schema in the anyOf - x.Nullable && + (x.Type & JsonSchemaType.Null) is JsonSchemaType.Null && !x.HasAnyProperty() && !x.IsExclusiveUnion() && !x.IsInclusiveUnion() && diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index c8ee3c7473..a970f3663c 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -207,8 +207,6 @@ internal static void CopyRelevantInformation(IOpenApiSchema source, IOpenApiSche openApiSchema.MinProperties = source.MinProperties; if (source.UniqueItems is not null) openApiSchema.UniqueItems = source.UniqueItems; - if (source.Nullable) - openApiSchema.Nullable = true; if (source.ReadOnly) openApiSchema.ReadOnly = true; if (source.WriteOnly) diff --git a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs index 4a5fec57c8..862ef81eb8 100644 --- a/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs +++ b/src/Kiota.Builder/Validation/OpenApiSchemaComparer.cs @@ -42,7 +42,6 @@ private void GetHashCodeInternal([DisallowNull] IOpenApiSchema obj, HashSet { uploadSessionSchema } @@ -3051,7 +3050,6 @@ public void SquishesLonelyNullablesBothAnyOf() AnyOf = new List { uploadSessionSchema, new OpenApiSchema { - Nullable = true, } } } @@ -3183,12 +3181,10 @@ public void SupportsNullableAnyOf() AnyOf = [ new OpenApiSchema { Type = JsonSchemaType.String, - Nullable = true }, new OpenApiSchema { Type = JsonSchemaType.Number, Format = "int64", - Nullable = true, } ] } @@ -5143,7 +5139,6 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() new OpenApiSchema { Type = JsonSchemaType.Object, - Nullable = true } } } From f3ec84823961c8aca5def98d98061760d0106b4e Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 4 Feb 2025 17:07:53 -0500 Subject: [PATCH 48/96] fix: schema reference mutation Signed-off-by: Vincent Biret --- .../Plugins/PluginsGenerationService.cs | 50 +++++++++++++++++-- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index a970f3663c..0f8c0274c1 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -134,7 +134,7 @@ public override void Visit(IOpenApiSchema schema) return; var allPropertiesToAdd = GetAllProperties(schema).ToArray(); foreach (var allOfEntry in schema.AllOf) - SelectFirstAnyOneOfVisitor.CopyRelevantInformation(allOfEntry, schema, false, false, false); + SelectFirstAnyOneOfVisitor.CopyRelevantInformation(allOfEntry, schema, false, false); foreach (var (key, value) in allPropertiesToAdd) schema.Properties.TryAdd(key, value); schema.AllOf.Clear(); @@ -149,6 +149,46 @@ private static IEnumerable> GetAllPropertie } } + private sealed class ReplaceFirstSchemaByReference : OpenApiVisitorBase + { + public override void Visit(OpenApiMediaType mediaType) + { + mediaType.Schema = GetFirstSchema(mediaType.Schema); + base.Visit(mediaType); + } + public override void Visit(IOpenApiParameter parameter) + { + if (parameter is OpenApiParameter openApiParameter) + openApiParameter.Schema = GetFirstSchema(parameter.Schema); + base.Visit(parameter); + } + public override void Visit(IOpenApiHeader header) + { + if (header is OpenApiHeader openApiHeader) + openApiHeader.Schema = GetFirstSchema(header.Schema); + base.Visit(header); + } + public override void Visit(IOpenApiSchema schema) + { + if (schema is OpenApiSchema openApiSchema) + { + openApiSchema.Items = GetFirstSchema(schema.Items); + var properties = new Dictionary(schema.Properties); + foreach (var (key, value) in properties) + schema.Properties[key] = GetFirstSchema(value); + } + base.Visit(schema); + } + private static IOpenApiSchema? GetFirstSchema(IOpenApiSchema? schema) + { + if (schema is null) return null; + if (schema.AnyOf is { Count: > 0 } && schema.AnyOf[0] is OpenApiSchemaReference anyOfSchemaReference) + return anyOfSchemaReference; + if (schema.OneOf is { Count: > 0 } && schema.OneOf[0] is OpenApiSchemaReference oneOfSchemaReference) + return oneOfSchemaReference; + return schema; + } + } private sealed class SelectFirstAnyOneOfVisitor : OpenApiVisitorBase { public override void Visit(IOpenApiSchema schema) @@ -165,7 +205,7 @@ public override void Visit(IOpenApiSchema schema) } base.Visit(schema); } - internal static void CopyRelevantInformation(IOpenApiSchema source, IOpenApiSchema target, bool includeProperties = true, bool includeReference = true, bool includeDiscriminator = true) + internal static void CopyRelevantInformation(IOpenApiSchema source, IOpenApiSchema target, bool includeProperties = true, bool includeDiscriminator = true) { if (target is OpenApiSchema openApiSchema) { @@ -230,8 +270,6 @@ internal static void CopyRelevantInformation(IOpenApiSchema source, IOpenApiSche if (source.Default is not null) openApiSchema.Default = source.Default; } - else if (includeReference && source is OpenApiSchemaReference sourceRef && target is OpenApiSchemaReference targetRef) - targetRef.Reference = sourceRef.Reference; } } @@ -286,6 +324,10 @@ private static void PrepareDescriptionForCopilot(OpenApiDocument document) var errorResponsesCleanupWalker = new OpenApiWalker(errorResponsesCleanupVisitor); errorResponsesCleanupWalker.Walk(document); + var replaceFirstSchemaByReference = new ReplaceFirstSchemaByReference(); + var replaceFirstSchemaByReferenceWalker = new OpenApiWalker(replaceFirstSchemaByReference); + replaceFirstSchemaByReferenceWalker.Walk(document); + var selectFirstAnyOneOfVisitor = new SelectFirstAnyOneOfVisitor(); var selectFirstAnyOneOfWalker = new OpenApiWalker(selectFirstAnyOneOfVisitor); selectFirstAnyOneOfWalker.Walk(document); From ca80001d4ebe7868eedeedf5afe0510c1c8978b8 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 6 Feb 2025 14:56:49 -0500 Subject: [PATCH 49/96] chore: bumps all openapi deps to 2.X line --- src/Kiota.Builder/Kiota.Builder.csproj | 8 ++++---- src/kiota/kiota.csproj | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index d9294a7e00..201d8ee572 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -44,10 +44,10 @@ - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/kiota/kiota.csproj b/src/kiota/kiota.csproj index 9d6b53b387..3e3082f83a 100644 --- a/src/kiota/kiota.csproj +++ b/src/kiota/kiota.csproj @@ -46,8 +46,8 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all From fbc9d63161bb84d87c44ebcb917b136848194b3d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 6 Feb 2025 15:29:32 -0500 Subject: [PATCH 50/96] fix: first batch of broken references in unit tests Signed-off-by: Vincent Biret --- .../ContentTypeMappingTests.cs | 111 ++---- ...nApiDeprecationExtensionExtensionsTests.cs | 20 - .../OpenApiSchemaExtensionsTests.cs | 357 ++++++------------ 3 files changed, 148 insertions(+), 340 deletions(-) diff --git a/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs b/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs index a04bc9bfde..159db34f5c 100644 --- a/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs +++ b/tests/Kiota.Builder.Tests/ContentTypeMappingTests.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Moq; using Xunit; @@ -82,22 +83,6 @@ public void Dispose() [Theory] public void GeneratesTheRightReturnTypeBasedOnContentAndStatus(string contentType, string statusCode, bool addModel, string acceptedContentType, string returnType) { - var myObjectSchema = new OpenApiSchema - { - Type = JsonSchemaType.Object, - Properties = new Dictionary { - { - "id", new OpenApiSchema { - Type = JsonSchemaType.String, - } - } - }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, - }; var document = new OpenApiDocument { Paths = new OpenApiPaths @@ -112,7 +97,7 @@ public void GeneratesTheRightReturnTypeBasedOnContentAndStatus(string contentTyp [statusCode] = new OpenApiResponse { Content = { [contentType] = new OpenApiMediaType { - Schema = addModel ? myObjectSchema : null + Schema = addModel ? new OpenApiSchemaReference("myobject") : null } } }, @@ -125,11 +110,23 @@ public void GeneratesTheRightReturnTypeBasedOnContentAndStatus(string contentTyp { Schemas = new Dictionary { { - "myobject", myObjectSchema + "myobject", new OpenApiSchema + { + Type = JsonSchemaType.Object, + Properties = new Dictionary { + { + "id", new OpenApiSchema { + Type = JsonSchemaType.String, + } + } + }, + } } } } }; + document.RegisterComponents(); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder( mockLogger.Object, @@ -175,22 +172,6 @@ public void GeneratesTheRightReturnTypeBasedOnContentAndStatus(string contentTyp [Theory] public void GeneratesTheRightParameterTypeBasedOnContentAndStatus(string contentType, bool addModel, string acceptedContentType, string parameterType) { - var myObjectSchema = new OpenApiSchema - { - Type = JsonSchemaType.Object, - Properties = new Dictionary { - { - "id", new OpenApiSchema { - Type = JsonSchemaType.String, - } - } - }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, - }; var document = new OpenApiDocument { Paths = new OpenApiPaths @@ -203,7 +184,7 @@ public void GeneratesTheRightParameterTypeBasedOnContentAndStatus(string content RequestBody = new OpenApiRequestBody { Content = { [contentType] = new OpenApiMediaType { - Schema = addModel ? myObjectSchema : null + Schema = addModel ? new OpenApiSchemaReference("myobject") : null } } }, @@ -219,11 +200,23 @@ public void GeneratesTheRightParameterTypeBasedOnContentAndStatus(string content { Schemas = new Dictionary { { - "myobject", myObjectSchema + "myobject", new OpenApiSchema + { + Type = JsonSchemaType.Object, + Properties = new Dictionary { + { + "id", new OpenApiSchema { + Type = JsonSchemaType.String, + } + } + }, + } } } } }; + document.RegisterComponents(); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder( mockLogger.Object, @@ -267,21 +260,7 @@ public void GeneratesTheRightAcceptHeaderBasedOnContentAndStatus(string contentM { ["200"] = new OpenApiResponse { Content = contentMediaTypes.Split(',').Select(x => new {Key = x.Trim(), value = new OpenApiMediaType { - Schema = new OpenApiSchema { - Type = JsonSchemaType.Object, - Properties = new Dictionary { - { - "id", new OpenApiSchema { - Type = JsonSchemaType.String, - } - } - }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, - } + Schema = new OpenApiSchemaReference("myobject"), } }).ToDictionary(x => x.Key, x => x.value) }, @@ -303,16 +282,13 @@ public void GeneratesTheRightAcceptHeaderBasedOnContentAndStatus(string contentM } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, } } } } }; + document.RegisterComponents(); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder( mockLogger.Object, @@ -356,21 +332,7 @@ public void GeneratesTheRightContentTypeHeaderBasedOnContentAndStatus(string con RequestBody = new OpenApiRequestBody { Content = contentMediaTypes.Split(',').Select(x => new {Key = x.Trim(), value = new OpenApiMediaType { - Schema = new OpenApiSchema { - Type = JsonSchemaType.Object, - Properties = new Dictionary { - { - "id", new OpenApiSchema { - Type = JsonSchemaType.String, - } - } - }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, - } + Schema = new OpenApiSchemaReference("myobject"), } }).ToDictionary(x => x.Key, x => x.value) }, @@ -391,16 +353,13 @@ public void GeneratesTheRightContentTypeHeaderBasedOnContentAndStatus(string con } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, } } } } }; + document.RegisterComponents(); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder( mockLogger.Object, diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiDeprecationExtensionExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiDeprecationExtensionExtensionsTests.cs index 10de8508c1..40995244f9 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiDeprecationExtensionExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiDeprecationExtensionExtensionsTests.cs @@ -206,11 +206,6 @@ public void GetsNoDeprecationOnOperationWithDeprecatedReferenceResponseSchema() { Schema = new OpenApiSchema { - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = "someSchema" - }, Deprecated = true, Extensions = new Dictionary { @@ -303,11 +298,6 @@ public void GetsNoDeprecationOnOperationWithDeprecatedReferenceRequestSchema() { Schema = new OpenApiSchema { - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = "someSchema" - }, Deprecated = true, Extensions = new Dictionary { @@ -404,11 +394,6 @@ public void GetsNoDeprecationInformationOnParameterWithDeprecatedReferenceSchema Deprecated = false, Schema = new OpenApiSchema { - Reference = new OpenApiReference - { - Id = "id", - Type = ReferenceType.Schema - }, Deprecated = true, Extensions = new Dictionary { @@ -468,11 +453,6 @@ public void GetsNoDeprecationInformationOnParameterWithDeprecatedReferenceConten { Schema = new OpenApiSchema { - Reference = new OpenApiReference - { - Type = ReferenceType.Schema, - Id = "id" - }, Deprecated = true, Extensions = new Dictionary { diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index 0b01dbe2b0..a9b6b34b1e 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -63,26 +63,13 @@ public void Defensive() [Fact] public void ExternalReferencesAreNotSupported() { - var mockSchema = new OpenApiSchema - { - Reference = new OpenApiReference - { - Id = "example.json#/path/to/component", - ExternalResource = "http://example.com/example.json", - }, - }; + var mockSchema = new OpenApiSchemaReference("example.json#/path/to/component", null, "http://example.com/example.json"); Assert.Throws(() => mockSchema.IsReferencedSchema()); } [Fact] public void LocalReferencesAreSupported() { - var mockSchema = new OpenApiSchema - { - Reference = new OpenApiReference - { - Id = "#/path/to/component", - }, - }; + var mockSchema = new OpenApiSchemaReference("#/path/to/component"); Assert.True(mockSchema.IsReferencedSchema()); } [Fact] @@ -111,20 +98,8 @@ public void GetSchemaNameAllOfReference() var schema = new OpenApiSchema { AllOf = [ - new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.entity" - } - }, - new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.user" - } - } + new OpenApiSchemaReference("microsoft.graph.entity"), + new OpenApiSchemaReference("microsoft.graph.user"), ] }; var names = schema.GetSchemaNames(); @@ -166,20 +141,8 @@ public void GetSchemaNameAllOfNestedReference() new OpenApiSchema() { AllOf = [ - new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.entity" - } - }, - new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.user" - } - } + new OpenApiSchemaReference("microsoft.graph.entity"), + new OpenApiSchemaReference("microsoft.graph.user"), ] } ] @@ -215,21 +178,9 @@ public void GetSchemaNameAnyOfReference() var schema = new OpenApiSchema { AnyOf = [ - new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.entity" - } - }, - new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.user" - } - } - ] + new OpenApiSchemaReference("microsoft.graph.entity"), + new OpenApiSchemaReference("microsoft.graph.user"), + ] }; var names = schema.GetSchemaNames(); Assert.Contains("entity", names); @@ -262,21 +213,9 @@ public void GetSchemaNameOneOfReference() var schema = new OpenApiSchema { OneOf = [ - new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.entity" - } - }, - new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.user" - } - } - ] + new OpenApiSchemaReference("microsoft.graph.entity"), + new OpenApiSchemaReference("microsoft.graph.user"), + ] }; var names = schema.GetSchemaNames(); Assert.Contains("entity", names); @@ -302,13 +241,7 @@ public void GetSchemaNameItemsReference() { var schema = new OpenApiSchema { - Items = new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.entity" - } - }, + Items = new OpenApiSchemaReference("microsoft.graph.entity") }; var names = schema.GetSchemaNames(); Assert.Contains("entity", names); @@ -329,13 +262,7 @@ public void GetSchemaNameTitleEmpty() [Fact] public void GetSchemaNameReference() { - var schema = new OpenApiSchema - { - Reference = new() - { - Id = "microsoft.graph.entity" - } - }; + var schema = new OpenApiSchemaReference("microsoft.graph.entity"); var names = schema.GetSchemaNames(); Assert.Contains("entity", names); Assert.Equal("entity", schema.GetSchemaName()); @@ -354,18 +281,10 @@ public void GetReferenceIdsAllOf() { var schema = new OpenApiSchema { - AllOf = new List { - new OpenApiSchema() { - Reference = new() { - Id = "microsoft.graph.entity" - } - }, - new OpenApiSchema() { - Reference = new() { - Id = "microsoft.graph.user" - } - } - } + AllOf = [ + new OpenApiSchemaReference("microsoft.graph.entity"), + new OpenApiSchemaReference("microsoft.graph.user") + ] }; var names = schema.GetSchemaReferenceIds(); Assert.Contains("microsoft.graph.entity", names); @@ -376,22 +295,14 @@ public void GetReferenceIdsAllOfNested() { var schema = new OpenApiSchema { - AllOf = new List { + AllOf = [ new OpenApiSchema() { - AllOf = new List { - new OpenApiSchema() { - Reference = new() { - Id = "microsoft.graph.entity" - } - }, - new OpenApiSchema() { - Reference = new() { - Id = "microsoft.graph.user" - } - } - } + AllOf = [ + new OpenApiSchemaReference("microsoft.graph.entity"), + new OpenApiSchemaReference("microsoft.graph.user") + ] } - } + ] }; var names = schema.GetSchemaReferenceIds(); Assert.Contains("microsoft.graph.entity", names); @@ -402,18 +313,10 @@ public void GetReferenceIdsAnyOf() { var schema = new OpenApiSchema { - AnyOf = new List { - new OpenApiSchema() { - Reference = new() { - Id = "microsoft.graph.entity" - } - }, - new OpenApiSchema() { - Reference = new() { - Id = "microsoft.graph.user" - } - } - } + AnyOf = [ + new OpenApiSchemaReference("microsoft.graph.entity"), + new OpenApiSchemaReference("microsoft.graph.user") + ] }; var names = schema.GetSchemaReferenceIds(); Assert.Contains("microsoft.graph.entity", names); @@ -424,18 +327,10 @@ public void GetReferenceIdsOneOf() { var schema = new OpenApiSchema { - OneOf = new List { - new OpenApiSchema() { - Reference = new() { - Id = "microsoft.graph.entity" - } - }, - new OpenApiSchema() { - Reference = new() { - Id = "microsoft.graph.user" - } - } - } + OneOf = [ + new OpenApiSchemaReference("microsoft.graph.entity"), + new OpenApiSchemaReference("microsoft.graph.user") + ] }; var names = schema.GetSchemaReferenceIds(); Assert.Contains("microsoft.graph.entity", names); @@ -446,13 +341,7 @@ public void GetReferenceIdsItems() { var schema = new OpenApiSchema { - Items = new OpenApiSchema() - { - Reference = new() - { - Id = "microsoft.graph.entity" - } - }, + Items = new OpenApiSchemaReference("microsoft.graph.entity"), }; var names = schema.GetSchemaReferenceIds(); Assert.Contains("microsoft.graph.entity", names); @@ -461,13 +350,7 @@ public void GetReferenceIdsItems() [Fact] public void GetReferenceIdsTitle() { - var schema = new OpenApiSchema - { - Reference = new() - { - Id = "microsoft.graph.entity" - } - }; + var schema = new OpenApiSchemaReference("microsoft.graph.entity"); var names = schema.GetSchemaReferenceIds(); Assert.Contains("microsoft.graph.entity", names); Assert.Single(names); @@ -484,23 +367,15 @@ public void IsInherited() { var schema = new OpenApiSchema { - AllOf = new List { - new OpenApiSchema() { - Type = JsonSchemaType.Object, - Reference = new() { - Id = "microsoft.graph.entity" - }, - Properties = new Dictionary() { - ["id"] = new OpenApiSchema() - } - }, + AllOf = [ + new OpenApiSchemaReference("microsoft.graph.entity"), new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema() } } - } + ] }; Assert.True(schema.IsInherited()); Assert.False(schema.IsIntersection()); @@ -508,35 +383,45 @@ public void IsInherited() [Fact] public void IsIntersection() { - var schema = new OpenApiSchema + var document = new OpenApiDocument() { - AllOf = new List { - new OpenApiSchema() { - Type = JsonSchemaType.Object, - Reference = new() { - Id = "microsoft.graph.entity" - }, - Properties = new Dictionary() { - ["id"] = new OpenApiSchema() - } - }, - new OpenApiSchema() { - Type = JsonSchemaType.Object, - Reference = new() { - Id = "microsoft.graph.user" + Components = new() + { + Schemas = new Dictionary + { + ["microsoft.graph.entity"] = new OpenApiSchema + { + Type = JsonSchemaType.Object, + Properties = new Dictionary() + { + ["id"] = new OpenApiSchema() + } }, - Properties = new Dictionary() { - ["firstName"] = new OpenApiSchema() + ["microsoft.graph.user"] = new OpenApiSchema + { + Type = JsonSchemaType.Object, + Properties = new Dictionary() + { + ["firstName"] = new OpenApiSchema() + } } } } }; + document.RegisterComponents(); + var schema = new OpenApiSchema + { + AllOf = [ + new OpenApiSchemaReference("microsoft.graph.entity", document), + new OpenApiSchemaReference("microsoft.graph.user", document), + ] + }; Assert.False(schema.IsInherited()); Assert.True(schema.IsIntersection()); schema = new OpenApiSchema { - AllOf = new List { + AllOf = [ new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = new Dictionary() { @@ -549,21 +434,21 @@ public void IsIntersection() ["firstName"] = new OpenApiSchema() } } - } + ] }; Assert.False(schema.IsInherited()); Assert.True(schema.IsIntersection()); schema = new OpenApiSchema { - AllOf = new List { + AllOf = [ new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = new Dictionary() { ["id"] = new OpenApiSchema() } } - } + ] }; Assert.False(schema.IsInherited()); Assert.False(schema.IsIntersection()); @@ -571,7 +456,7 @@ public void IsIntersection() schema = new OpenApiSchema { Title = "Trader Id", - AllOf = new List { + AllOf = [ new OpenApiSchema() { Title = "UserId", @@ -584,7 +469,7 @@ public void IsIntersection() Id = "UserId" // This property makes the schema "meaningful" } } - }, + ], Reference = new OpenApiReference { Id = "TraderId" // This property makes the schema "meaningful" @@ -601,7 +486,7 @@ public void MergesIntersection() { Description = "description", Deprecated = true, - AllOf = new List { + AllOf = [ new OpenApiSchema() { Type = JsonSchemaType.Object, Reference = new() { @@ -620,7 +505,7 @@ public void MergesIntersection() ["firstName"] = new OpenApiSchema() } } - } + ] }; var result = schema.MergeIntersectionSchemaEntries(); Assert.False(schema.IsInherited()); @@ -637,7 +522,7 @@ public void MergesIntersectionRecursively() { Description = "description", Deprecated = true, - AllOf = new List { + AllOf = [ new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = new Dictionary() { @@ -646,7 +531,7 @@ public void MergesIntersectionRecursively() }, new OpenApiSchema() { Type = JsonSchemaType.Object, - AllOf = new List() { + AllOf = [ new OpenApiSchema() { Type = JsonSchemaType.Object, Properties = new Dictionary() { @@ -660,9 +545,9 @@ public void MergesIntersectionRecursively() ["lastName"] = new OpenApiSchema() } }, - } + ] } - } + ] }; var result = schema.MergeIntersectionSchemaEntries(); Assert.False(schema.IsInherited()); @@ -1043,7 +928,7 @@ public void IsEnumFailsOnEmptyMembers() var schema = new OpenApiSchema { Type = JsonSchemaType.String, - Enum = new List(), + Enum = [], }; Assert.False(schema.IsEnum()); @@ -1053,15 +938,15 @@ public void IsEnumFailsOnEmptyMembers() private static readonly OpenApiSchema enumSchema = new OpenApiSchema { Title = "riskLevel", - Enum = new List - { + Enum = + [ "low", "medium", "high", "hidden", "none", "unknownFutureValue" - }, + ], Type = JsonSchemaType.String }; [Fact] @@ -1069,14 +954,14 @@ public void IsEnumIgnoresNullableUnions() { var schema = new OpenApiSchema { - AnyOf = new List - { + AnyOf = + [ enumSchema, new OpenApiSchema { Type = JsonSchemaType.Object, } - } + ] }; Assert.False(schema.IsEnum()); } @@ -1085,14 +970,14 @@ public void IsEnumFailsOnNullableInheritance() { var schema = new OpenApiSchema { - AllOf = new List - { + AllOf = + [ enumSchema, new OpenApiSchema { Type = JsonSchemaType.Object, } - } + ] }; Assert.False(schema.IsEnum()); } @@ -1101,14 +986,14 @@ public void IsEnumIgnoresNullableExclusiveUnions() { var schema = new OpenApiSchema { - OneOf = new List - { + OneOf = + [ enumSchema, new OpenApiSchema { Type = JsonSchemaType.Object, } - } + ] }; Assert.False(schema.IsEnum()); } @@ -1122,15 +1007,15 @@ public void IsEnumDoesNotMaskExclusiveUnions() { var schema = new OpenApiSchema { - OneOf = new List - { + OneOf = + [ enumSchema, numberSchema, new OpenApiSchema { Type = JsonSchemaType.Object, } - } + ] }; Assert.False(schema.IsEnum()); } @@ -1139,15 +1024,15 @@ public void IsEnumDoesNotMaskUnions() { var schema = new OpenApiSchema { - AnyOf = new List - { + AnyOf = + [ enumSchema, numberSchema, new OpenApiSchema { Type = JsonSchemaType.Object, } - } + ] }; Assert.False(schema.IsEnum()); } @@ -1156,8 +1041,8 @@ public void IsOdataPrimitive() { var schema = new OpenApiSchema { - OneOf = new List - { + OneOf = + [ new OpenApiSchema() { Type = JsonSchemaType.Number, @@ -1169,15 +1054,15 @@ public void IsOdataPrimitive() }, new OpenApiSchema() { - Enum = new List - { + Enum = + [ "INF", "INF", "NaN", - }, + ], Type = JsonSchemaType.String, } - } + ] }; Assert.True(schema.IsODataPrimitiveType()); } @@ -1186,8 +1071,8 @@ public void IsOdataPrimitiveBackwardCompatible() { var schema = new OpenApiSchema { - OneOf = new List - { + OneOf = + [ new OpenApiSchema() { Type = JsonSchemaType.Number, @@ -1199,14 +1084,14 @@ public void IsOdataPrimitiveBackwardCompatible() }, new OpenApiSchema() { - Enum = new List() - { + Enum = + [ "INF", "INF", "NaN", - } + ] } - } + ] }; Assert.True(schema.IsODataPrimitiveType()); } @@ -1215,27 +1100,13 @@ public void ReturnsEmptyPropertyNameOnCircularReferences() { var entitySchema = new OpenApiSchema { - Reference = new OpenApiReference - { - Id = "microsoft.graph.entity" - }, Properties = new Dictionary { - ["id"] = new OpenApiSchema - { - Reference = new OpenApiReference - { - Id = "microsoft.graph.entity" - } - } + ["id"] = new OpenApiSchemaReference("microsoft.graph.entity") } }; var userSchema = new OpenApiSchema { - Reference = new OpenApiReference - { - Id = "microsoft.graph.user" - }, OneOf = [ entitySchema, @@ -1244,13 +1115,7 @@ public void ReturnsEmptyPropertyNameOnCircularReferences() Type = JsonSchemaType.Object, Properties = new Dictionary { - ["firstName"] = new OpenApiSchema - { - Reference = new OpenApiReference - { - Id = "microsoft.graph.entity" - } - } + ["firstName"] = new OpenApiSchemaReference("microsoft.graph.entity") } } ], @@ -1263,6 +1128,10 @@ public void ReturnsEmptyPropertyNameOnCircularReferences() } } }; + var document = new OpenApiDocument(); + document.AddComponent("microsoft.graph.entity", entitySchema); + document.AddComponent("microsoft.graph.user", userSchema); + document.SetReferenceHostDocument(); entitySchema.AllOf = [ userSchema From 1e91b2cce25fc36d683b8c30f80889d23d101b95 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 7 Feb 2025 09:54:03 -0500 Subject: [PATCH 51/96] fix: additional batch of reference fixes Signed-off-by: Vincent Biret --- .../OpenApiSchemaExtensionsTests.cs | 95 ++++++++----------- .../OpenApiUrlTreeNodeExtensionsTests.cs | 43 ++++----- 2 files changed, 58 insertions(+), 80 deletions(-) diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index a9b6b34b1e..916c79edf3 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -452,32 +452,29 @@ public void IsIntersection() }; Assert.False(schema.IsInherited()); Assert.False(schema.IsIntersection()); + var userIdSchema = new OpenApiSchema + { + Title = "UserId", + Description = "unique identifier", + Type = JsonSchemaType.String, + Pattern = "^[1-9][0-9]*$", + Example = "1323232", + }; + var tmpDocument = new OpenApiDocument(); + tmpDocument.AddComponent("UserId", userIdSchema); schema = new OpenApiSchema { Title = "Trader Id", AllOf = [ - new OpenApiSchema() - { - Title = "UserId", - Description = "unique identifier", - Type = JsonSchemaType.String, - Pattern = "^[1-9][0-9]*$", - Example = "1323232", - Reference = new OpenApiReference - { - Id = "UserId" // This property makes the schema "meaningful" - } - } + new OpenApiSchemaReference("UserId", tmpDocument),// This property makes the schema "meaningful" ], - Reference = new OpenApiReference - { - Id = "TraderId" // This property makes the schema "meaningful" - } }; + tmpDocument.AddComponent("TraderId", schema); + var schemaReference = new OpenApiSchemaReference("TraderId", tmpDocument); // This property makes the schema "meaningful" - Assert.False(schema.IsInherited()); - Assert.False(schema.IsIntersection()); + Assert.False(schemaReference.IsInherited()); + Assert.False(schemaReference.IsIntersection()); } [Fact] public void MergesIntersection() @@ -489,18 +486,12 @@ public void MergesIntersection() AllOf = [ new OpenApiSchema() { Type = JsonSchemaType.Object, - Reference = new() { - Id = "microsoft.graph.entity" - }, Properties = new Dictionary() { ["id"] = new OpenApiSchema() } }, new OpenApiSchema() { Type = JsonSchemaType.Object, - Reference = new() { - Id = "microsoft.graph.user" - }, Properties = new Dictionary() { ["firstName"] = new OpenApiSchema() } @@ -564,6 +555,11 @@ public class MergeSingleInclusiveUnionInheritanceOrIntersectionSchemaEntries [Fact] public void DoesMergeWithInheritance() { + var baseClassSchema = new OpenApiSchema() + { + }; + var document = new OpenApiDocument(); + document.AddComponent("BaseClass", baseClassSchema); var schema = new OpenApiSchema() { Type = JsonSchemaType.Object, @@ -577,13 +573,7 @@ public void DoesMergeWithInheritance() }, AllOf = [ - new OpenApiSchema() - { - Reference = new() - { - Id = "BaseClass" - }, - }, + new OpenApiSchemaReference("BaseClass", document), new OpenApiSchema() { Type = JsonSchemaType.Object, @@ -662,6 +652,11 @@ public void DoesMergeWithIntersection() [Fact] public void DoesNotMergeWithMoreThanOneInclusiveEntry() { + var baseClassSchema = new OpenApiSchema() + { + }; + var document = new OpenApiDocument(); + document.AddComponent("BaseClass", baseClassSchema); var schema = new OpenApiSchema() { Type = JsonSchemaType.Object, @@ -675,13 +670,7 @@ public void DoesNotMergeWithMoreThanOneInclusiveEntry() }, AllOf = [ - new OpenApiSchema() - { - Reference = new() - { - Id = "BaseClass" - }, - }, + new OpenApiSchemaReference("BaseClass", document), new OpenApiSchema() { Type = JsonSchemaType.Object, @@ -693,7 +682,7 @@ public void DoesNotMergeWithMoreThanOneInclusiveEntry() }, ] }, - new() { Type = JsonSchemaType.Object }, + new OpenApiSchema() { Type = JsonSchemaType.Object }, ], }; @@ -736,6 +725,11 @@ public class MergeSingleExclusiveUnionInheritanceOrIntersectionSchemaEntries [Fact] public void DoesMergeWithInheritance() { + var baseClassSchema = new OpenApiSchema() + { + }; + var document = new OpenApiDocument(); + document.AddComponent("BaseClass", baseClassSchema); var schema = new OpenApiSchema() { Type = JsonSchemaType.Object, @@ -749,13 +743,7 @@ public void DoesMergeWithInheritance() }, AllOf = [ - new OpenApiSchema() - { - Reference = new() - { - Id = "BaseClass" - }, - }, + new OpenApiSchemaReference("BaseClass", document), new OpenApiSchema() { Type = JsonSchemaType.Object, @@ -834,6 +822,11 @@ public void DoesMergeWithIntersection() [Fact] public void DoesNotMergeWithMoreThanOneExclusiveEntry() { + var baseClassSchema = new OpenApiSchema() + { + }; + var document = new OpenApiDocument(); + document.AddComponent("BaseClass", baseClassSchema); var schema = new OpenApiSchema() { Type = JsonSchemaType.Object, @@ -847,13 +840,7 @@ public void DoesNotMergeWithMoreThanOneExclusiveEntry() }, AllOf = [ - new OpenApiSchema() - { - Reference = new() - { - Id = "BaseClass" - }, - }, + new OpenApiSchemaReference("BaseClass", document), new OpenApiSchema() { Type = JsonSchemaType.Object, @@ -865,7 +852,7 @@ public void DoesNotMergeWithMoreThanOneExclusiveEntry() }, ] }, - new() { Type = JsonSchemaType.Object }, + new OpenApiSchema() { Type = JsonSchemaType.Object }, ], }; diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs index 2b3602b0ee..a2ce802019 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiUrlTreeNodeExtensionsTests.cs @@ -7,6 +7,7 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Xunit; @@ -701,6 +702,11 @@ public void GetsClassNameWithSegmentsToSkipForClassNames() { Paths = new(), }; + doc.AddComponent("microsoft.graph.json", new OpenApiSchema + { + Type = JsonSchemaType.Object, + Title = "json", + }); doc.Paths.Add("/reviews/{resource-type}.json", new OpenApiPathItem() { Operations = new Dictionary { @@ -727,15 +733,7 @@ public void GetsClassNameWithSegmentsToSkipForClassNames() { "application/json", new() { - Schema = new OpenApiSchema() - { - Type = JsonSchemaType.Object, - Title = "json", - Reference = new OpenApiReference() - { - Id = "microsoft.graph.json" - } - } + Schema = new OpenApiSchemaReference("microsoft.graph.json"), } } } @@ -746,6 +744,7 @@ public void GetsClassNameWithSegmentsToSkipForClassNames() } } }); + doc.SetReferenceHostDocument(); var node = OpenApiUrlTreeNode.Create(doc, Label); var result = node.Children["reviews"].Children["{resource-type}.json"].GetClassName(new() { "application/json" }); @@ -777,10 +776,6 @@ public void SinglePathParametersAreDeduplicated() } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/microsoft.graph.user" - }, }; var document = new OpenApiDocument { @@ -807,7 +802,7 @@ public void SinglePathParametersAreDeduplicated() Content = { ["application/json"] = new OpenApiMediaType { - Schema = userSchema + Schema = new OpenApiSchemaReference("microsoft.graph.user") } } } @@ -836,7 +831,7 @@ public void SinglePathParametersAreDeduplicated() Content = { ["application/json"] = new OpenApiMediaType { - Schema = userSchema + Schema = new OpenApiSchemaReference("microsoft.graph.user") } } } @@ -865,7 +860,7 @@ public void SinglePathParametersAreDeduplicated() Content = { ["application/json"] = new OpenApiMediaType { - Schema = userSchema + Schema = new OpenApiSchemaReference("microsoft.graph.user") } } } @@ -883,6 +878,8 @@ public void SinglePathParametersAreDeduplicated() } } }; + document.RegisterComponents(); + document.SetReferenceHostDocument(); var mockLogger = new CountLogger(); var builder = new KiotaBuilder(mockLogger, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -920,10 +917,6 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/owner" - }, }; var repoSchema = new OpenApiSchema { @@ -935,10 +928,6 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/repo" - }, }; var document = new OpenApiDocument { @@ -955,7 +944,7 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() Content = { ["application/json"] = new OpenApiMediaType { - Schema = repoSchema + Schema = new OpenApiSchemaReference("repo") } } } @@ -974,7 +963,7 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() Content = { ["application/json"] = new OpenApiMediaType { - Schema = repoSchema + Schema = new OpenApiSchemaReference("repo") } } } @@ -991,6 +980,8 @@ public void SinglePathParametersAreDeduplicatedAndOrderIsRespected() } } }; + document.RegisterComponents(); + document.SetReferenceHostDocument(); var mockLogger = new CountLogger(); var builder = new KiotaBuilder(mockLogger, new GenerationConfiguration { ClientClassName = "GitHub", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); From 88f3d6ff0a2667652b52b85b469676ed03952e34 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 7 Feb 2025 09:59:15 -0500 Subject: [PATCH 52/96] chore: updates plugin manifest reference Signed-off-by: Vincent Biret --- src/Kiota.Builder/Kiota.Builder.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index b3270bba38..fcf35562f5 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -47,7 +47,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive From 90056461612d97983a40681b8f95bc9677dfcc8a Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 7 Feb 2025 09:59:29 -0500 Subject: [PATCH 53/96] chore: updates plugins manifest namespace Signed-off-by: Vincent Biret --- .../Configuration/PluginAuthConfiguration.cs | 2 +- src/Kiota.Builder/Plugins/AuthComparer.cs | 2 +- .../Plugins/OpenAPiRuntimeComparer.cs | 2 +- .../Plugins/OpenApiRuntimeSpecComparer.cs | 2 +- .../Plugins/PluginsGenerationService.cs | 2 +- .../ApiPluginConfiguration.cs | 2 +- .../Plugins/OpenAPIRuntimeComparerTests.cs | 2 +- .../Plugins/PluginsGenerationServiceTests.cs | 682 +++++++++--------- 8 files changed, 348 insertions(+), 348 deletions(-) diff --git a/src/Kiota.Builder/Configuration/PluginAuthConfiguration.cs b/src/Kiota.Builder/Configuration/PluginAuthConfiguration.cs index 3351146592..189b0809fc 100644 --- a/src/Kiota.Builder/Configuration/PluginAuthConfiguration.cs +++ b/src/Kiota.Builder/Configuration/PluginAuthConfiguration.cs @@ -1,6 +1,6 @@ using System; using Microsoft.OpenApi.Models; -using Microsoft.Plugins.Manifest; +using Microsoft.DeclarativeAgents.Manifest; namespace Kiota.Builder.Configuration; diff --git a/src/Kiota.Builder/Plugins/AuthComparer.cs b/src/Kiota.Builder/Plugins/AuthComparer.cs index cf71b0c97f..5a428a3e27 100644 --- a/src/Kiota.Builder/Plugins/AuthComparer.cs +++ b/src/Kiota.Builder/Plugins/AuthComparer.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using Microsoft.Plugins.Manifest; +using Microsoft.DeclarativeAgents.Manifest; namespace Kiota.Builder.Plugins; diff --git a/src/Kiota.Builder/Plugins/OpenAPiRuntimeComparer.cs b/src/Kiota.Builder/Plugins/OpenAPiRuntimeComparer.cs index 4aab99b810..0e0cd81a9e 100644 --- a/src/Kiota.Builder/Plugins/OpenAPiRuntimeComparer.cs +++ b/src/Kiota.Builder/Plugins/OpenAPiRuntimeComparer.cs @@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Kiota.Builder.Lock; -using Microsoft.Plugins.Manifest; +using Microsoft.DeclarativeAgents.Manifest; namespace Kiota.Builder.Plugins; diff --git a/src/Kiota.Builder/Plugins/OpenApiRuntimeSpecComparer.cs b/src/Kiota.Builder/Plugins/OpenApiRuntimeSpecComparer.cs index fefc58a16f..7f955cb0f6 100644 --- a/src/Kiota.Builder/Plugins/OpenApiRuntimeSpecComparer.cs +++ b/src/Kiota.Builder/Plugins/OpenApiRuntimeSpecComparer.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; -using Microsoft.Plugins.Manifest; +using Microsoft.DeclarativeAgents.Manifest; namespace Kiota.Builder.Plugins; diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index 0f8c0274c1..cd843420d8 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -17,7 +17,7 @@ using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Writers; -using Microsoft.Plugins.Manifest; +using Microsoft.DeclarativeAgents.Manifest; namespace Kiota.Builder.Plugins; diff --git a/src/Kiota.Builder/WorkspaceManagement/ApiPluginConfiguration.cs b/src/Kiota.Builder/WorkspaceManagement/ApiPluginConfiguration.cs index a4394aaf38..85bf13e49d 100644 --- a/src/Kiota.Builder/WorkspaceManagement/ApiPluginConfiguration.cs +++ b/src/Kiota.Builder/WorkspaceManagement/ApiPluginConfiguration.cs @@ -3,7 +3,7 @@ using System.Linq; using Kiota.Builder.Configuration; using Microsoft.OpenApi.ApiManifest; -using Microsoft.Plugins.Manifest; +using Microsoft.DeclarativeAgents.Manifest; namespace Kiota.Builder.WorkspaceManagement; diff --git a/tests/Kiota.Builder.Tests/Plugins/OpenAPIRuntimeComparerTests.cs b/tests/Kiota.Builder.Tests/Plugins/OpenAPIRuntimeComparerTests.cs index eee5df2915..76d9b18d44 100644 --- a/tests/Kiota.Builder.Tests/Plugins/OpenAPIRuntimeComparerTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/OpenAPIRuntimeComparerTests.cs @@ -1,6 +1,6 @@ using System; using Kiota.Builder.Plugins; -using Microsoft.Plugins.Manifest; +using Microsoft.DeclarativeAgents.Manifest; using Xunit; namespace Kiota.Builder.Tests.Plugins; diff --git a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs index db7d7b1072..cc8accbfbe 100644 --- a/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs +++ b/tests/Kiota.Builder.Tests/Plugins/PluginsGenerationServiceTests.cs @@ -11,36 +11,36 @@ using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Services; -using Microsoft.Plugins.Manifest; +using Microsoft.DeclarativeAgents.Manifest; using Moq; using Xunit; namespace Kiota.Builder.Tests.Plugins; public sealed class PluginsGenerationServiceTests : IDisposable { - private readonly HttpClient _httpClient = new(); - private readonly ILogger _logger = new Mock>().Object; - [Fact] - public void Defensive() - { - Assert.Throws(() => new PluginsGenerationService(null, OpenApiUrlTreeNode.Create(), new(), "foo", _logger)); - Assert.Throws(() => new PluginsGenerationService(new(), null, new(), "foo", _logger)); - Assert.Throws(() => new PluginsGenerationService(new(), OpenApiUrlTreeNode.Create(), null, "foo", _logger)); - Assert.Throws(() => new PluginsGenerationService(new(), OpenApiUrlTreeNode.Create(), new(), string.Empty, _logger)); - } - - public void Dispose() - { - _httpClient.Dispose(); - } - - [Theory] - [InlineData("client", "client")] - [InlineData("Budget Tracker", "BudgetTracker")]//drop the space - [InlineData("My-Super complex() %@#$& Name", "MySupercomplexName")]//drop the space and special characters - public async Task GeneratesManifestAsync(string inputPluginName, string expectedPluginName) - { - var simpleDescriptionContent = @"openapi: 3.0.0 + private readonly HttpClient _httpClient = new(); + private readonly ILogger _logger = new Mock>().Object; + [Fact] + public void Defensive() + { + Assert.Throws(() => new PluginsGenerationService(null, OpenApiUrlTreeNode.Create(), new(), "foo", _logger)); + Assert.Throws(() => new PluginsGenerationService(new(), null, new(), "foo", _logger)); + Assert.Throws(() => new PluginsGenerationService(new(), OpenApiUrlTreeNode.Create(), null, "foo", _logger)); + Assert.Throws(() => new PluginsGenerationService(new(), OpenApiUrlTreeNode.Create(), new(), string.Empty, _logger)); + } + + public void Dispose() + { + _httpClient.Dispose(); + } + + [Theory] + [InlineData("client", "client")] + [InlineData("Budget Tracker", "BudgetTracker")]//drop the space + [InlineData("My-Super complex() %@#$& Name", "MySupercomplexName")]//drop the space and special characters + public async Task GeneratesManifestAsync(string inputPluginName, string expectedPluginName) + { + var simpleDescriptionContent = @"openapi: 3.0.0 info: title: test version: 1.0 @@ -72,59 +72,59 @@ public async Task GeneratesManifestAsync(string inputPluginName, string expected responses: '200': description: test"; - var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; - await File.WriteAllTextAsync(simpleDescriptionPath, simpleDescriptionContent); - var openAPIDocumentDS = new OpenApiDocumentDownloadService(_httpClient, _logger); - var outputDirectory = Path.Combine(workingDirectory, "output"); - var generationConfiguration = new GenerationConfiguration - { - OutputPath = outputDirectory, - OpenAPIFilePath = simpleDescriptionPath, - PluginTypes = [PluginType.APIPlugin, PluginType.APIManifest, PluginType.OpenAI], - ClientClassName = inputPluginName, - ApiRootUrl = "http://localhost/", //Kiota builder would set this for us - }; - var (openAPIDocumentStream, _) = await openAPIDocumentDS.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); - var openApiDocument = await openAPIDocumentDS.GetDocumentFromStreamAsync(openAPIDocumentStream, generationConfiguration); - KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); - var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); - - var pluginsGenerationService = new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory, _logger); - await pluginsGenerationService.GenerateManifestAsync(); - - Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apiplugin.json"))); - Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apimanifest.json"))); - // v1 plugins are not generated anymore - Assert.False(File.Exists(Path.Combine(outputDirectory, OpenAIPluginFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-openapi.yml"))); - Assert.False(File.Exists(Path.Combine(outputDirectory, "manifest.json"))); - Assert.False(File.Exists(Path.Combine(outputDirectory, "color.png"))); - Assert.False(File.Exists(Path.Combine(outputDirectory, "outline.png"))); - - // Validate the v2 plugin - var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apiplugin.json")); - using var jsonDocument = JsonDocument.Parse(manifestContent); - var resultingManifest = PluginManifestDocument.Load(jsonDocument.RootElement); - Assert.NotNull(resultingManifest.Document); - Assert.Equal($"{expectedPluginName.ToLower()}-openapi.yml", resultingManifest.Document.Runtimes.OfType().First().Spec.Url); - Assert.Equal(2, resultingManifest.Document.Functions.Count);// all functions are generated despite missing operationIds - Assert.Contains("description for test path with id", resultingManifest.Document.Functions[1].Description);// Uses the operation description - Assert.Equal(2, resultingManifest.Document.Capabilities.ConversationStarters.Count);// conversation starters are generated for each function - Assert.Contains("Summary for test path with id", resultingManifest.Document.Capabilities.ConversationStarters[1].Text);// Uses the operation summary - Assert.True(resultingManifest.Document.Capabilities.ConversationStarters[1].Text.Length <= 50);// Conversation starters are limited to 50 characters - Assert.Equal(expectedPluginName, resultingManifest.Document.Namespace);// namespace is cleaned up. - Assert.Empty(resultingManifest.Problems);// no problems are expected with names - Assert.Equal("test description we've created", resultingManifest.Document.DescriptionForHuman);// description is pulled from info - } - private const string ManifestFileName = "client-apiplugin.json"; - private const string OpenAIPluginFileName = "openai-plugins.json"; - private const string OpenApiFileName = "client-openapi.yml"; - - [Fact] - public async Task ThrowsOnEmptyPathsAfterFilteringAsync() + var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; + await File.WriteAllTextAsync(simpleDescriptionPath, simpleDescriptionContent); + var openAPIDocumentDS = new OpenApiDocumentDownloadService(_httpClient, _logger); + var outputDirectory = Path.Combine(workingDirectory, "output"); + var generationConfiguration = new GenerationConfiguration { - var simpleDescriptionContent = @"openapi: 3.0.0 + OutputPath = outputDirectory, + OpenAPIFilePath = simpleDescriptionPath, + PluginTypes = [PluginType.APIPlugin, PluginType.APIManifest, PluginType.OpenAI], + ClientClassName = inputPluginName, + ApiRootUrl = "http://localhost/", //Kiota builder would set this for us + }; + var (openAPIDocumentStream, _) = await openAPIDocumentDS.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); + var openApiDocument = await openAPIDocumentDS.GetDocumentFromStreamAsync(openAPIDocumentStream, generationConfiguration); + KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); + var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); + + var pluginsGenerationService = new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory, _logger); + await pluginsGenerationService.GenerateManifestAsync(); + + Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apiplugin.json"))); + Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apimanifest.json"))); + // v1 plugins are not generated anymore + Assert.False(File.Exists(Path.Combine(outputDirectory, OpenAIPluginFileName))); + Assert.True(File.Exists(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-openapi.yml"))); + Assert.False(File.Exists(Path.Combine(outputDirectory, "manifest.json"))); + Assert.False(File.Exists(Path.Combine(outputDirectory, "color.png"))); + Assert.False(File.Exists(Path.Combine(outputDirectory, "outline.png"))); + + // Validate the v2 plugin + var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, $"{expectedPluginName.ToLower()}-apiplugin.json")); + using var jsonDocument = JsonDocument.Parse(manifestContent); + var resultingManifest = PluginManifestDocument.Load(jsonDocument.RootElement); + Assert.NotNull(resultingManifest.Document); + Assert.Equal($"{expectedPluginName.ToLower()}-openapi.yml", resultingManifest.Document.Runtimes.OfType().First().Spec.Url); + Assert.Equal(2, resultingManifest.Document.Functions.Count);// all functions are generated despite missing operationIds + Assert.Contains("description for test path with id", resultingManifest.Document.Functions[1].Description);// Uses the operation description + Assert.Equal(2, resultingManifest.Document.Capabilities.ConversationStarters.Count);// conversation starters are generated for each function + Assert.Contains("Summary for test path with id", resultingManifest.Document.Capabilities.ConversationStarters[1].Text);// Uses the operation summary + Assert.True(resultingManifest.Document.Capabilities.ConversationStarters[1].Text.Length <= 50);// Conversation starters are limited to 50 characters + Assert.Equal(expectedPluginName, resultingManifest.Document.Namespace);// namespace is cleaned up. + Assert.Empty(resultingManifest.Problems);// no problems are expected with names + Assert.Equal("test description we've created", resultingManifest.Document.DescriptionForHuman);// description is pulled from info + } + private const string ManifestFileName = "client-apiplugin.json"; + private const string OpenAIPluginFileName = "openai-plugins.json"; + private const string OpenApiFileName = "client-openapi.yml"; + + [Fact] + public async Task ThrowsOnEmptyPathsAfterFilteringAsync() + { + var simpleDescriptionContent = @"openapi: 3.0.0 info: title: test version: 1.0 @@ -138,27 +138,27 @@ public async Task ThrowsOnEmptyPathsAfterFilteringAsync() responses: '200': description: test"; - var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; - await File.WriteAllTextAsync(simpleDescriptionPath, simpleDescriptionContent); - var outputDirectory = Path.Combine(workingDirectory, "output"); - var generationConfiguration = new GenerationConfiguration - { - OutputPath = outputDirectory, - OpenAPIFilePath = simpleDescriptionPath, - PluginTypes = [PluginType.APIPlugin, PluginType.APIManifest, PluginType.OpenAI], - ClientClassName = "testPlugin", - IncludePatterns = ["test/id"]// this would filter out all paths - }; - var kiotaBuilder = new KiotaBuilder(new Mock>().Object, generationConfiguration, _httpClient, true); - var exception = await Assert.ThrowsAsync(async () => await kiotaBuilder.GeneratePluginAsync(CancellationToken.None)); - Assert.Equal("No paths found in the OpenAPI document.", exception.Message); - } - - [Fact] - public async Task GeneratesManifestAndCleansUpInputDescriptionAsync() + var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; + await File.WriteAllTextAsync(simpleDescriptionPath, simpleDescriptionContent); + var outputDirectory = Path.Combine(workingDirectory, "output"); + var generationConfiguration = new GenerationConfiguration { - var simpleDescriptionContent = @"openapi: 3.0.0 + OutputPath = outputDirectory, + OpenAPIFilePath = simpleDescriptionPath, + PluginTypes = [PluginType.APIPlugin, PluginType.APIManifest, PluginType.OpenAI], + ClientClassName = "testPlugin", + IncludePatterns = ["test/id"]// this would filter out all paths + }; + var kiotaBuilder = new KiotaBuilder(new Mock>().Object, generationConfiguration, _httpClient, true); + var exception = await Assert.ThrowsAsync(async () => await kiotaBuilder.GeneratePluginAsync(CancellationToken.None)); + Assert.Equal("No paths found in the OpenAPI document.", exception.Message); + } + + [Fact] + public async Task GeneratesManifestAndCleansUpInputDescriptionAsync() + { + var simpleDescriptionContent = @"openapi: 3.0.0 info: title: test version: 1.0 @@ -225,87 +225,87 @@ public async Task GeneratesManifestAndCleansUpInputDescriptionAsync() type: string body: type: string"; - var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; - await File.WriteAllTextAsync(simpleDescriptionPath, simpleDescriptionContent); - var openAPIDocumentDS = new OpenApiDocumentDownloadService(_httpClient, _logger); - var outputDirectory = Path.Combine(workingDirectory, "output"); - var generationConfiguration = new GenerationConfiguration - { - OutputPath = outputDirectory, - OpenAPIFilePath = simpleDescriptionPath, - PluginTypes = [PluginType.APIPlugin], - ClientClassName = "client", - ApiRootUrl = "http://localhost/", //Kiota builder would set this for us - }; - var (openAPIDocumentStream, _) = await openAPIDocumentDS.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); - var openApiDocument = await openAPIDocumentDS.GetDocumentFromStreamAsync(openAPIDocumentStream, generationConfiguration); - KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); - var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); - - var pluginsGenerationService = new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory, _logger); - await pluginsGenerationService.GenerateManifestAsync(); - - Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); - - // Validate the v2 plugin - var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, ManifestFileName)); - using var jsonDocument = JsonDocument.Parse(manifestContent); - var resultingManifest = PluginManifestDocument.Load(jsonDocument.RootElement); - Assert.NotNull(resultingManifest.Document); - Assert.Equal(OpenApiFileName, resultingManifest.Document.Runtimes.OfType().First().Spec.Url); - Assert.Equal(2, resultingManifest.Document.Functions.Count);// all functions are generated despite missing operationIds - Assert.Equal(2, resultingManifest.Document.Capabilities.ConversationStarters.Count);// conversation starters are generated for each function - Assert.Empty(resultingManifest.Problems);// no problems are expected with names - - // Validate the original file. - using var originalOpenApiFile = File.OpenRead(simpleDescriptionPath); - var originalResult = await OpenApiDocument.LoadAsync(originalOpenApiFile, "yaml"); - var originalDocument = originalResult.Document; - Assert.Empty(originalResult.Diagnostic.Errors); - - Assert.Equal(originalDocument.Paths["/test"].Operations[OperationType.Get].Description, resultingManifest.Document.Functions[0].Description);// pulls from description - Assert.Equal(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Summary, resultingManifest.Document.Functions[1].Description);// pulls from summary - Assert.NotNull(originalDocument.Paths["/test"].Operations[OperationType.Get].ExternalDocs); // existing external docs - Assert.Equal(2, originalDocument.Components.Schemas.Count);// one schema originally - Assert.Single(originalDocument.Extensions); // single unsupported extension at root - Assert.Equal(2, originalDocument.Paths.Count); // document has only two paths - Assert.Equal(2, originalDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count); // 2 responses originally - Assert.Single(originalDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // 1 UNsupported extension - Assert.Equal(2, originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count); // 2 responses originally - Assert.Single(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension - Assert.Equal(2, originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.AllOf[0].Properties["id"].AnyOf.Count); // anyOf we selected - - // Validate the output open api file - using var resultOpenApiFile = File.OpenRead(Path.Combine(outputDirectory, OpenApiFileName)); - var resultResult = await OpenApiDocument.LoadAsync(resultOpenApiFile, "yaml"); - var resultDocument = resultResult.Document; - Assert.Empty(resultResult.Diagnostic.Errors); - - // Assertions / validations - Assert.Empty(resultDocument.Components.Schemas);// no schema is referenced. so ensure they are all removed - Assert.Empty(resultDocument.Extensions); // no extension at root (unsupported extension is removed) - Assert.Equal(2, resultDocument.Paths.Count); // document has only two paths - Assert.Equal(originalDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count - 1, resultDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count); // We removed the error response - Assert.NotEmpty(resultDocument.Paths["/test"].Operations[OperationType.Get].Responses["200"].Description); // response description string is not empty - Assert.Null(resultDocument.Paths["/test"].Operations[OperationType.Get].ExternalDocs); // external docs are removed - Assert.Empty(resultDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // NO UNsupported extension - Assert.Equal(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count - 1, resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count); // Responses are still intact. - Assert.NotEmpty(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Description);// response description string is not empty - Assert.Single(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension still present in operation - Assert.Empty(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.AllOf); // allOf were merged - Assert.Empty(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.Properties["id"].AnyOf); // anyOf we selected - Assert.Equal(JsonSchemaType.String, resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.Properties["id"].Type.Value); - Assert.DoesNotContain("500", resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Keys, StringComparer.OrdinalIgnoreCase); // We removed the error response - } - - #region Security - - public static TheoryData>> - SecurityInformationSuccess() + var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; + await File.WriteAllTextAsync(simpleDescriptionPath, simpleDescriptionContent); + var openAPIDocumentDS = new OpenApiDocumentDownloadService(_httpClient, _logger); + var outputDirectory = Path.Combine(workingDirectory, "output"); + var generationConfiguration = new GenerationConfiguration { - return new TheoryData>> + OutputPath = outputDirectory, + OpenAPIFilePath = simpleDescriptionPath, + PluginTypes = [PluginType.APIPlugin], + ClientClassName = "client", + ApiRootUrl = "http://localhost/", //Kiota builder would set this for us + }; + var (openAPIDocumentStream, _) = await openAPIDocumentDS.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); + var openApiDocument = await openAPIDocumentDS.GetDocumentFromStreamAsync(openAPIDocumentStream, generationConfiguration); + KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); + var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); + + var pluginsGenerationService = new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory, _logger); + await pluginsGenerationService.GenerateManifestAsync(); + + Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); + Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); + + // Validate the v2 plugin + var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, ManifestFileName)); + using var jsonDocument = JsonDocument.Parse(manifestContent); + var resultingManifest = PluginManifestDocument.Load(jsonDocument.RootElement); + Assert.NotNull(resultingManifest.Document); + Assert.Equal(OpenApiFileName, resultingManifest.Document.Runtimes.OfType().First().Spec.Url); + Assert.Equal(2, resultingManifest.Document.Functions.Count);// all functions are generated despite missing operationIds + Assert.Equal(2, resultingManifest.Document.Capabilities.ConversationStarters.Count);// conversation starters are generated for each function + Assert.Empty(resultingManifest.Problems);// no problems are expected with names + + // Validate the original file. + using var originalOpenApiFile = File.OpenRead(simpleDescriptionPath); + var originalResult = await OpenApiDocument.LoadAsync(originalOpenApiFile, "yaml"); + var originalDocument = originalResult.Document; + Assert.Empty(originalResult.Diagnostic.Errors); + + Assert.Equal(originalDocument.Paths["/test"].Operations[OperationType.Get].Description, resultingManifest.Document.Functions[0].Description);// pulls from description + Assert.Equal(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Summary, resultingManifest.Document.Functions[1].Description);// pulls from summary + Assert.NotNull(originalDocument.Paths["/test"].Operations[OperationType.Get].ExternalDocs); // existing external docs + Assert.Equal(2, originalDocument.Components.Schemas.Count);// one schema originally + Assert.Single(originalDocument.Extensions); // single unsupported extension at root + Assert.Equal(2, originalDocument.Paths.Count); // document has only two paths + Assert.Equal(2, originalDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count); // 2 responses originally + Assert.Single(originalDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // 1 UNsupported extension + Assert.Equal(2, originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count); // 2 responses originally + Assert.Single(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension + Assert.Equal(2, originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.AllOf[0].Properties["id"].AnyOf.Count); // anyOf we selected + + // Validate the output open api file + using var resultOpenApiFile = File.OpenRead(Path.Combine(outputDirectory, OpenApiFileName)); + var resultResult = await OpenApiDocument.LoadAsync(resultOpenApiFile, "yaml"); + var resultDocument = resultResult.Document; + Assert.Empty(resultResult.Diagnostic.Errors); + + // Assertions / validations + Assert.Empty(resultDocument.Components.Schemas);// no schema is referenced. so ensure they are all removed + Assert.Empty(resultDocument.Extensions); // no extension at root (unsupported extension is removed) + Assert.Equal(2, resultDocument.Paths.Count); // document has only two paths + Assert.Equal(originalDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count - 1, resultDocument.Paths["/test"].Operations[OperationType.Get].Responses.Count); // We removed the error response + Assert.NotEmpty(resultDocument.Paths["/test"].Operations[OperationType.Get].Responses["200"].Description); // response description string is not empty + Assert.Null(resultDocument.Paths["/test"].Operations[OperationType.Get].ExternalDocs); // external docs are removed + Assert.Empty(resultDocument.Paths["/test"].Operations[OperationType.Get].Extensions); // NO UNsupported extension + Assert.Equal(originalDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count - 1, resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Count); // Responses are still intact. + Assert.NotEmpty(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Description);// response description string is not empty + Assert.Single(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Extensions); // 1 supported extension still present in operation + Assert.Empty(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.AllOf); // allOf were merged + Assert.Empty(resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.Properties["id"].AnyOf); // anyOf we selected + Assert.Equal(JsonSchemaType.String, resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses["200"].Content["application/json"].Schema.Properties["id"].Type.Value); + Assert.DoesNotContain("500", resultDocument.Paths["/test/{id}"].Operations[OperationType.Get].Responses.Keys, StringComparer.OrdinalIgnoreCase); // We removed the error response + } + + #region Security + + public static TheoryData>> + SecurityInformationSuccess() + { + return new TheoryData>> { // security requirement in operation object { @@ -460,14 +460,14 @@ public static TheoryData> assertions) - { - var apiDescription = $""" + } + + [Theory] + [MemberData(nameof(SecurityInformationSuccess))] + public async Task GeneratesManifestWithAuthAsync(string securitySchemesComponent, string rootSecurity, + string operationSecurity, PluginAuthConfiguration pluginAuthConfiguration, Action> assertions) + { + var apiDescription = $""" openapi: 3.0.0 info: title: test @@ -483,56 +483,56 @@ public async Task GeneratesManifestWithAuthAsync(string securitySchemesComponent {rootSecurity} components: {securitySchemesComponent} """; - var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; - await File.WriteAllTextAsync(simpleDescriptionPath, apiDescription); - var openApiDocumentDs = new OpenApiDocumentDownloadService(_httpClient, _logger); - var outputDirectory = Path.Combine(workingDirectory, "output"); - var generationConfiguration = new GenerationConfiguration - { - OutputPath = outputDirectory, - OpenAPIFilePath = simpleDescriptionPath, - PluginTypes = [PluginType.APIPlugin], - ClientClassName = "client", - ApiRootUrl = "http://localhost/", //Kiota builder would set this for us - PluginAuthInformation = pluginAuthConfiguration, - }; - var (openApiDocumentStream, _) = - await openApiDocumentDs.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); - var openApiDocument = - await openApiDocumentDs.GetDocumentFromStreamAsync(openApiDocumentStream, generationConfiguration); - Assert.NotNull(openApiDocument); - KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); - var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); - - var pluginsGenerationService = - new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory, _logger); - await pluginsGenerationService.GenerateManifestAsync(); - - Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); - - // Validate the v2 plugin - var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, ManifestFileName)); - using var jsonDocument = JsonDocument.Parse(manifestContent); - var resultingManifest = PluginManifestDocument.Load(jsonDocument.RootElement); - - assertions(resultingManifest); - // Cleanup - try - { - Directory.Delete(outputDirectory, true); - } - catch (Exception) - { - // ignored - } + var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; + await File.WriteAllTextAsync(simpleDescriptionPath, apiDescription); + var openApiDocumentDs = new OpenApiDocumentDownloadService(_httpClient, _logger); + var outputDirectory = Path.Combine(workingDirectory, "output"); + var generationConfiguration = new GenerationConfiguration + { + OutputPath = outputDirectory, + OpenAPIFilePath = simpleDescriptionPath, + PluginTypes = [PluginType.APIPlugin], + ClientClassName = "client", + ApiRootUrl = "http://localhost/", //Kiota builder would set this for us + PluginAuthInformation = pluginAuthConfiguration, + }; + var (openApiDocumentStream, _) = + await openApiDocumentDs.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); + var openApiDocument = + await openApiDocumentDs.GetDocumentFromStreamAsync(openApiDocumentStream, generationConfiguration); + Assert.NotNull(openApiDocument); + KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); + var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); + + var pluginsGenerationService = + new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory, _logger); + await pluginsGenerationService.GenerateManifestAsync(); + + Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); + Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); + + // Validate the v2 plugin + var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, ManifestFileName)); + using var jsonDocument = JsonDocument.Parse(manifestContent); + var resultingManifest = PluginManifestDocument.Load(jsonDocument.RootElement); + + assertions(resultingManifest); + // Cleanup + try + { + Directory.Delete(outputDirectory, true); } - - [Fact] - public async Task GeneratesManifestWithMultipleSecuritySchemesAsync() + catch (Exception) { - var apiDescription = """ + // ignored + } + } + + [Fact] + public async Task GeneratesManifestWithMultipleSecuritySchemesAsync() + { + var apiDescription = """ openapi: 3.0.0 info: title: test @@ -561,69 +561,69 @@ public async Task GeneratesManifestWithMultipleSecuritySchemesAsync() }, } """; - var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; - await File.WriteAllTextAsync(simpleDescriptionPath, apiDescription); - var openApiDocumentDs = new OpenApiDocumentDownloadService(_httpClient, _logger); - var outputDirectory = Path.Combine(workingDirectory, "output"); - var generationConfiguration = new GenerationConfiguration - { - OutputPath = outputDirectory, - OpenAPIFilePath = simpleDescriptionPath, - PluginTypes = [PluginType.APIPlugin], - ClientClassName = "client", - ApiRootUrl = "http://localhost/", //Kiota builder would set this for us - }; - var (openApiDocumentStream, _) = - await openApiDocumentDs.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); - var openApiDocument = - await openApiDocumentDs.GetDocumentFromStreamAsync(openApiDocumentStream, generationConfiguration); - Assert.NotNull(openApiDocument); - KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); - var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); - - var pluginsGenerationService = - new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory, _logger); - await pluginsGenerationService.GenerateManifestAsync(); - - Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); - Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); - - // Validate the v2 plugin - var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, ManifestFileName)); - using var jsonDocument = JsonDocument.Parse(manifestContent); - var resultingManifest = PluginManifestDocument.Load(jsonDocument.RootElement); - - Assert.NotNull(resultingManifest.Document); - Assert.Empty(resultingManifest.Problems); - Assert.NotEmpty(resultingManifest.Document.Runtimes); - var auth0 = resultingManifest.Document.Runtimes[0].Auth; - Assert.IsType(auth0); - Assert.Equal(AuthType.ApiKeyPluginVault, auth0.Type); - Assert.Equal("{apiKey0_REGISTRATION_ID}", ((ApiKeyPluginVault)auth0!).ReferenceId); - var auth1 = resultingManifest.Document.Runtimes[1].Auth; - Assert.IsType(auth1); - Assert.Equal(AuthType.ApiKeyPluginVault, auth1.Type); - Assert.Equal("{apiKey1_REGISTRATION_ID}", ((ApiKeyPluginVault)auth1!).ReferenceId); - // Cleanup - try - { - Directory.Delete(outputDirectory); - } - catch (Exception) - { - // ignored - } + var workingDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + var simpleDescriptionPath = Path.Combine(workingDirectory) + "description.yaml"; + await File.WriteAllTextAsync(simpleDescriptionPath, apiDescription); + var openApiDocumentDs = new OpenApiDocumentDownloadService(_httpClient, _logger); + var outputDirectory = Path.Combine(workingDirectory, "output"); + var generationConfiguration = new GenerationConfiguration + { + OutputPath = outputDirectory, + OpenAPIFilePath = simpleDescriptionPath, + PluginTypes = [PluginType.APIPlugin], + ClientClassName = "client", + ApiRootUrl = "http://localhost/", //Kiota builder would set this for us + }; + var (openApiDocumentStream, _) = + await openApiDocumentDs.LoadStreamAsync(simpleDescriptionPath, generationConfiguration, null, false); + var openApiDocument = + await openApiDocumentDs.GetDocumentFromStreamAsync(openApiDocumentStream, generationConfiguration); + Assert.NotNull(openApiDocument); + KiotaBuilder.CleanupOperationIdForPlugins(openApiDocument); + var urlTreeNode = OpenApiUrlTreeNode.Create(openApiDocument, Constants.DefaultOpenApiLabel); + + var pluginsGenerationService = + new PluginsGenerationService(openApiDocument, urlTreeNode, generationConfiguration, workingDirectory, _logger); + await pluginsGenerationService.GenerateManifestAsync(); + + Assert.True(File.Exists(Path.Combine(outputDirectory, ManifestFileName))); + Assert.True(File.Exists(Path.Combine(outputDirectory, OpenApiFileName))); + + // Validate the v2 plugin + var manifestContent = await File.ReadAllTextAsync(Path.Combine(outputDirectory, ManifestFileName)); + using var jsonDocument = JsonDocument.Parse(manifestContent); + var resultingManifest = PluginManifestDocument.Load(jsonDocument.RootElement); + + Assert.NotNull(resultingManifest.Document); + Assert.Empty(resultingManifest.Problems); + Assert.NotEmpty(resultingManifest.Document.Runtimes); + var auth0 = resultingManifest.Document.Runtimes[0].Auth; + Assert.IsType(auth0); + Assert.Equal(AuthType.ApiKeyPluginVault, auth0.Type); + Assert.Equal("{apiKey0_REGISTRATION_ID}", ((ApiKeyPluginVault)auth0!).ReferenceId); + var auth1 = resultingManifest.Document.Runtimes[1].Auth; + Assert.IsType(auth1); + Assert.Equal(AuthType.ApiKeyPluginVault, auth1.Type); + Assert.Equal("{apiKey1_REGISTRATION_ID}", ((ApiKeyPluginVault)auth1!).ReferenceId); + // Cleanup + try + { + Directory.Delete(outputDirectory); + } + catch (Exception) + { + // ignored } + } - #endregion + #endregion - #region Validation + #region Validation - public static TheoryData> - ValidationSchemaTestInput() - { - return new TheoryData> + public static TheoryData> + ValidationSchemaTestInput() + { + return new TheoryData> { // AllOf // simple disjoint @@ -743,13 +743,13 @@ public static TheoryData> } }, }; - } + } - [Theory] - [MemberData(nameof(ValidationSchemaTestInput))] - public async Task MergesAllOfRequestBodyAsync(string content, Action assertions) - { - var apiDescription = $""" + [Theory] + [MemberData(nameof(ValidationSchemaTestInput))] + public async Task MergesAllOfRequestBodyAsync(string content, Action assertions) + { + var apiDescription = $""" openapi: 3.0.0 info: title: test @@ -765,50 +765,50 @@ public async Task MergesAllOfRequestBodyAsync(string content, Action Date: Fri, 7 Feb 2025 15:16:37 -0500 Subject: [PATCH 54/96] fix: additional batch of reference fixes Signed-off-by: Vincent Biret --- .../Kiota.Builder.Tests/KiotaBuilderTests.cs | 211 ++++-------------- 1 file changed, 44 insertions(+), 167 deletions(-) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 916148346d..6c10c19afe 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -19,6 +19,7 @@ using Microsoft.OpenApi.MicrosoftExtensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Moq; @@ -1555,11 +1556,7 @@ public void MultiNestedArraysSupportedAsUntypedNodes() } } }, - }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/bar.foo" - }, + } }; var document = new OpenApiDocument { @@ -1576,7 +1573,7 @@ public void MultiNestedArraysSupportedAsUntypedNodes() Content = { ["application/json"] = new OpenApiMediaType { - Schema = fooSchema + Schema = new OpenApiSchemaReference("bar.foo") } } } @@ -1585,15 +1582,9 @@ public void MultiNestedArraysSupportedAsUntypedNodes() } }, }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "bar.foo", fooSchema - } - } - } }; + document.AddComponent("bar.foo", fooSchema); + document.SetReferenceHostDocument(); var mockLogger = new CountLogger(); var builder = new KiotaBuilder(mockLogger, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -1622,10 +1613,6 @@ public void Object_Arrays_are_supported() } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/microsoft.graph.user" - }, }; var document = new OpenApiDocument { @@ -1648,7 +1635,7 @@ public void Object_Arrays_are_supported() { "value", new OpenApiSchema { Type = JsonSchemaType.Array, - Items = userSchema + Items = new OpenApiSchemaReference("microsoft.graph.user") } }, { @@ -1668,15 +1655,9 @@ public void Object_Arrays_are_supported() } }, }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.user", userSchema - } - } - } }; + document.AddComponent("microsoft.graph.user", userSchema); + document.SetReferenceHostDocument(); var mockLogger = new CountLogger(); var builder = new KiotaBuilder(mockLogger, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -1759,10 +1740,6 @@ public void Supports_Path_Parameters() } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/microsoft.graph.resourceAction" - }, }; var permissionSchema = new OpenApiSchema { @@ -1773,16 +1750,12 @@ public void Supports_Path_Parameters() Type = JsonSchemaType.Array, Items = new OpenApiSchema { AnyOf = new List { - resourceActionSchema, + new OpenApiSchemaReference("microsoft.graph.resourceAction"), } } } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/microsoft.graph.rolePermission" - }, }; var document = new OpenApiDocument { @@ -1814,7 +1787,7 @@ public void Supports_Path_Parameters() Type = JsonSchemaType.Array, Items = new OpenApiSchema { AnyOf = new List { - permissionSchema, + new OpenApiSchemaReference("microsoft.graph.rolePermission"), } } } @@ -1826,14 +1799,10 @@ public void Supports_Path_Parameters() } }, }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { "microsoft.graph.rolePermission", permissionSchema }, - { "microsoft.graph.resourceAction", resourceActionSchema }, - } - } }; + document.AddComponent("microsoft.graph.resourceAction", resourceActionSchema); + document.AddComponent("microsoft.graph.rolePermission", permissionSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -1878,10 +1847,6 @@ public void Supports_Path_Query_And_Header_Parameters() } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/microsoft.graph.resourceAction" - }, }; var permissionSchema = new OpenApiSchema { @@ -1892,16 +1857,12 @@ public void Supports_Path_Query_And_Header_Parameters() Type = JsonSchemaType.Array, Items = new OpenApiSchema { AnyOf = new List { - resourceActionSchema, + new OpenApiSchemaReference("microsoft.graph.resourceAction"), } } } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/microsoft.graph.rolePermission" - }, }; var document = new OpenApiDocument { @@ -1962,7 +1923,7 @@ public void Supports_Path_Query_And_Header_Parameters() Type = JsonSchemaType.Array, Items = new OpenApiSchema { AnyOf = new List { - permissionSchema, + new OpenApiSchemaReference("microsoft.graph.rolePermission"), } } } @@ -1974,14 +1935,10 @@ public void Supports_Path_Query_And_Header_Parameters() } }, }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { "microsoft.graph.rolePermission", permissionSchema }, - { "microsoft.graph.resourceAction", resourceActionSchema }, - } - } }; + document.AddComponent("microsoft.graph.resourceAction", resourceActionSchema); + document.AddComponent("microsoft.graph.rolePermission", permissionSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost", Language = GenerationLanguage.CLI }, _httpClient); var node = builder.CreateUriSpace(document); @@ -2108,10 +2065,6 @@ public void Inline_Property_Inheritance_Is_Supported() } } }, - Reference = new OpenApiReference - { - Id = "resource" - }, }; var document = new OpenApiDocument { @@ -2149,7 +2102,7 @@ public void Inline_Property_Inheritance_Is_Supported() } }, AllOf = [ - resourceSchema, + new OpenApiSchemaReference("resource"), ] } } @@ -2163,15 +2116,9 @@ public void Inline_Property_Inheritance_Is_Supported() } }, }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "#/components/resource", resourceSchema - } - } - } }; + document.AddComponent("resource", resourceSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -2198,16 +2145,12 @@ public void Inline_Property_Inheritance_Is_Supported2() var resourceSchema = new OpenApiSchema { Type = JsonSchemaType.Object, - Reference = new OpenApiReference - { - Id = "resource" - }, }; var properties = new Dictionary { { "info", new OpenApiSchema { Type = JsonSchemaType.String, } }, - { "derivedResource", new OpenApiSchema { AllOf = new List { resourceSchema, } } }, + { "derivedResource", new OpenApiSchema { AllOf = new List { new OpenApiSchemaReference("resource"), } } }, }; resourceSchema.Properties = properties; @@ -2230,7 +2173,7 @@ public void Inline_Property_Inheritance_Is_Supported2() Schema = new OpenApiSchema { AllOf = new List() { - resourceSchema + new OpenApiSchemaReference("resource"), } } } @@ -2241,15 +2184,9 @@ public void Inline_Property_Inheritance_Is_Supported2() } }, }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "#/components/resource", resourceSchema - } - } - } }; + document.AddComponent("resource", resourceSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -2635,11 +2572,6 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.error", - Type = ReferenceType.Schema - }, }; var errorResponse = new OpenApiResponse { @@ -2647,14 +2579,9 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() { ["application/json"] = new OpenApiMediaType { - Schema = errorSchema + Schema = new OpenApiSchemaReference("microsoft.graph.error") } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.error", - Type = ReferenceType.Response - }, }; var document = new OpenApiDocument { @@ -2687,28 +2614,18 @@ public void DoesntAddSuffixesToErrorTypesWhenComponents() } } }, - ["4XX"] = errorResponse, - ["5XX"] = errorResponse, - ["401"] = errorResponse + ["4XX"] = new OpenApiResponseReference("microsoft.graph.error"), + ["5XX"] = new OpenApiResponseReference("microsoft.graph.error"), + ["401"] = new OpenApiResponseReference("microsoft.graph.error") } } } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.error", errorSchema - } - }, - Responses = new Dictionary { - { - "microsoft.graph.error", errorResponse - } - } - }, }; + document.AddComponent("microsoft.graph.error", errorSchema); + document.AddComponent("microsoft.graph.error", errorResponse); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); builder.SetOpenApiDocument(document); @@ -2743,11 +2660,6 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.error", - Type = ReferenceType.Schema - }, }; var errorResponse = new OpenApiResponse { @@ -2755,14 +2667,9 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() { ["application/json"] = new OpenApiMediaType { - Schema = errorSchema + Schema = new OpenApiSchemaReference("microsoft.graph.error") } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.error", - Type = ReferenceType.Response - }, }; var document = new OpenApiDocument { @@ -2795,27 +2702,17 @@ public void UsesDefaultAs4XXAnd5XXWhenAbsent() } } }, - ["default"] = errorResponse, - ["401"] = errorResponse + ["default"] = new OpenApiResponseReference("microsoft.graph.error"), + ["401"] = new OpenApiResponseReference("microsoft.graph.error") } } } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.error", errorSchema - } - }, - Responses = new Dictionary { - { - "microsoft.graph.error", errorResponse - } - } - }, }; + document.AddComponent("microsoft.graph.error", errorSchema); + document.AddComponent("microsoft.graph.error", errorResponse); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); builder.SetOpenApiDocument(document); @@ -2858,26 +2755,16 @@ public void DoesntAddPropertyHolderOnNonAdditionalModels() } } }, - Reference = new OpenApiReference - { - Id = "weatherForecast", - Type = ReferenceType.Schema - }, }; - var forecastResponse = new OpenApiResponse + var weatherForecastResponse = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = weatherForecastSchema + Schema = new OpenApiSchemaReference("weatherForecast") } }, - Reference = new OpenApiReference - { - Id = "weatherForecast", - Type = ReferenceType.Response - }, }; var document = new OpenApiDocument { @@ -2890,26 +2777,16 @@ public void DoesntAddPropertyHolderOnNonAdditionalModels() { Responses = new OpenApiResponses { - ["200"] = forecastResponse + ["200"] = new OpenApiResponseReference("weatherForecast") } } } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "weatherForecast", weatherForecastSchema - } - }, - Responses = new Dictionary { - { - "weatherForecast", forecastResponse - } - } - }, }; + document.AddComponent("weatherForecast", weatherForecastSchema); + document.AddComponent("weatherForecast", weatherForecastResponse); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); builder.SetOpenApiDocument(document); From 457a8106c09aa8dafd57e789b8e7054f32049b78 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 10 Feb 2025 14:21:11 -0500 Subject: [PATCH 55/96] fix: final batch of reference updates --- .../Kiota.Builder.Tests/KiotaBuilderTests.cs | 1010 ++++------------- 1 file changed, 197 insertions(+), 813 deletions(-) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 6c10c19afe..f8eea70ec2 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -2818,11 +2818,6 @@ public void SquishesLonelyNullables() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.uploadSession", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -2843,7 +2838,7 @@ public void SquishesLonelyNullables() Schema = new OpenApiSchema { AnyOf = new List { - uploadSessionSchema + new OpenApiSchemaReference("microsoft.graph.uploadSession") } } } @@ -2854,15 +2849,9 @@ public void SquishesLonelyNullables() } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.uploadSession", uploadSessionSchema - } - }, - }, }; + document.AddComponent("microsoft.graph.uploadSession", uploadSessionSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); builder.SetOpenApiDocument(document); @@ -2900,11 +2889,6 @@ public void SquishesLonelyNullablesBothAnyOf() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.uploadSession", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -2925,7 +2909,7 @@ public void SquishesLonelyNullablesBothAnyOf() Schema = new OpenApiSchema { AnyOf = new List { - uploadSessionSchema, + new OpenApiSchemaReference("microsoft.graph.uploadSession"), new OpenApiSchema { } } @@ -2938,15 +2922,9 @@ public void SquishesLonelyNullablesBothAnyOf() } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.uploadSession", uploadSessionSchema - } - }, - }, }; + document.AddComponent("microsoft.graph.uploadSession", uploadSessionSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); builder.SetOpenApiDocument(document); @@ -2987,11 +2965,6 @@ public void SupportsArraysInComposedTypes() } } }, - Reference = new OpenApiReference - { - Id = "anyOfNullable", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -3009,7 +2982,7 @@ public void SupportsArraysInComposedTypes() Content = new Dictionary { ["application/json"] = new OpenApiMediaType { - Schema = anyOfSchema + Schema = new OpenApiSchemaReference("anyOfNullable") } } } @@ -3018,15 +2991,9 @@ public void SupportsArraysInComposedTypes() } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "anyOfNullable", anyOfSchema - } - }, - }, }; + document.AddComponent("anyOfNullable", anyOfSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); builder.SetOpenApiDocument(document); @@ -3067,11 +3034,6 @@ public void SupportsNullableAnyOf() } } }, - Reference = new OpenApiReference - { - Id = "anyOfNullable", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -3089,7 +3051,7 @@ public void SupportsNullableAnyOf() Content = new Dictionary { ["application/json"] = new OpenApiMediaType { - Schema = anyOfSchema + Schema = new OpenApiSchemaReference("anyOfNullable") } } } @@ -3098,15 +3060,9 @@ public void SupportsNullableAnyOf() } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "anyOfNullable", anyOfSchema - } - }, - }, }; + document.AddComponent("anyOfNullable", anyOfSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); builder.SetOpenApiDocument(document); @@ -3157,11 +3113,6 @@ public void AddsDiscriminatorMappings() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.entity", - Type = ReferenceType.Schema - }, }; var directoryObjectSchema = new OpenApiSchema { @@ -3178,13 +3129,8 @@ public void AddsDiscriminatorMappings() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObject", - Type = ReferenceType.Schema - }, AllOf = new List { - entitySchema + new OpenApiSchemaReference("microsoft.graph.entity") }, }; var directoryObjects = new OpenApiResponse @@ -3193,14 +3139,9 @@ public void AddsDiscriminatorMappings() { ["application/json"] = new OpenApiMediaType { - Schema = entitySchema + Schema = new OpenApiSchemaReference("microsoft.graph.entity") } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObjects", - Type = ReferenceType.Response - }, }; var document = new OpenApiDocument { @@ -3213,29 +3154,17 @@ public void AddsDiscriminatorMappings() { Responses = new OpenApiResponses { - ["200"] = directoryObjects, + ["200"] = new OpenApiResponseReference("microsoft.graph.directoryObjects"), } } } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.entity", entitySchema - }, - { - "microsoft.graph.directoryObject", directoryObjectSchema - } - }, - Responses = new Dictionary { - { - "microsoft.graph.directoryObjects", directoryObjects - } - } - }, }; + document.AddComponent("microsoft.graph.entity", entitySchema); + document.AddComponent("microsoft.graph.directoryObject", directoryObjectSchema); + document.AddComponent("microsoft.graph.directoryObjects", directoryObjects); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -3292,11 +3221,6 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.entity", - Type = ReferenceType.Schema - }, }; var directoryObjectSchema = new OpenApiSchema { @@ -3313,13 +3237,8 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObject", - Type = ReferenceType.Schema - }, AllOf = new List { - entitySchema + new OpenApiSchemaReference("microsoft.graph.entity") }, }; var fileSchema = new OpenApiSchema @@ -3337,11 +3256,6 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.file", - Type = ReferenceType.Schema - }, }; var directoryObjects = new OpenApiResponse() { @@ -3349,14 +3263,9 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() { ["application/json"] = new OpenApiMediaType() { - Schema = entitySchema + Schema = new OpenApiSchemaReference("microsoft.graph.entity") } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObjects", - Type = ReferenceType.Response - }, }; var document = new OpenApiDocument() { @@ -3368,32 +3277,18 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() [OperationType.Get] = new OpenApiOperation() { Responses = new OpenApiResponses { - ["200"] = directoryObjects, + ["200"] = new OpenApiResponseReference("microsoft.graph.directoryObjects"), } } } } }, - Components = new OpenApiComponents() - { - Schemas = new Dictionary { - { - "microsoft.graph.entity", entitySchema - }, - { - "microsoft.graph.directoryObject", directoryObjectSchema - }, - { - "microsoft.graph.file", fileSchema - } - }, - Responses = new Dictionary { - { - "microsoft.graph.directoryObjects", directoryObjects - } - } - }, }; + document.AddComponent("microsoft.graph.entity", entitySchema); + document.AddComponent("microsoft.graph.directoryObject", directoryObjectSchema); + document.AddComponent("microsoft.graph.file", fileSchema); + document.AddComponent("microsoft.graph.directoryObjects", directoryObjects); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration() { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -3432,11 +3327,6 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() { PropertyName = "@odata.type", }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.entity", - Type = ReferenceType.Schema - }, }; var directoryObjectSchema = new OpenApiSchema { @@ -3456,23 +3346,13 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() Required = new HashSet { "@odata.type" }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObject", - Type = ReferenceType.Schema - }, }; var directoryObjectsResponse = new OpenApiSchema { Type = JsonSchemaType.Object, OneOf = new List { - entitySchema, - directoryObjectSchema - }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObjects", - Type = ReferenceType.Schema + new OpenApiSchemaReference("microsoft.graph.entity"), + new OpenApiSchemaReference("microsoft.graph.directoryObject") }, }; var directoryObjects = new OpenApiResponse @@ -3481,14 +3361,9 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() { ["application/json"] = new OpenApiMediaType { - Schema = directoryObjectsResponse + Schema = new OpenApiSchemaReference("microsoft.graph.directoryObject") } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObjects", - Type = ReferenceType.Response - }, }; var document = new OpenApiDocument { @@ -3501,32 +3376,18 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() { Responses = new OpenApiResponses { - ["200"] = directoryObjects, + ["200"] = new OpenApiResponseReference("microsoft.graph.directoryObjects"), } } } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.entity", entitySchema - }, - { - "microsoft.graph.directoryObject", directoryObjectSchema - }, - { - "microsoft.graph.directoryObjects", directoryObjectsResponse - } - }, - Responses = new Dictionary { - { - "microsoft.graph.directoryObjects", directoryObjects - } - } - }, }; + document.AddComponent("microsoft.graph.entity", entitySchema); + document.AddComponent("microsoft.graph.directoryObject", directoryObjectSchema); + document.AddComponent("microsoft.graph.directoryObjects", directoryObjectsResponse); + document.AddComponent("microsoft.graph.directoryObjects", directoryObjects); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var config = new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }; var builder = new KiotaBuilder(mockLogger.Object, config, _httpClient); @@ -3571,17 +3432,12 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() { PropertyName = "@odata.type", }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.entity", - Type = ReferenceType.Schema - }, }; var directoryObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, AllOf = new List { - entitySchema, + new OpenApiSchemaReference("microsoft.graph.entity"), new OpenApiSchema { Properties = new Dictionary { { @@ -3600,17 +3456,12 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObject", - Type = ReferenceType.Schema - }, }; var userSchema = new OpenApiSchema { Type = JsonSchemaType.Object, AllOf = new List { - directoryObjectSchema, + new OpenApiSchemaReference("microsoft.graph.directoryObject"), new OpenApiSchema { Properties = new Dictionary { { @@ -3629,11 +3480,6 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.user", - Type = ReferenceType.Schema - }, }; var directoryObjects = new OpenApiResponse { @@ -3641,14 +3487,9 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() { ["application/json"] = new OpenApiMediaType { - Schema = directoryObjectSchema + Schema = new OpenApiSchemaReference("microsoft.graph.directoryObject") } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObjects", - Type = ReferenceType.Response - }, }; var document = new OpenApiDocument { @@ -3661,32 +3502,18 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() { Responses = new OpenApiResponses { - ["200"] = directoryObjects, + ["200"] = new OpenApiResponseReference("microsoft.graph.directoryObjects"), } } } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.entity", entitySchema - }, - { - "microsoft.graph.directoryObject", directoryObjectSchema - }, - { - "microsoft.graph.user", userSchema - } - }, - Responses = new Dictionary { - { - "microsoft.graph.directoryObjects", directoryObjects - } - } - }, }; + document.AddComponent("microsoft.graph.entity", entitySchema); + document.AddComponent("microsoft.graph.directoryObject", directoryObjectSchema); + document.AddComponent("microsoft.graph.user", userSchema); + document.AddComponent("microsoft.graph.directoryObjects", directoryObjects); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var config = new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }; var builder = new KiotaBuilder(mockLogger.Object, config, _httpClient); @@ -3754,17 +3581,12 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings } } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.entity", - Type = ReferenceType.Schema - }, }; var directoryObjectSchema = new OpenApiSchema { Type = JsonSchemaType.Object, AllOf = [ - entitySchema, + new OpenApiSchemaReference("microsoft.graph.entity"), new OpenApiSchema { Properties = new Dictionary { @@ -3784,17 +3606,12 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings } } ], - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObject", - Type = ReferenceType.Schema - }, }; var userSchema = new OpenApiSchema { Type = JsonSchemaType.Object, AllOf = [ - directoryObjectSchema, + new OpenApiSchemaReference("microsoft.graph.directoryObject"), new OpenApiSchema { Properties = new Dictionary { @@ -3814,11 +3631,6 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings } } ], - Reference = new OpenApiReference - { - Id = "microsoft.graph.user", - Type = ReferenceType.Schema - }, }; var directoryObjects = new OpenApiResponse { @@ -3826,14 +3638,9 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings { ["application/json"] = new OpenApiMediaType { - Schema = directoryObjectSchema + Schema = new OpenApiSchemaReference("microsoft.graph.directoryObject") } }, - Reference = new OpenApiReference - { - Id = "microsoft.graph.directoryObjects", - Type = ReferenceType.Response - }, }; var document = new OpenApiDocument { @@ -3846,32 +3653,18 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitWithParentHavingMappings { Responses = new OpenApiResponses { - ["200"] = directoryObjects, + ["200"] = new OpenApiResponseReference("microsoft.graph.directoryObjects"), } } } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.entity", entitySchema - }, - { - "microsoft.graph.directoryObject", directoryObjectSchema - }, - { - "microsoft.graph.user", userSchema - } - }, - Responses = new Dictionary { - { - "microsoft.graph.directoryObjects", directoryObjects - } - } - }, }; + document.AddComponent("microsoft.graph.entity", entitySchema); + document.AddComponent("microsoft.graph.directoryObject", directoryObjectSchema); + document.AddComponent("microsoft.graph.user", userSchema); + document.AddComponent("microsoft.graph.directoryObjects", directoryObjects); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var config = new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }; var builder = new KiotaBuilder(mockLogger.Object, config, _httpClient); @@ -3909,11 +3702,6 @@ public void UnionOfPrimitiveTypesWorks() } } }, - Reference = new OpenApiReference - { - Id = "subNS.simpleObject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -3931,7 +3719,7 @@ public void UnionOfPrimitiveTypesWorks() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { OneOf = new List { - simpleObjet, + new OpenApiSchemaReference("subNS.simpleObject"), new OpenApiSchema { Type = JsonSchemaType.Number } @@ -3945,15 +3733,9 @@ public void UnionOfPrimitiveTypesWorks() } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "subNS.simpleObject", simpleObjet - } - } - }, }; + document.AddComponent("subNS.simpleObject", simpleObjet); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -4026,11 +3808,6 @@ public void UnionOfInlineSchemasWorks() } } }, - Reference = new OpenApiReference - { - Id = "subNS.simpleObject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -4048,7 +3825,7 @@ public void UnionOfInlineSchemasWorks() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { OneOf = new List { - simpleObjet, + new OpenApiSchemaReference("subNS.simpleObject"), new OpenApiSchema { Type = JsonSchemaType.Object, Properties = new Dictionary { @@ -4069,15 +3846,9 @@ public void UnionOfInlineSchemasWorks() } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "subNS.simpleObject", simpleObjet - } - } - }, }; + document.AddComponent("subNS.simpleObject", simpleObjet); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -4108,11 +3879,6 @@ public void IntersectionOfPrimitiveTypesWorks() } } }, - Reference = new OpenApiReference - { - Id = "subNS.simpleObject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -4130,7 +3896,7 @@ public void IntersectionOfPrimitiveTypesWorks() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { AnyOf = new List { - simpleObjet, + new OpenApiSchemaReference("subNS.simpleObject"), new OpenApiSchema { Type = JsonSchemaType.Number } @@ -4144,15 +3910,9 @@ public void IntersectionOfPrimitiveTypesWorks() } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "subNS.simpleObject", simpleObjet - } - } - }, }; + document.AddComponent("subNS.simpleObject", simpleObjet); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -4183,11 +3943,6 @@ public void IntersectionOfInlineSchemasWorks() } } }, - Reference = new OpenApiReference - { - Id = "subNS.simpleObject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -4205,7 +3960,7 @@ public void IntersectionOfInlineSchemasWorks() ["application/json"] = new OpenApiMediaType { Schema = new OpenApiSchema { AnyOf = new List { - simpleObjet, + new OpenApiSchemaReference("subNS.simpleObject"), new OpenApiSchema { Type = JsonSchemaType.Object, Properties = new Dictionary { @@ -4226,15 +3981,9 @@ public void IntersectionOfInlineSchemasWorks() } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "subNS.simpleObject", simpleObjet - } - } - }, }; + document.AddComponent("subNS.simpleObject", simpleObjet); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -4279,17 +4028,12 @@ public void InheritedTypeWithInlineSchemaWorks() } } }, - Reference = new OpenApiReference - { - Id = "subNS.baseObject", - Type = ReferenceType.Schema - }, }; var derivedObject = new OpenApiSchema { Type = JsonSchemaType.Object, AllOf = [ - baseObject, + new OpenApiSchemaReference("subNS.baseObject"), new OpenApiSchema { Type = JsonSchemaType.Object, @@ -4311,17 +4055,12 @@ public void InheritedTypeWithInlineSchemaWorks() }, } ], - Reference = new OpenApiReference - { - Id = "subNS.derivedObject", - Type = ReferenceType.Schema - }, }; var secondLevelDerivedObject = new OpenApiSchema { Type = JsonSchemaType.Object, AllOf = [ - derivedObject, + new OpenApiSchemaReference("subNS.derivedObject"), new OpenApiSchema { Type = JsonSchemaType.Object, @@ -4334,11 +4073,6 @@ public void InheritedTypeWithInlineSchemaWorks() } } ], - Reference = new OpenApiReference - { - Id = "subNS.secondLevelDerivedObject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -4354,7 +4088,7 @@ public void InheritedTypeWithInlineSchemaWorks() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = derivedObject + Schema = new OpenApiSchemaReference("subNS.derivedObject") } } }, @@ -4363,21 +4097,11 @@ public void InheritedTypeWithInlineSchemaWorks() } } }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "subNS.baseObject", baseObject - }, - { - "subNS.derivedObject", derivedObject - }, - { - "subNS.secondLevelDerivedObject", secondLevelDerivedObject - } - } - }, }; + document.AddComponent("subNS.baseObject", baseObject); + document.AddComponent("subNS.derivedObject", derivedObject); + document.AddComponent("subNS.secondLevelDerivedObject", secondLevelDerivedObject); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -4807,11 +4531,6 @@ public void DoesntGenerateNamespacesWhenNotRequired() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -4827,7 +4546,7 @@ public void DoesntGenerateNamespacesWhenNotRequired() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -4836,15 +4555,9 @@ public void DoesntGenerateNamespacesWhenNotRequired() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -4869,11 +4582,6 @@ public void GeneratesNamesapacesWhenRequired() } } }, - Reference = new OpenApiReference - { - Id = "subns.myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -4889,7 +4597,7 @@ public void GeneratesNamesapacesWhenRequired() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("subns.myobject") } } }, @@ -4898,15 +4606,9 @@ public void GeneratesNamesapacesWhenRequired() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "subns.myobject", myObjectSchema - } - } - } }; + document.AddComponent("subns.myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -4931,11 +4633,6 @@ public void IdsResultInIndexers() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -4951,7 +4648,7 @@ public void IdsResultInIndexers() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -4960,15 +4657,9 @@ public void IdsResultInIndexers() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -5012,7 +4703,7 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() { AnyOf = new List { - enumSchema, + new OpenApiSchemaReference("riskLevel"), new OpenApiSchema { Type = JsonSchemaType.Object, @@ -5022,11 +4713,6 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument @@ -5043,7 +4729,7 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5051,20 +4737,11 @@ public void HandlesCollectionOfEnumSchemasInAnyOfWithNullable() } } } - }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - }, - { - "riskLevel", enumSchema - } - }, - } }; + document.AddComponent("myobject", myObjectSchema); + document.AddComponent("riskLevel", enumSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -5106,15 +4783,10 @@ public void HandlesCollectionOfEnumSchemas() { "signInRiskLevels", new OpenApiSchema { Type = JsonSchemaType.Array, - Items = enumSchema + Items = new OpenApiSchemaReference("riskLevel") } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument @@ -5131,7 +4803,7 @@ public void HandlesCollectionOfEnumSchemas() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5140,19 +4812,10 @@ public void HandlesCollectionOfEnumSchemas() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - }, - { - "riskLevel", enumSchema - } - }, - - } }; + document.AddComponent("myobject", myObjectSchema); + document.AddComponent("riskLevel", enumSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -5185,11 +4848,6 @@ public void InlinePropertiesGenerateTypes() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -5205,7 +4863,7 @@ public void InlinePropertiesGenerateTypes() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5213,16 +4871,10 @@ public void InlinePropertiesGenerateTypes() } } } - }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -5248,11 +4900,6 @@ public void ModelsDoesntUsePathDescriptionWhenAvailable() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -5272,7 +4919,7 @@ public void ModelsDoesntUsePathDescriptionWhenAvailable() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5280,16 +4927,10 @@ public void ModelsDoesntUsePathDescriptionWhenAvailable() } } } - }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -5313,11 +4954,6 @@ public void CleansUpInvalidDescriptionCharacters() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, Description = @" some description with invalid characters: ", }; @@ -5335,7 +4971,7 @@ public void CleansUpInvalidDescriptionCharacters() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5344,15 +4980,9 @@ public void CleansUpInvalidDescriptionCharacters() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -5380,11 +5010,6 @@ public void AcceptVendorsTypes(string contentType) } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -5400,7 +5025,7 @@ public void AcceptVendorsTypes(string contentType) ["200"] = new OpenApiResponse { Content = { [contentType] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5409,15 +5034,9 @@ public void AcceptVendorsTypes(string contentType) } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -5519,11 +5138,6 @@ public void Considers200WithSchemaOver2XXWithSchema() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var myOtherObjectSchema = new OpenApiSchema { @@ -5535,11 +5149,6 @@ public void Considers200WithSchemaOver2XXWithSchema() } } }, - Reference = new OpenApiReference - { - Id = "myotherobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -5555,14 +5164,14 @@ public void Considers200WithSchemaOver2XXWithSchema() ["2XX"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myOtherObjectSchema + Schema = new OpenApiSchemaReference("myotherobject") } } }, ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5571,14 +5180,10 @@ public void Considers200WithSchemaOver2XXWithSchema() } } }, - Components = new() - { - Schemas = new Dictionary { - { "myobject", myObjectSchema }, - { "myotherobject", myOtherObjectSchema }, - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.AddComponent("myotherobject", myOtherObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder( mockLogger.Object, @@ -5612,11 +5217,6 @@ public void Considers2XXWithSchemaOver204WithNoSchema() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -5632,7 +5232,7 @@ public void Considers2XXWithSchemaOver204WithNoSchema() ["2XX"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5642,15 +5242,9 @@ public void Considers2XXWithSchemaOver204WithNoSchema() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder( mockLogger.Object, @@ -5674,22 +5268,6 @@ public void Considers2XXWithSchemaOver204WithNoSchema() [Fact] public void Considers204WithNoSchemaOver206WithNoSchema() { - var myObjectSchema = new OpenApiSchema - { - Type = JsonSchemaType.Object, - Properties = new Dictionary { - { - "id", new OpenApiSchema { - Type = JsonSchemaType.String, - } - } - }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, - }; var document = new OpenApiDocument { Paths = new OpenApiPaths @@ -5708,14 +5286,6 @@ public void Considers204WithNoSchemaOver206WithNoSchema() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; var mockLogger = new Mock>(); var builder = new KiotaBuilder( @@ -5756,11 +5326,6 @@ public void DoesntGenerateVoidExecutorOnMixedNoContent(int statusCode) } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -5776,7 +5341,7 @@ public void DoesntGenerateVoidExecutorOnMixedNoContent(int statusCode) ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5786,15 +5351,9 @@ public void DoesntGenerateVoidExecutorOnMixedNoContent(int statusCode) } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -5827,11 +5386,6 @@ public void GeneratesVoidReturnTypeForNoContent(int statusCode) } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -5847,7 +5401,7 @@ public void GeneratesVoidReturnTypeForNoContent(int statusCode) [statusCode.ToString()] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5856,15 +5410,9 @@ public void GeneratesVoidReturnTypeForNoContent(int statusCode) } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -5884,11 +5432,7 @@ public void GeneratesVoidReturnTypeForNoContent(int statusCode) [Theory] public void StripsCommonModelsPrefix(string[] componentNames, string stripPrefix) { - var paths = new OpenApiPaths(); - var components = new OpenApiComponents - { - Schemas = new Dictionary() - }; + var document = new OpenApiDocument(); foreach (var componentName in componentNames) { var myObjectSchema = new OpenApiSchema @@ -5901,13 +5445,8 @@ public void StripsCommonModelsPrefix(string[] componentNames, string stripPrefix } } }, - Reference = new OpenApiReference - { - Id = componentName, - Type = ReferenceType.Schema - }, }; - paths.Add($"answer{componentName}", new OpenApiPathItem + document.Paths.Add($"answer{componentName}", new OpenApiPathItem { Operations = { [OperationType.Get] = new OpenApiOperation @@ -5917,7 +5456,7 @@ public void StripsCommonModelsPrefix(string[] componentNames, string stripPrefix ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference(componentName) } } }, @@ -5925,13 +5464,10 @@ public void StripsCommonModelsPrefix(string[] componentNames, string stripPrefix } } }); - components.Schemas.Add(componentName, myObjectSchema); + document.AddComponent(componentName, myObjectSchema); } - var document = new OpenApiDocument - { - Paths = paths, - Components = components, - }; + document.SetReferenceHostDocument(); + var result = KiotaBuilder.GetDeeperMostCommonNamespaceNameForModels(document); Assert.Equal(stripPrefix, result); } @@ -5948,11 +5484,6 @@ public void HandlesContentParameters() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -5987,7 +5518,7 @@ public void HandlesContentParameters() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -5996,15 +5527,9 @@ public void HandlesContentParameters() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -6034,11 +5559,6 @@ public void HandlesPagingExtension() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -6057,7 +5577,7 @@ public void HandlesPagingExtension() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6066,15 +5586,9 @@ public void HandlesPagingExtension() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -6103,11 +5617,6 @@ public void SetsReadonlyProperties(bool isReadonly) } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -6123,7 +5632,7 @@ public void SetsReadonlyProperties(bool isReadonly) ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6131,16 +5640,10 @@ public void SetsReadonlyProperties(bool isReadonly) } } } - }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "TestClient", ClientNamespaceName = "TestSdk", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -6165,11 +5668,6 @@ public void SupportsIncludeFilterOnRootPath(string inputPattern, int expectedPat } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -6185,7 +5683,7 @@ public void SupportsIncludeFilterOnRootPath(string inputPattern, int expectedPat ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6194,15 +5692,9 @@ public void SupportsIncludeFilterOnRootPath(string inputPattern, int expectedPat } }, }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { @@ -6229,11 +5721,6 @@ public void SupportsIncludeFilter() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -6249,7 +5736,7 @@ public void SupportsIncludeFilter() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6267,7 +5754,7 @@ public void SupportsIncludeFilter() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6275,16 +5762,10 @@ public void SupportsIncludeFilter() } } }, - }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { @@ -6313,11 +5794,6 @@ public void SupportsExcludeFilter() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -6333,7 +5809,7 @@ public void SupportsExcludeFilter() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6351,7 +5827,7 @@ public void SupportsExcludeFilter() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6359,16 +5835,10 @@ public void SupportsExcludeFilter() } } }, - }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { @@ -6397,11 +5867,6 @@ public void SupportsIncludeFilterWithOperation() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -6417,7 +5882,7 @@ public void SupportsIncludeFilterWithOperation() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6428,7 +5893,7 @@ public void SupportsIncludeFilterWithOperation() RequestBody = new OpenApiRequestBody { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6437,7 +5902,7 @@ public void SupportsIncludeFilterWithOperation() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6448,7 +5913,7 @@ public void SupportsIncludeFilterWithOperation() RequestBody = new OpenApiRequestBody { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6457,7 +5922,7 @@ public void SupportsIncludeFilterWithOperation() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6475,7 +5940,7 @@ public void SupportsIncludeFilterWithOperation() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6493,7 +5958,7 @@ public void SupportsIncludeFilterWithOperation() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6501,16 +5966,10 @@ public void SupportsIncludeFilterWithOperation() } } }, - }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { @@ -6551,11 +6010,6 @@ public void SupportsIndexingParametersInSubPaths() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -6581,7 +6035,7 @@ public void SupportsIndexingParametersInSubPaths() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -6589,16 +6043,10 @@ public void SupportsIndexingParametersInSubPaths() } } }, - }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { @@ -6868,11 +6316,11 @@ public async Task IndexerTypeIsAccurateAndBackwardCompatibleIndexersAreAddedAsyn Assert.Equal("The id of the author's posts to retrieve", authorsCollectionIndexer.IndexParameter.Documentation.DescriptionTemplate, StringComparer.OrdinalIgnoreCase); Assert.False(authorsCollectionIndexer.IndexParameter.Type.IsNullable); Assert.False(authorsCollectionIndexer.Deprecation.IsDeprecated); - var authorsCllectionStringIndexer = authorsCollectionRequestBuilder.FindChildByName($"{authorsCollectionIndexer.Name}-string"); - Assert.NotNull(authorsCllectionStringIndexer); - Assert.Equal("string", authorsCllectionStringIndexer.IndexParameter.Type.Name); - Assert.True(authorsCllectionStringIndexer.IndexParameter.Type.IsNullable); - Assert.True(authorsCllectionStringIndexer.Deprecation.IsDeprecated); + var authorsCollectionStringIndexer = authorsCollectionRequestBuilder.FindChildByName($"{authorsCollectionIndexer.Name}-string"); + Assert.NotNull(authorsCollectionStringIndexer); + Assert.Equal("string", authorsCollectionStringIndexer.IndexParameter.Type.Name); + Assert.True(authorsCollectionStringIndexer.IndexParameter.Type.IsNullable); + Assert.True(authorsCollectionStringIndexer.Deprecation.IsDeprecated); var authorsItemRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.authors.item"); Assert.NotNull(authorsItemRequestBuilderNamespace); var authorsItemRequestBuilder = authorsItemRequestBuilderNamespace.FindChildByName("authorItemRequestBuilder"); @@ -6887,11 +6335,11 @@ public async Task IndexerTypeIsAccurateAndBackwardCompatibleIndexersAreAddedAsyn Assert.Equal("The id of the actor", actorsCollectionIndexer.IndexParameter.Documentation.DescriptionTemplate, StringComparer.OrdinalIgnoreCase); Assert.False(actorsCollectionIndexer.IndexParameter.Type.IsNullable); Assert.False(actorsCollectionIndexer.Deprecation.IsDeprecated); - var actorsCllectionStringIndexer = actorsCollectionRequestBuilder.FindChildByName($"{actorsCollectionIndexer.Name}-string"); - Assert.NotNull(actorsCllectionStringIndexer); - Assert.Equal("string", actorsCllectionStringIndexer.IndexParameter.Type.Name); - Assert.True(actorsCllectionStringIndexer.IndexParameter.Type.IsNullable); - Assert.True(actorsCllectionStringIndexer.Deprecation.IsDeprecated); + var actorsCollectionStringIndexer = actorsCollectionRequestBuilder.FindChildByName($"{actorsCollectionIndexer.Name}-string"); + Assert.NotNull(actorsCollectionStringIndexer); + Assert.Equal("string", actorsCollectionStringIndexer.IndexParameter.Type.Name); + Assert.True(actorsCollectionStringIndexer.IndexParameter.Type.IsNullable); + Assert.True(actorsCollectionStringIndexer.Deprecation.IsDeprecated); var actorsItemRequestBuilderNamespace = codeModel.FindNamespaceByName("ApiSdk.actors.item"); Assert.NotNull(actorsItemRequestBuilderNamespace); var actorsItemRequestBuilder = actorsItemRequestBuilderNamespace.FindChildByName("actorItemRequestBuilder"); @@ -7026,10 +6474,6 @@ public void AddReservedPathParameterSymbol() } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/microsoft.graph.user" - }, }; var document = new OpenApiDocument { @@ -7061,7 +6505,7 @@ public void AddReservedPathParameterSymbol() Content = { ["application/json"] = new OpenApiMediaType { - Schema = userSchema + Schema = new OpenApiSchemaReference("microsoft.graph.user") } } } @@ -7070,15 +6514,9 @@ public void AddReservedPathParameterSymbol() } }, }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.user", userSchema - } - } - } }; + document.AddComponent("microsoft.graph.user", userSchema); + document.SetReferenceHostDocument(); var mockLogger = new CountLogger(); var builder = new KiotaBuilder(mockLogger, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -7107,10 +6545,6 @@ public void DoesNotAddReservedPathParameterSymbol() } } }, - Reference = new OpenApiReference - { - Id = "#/components/schemas/microsoft.graph.user" - }, }; var document = new OpenApiDocument { @@ -7142,7 +6576,7 @@ public void DoesNotAddReservedPathParameterSymbol() Content = { ["application/json"] = new OpenApiMediaType { - Schema = userSchema + Schema = new OpenApiSchemaReference("microsoft.graph.user") } } } @@ -7151,15 +6585,9 @@ public void DoesNotAddReservedPathParameterSymbol() } }, }, - Components = new OpenApiComponents - { - Schemas = new Dictionary { - { - "microsoft.graph.user", userSchema - } - } - } }; + document.AddComponent("microsoft.graph.user", userSchema); + document.SetReferenceHostDocument(); var mockLogger = new CountLogger(); var builder = new KiotaBuilder(mockLogger, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); var node = builder.CreateUriSpace(document); @@ -9760,11 +9188,6 @@ public void SupportsIncludeFilterAndExcludeWithOperation() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -9780,7 +9203,7 @@ public void SupportsIncludeFilterAndExcludeWithOperation() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9791,7 +9214,7 @@ public void SupportsIncludeFilterAndExcludeWithOperation() RequestBody = new OpenApiRequestBody { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9800,7 +9223,7 @@ public void SupportsIncludeFilterAndExcludeWithOperation() ["201"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9818,7 +9241,7 @@ public void SupportsIncludeFilterAndExcludeWithOperation() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9829,7 +9252,7 @@ public void SupportsIncludeFilterAndExcludeWithOperation() RequestBody = new OpenApiRequestBody { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9848,15 +9271,9 @@ public void SupportsIncludeFilterAndExcludeWithOperation() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { @@ -9904,11 +9321,6 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -9924,7 +9336,7 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9935,7 +9347,7 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() RequestBody = new OpenApiRequestBody { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9944,7 +9356,7 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() ["201"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9962,7 +9374,7 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9973,7 +9385,7 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() RequestBody = new OpenApiRequestBody { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -9992,15 +9404,9 @@ public void SupportsIncludeFilterAndExcludeWithOperationForSpecificPath() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); var mockLogger = new Mock>(); var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { @@ -10048,11 +9454,6 @@ public void CleansUpOperationIdAddsMissingOperationId() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -10068,7 +9469,7 @@ public void CleansUpOperationIdAddsMissingOperationId() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -10079,7 +9480,7 @@ public void CleansUpOperationIdAddsMissingOperationId() RequestBody = new OpenApiRequestBody { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -10088,7 +9489,7 @@ public void CleansUpOperationIdAddsMissingOperationId() ["201"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -10097,15 +9498,9 @@ public void CleansUpOperationIdAddsMissingOperationId() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); KiotaBuilder.CleanupOperationIdForPlugins(document); var operations = document.Paths.SelectMany(path => path.Value.Operations).ToList(); foreach (var path in operations) @@ -10149,11 +9544,6 @@ public void CleansUpOperationIdChangesOperationId() } } }, - Reference = new OpenApiReference - { - Id = "myobject", - Type = ReferenceType.Schema - }, }; var document = new OpenApiDocument { @@ -10169,7 +9559,7 @@ public void CleansUpOperationIdChangesOperationId() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -10181,7 +9571,7 @@ public void CleansUpOperationIdChangesOperationId() RequestBody = new OpenApiRequestBody { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -10190,7 +9580,7 @@ public void CleansUpOperationIdChangesOperationId() ["201"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -10209,7 +9599,7 @@ public void CleansUpOperationIdChangesOperationId() ["200"] = new OpenApiResponse { Content = { ["application/json"] = new OpenApiMediaType { - Schema = myObjectSchema + Schema = new OpenApiSchemaReference("myobject") } } }, @@ -10219,15 +9609,9 @@ public void CleansUpOperationIdChangesOperationId() } } }, - Components = new() - { - Schemas = new Dictionary { - { - "myobject", myObjectSchema - } - } - } }; + document.AddComponent("myobject", myObjectSchema); + document.SetReferenceHostDocument(); KiotaBuilder.CleanupOperationIdForPlugins(document); var operations = document.Paths.SelectMany(path => path.Value.Operations).ToList(); foreach (var path in operations) From baa762c17b6e4a8990a47d400452327b698b69a4 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 10 Feb 2025 15:10:54 -0500 Subject: [PATCH 56/96] fix: reference request body generation Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index fd4a812be4..21b531e032 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1564,7 +1564,7 @@ private static bool IsSupportedMultipartDefault(IOpenApiSchema openApiSchema, private void AddRequestBuilderMethodParameters(OpenApiUrlTreeNode currentNode, OperationType operationType, OpenApiOperation operation, CodeClass requestConfigClass, CodeMethod method) { if (operation.RequestBody is not null && - operation.GetRequestSchema(config.StructuredMimeTypes) is OpenApiSchema requestBodySchema) + operation.GetRequestSchema(config.StructuredMimeTypes) is IOpenApiSchema requestBodySchema) { CodeTypeBase requestBodyType; if (operation.RequestBody.Content.IsMultipartFormDataSchema(config.StructuredMimeTypes) From 356b40f864951e855b1e20a6fc0e1ce46eb23607 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 10 Feb 2025 15:19:27 -0500 Subject: [PATCH 57/96] fix: schema type for deprecation information Signed-off-by: Vincent Biret --- .../Extensions/OpenApiDeprecationExtensionExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs index b4fbd3f267..9d07a926ae 100644 --- a/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs @@ -36,14 +36,14 @@ internal static DeprecationInformation GetDeprecationInformation(this OpenApiOpe else if (operation.Responses?.Values .SelectMany(static x => x.Content.Values) .Select(static x => x?.Schema) - .OfType() + .OfType() .Where(static x => !x.IsReferencedSchema()) .Select(static x => x.GetDeprecationInformation()) .FirstOrDefault(static x => x.IsDeprecated) is DeprecationInformation responseDeprecationInformation) return responseDeprecationInformation; else if (operation.RequestBody?.Content.Values .Select(static x => x?.Schema) - .OfType() + .OfType() .Where(static x => !x.IsReferencedSchema()) .Select(static x => x.GetDeprecationInformation()) .FirstOrDefault(static x => x.IsDeprecated) is DeprecationInformation requestDeprecationInformation) From 7bf177eaf139bb0d54194afa912b48ab33b9b49f Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 10 Feb 2025 15:19:46 -0500 Subject: [PATCH 58/96] fix: schema type for multipart detection Signed-off-by: Vincent Biret --- src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs index 194683e0cd..ec8dd8fa8c 100644 --- a/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs @@ -46,7 +46,7 @@ internal static IEnumerable GetResponseSchemas(this OpenApiOpera private static readonly StructuredMimeTypesCollection multipartMimeTypes = new(["multipart/form-data"]); internal static bool IsMultipartFormDataSchema(this IDictionary source, StructuredMimeTypesCollection structuredMimeTypes) { - return source.GetValidSchemas(structuredMimeTypes).FirstOrDefault() is OpenApiSchema schema && + return source.GetValidSchemas(structuredMimeTypes).FirstOrDefault() is IOpenApiSchema schema && source.GetValidSchemas(multipartMimeTypes).FirstOrDefault() == schema; } internal static bool IsMultipartTopMimeType(this IDictionary source, StructuredMimeTypesCollection structuredMimeTypes) From e550ce6d8356da1dce710527ace36b65a98ac297 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 10 Feb 2025 15:20:15 -0500 Subject: [PATCH 59/96] fix: schema type for merging schemas Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index 4ee83928bb..2810fbd825 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -71,7 +71,7 @@ public static bool IsArray(this IOpenApiSchema? schema) (schema.Items.IsComposedEnum() || schema.Items.IsEnum() || schema.Items.IsSemanticallyMeaningful() || - FlattenEmptyEntries([schema.Items], static x => x.AnyOf.Union(x.AllOf).Union(x.OneOf).ToList(), 1).FirstOrDefault() is OpenApiSchema flat && flat.IsSemanticallyMeaningful()); + FlattenEmptyEntries([schema.Items], static x => x.AnyOf.Union(x.AllOf).Union(x.OneOf).ToList(), 1).FirstOrDefault() is IOpenApiSchema flat && flat.IsSemanticallyMeaningful()); } public static bool IsObjectType(this IOpenApiSchema? schema) @@ -129,7 +129,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) { if (schema is not null && schema.IsInclusiveUnion(0) - && schema.AnyOf.OnlyOneOrDefault() is OpenApiSchema subSchema + && schema.AnyOf.OnlyOneOrDefault() is IOpenApiSchema subSchema && (subSchema.IsInherited() || subSchema.IsIntersection())) { var result = schema.CreateShallowCopy(); @@ -146,7 +146,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) { if (schema is not null && schema.IsExclusiveUnion(0) - && schema.OneOf.OnlyOneOrDefault() is OpenApiSchema subSchema + && schema.OneOf.OnlyOneOrDefault() is IOpenApiSchema subSchema && (subSchema.IsInherited() || subSchema.IsIntersection())) { var result = schema.CreateShallowCopy(); @@ -173,12 +173,12 @@ public static bool IsInherited(this IOpenApiSchema? schema) .ToArray(); var entriesToMerge = meaningfulSchemas.FlattenEmptyEntries(static x => x.AllOf).Union(meaningfulSchemas).ToArray(); if (entriesToMerge.Select(static x => x.Discriminator).OfType().FirstOrDefault() is OpenApiDiscriminator discriminator && - result is OpenApiSchema resultSchema) - if (resultSchema.Discriminator is null) - resultSchema.Discriminator = discriminator; - else if (string.IsNullOrEmpty(resultSchema.Discriminator.PropertyName) && !string.IsNullOrEmpty(discriminator.PropertyName)) + result is IOpenApiSchema resultSchema) + if (resultSchema.Discriminator is null && resultSchema is OpenApiSchema openApiSchema) + openApiSchema.Discriminator = discriminator; + else if (resultSchema.Discriminator is not null && string.IsNullOrEmpty(resultSchema.Discriminator.PropertyName) && !string.IsNullOrEmpty(discriminator.PropertyName)) resultSchema.Discriminator.PropertyName = discriminator.PropertyName; - else if (discriminator.Mapping?.Any() ?? false) + else if (resultSchema.Discriminator is not null && (discriminator.Mapping?.Any() ?? false)) resultSchema.Discriminator.Mapping = discriminator.Mapping.ToDictionary(static x => x.Key, static x => x.Value); result.TryAddProperties(entriesToMerge.SelectMany(static x => x.Properties)); From 1c0b0278146e6248c44e5345aabcc3da71bb5d24 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 10 Feb 2025 15:23:45 -0500 Subject: [PATCH 60/96] fix: schema type for model generation Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 21b531e032..6441dcaed1 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1737,7 +1737,7 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace), // inline schema + referenced schema (false, { Length: > 0 }, { Length: 1 }, _) => - AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries([.. referencedSchemas], static x => x is OpenApiSchema)!, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), + AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries([.. referencedSchemas], static x => x is IOpenApiSchema)!, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // properties + referenced schema (true, { Length: 0 }, { Length: 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), @@ -1779,7 +1779,7 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode if (!currentClass.Documentation.DescriptionAvailable && new string[] { schema.Description } .Union(schema.AllOf - .OfType() + .OfType() .Select(static x => x.Description)) .FirstOrDefault(static x => !string.IsNullOrEmpty(x)) is string description) currentClass.Documentation.DescriptionTemplate = description.CleanupDescription(); // the last allof entry often is not a reference and doesn't have a description. @@ -1888,13 +1888,13 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, IOp } // type: object with single oneOf referring to inheritance or intersection - if (schema.IsObjectType() && schema.MergeSingleExclusiveUnionInheritanceOrIntersectionSchemaEntries() is OpenApiSchema mergedExclusiveUnionSchema) + if (schema.IsObjectType() && schema.MergeSingleExclusiveUnionInheritanceOrIntersectionSchemaEntries() is IOpenApiSchema mergedExclusiveUnionSchema) { return CreateModelDeclarations(currentNode, mergedExclusiveUnionSchema, operation, parentElement, suffixForInlineSchema, response, typeNameForInlineSchema, isRequestBody); } // type: object with single anyOf referring to inheritance or intersection - if (schema.IsObjectType() && schema.MergeSingleInclusiveUnionInheritanceOrIntersectionSchemaEntries() is OpenApiSchema mergedInclusiveUnionSchema) + if (schema.IsObjectType() && schema.MergeSingleInclusiveUnionInheritanceOrIntersectionSchemaEntries() is IOpenApiSchema mergedInclusiveUnionSchema) { return CreateModelDeclarations(currentNode, mergedInclusiveUnionSchema, operation, parentElement, suffixForInlineSchema, response, typeNameForInlineSchema, isRequestBody); } From d302dbfc3f90ff5c6f56df0680594179114ecde0 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 10 Feb 2025 15:24:51 -0500 Subject: [PATCH 61/96] fix: schema type for validation rules Signed-off-by: Vincent Biret --- src/Kiota.Builder/Validation/GetWithBody.cs | 3 ++- src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs | 3 ++- .../Validation/KnownAndNotSupportedFormats.cs | 4 ++-- src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs | 7 ++++--- .../Validation/ValidationRuleSetExtensions.cs | 7 ++++--- tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs | 3 ++- .../Validation/InconsistentTypeFormatPairTests.cs | 3 ++- .../Validation/KnownAndNotSupportedFormatsTests.cs | 3 ++- 8 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/Kiota.Builder/Validation/GetWithBody.cs b/src/Kiota.Builder/Validation/GetWithBody.cs index a4f60dee96..dbd6086fe0 100644 --- a/src/Kiota.Builder/Validation/GetWithBody.cs +++ b/src/Kiota.Builder/Validation/GetWithBody.cs @@ -1,9 +1,10 @@ using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Validations; namespace Kiota.Builder.Validation; -public class GetWithBody : ValidationRule +public class GetWithBody : ValidationRule { public GetWithBody() : base(nameof(GetWithBody), static (context, pathItem) => { diff --git a/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs b/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs index ecdd6edc2f..510333254f 100644 --- a/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs +++ b/src/Kiota.Builder/Validation/InconsistentTypeFormatPair.cs @@ -1,11 +1,12 @@ using System; using System.Collections.Generic; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Validations; namespace Kiota.Builder.Validation; -public class InconsistentTypeFormatPair : ValidationRule +public class InconsistentTypeFormatPair : ValidationRule { private static readonly Dictionary> validPairs = new() { diff --git a/src/Kiota.Builder/Validation/KnownAndNotSupportedFormats.cs b/src/Kiota.Builder/Validation/KnownAndNotSupportedFormats.cs index 4dc4c5922d..36b731b8ad 100644 --- a/src/Kiota.Builder/Validation/KnownAndNotSupportedFormats.cs +++ b/src/Kiota.Builder/Validation/KnownAndNotSupportedFormats.cs @@ -1,12 +1,12 @@  using System; using System.Collections.Generic; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Validations; namespace Kiota.Builder.Validation; -public class KnownAndNotSupportedFormats : ValidationRule +public class KnownAndNotSupportedFormats : ValidationRule { internal static readonly HashSet knownAndUnsupportedFormats = new(StringComparer.OrdinalIgnoreCase) { "email", diff --git a/src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs b/src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs index 917ba8a289..d763e132f5 100644 --- a/src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs +++ b/src/Kiota.Builder/Validation/UrlFormEncodedComplex.cs @@ -3,6 +3,7 @@ using Kiota.Builder.Configuration; using Kiota.Builder.Extensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Validations; namespace Kiota.Builder.Validation; @@ -13,14 +14,14 @@ public class UrlFormEncodedComplex : ValidationRule }; public UrlFormEncodedComplex() : base(nameof(UrlFormEncodedComplex), static (context, operation) => { - if (operation.GetRequestSchema(validContentTypes) is OpenApiSchema requestSchema) + if (operation.GetRequestSchema(validContentTypes) is { } requestSchema) ValidateSchema(requestSchema, context, "request body"); - if (operation.GetResponseSchema(validContentTypes) is OpenApiSchema responseSchema) + if (operation.GetResponseSchema(validContentTypes) is { } responseSchema) ValidateSchema(responseSchema, context, "response body"); }) { } - private static void ValidateSchema(OpenApiSchema schema, IValidationContext context, string schemaName) + private static void ValidateSchema(IOpenApiSchema schema, IValidationContext context, string schemaName) { if (schema == null) return; if (!schema.IsObjectType()) diff --git a/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs b/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs index 523bbcfc3a..c6cb1b0d65 100644 --- a/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs +++ b/src/Kiota.Builder/Validation/ValidationRuleSetExtensions.cs @@ -1,6 +1,7 @@ using System; using Kiota.Builder.Configuration; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Validations; namespace Kiota.Builder.Validation; @@ -16,9 +17,9 @@ public static void AddKiotaValidationRules(this ValidationRuleSet ruleSet, Gener ruleSet.AddRuleIfEnabled(configuration, new NoServerEntry(), typeof(OpenApiDocument)); ruleSet.AddRuleIfEnabled(configuration, new MultipleServerEntries(), typeof(OpenApiDocument)); - ruleSet.AddRuleIfEnabled(configuration, new GetWithBody(), typeof(OpenApiPathItem)); - ruleSet.AddRuleIfEnabled(configuration, new KnownAndNotSupportedFormats(), typeof(OpenApiSchema)); - ruleSet.AddRuleIfEnabled(configuration, new InconsistentTypeFormatPair(), typeof(OpenApiSchema)); + ruleSet.AddRuleIfEnabled(configuration, new GetWithBody(), typeof(IOpenApiPathItem)); + ruleSet.AddRuleIfEnabled(configuration, new KnownAndNotSupportedFormats(), typeof(IOpenApiSchema)); + ruleSet.AddRuleIfEnabled(configuration, new InconsistentTypeFormatPair(), typeof(IOpenApiSchema)); ruleSet.AddRuleIfEnabled(configuration, new UrlFormEncodedComplex(), typeof(OpenApiOperation)); ruleSet.AddRuleIfEnabled(configuration, new DivergentResponseSchema(configuration), typeof(OpenApiOperation)); ruleSet.AddRuleIfEnabled(configuration, new MissingDiscriminator(configuration), typeof(OpenApiDocument)); diff --git a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs index 89ea47f7b1..2289b89101 100644 --- a/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/GetWithBodyTests.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Readers; using Microsoft.OpenApi.Validations; @@ -84,7 +85,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new GetWithBody(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(OpenApiPathItem), [rule]); + settings.RuleSet.Add(typeof(IOpenApiPathItem), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs index 4c3d61f8f3..bb2e4d7dea 100644 --- a/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/InconsistentTypeFormatPairTests.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Readers; using Xunit; @@ -81,7 +82,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new InconsistentTypeFormatPair(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(OpenApiSchema), [rule]); + settings.RuleSet.Add(typeof(IOpenApiSchema), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); diff --git a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs index abc24f3ac3..81ee36bba5 100644 --- a/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs +++ b/tests/Kiota.Builder.Tests/Validation/KnownAndNotSupportedFormatsTests.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Kiota.Builder.Validation; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Reader; using Microsoft.OpenApi.Readers; using Xunit; @@ -81,7 +82,7 @@ private static async Task GetDiagnosticFromDocumentAsync(stri var rule = new KnownAndNotSupportedFormats(); using var stream = new MemoryStream(Encoding.UTF8.GetBytes(document)); var settings = new OpenApiReaderSettings(); - settings.RuleSet.Add(typeof(OpenApiSchema), [rule]); + settings.RuleSet.Add(typeof(IOpenApiSchema), [rule]); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yaml, new OpenApiYamlReader()); OpenApiReaderRegistry.RegisterReader(OpenApiConstants.Yml, new OpenApiYamlReader()); var result = await OpenApiDocument.LoadAsync(stream, "yaml", settings); From 32b91fcaaff4d2b7fb5001c7931ee9c3d4dba001 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 10 Feb 2025 15:33:52 -0500 Subject: [PATCH 62/96] fix: typo in reference conversion Signed-off-by: Vincent Biret --- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index f8eea70ec2..98a233a702 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -3361,7 +3361,7 @@ public async Task AddsDiscriminatorMappingsOneOfImplicitAsync() { ["application/json"] = new OpenApiMediaType { - Schema = new OpenApiSchemaReference("microsoft.graph.directoryObject") + Schema = new OpenApiSchemaReference("microsoft.graph.directoryObjects") } }, }; From a9aa5a5499968265f56ffc14859417c4162564b8 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 11 Feb 2025 08:35:56 -0500 Subject: [PATCH 63/96] fix: removes duplicated usings Signed-off-by: Vincent Biret --- src/Kiota.Builder/Configuration/PluginAuthConfiguration.cs | 1 - src/Kiota.Builder/Plugins/PluginsGenerationService.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Kiota.Builder/Configuration/PluginAuthConfiguration.cs b/src/Kiota.Builder/Configuration/PluginAuthConfiguration.cs index 9646f491c8..407f35127d 100644 --- a/src/Kiota.Builder/Configuration/PluginAuthConfiguration.cs +++ b/src/Kiota.Builder/Configuration/PluginAuthConfiguration.cs @@ -1,7 +1,6 @@ using System; using Microsoft.DeclarativeAgents.Manifest; using Microsoft.OpenApi.Models; -using Microsoft.DeclarativeAgents.Manifest; namespace Kiota.Builder.Configuration; diff --git a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs index 7c18304312..63d858edd8 100644 --- a/src/Kiota.Builder/Plugins/PluginsGenerationService.cs +++ b/src/Kiota.Builder/Plugins/PluginsGenerationService.cs @@ -18,7 +18,6 @@ using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Microsoft.OpenApi.Writers; -using Microsoft.DeclarativeAgents.Manifest; namespace Kiota.Builder.Plugins; From 6c659887d95ce1f2bbf20ed11b5cd69ea3c128a7 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Tue, 11 Feb 2025 14:48:02 -0500 Subject: [PATCH 64/96] chore: code linting Signed-off-by: Vincent Biret --- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 98a233a702..bbee84b8c1 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -3294,8 +3294,8 @@ public void DoesntAddDiscriminatorMappingsOfNonDerivedTypes() var node = builder.CreateUriSpace(document); var codeModel = builder.CreateSourceModel(node); var entityClass = codeModel.FindChildByName("entity", true); - var directoryObjectClass = codeModel.FindChildByName("directoryObject", true); Assert.NotNull(entityClass); + Assert.NotNull(codeModel.FindChildByName("directoryObject", true)); var factoryMethod = entityClass.GetChildElements(true).OfType().FirstOrDefault(x => x.IsOfKind(CodeMethodKind.Factory)); Assert.NotNull(factoryMethod); Assert.Equal("@odata.type", entityClass.DiscriminatorInformation.DiscriminatorPropertyName); From ffbc12cbc9423d407b1128462fce689aadc464c7 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 10:42:03 -0500 Subject: [PATCH 65/96] fix: discriminator inherited class creation Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 6441dcaed1..214cd6f876 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -2107,6 +2107,17 @@ private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, IOpenApiSchema s AddDiscriminatorMethod(newClass, schema.GetDiscriminatorPropertyName(), mappings, static s => s); return newClass; } + /// + /// Creates a reference to the component so inheritance scenarios get the right class name + /// + /// Component to lookup + /// A reference to the component schema + private OpenApiSchemaReference? GetSchemaReferenceToComponentSchema(string componentName) + { + if (openApiDocument?.Components?.Schemas?.ContainsKey(componentName) ?? false) + return new OpenApiSchemaReference(componentName, openApiDocument); + return null; + } private IEnumerable> GetDiscriminatorMappings(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, CodeNamespace currentNamespace, CodeClass? baseClass, OpenApiOperation? currentOperation) { // Generate types that this discriminator references @@ -2292,7 +2303,7 @@ internal static void AddDiscriminatorMethod(CodeClass newClass, string discrimin private CodeType? GetCodeTypeForMapping(OpenApiUrlTreeNode currentNode, string referenceId, CodeNamespace currentNamespace, CodeClass? baseClass, OpenApiOperation? currentOperation) { var componentKey = referenceId?.Replace("#/components/schemas/", string.Empty, StringComparison.OrdinalIgnoreCase); - if (openApiDocument == null || string.IsNullOrEmpty(componentKey) || openApiDocument.Components?.Schemas is null || !openApiDocument.Components.Schemas.TryGetValue(componentKey, out var discriminatorSchema)) + if (openApiDocument == null || string.IsNullOrEmpty(componentKey) || openApiDocument.Components?.Schemas is null || GetSchemaReferenceToComponentSchema(componentKey) is not { } discriminatorSchema) { logger.LogWarning("Discriminator {ComponentKey} not found in the OpenAPI document.", componentKey); return null; From 5abacaa0aa78054c12a8670b7be17b8b75b5de47 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 10:51:25 -0500 Subject: [PATCH 66/96] chore: code linting Signed-off-by: Vincent Biret --- src/Kiota.Builder/Writers/TypeScript/CodeFunctionWriter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Kiota.Builder/Writers/TypeScript/CodeFunctionWriter.cs b/src/Kiota.Builder/Writers/TypeScript/CodeFunctionWriter.cs index 4608d707aa..96244dee1c 100644 --- a/src/Kiota.Builder/Writers/TypeScript/CodeFunctionWriter.cs +++ b/src/Kiota.Builder/Writers/TypeScript/CodeFunctionWriter.cs @@ -330,9 +330,9 @@ private string GetSerializerFunctionName(CodeElement codeElement, CodeType retur private string FindFunctionInNameSpace(string functionName, CodeElement codeElement, CodeType returnType) { - var myNamespace = returnType.TypeDefinition!.GetImmediateParentOfType(); + var myNamespace = returnType.TypeDefinition?.GetImmediateParentOfType() ?? throw new InvalidOperationException("Namespace not found for return type"); - CodeFunction[] codeFunctions = myNamespace.FindChildrenByName(functionName).ToArray(); + CodeFunction[] codeFunctions = [.. myNamespace.FindChildrenByName(functionName)]; var codeFunction = Array.Find(codeFunctions, func => func.GetImmediateParentOfType().Name == myNamespace.Name) ?? From 698963c52acacc419bfa7434a7022363dfa8f993 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 10:58:55 -0500 Subject: [PATCH 67/96] chore; code linting Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 214cd6f876..b07eff5a71 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1737,7 +1737,7 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace), // inline schema + referenced schema (false, { Length: > 0 }, { Length: 1 }, _) => - AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries([.. referencedSchemas], static x => x is IOpenApiSchema)!, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), + AddModelDeclarationIfDoesntExist(currentNode, operation, schema.MergeAllOfSchemaEntries([.. referencedSchemas], static x => x is not null)!, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), // properties + referenced schema (true, { Length: 0 }, { Length: 1 }, _) => AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace, CreateInheritedModelDeclaration(currentNode, referencedSchemas[0], operation, classNameSuffix, codeNamespace, isRequestBody, string.Empty)), From 4e438dd808f823e2ab126dc66137d601790c2d85 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 14:19:13 -0500 Subject: [PATCH 68/96] fix: schema all of merging causes side effects Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index 2810fbd825..b44950bc0b 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -163,7 +163,13 @@ public static bool IsInherited(this IOpenApiSchema? schema) { if (schema is null) return null; if (!schema.IsIntersection() && !overrideIntersection) return schema; - var result = schema.CreateShallowCopy(); + var result = schema switch + { + OpenApiSchema oas => (OpenApiSchema)oas.CreateShallowCopy(), + OpenApiSchemaReference oasr when oasr.Target is OpenApiSchema target => (OpenApiSchema)target.CreateShallowCopy(), + OpenApiSchemaReference => throw new InvalidOperationException("The schema reference is not resolved"), + _ => throw new InvalidOperationException("The schema type is not supported") + }; result.AllOf.Clear(); var meaningfulSchemas = schema.AllOf .Where(x => (x.IsSemanticallyMeaningful() || x.AllOf.Any()) && (filter == null || filter(x))) @@ -172,14 +178,13 @@ public static bool IsInherited(this IOpenApiSchema? schema) .OfType() .ToArray(); var entriesToMerge = meaningfulSchemas.FlattenEmptyEntries(static x => x.AllOf).Union(meaningfulSchemas).ToArray(); - if (entriesToMerge.Select(static x => x.Discriminator).OfType().FirstOrDefault() is OpenApiDiscriminator discriminator && - result is IOpenApiSchema resultSchema) - if (resultSchema.Discriminator is null && resultSchema is OpenApiSchema openApiSchema) - openApiSchema.Discriminator = discriminator; - else if (resultSchema.Discriminator is not null && string.IsNullOrEmpty(resultSchema.Discriminator.PropertyName) && !string.IsNullOrEmpty(discriminator.PropertyName)) - resultSchema.Discriminator.PropertyName = discriminator.PropertyName; - else if (resultSchema.Discriminator is not null && (discriminator.Mapping?.Any() ?? false)) - resultSchema.Discriminator.Mapping = discriminator.Mapping.ToDictionary(static x => x.Key, static x => x.Value); + if (entriesToMerge.Select(static x => x.Discriminator).OfType().FirstOrDefault() is OpenApiDiscriminator discriminator) + if (result.Discriminator is null) + result.Discriminator = discriminator; + else if (result.Discriminator is not null && string.IsNullOrEmpty(result.Discriminator.PropertyName) && !string.IsNullOrEmpty(discriminator.PropertyName)) + result.Discriminator.PropertyName = discriminator.PropertyName; + else if (result.Discriminator is not null && (discriminator.Mapping?.Any() ?? false)) + result.Discriminator.Mapping = discriminator.Mapping.ToDictionary(static x => x.Key, static x => x.Value); result.TryAddProperties(entriesToMerge.SelectMany(static x => x.Properties)); From fc4fed811b0282af78ac92d5caa72870a8dffbcb Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 14:25:36 -0500 Subject: [PATCH 69/96] fix: deprecation information propagation Signed-off-by: Vincent Biret --- .../OpenApiDeprecationExtensionExtensions.cs | 6 +- ...nApiDeprecationExtensionExtensionsTests.cs | 117 ++++++++++-------- 2 files changed, 67 insertions(+), 56 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs index 9d07a926ae..afafdc03a1 100644 --- a/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiDeprecationExtensionExtensions.cs @@ -36,15 +36,13 @@ internal static DeprecationInformation GetDeprecationInformation(this OpenApiOpe else if (operation.Responses?.Values .SelectMany(static x => x.Content.Values) .Select(static x => x?.Schema) - .OfType() - .Where(static x => !x.IsReferencedSchema()) + .OfType() .Select(static x => x.GetDeprecationInformation()) .FirstOrDefault(static x => x.IsDeprecated) is DeprecationInformation responseDeprecationInformation) return responseDeprecationInformation; else if (operation.RequestBody?.Content.Values .Select(static x => x?.Schema) - .OfType() - .Where(static x => !x.IsReferencedSchema()) + .OfType() .Select(static x => x.GetDeprecationInformation()) .FirstOrDefault(static x => x.IsDeprecated) is DeprecationInformation requestDeprecationInformation) return requestDeprecationInformation; diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiDeprecationExtensionExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiDeprecationExtensionExtensionsTests.cs index 40995244f9..41711fad5c 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiDeprecationExtensionExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiDeprecationExtensionExtensionsTests.cs @@ -6,6 +6,7 @@ using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.MicrosoftExtensions; using Microsoft.OpenApi.Models; +using Microsoft.OpenApi.Models.References; using Microsoft.OpenApi.Services; using Xunit; @@ -192,6 +193,21 @@ public void GetsDeprecationOnOperationWithDeprecatedInlineResponseSchema() [Fact] public void GetsNoDeprecationOnOperationWithDeprecatedReferenceResponseSchema() { + var schema = new OpenApiSchema + { + Deprecated = true, + Extensions = new Dictionary + { + { OpenApiDeprecationExtension.Name, new OpenApiDeprecationExtension { + Description = "description", + Version = "version", + RemovalDate = new DateTimeOffset(2023, 05, 04, 0, 0, 0, TimeSpan.Zero), + Date = new DateTimeOffset(2021, 05, 04, 0, 0, 0, TimeSpan.Zero), + } } + } + }; + var document = new OpenApiDocument(); + document.AddComponent("schema", schema); var operation = new OpenApiOperation { Deprecated = false, @@ -204,19 +220,7 @@ public void GetsNoDeprecationOnOperationWithDeprecatedReferenceResponseSchema() { { "application/json", new OpenApiMediaType { - Schema = new OpenApiSchema - { - Deprecated = true, - Extensions = new Dictionary - { - { OpenApiDeprecationExtension.Name, new OpenApiDeprecationExtension { - Description = "description", - Version = "version", - RemovalDate = new DateTimeOffset(2023, 05, 04, 0, 0, 0, TimeSpan.Zero), - Date = new DateTimeOffset(2021, 05, 04, 0, 0, 0, TimeSpan.Zero), - } } - } - } + Schema = new OpenApiSchemaReference("schema", document) } } } @@ -287,6 +291,21 @@ public void GetsDeprecationOnOperationWithNullRequestBodyContentTypeInstance() [Fact] public void GetsNoDeprecationOnOperationWithDeprecatedReferenceRequestSchema() { + var schema = new OpenApiSchema + { + Deprecated = true, + Extensions = new Dictionary + { + { OpenApiDeprecationExtension.Name, new OpenApiDeprecationExtension { + Description = "description", + Version = "version", + RemovalDate = new DateTimeOffset(2023, 05, 04, 0, 0, 0, TimeSpan.Zero), + Date = new DateTimeOffset(2021, 05, 04, 0, 0, 0, TimeSpan.Zero), + } } + } + }; + var document = new OpenApiDocument(); + document.AddComponent("schema", schema); var operation = new OpenApiOperation { Deprecated = false, @@ -296,19 +315,7 @@ public void GetsNoDeprecationOnOperationWithDeprecatedReferenceRequestSchema() { { "application/json", new OpenApiMediaType { - Schema = new OpenApiSchema - { - Deprecated = true, - Extensions = new Dictionary - { - { OpenApiDeprecationExtension.Name, new OpenApiDeprecationExtension { - Description = "description", - Version = "version", - RemovalDate = new DateTimeOffset(2023, 05, 04, 0, 0, 0, TimeSpan.Zero), - Date = new DateTimeOffset(2021, 05, 04, 0, 0, 0, TimeSpan.Zero), - } } - } - } + Schema = new OpenApiSchemaReference("schema", document) } } } @@ -389,23 +396,26 @@ public void GetsDeprecationInformationOnParameterWithDeprecatedInlineSchema() [Fact] public void GetsNoDeprecationInformationOnParameterWithDeprecatedReferenceSchema() { - var parameter = new OpenApiParameter + var schema = new OpenApiSchema { - Deprecated = false, - Schema = new OpenApiSchema + Deprecated = true, + Extensions = new Dictionary { - Deprecated = true, - Extensions = new Dictionary - { - { OpenApiDeprecationExtension.Name, new OpenApiDeprecationExtension { - Description = "description", - Version = "version", - RemovalDate = new DateTimeOffset(2023, 05, 04, 0, 0, 0, TimeSpan.Zero), - Date = new DateTimeOffset(2021, 05, 04, 0, 0, 0, TimeSpan.Zero), - } } - } + { OpenApiDeprecationExtension.Name, new OpenApiDeprecationExtension { + Description = "description", + Version = "version", + RemovalDate = new DateTimeOffset(2023, 05, 04, 0, 0, 0, TimeSpan.Zero), + Date = new DateTimeOffset(2021, 05, 04, 0, 0, 0, TimeSpan.Zero), + } } } }; + var document = new OpenApiDocument(); + document.AddComponent("schema", schema); + var parameter = new OpenApiParameter + { + Deprecated = false, + Schema = new OpenApiSchemaReference("schema", document) + }; var deprecationInformation = parameter.GetDeprecationInformation(); Assert.NotNull(deprecationInformation); Assert.False(deprecationInformation.IsDeprecated); @@ -445,25 +455,28 @@ public void GetsDeprecationInformationOnParameterWithDeprecatedInlineContentSche [Fact] public void GetsNoDeprecationInformationOnParameterWithDeprecatedReferenceContentSchema() { + var schema = new OpenApiSchema + { + Deprecated = true, + Extensions = new Dictionary + { + { OpenApiDeprecationExtension.Name, new OpenApiDeprecationExtension { + Description = "description", + Version = "version", + RemovalDate = new DateTimeOffset(2023, 05, 04, 0, 0, 0, TimeSpan.Zero), + Date = new DateTimeOffset(2021, 05, 04, 0, 0, 0, TimeSpan.Zero), + } } + } + }; + var document = new OpenApiDocument(); + document.AddComponent("schema", schema); var parameter = new OpenApiParameter { Deprecated = false, Content = new Dictionary() { { "application/json", new OpenApiMediaType() { - Schema = new OpenApiSchema - { - Deprecated = true, - Extensions = new Dictionary - { - { OpenApiDeprecationExtension.Name, new OpenApiDeprecationExtension { - Description = "description", - Version = "version", - RemovalDate = new DateTimeOffset(2023, 05, 04, 0, 0, 0, TimeSpan.Zero), - Date = new DateTimeOffset(2021, 05, 04, 0, 0, 0, TimeSpan.Zero), - } } - } - } + Schema = new OpenApiSchemaReference("schema", document) } } } From d72898e01201bee9a53e9a79c510121645da5419 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 14:31:46 -0500 Subject: [PATCH 70/96] chore: makes test non order specific Signed-off-by: Vincent Biret --- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index bbee84b8c1..253bb8e8d1 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -740,9 +740,9 @@ public async Task NamesComponentsInlineSchemasProperlyAsync() Assert.NotNull(unionType); Assert.Equal("directoryObject_deletedDateTime", unionType.Name, StringComparer.OrdinalIgnoreCase); Assert.Equal(3, unionType.Types.Count()); - Assert.Equal("DateTimeOffset", unionType.Types.First().Name, StringComparer.OrdinalIgnoreCase); - Assert.Equal("directoryObject_deletedDateTimeMember1", unionType.Types.ElementAt(1).Name, StringComparer.OrdinalIgnoreCase); - Assert.Equal("int64", unionType.Types.ElementAt(2).Name, StringComparer.OrdinalIgnoreCase); + Assert.Contains(unionType.Types, t => "DateTimeOffset".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); + Assert.Contains(unionType.Types, t => "directoryObject_deletedDateTimeMember1".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); + Assert.Contains(unionType.Types, t => "int64".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); Assert.Null(modelsNS.FindChildByName("users")); } [Theory] From 9f0186072aac940676a93ed19d602e47bf3ba4ca Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 14:32:50 -0500 Subject: [PATCH 71/96] chore: code linting Signed-off-by: Vincent Biret --- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 253bb8e8d1..0b6050f4a6 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -736,8 +736,7 @@ public async Task NamesComponentsInlineSchemasProperlyAsync() Assert.NotNull(doClass); var deletedDateTimeProperty = doClass.FindChildByName("DeletedDateTime", false); Assert.NotNull(deletedDateTimeProperty); - var unionType = deletedDateTimeProperty.Type as CodeUnionType; - Assert.NotNull(unionType); + var unionType = Assert.IsType(deletedDateTimeProperty.Type); Assert.Equal("directoryObject_deletedDateTime", unionType.Name, StringComparer.OrdinalIgnoreCase); Assert.Equal(3, unionType.Types.Count()); Assert.Contains(unionType.Types, t => "DateTimeOffset".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); From 97e91ba093b57909d088ec627186e175105f781c Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 14:39:23 -0500 Subject: [PATCH 72/96] fix: nullable conversion derails primitive types Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index b07eff5a71..a29dfbaa78 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1202,7 +1202,7 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten var typeName = typeNames.Find(static x => x is not null && !typeNamesToSkip.Contains(x.Value)); var format = typeSchema?.Format ?? typeSchema?.Items?.Format; - return (typeName, format?.ToLowerInvariant()) switch + return (typeName & ~JsonSchemaType.Null, format?.ToLowerInvariant()) switch { (_, "byte") => new CodeType { Name = "base64", IsExternal = true }, (_, "binary") => new CodeType { Name = "binary", IsExternal = true }, From e7f1da86a9112bf06abeee8090773854ee5389ff Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 14:42:39 -0500 Subject: [PATCH 73/96] chore: code linting Signed-off-by: Vincent Biret --- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 0b6050f4a6..0ccc49a82f 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -739,9 +739,9 @@ public async Task NamesComponentsInlineSchemasProperlyAsync() var unionType = Assert.IsType(deletedDateTimeProperty.Type); Assert.Equal("directoryObject_deletedDateTime", unionType.Name, StringComparer.OrdinalIgnoreCase); Assert.Equal(3, unionType.Types.Count()); - Assert.Contains(unionType.Types, t => "DateTimeOffset".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); - Assert.Contains(unionType.Types, t => "directoryObject_deletedDateTimeMember1".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); - Assert.Contains(unionType.Types, t => "int64".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); + Assert.Single(unionType.Types, t => "DateTimeOffset".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); + Assert.Single(unionType.Types, t => "directoryObject_deletedDateTimeMember1".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); + Assert.Single(unionType.Types, t => "int64".Equals(t.Name, StringComparison.OrdinalIgnoreCase)); Assert.Null(modelsNS.FindChildByName("users")); } [Theory] @@ -8541,8 +8541,8 @@ a database instance and cannot be changed once set. var node = builder.CreateUriSpace(document); var codeModel = builder.CreateSourceModel(node); var registeredModelClass = codeModel.FindChildByName("RegisteredModel"); - Assert.Null(registeredModelClass.StartBlock.Inherits); Assert.NotNull(registeredModelClass); + Assert.Null(registeredModelClass.StartBlock.Inherits); Assert.Single(registeredModelClass.Properties, static x => x.Kind is CodePropertyKind.AdditionalData); Assert.Single(registeredModelClass.Properties, static x => x.Name.Equals("name", StringComparison.OrdinalIgnoreCase)); Assert.Single(registeredModelClass.Properties, static x => x.Name.Equals("id", StringComparison.OrdinalIgnoreCase)); From acdfe74facf0c60cbf1a8f794e61738a17c87d9d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 15:01:01 -0500 Subject: [PATCH 74/96] fix: merging logic should use target Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index b44950bc0b..b3d4dbffc9 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -110,7 +110,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) internal static IOpenApiSchema? MergeInclusiveUnionSchemaEntries(this IOpenApiSchema? schema) { if (schema is null || !schema.IsInclusiveUnion(0)) return null; - var result = schema.CreateShallowCopy(); + var result = schema.GetSchemaOrTargetShallowCopy(); result.AnyOf.Clear(); result.TryAddProperties(schema.AnyOf.SelectMany(static x => x.Properties)); return result; @@ -119,7 +119,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) internal static IOpenApiSchema? MergeExclusiveUnionSchemaEntries(this IOpenApiSchema? schema) { if (schema is null || !schema.IsExclusiveUnion(0)) return null; - var result = schema.CreateShallowCopy(); + var result = schema.GetSchemaOrTargetShallowCopy(); result.OneOf.Clear(); result.TryAddProperties(schema.OneOf.SelectMany(static x => x.Properties)); return result; @@ -132,7 +132,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) && schema.AnyOf.OnlyOneOrDefault() is IOpenApiSchema subSchema && (subSchema.IsInherited() || subSchema.IsIntersection())) { - var result = schema.CreateShallowCopy(); + var result = schema.GetSchemaOrTargetShallowCopy(); result.AnyOf.Clear(); result.TryAddProperties(subSchema.Properties); result.AllOf.AddRange(subSchema.AllOf); @@ -149,7 +149,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) && schema.OneOf.OnlyOneOrDefault() is IOpenApiSchema subSchema && (subSchema.IsInherited() || subSchema.IsIntersection())) { - var result = schema.CreateShallowCopy(); + var result = schema.GetSchemaOrTargetShallowCopy(); result.OneOf.Clear(); result.TryAddProperties(subSchema.Properties); result.AllOf.AddRange(subSchema.AllOf); @@ -159,17 +159,23 @@ public static bool IsInherited(this IOpenApiSchema? schema) return null; } - internal static IOpenApiSchema? MergeIntersectionSchemaEntries(this IOpenApiSchema? schema, HashSet? schemasToExclude = default, bool overrideIntersection = false, Func? filter = default) + private static OpenApiSchema GetSchemaOrTargetShallowCopy(this IOpenApiSchema? schema) { - if (schema is null) return null; - if (!schema.IsIntersection() && !overrideIntersection) return schema; - var result = schema switch + return schema switch { OpenApiSchema oas => (OpenApiSchema)oas.CreateShallowCopy(), OpenApiSchemaReference oasr when oasr.Target is OpenApiSchema target => (OpenApiSchema)target.CreateShallowCopy(), OpenApiSchemaReference => throw new InvalidOperationException("The schema reference is not resolved"), _ => throw new InvalidOperationException("The schema type is not supported") }; + } + + internal static IOpenApiSchema? MergeIntersectionSchemaEntries(this IOpenApiSchema? schema, HashSet? schemasToExclude = default, bool overrideIntersection = false, Func? filter = default) + { + if (schema is null) return null; + if (!schema.IsIntersection() && !overrideIntersection) return schema; + + var result = schema.GetSchemaOrTargetShallowCopy(); result.AllOf.Clear(); var meaningfulSchemas = schema.AllOf .Where(x => (x.IsSemanticallyMeaningful() || x.AllOf.Any()) && (filter == null || filter(x))) @@ -191,7 +197,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) return result; } - internal static void TryAddProperties(this IOpenApiSchema schema, IEnumerable> properties) + internal static void TryAddProperties(this OpenApiSchema schema, IEnumerable> properties) { foreach (var property in properties) { From a4eccd690c2f765c5cf00a696a887f4611e9b1e4 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Wed, 12 Feb 2025 15:16:25 -0500 Subject: [PATCH 75/96] fix: description taken from all of inline entry Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index a29dfbaa78..4034c5f44c 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1779,7 +1779,7 @@ private CodeClass CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode if (!currentClass.Documentation.DescriptionAvailable && new string[] { schema.Description } .Union(schema.AllOf - .OfType() + .OfType() .Select(static x => x.Description)) .FirstOrDefault(static x => !string.IsNullOrEmpty(x)) is string description) currentClass.Documentation.DescriptionTemplate = description.CleanupDescription(); // the last allof entry often is not a reference and doesn't have a description. From a666b61d0a99e3d78055fde5681d3f09902562a7 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 13 Feb 2025 14:03:05 -0500 Subject: [PATCH 76/96] fix: set both discriminator property and mapping when available Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index b3d4dbffc9..aafef83f82 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -187,10 +187,13 @@ private static OpenApiSchema GetSchemaOrTargetShallowCopy(this IOpenApiSchema? s if (entriesToMerge.Select(static x => x.Discriminator).OfType().FirstOrDefault() is OpenApiDiscriminator discriminator) if (result.Discriminator is null) result.Discriminator = discriminator; - else if (result.Discriminator is not null && string.IsNullOrEmpty(result.Discriminator.PropertyName) && !string.IsNullOrEmpty(discriminator.PropertyName)) - result.Discriminator.PropertyName = discriminator.PropertyName; - else if (result.Discriminator is not null && (discriminator.Mapping?.Any() ?? false)) - result.Discriminator.Mapping = discriminator.Mapping.ToDictionary(static x => x.Key, static x => x.Value); + else + { + if (string.IsNullOrEmpty(result.Discriminator.PropertyName) && !string.IsNullOrEmpty(discriminator.PropertyName)) + result.Discriminator.PropertyName = discriminator.PropertyName; + if (discriminator.Mapping?.Any() ?? false) + result.Discriminator.Mapping = discriminator.Mapping.ToDictionary(static x => x.Key, static x => x.Value); + } result.TryAddProperties(entriesToMerge.SelectMany(static x => x.Properties)); From 53d8536e25ebdca95105a069379513238ee67bb6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 13 Feb 2025 14:43:29 -0500 Subject: [PATCH 77/96] chore: additional validation Signed-off-by: Vincent Biret --- tests/Kiota.Builder.Tests/KiotaBuilderTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 0ccc49a82f..c54ee5c6a2 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -3541,6 +3541,7 @@ public async Task AddsDiscriminatorMappingsAllOfImplicitAsync() var doFactoryMethod = directoryObjectClass.GetChildElements(true).OfType().FirstOrDefault(static x => x.IsOfKind(CodeMethodKind.Factory)); Assert.NotNull(doFactoryMethod); Assert.Single(directoryObjectClass.DiscriminatorInformation.DiscriminatorMappings); + Assert.DoesNotContain(directoryObjectClass.Properties, static x => x.Name.Equals("id", StringComparison.OrdinalIgnoreCase)); Assert.Contains("microsoft.graph.user", directoryObjectClass.DiscriminatorInformation.DiscriminatorMappings.Select(static x => x.Key)); Assert.Empty(userClass.DiscriminatorInformation.DiscriminatorMappings); } From 3fc3a49a4b53773c478c2d386edad0f167eeed83 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 13 Feb 2025 15:05:37 -0500 Subject: [PATCH 78/96] fix: missing discriminator information Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 8 +++++- src/Kiota.Builder/KiotaBuilder.cs | 6 ++++- .../OpenApiKiotaMergedExtension.cs | 26 +++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaMergedExtension.cs diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index aafef83f82..9960527129 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.Json; +using Kiota.Builder.OpenApiExtensions; using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models.Interfaces; using Microsoft.OpenApi.Models.References; @@ -178,9 +179,9 @@ private static OpenApiSchema GetSchemaOrTargetShallowCopy(this IOpenApiSchema? s var result = schema.GetSchemaOrTargetShallowCopy(); result.AllOf.Clear(); var meaningfulSchemas = schema.AllOf + .Where(x => x is not null && (schemasToExclude is null || !schemasToExclude.Contains(x))) .Where(x => (x.IsSemanticallyMeaningful() || x.AllOf.Any()) && (filter == null || filter(x))) .Select(x => MergeIntersectionSchemaEntries(x, schemasToExclude, overrideIntersection, filter)) - .Where(x => x is not null && (schemasToExclude is null || !schemasToExclude.Contains(x))) .OfType() .ToArray(); var entriesToMerge = meaningfulSchemas.FlattenEmptyEntries(static x => x.AllOf).Union(meaningfulSchemas).ToArray(); @@ -195,6 +196,11 @@ private static OpenApiSchema GetSchemaOrTargetShallowCopy(this IOpenApiSchema? s result.Discriminator.Mapping = discriminator.Mapping.ToDictionary(static x => x.Key, static x => x.Value); } + if (schema is OpenApiSchemaReference schemaReference) + { + schema.Extensions.TryAdd(OpenApiKiotaMergedExtension.Name, new OpenApiKiotaMergedExtension(schemaReference.Reference.Id)); + } + result.TryAddProperties(entriesToMerge.SelectMany(static x => x.Properties)); return result; diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 4034c5f44c..437f119bbe 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -2099,8 +2099,12 @@ private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, IOpenApiSchema s } } + var lookupSchema = schema.Extensions.TryGetValue(OpenApiKiotaMergedExtension.Name, out var rawExtension) && + rawExtension is OpenApiKiotaMergedExtension kiotaMergedExtension ? + new OpenApiSchemaReference(kiotaMergedExtension.OriginalName, openApiDocument) : + schema; // Recurse into the discriminator & generate its referenced types - var mappings = GetDiscriminatorMappings(currentNode, schema, currentNamespace, newClass, currentOperation) + var mappings = GetDiscriminatorMappings(currentNode, lookupSchema, currentNamespace, newClass, currentOperation) .Where(x => x.Value is { TypeDefinition: CodeClass definition } && definition.DerivesFrom(newClass)); // only the mappings that derive from the current class diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaMergedExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaMergedExtension.cs new file mode 100644 index 0000000000..c614aaab48 --- /dev/null +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaMergedExtension.cs @@ -0,0 +1,26 @@ + +using System; +using Microsoft.OpenApi; +using Microsoft.OpenApi.Interfaces; +using Microsoft.OpenApi.Writers; + +namespace Kiota.Builder.OpenApiExtensions; +/// +/// Temporary stores the original reference id when we merge schemas so the reference id can be used to lookup the inheritance index and find the discriminator values +/// +internal class OpenApiKiotaMergedExtension : IOpenApiExtension +{ + public static string Name => "x-kiota-merged"; + public string OriginalName + { + get; + } + public OpenApiKiotaMergedExtension(string originalName) + { + ArgumentException.ThrowIfNullOrEmpty(originalName); + OriginalName = originalName; + } + public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion) + { + } +} From 297ab95b3713165fdd3fb1112b6523bc9d764289 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 14 Feb 2025 09:34:33 -0500 Subject: [PATCH 79/96] fix: merged schema original name for class generation Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 10 +++++++++- src/Kiota.Builder/KiotaBuilder.cs | 5 ++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index 9960527129..69eeb01be8 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -34,6 +34,7 @@ public static IEnumerable GetSchemaNames(this IOpenApiSchema schema, boo return schema switch { OpenApiSchemaReference reference => reference.Reference?.Id, + OpenApiSchema s when s.GetMergedSchemaOriginalReferenceId() is string originalReferenceId => originalReferenceId, _ => null, }; } @@ -198,7 +199,7 @@ private static OpenApiSchema GetSchemaOrTargetShallowCopy(this IOpenApiSchema? s if (schema is OpenApiSchemaReference schemaReference) { - schema.Extensions.TryAdd(OpenApiKiotaMergedExtension.Name, new OpenApiKiotaMergedExtension(schemaReference.Reference.Id)); + result.Extensions.TryAdd(OpenApiKiotaMergedExtension.Name, new OpenApiKiotaMergedExtension(schemaReference.Reference.Id)); } result.TryAddProperties(entriesToMerge.SelectMany(static x => x.Properties)); @@ -206,6 +207,13 @@ private static OpenApiSchema GetSchemaOrTargetShallowCopy(this IOpenApiSchema? s return result; } + internal static string? GetMergedSchemaOriginalReferenceId(this IOpenApiSchema schema) + { + return schema.Extensions.TryGetValue(OpenApiKiotaMergedExtension.Name, out var extension) && extension is OpenApiKiotaMergedExtension mergedExtension ? + mergedExtension.OriginalName : + null; + } + internal static void TryAddProperties(this OpenApiSchema schema, IEnumerable> properties) { foreach (var property in properties) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 437f119bbe..46d81499f9 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -2099,9 +2099,8 @@ private CodeClass AddModelClass(OpenApiUrlTreeNode currentNode, IOpenApiSchema s } } - var lookupSchema = schema.Extensions.TryGetValue(OpenApiKiotaMergedExtension.Name, out var rawExtension) && - rawExtension is OpenApiKiotaMergedExtension kiotaMergedExtension ? - new OpenApiSchemaReference(kiotaMergedExtension.OriginalName, openApiDocument) : + var lookupSchema = schema.GetMergedSchemaOriginalReferenceId() is string originalName ? + new OpenApiSchemaReference(originalName, openApiDocument) : schema; // Recurse into the discriminator & generate its referenced types var mappings = GetDiscriminatorMappings(currentNode, lookupSchema, currentNamespace, newClass, currentOperation) From 4e49a050d28d6fce5062bbd5944ea7b11daba7ba Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 14 Feb 2025 09:44:43 -0500 Subject: [PATCH 80/96] fix: additional merging names and scenarios Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index 69eeb01be8..821e79c8d0 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -115,6 +115,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) var result = schema.GetSchemaOrTargetShallowCopy(); result.AnyOf.Clear(); result.TryAddProperties(schema.AnyOf.SelectMany(static x => x.Properties)); + schema.AddOriginalReferenceIdExtension(result); return result; } @@ -124,6 +125,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) var result = schema.GetSchemaOrTargetShallowCopy(); result.OneOf.Clear(); result.TryAddProperties(schema.OneOf.SelectMany(static x => x.Properties)); + schema.AddOriginalReferenceIdExtension(result); return result; } @@ -138,6 +140,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) result.AnyOf.Clear(); result.TryAddProperties(subSchema.Properties); result.AllOf.AddRange(subSchema.AllOf); + schema.AddOriginalReferenceIdExtension(result); return result; } @@ -155,6 +158,7 @@ public static bool IsInherited(this IOpenApiSchema? schema) result.OneOf.Clear(); result.TryAddProperties(subSchema.Properties); result.AllOf.AddRange(subSchema.AllOf); + schema.AddOriginalReferenceIdExtension(result); return result; } @@ -197,16 +201,26 @@ private static OpenApiSchema GetSchemaOrTargetShallowCopy(this IOpenApiSchema? s result.Discriminator.Mapping = discriminator.Mapping.ToDictionary(static x => x.Key, static x => x.Value); } - if (schema is OpenApiSchemaReference schemaReference) - { - result.Extensions.TryAdd(OpenApiKiotaMergedExtension.Name, new OpenApiKiotaMergedExtension(schemaReference.Reference.Id)); - } + schema.AddOriginalReferenceIdExtension(result); result.TryAddProperties(entriesToMerge.SelectMany(static x => x.Properties)); return result; } + /// + /// Adds a temporary extension to the schema to store the original reference id of the schema being merged. + /// This is used to keep track of the original reference id of the schema being merged when the schema is a reference. + /// The reference id is used to generate the class name of the schema. + /// + /// Original schema that was merged. + /// Resulting merged schema. + private static void AddOriginalReferenceIdExtension(this IOpenApiSchema schema, OpenApiSchema result) + { + if (schema is not OpenApiSchemaReference schemaReference) return; + result.Extensions.TryAdd(OpenApiKiotaMergedExtension.Name, new OpenApiKiotaMergedExtension(schemaReference.Reference.Id)); + } + internal static string? GetMergedSchemaOriginalReferenceId(this IOpenApiSchema schema) { return schema.Extensions.TryGetValue(OpenApiKiotaMergedExtension.Name, out var extension) && extension is OpenApiKiotaMergedExtension mergedExtension ? From 33fbd6c063be5e243d57f58588f6642a10df4906 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 14 Feb 2025 09:49:19 -0500 Subject: [PATCH 81/96] chore: formatting --- .../OpenApiExtensions/OpenApiKiotaMergedExtension.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaMergedExtension.cs b/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaMergedExtension.cs index c614aaab48..3556fe5e4d 100644 --- a/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaMergedExtension.cs +++ b/src/Kiota.Builder/OpenApiExtensions/OpenApiKiotaMergedExtension.cs @@ -1,4 +1,4 @@ - + using System; using Microsoft.OpenApi; using Microsoft.OpenApi.Interfaces; From 7d01be8e982ac760fb3ad2801ac524e3f8419e17 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 14 Feb 2025 12:48:59 -0500 Subject: [PATCH 82/96] chore: adds sanity tests for primitive and null types Signed-off-by: Vincent Biret --- .../Kiota.Builder.Tests/KiotaBuilderTests.cs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index c54ee5c6a2..3bcd84a4c5 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -4151,6 +4151,35 @@ public void InheritedTypeWithInlineSchemaWorks() [InlineData(JsonSchemaType.Boolean, "", "boolean")] [InlineData(JsonSchemaType.String, "byte", "base64")] [InlineData(JsonSchemaType.String, "binary", "binary")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "", "string")]// https://spec.openapis.org/registry/format/ + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "commonmark", "string")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "html", "string")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "date-time", "DateTimeOffset")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "duration", "TimeSpan")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "date", "DateOnly")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "time", "TimeOnly")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "base64url", "base64url")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "uuid", "Guid")] + // floating points can only be declared as numbers + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "double", "double")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "float", "float")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "decimal", "decimal")] + // integers can only be declared as numbers or integers + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "int32", "integer")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "int32", "integer")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "int64", "int64")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "int64", "int64")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "int8", "sbyte")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "int8", "sbyte")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "int16", "integer")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "int16", "integer")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "uint8", "byte")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "uint8", "byte")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "", "double")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "", "integer")] + [InlineData(JsonSchemaType.Boolean | JsonSchemaType.Null, "", "boolean")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "byte", "base64")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "binary", "binary")] [Theory] public void MapsPrimitiveFormats(JsonSchemaType type, string format, string expected) { @@ -4218,6 +4247,32 @@ public void MapsPrimitiveFormats(JsonSchemaType type, string format, string expe [InlineData(JsonSchemaType.Boolean, "", "boolean")] [InlineData(JsonSchemaType.String, "byte", "base64")] [InlineData(JsonSchemaType.String, "binary", "binary")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "", "string")]// https://spec.openapis.org/registry/format/ + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "commonmark", "string")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "html", "string")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "date-time", "DateTimeOffset")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "duration", "TimeSpan")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "date", "DateOnly")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "time", "TimeOnly")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "base64url", "base64url")] + // floating points can only be declared as numbers + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "double", "double")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "float", "float")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "decimal", "decimal")] + // integers can only be declared as numbers or integers + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "int32", "integer")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "int32", "integer")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "int64", "int64")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "int64", "int64")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "int8", "sbyte")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "int8", "sbyte")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "uint8", "byte")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "uint8", "byte")] + [InlineData(JsonSchemaType.Number | JsonSchemaType.Null, "", "double")] + [InlineData(JsonSchemaType.Integer | JsonSchemaType.Null, "", "integer")] + [InlineData(JsonSchemaType.Boolean | JsonSchemaType.Null, "", "boolean")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "byte", "base64")] + [InlineData(JsonSchemaType.String | JsonSchemaType.Null, "binary", "binary")] [Theory] public void MapsQueryParameterTypes(JsonSchemaType type, string format, string expected) { From a2e3a663b404cb0611755f80c5111fa073081509 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 14 Feb 2025 13:43:54 -0500 Subject: [PATCH 83/96] feat: adds support for array of types as union types Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 14 ++++++- src/Kiota.Builder/KiotaBuilder.cs | 24 ++++++++++- .../OpenApiSchemaExtensionsTests.cs | 16 +++++++ .../Kiota.Builder.Tests/KiotaBuilderTests.cs | 42 +++++++++++++++++++ 4 files changed, 93 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index 821e79c8d0..8be7af48f3 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -244,9 +244,20 @@ public static bool IsIntersection(this IOpenApiSchema? schema) public static bool IsExclusiveUnion(this IOpenApiSchema? schema, uint exclusiveMinimumNumberOfEntries = 1) { - return schema?.OneOf?.Count(static x => IsSemanticallyMeaningful(x, true)) > exclusiveMinimumNumberOfEntries; + if (schema is null) return false; + return schema.OneOf?.Count(static x => IsSemanticallyMeaningful(x, true)) > exclusiveMinimumNumberOfEntries || + schema.IsArrayOfTypes(); // so we don't consider one of object/nullable as a union type } + public static bool IsArrayOfTypes(this IOpenApiSchema? schema) + { + if (schema is null) return false; + return schema.Type.HasValue && !IsPowerOfTwo((uint)(schema.Type.Value & ~JsonSchemaType.Null)); + } + private static bool IsPowerOfTwo(uint x) + { + return (x & (x - 1)) == 0; + } private static readonly HashSet oDataTypes = [ JsonSchemaType.Number, JsonSchemaType.Integer, @@ -269,6 +280,7 @@ private static bool IsODataPrimitiveTypeBackwardCompatible(this IOpenApiSchema s } public static bool IsODataPrimitiveType(this IOpenApiSchema schema) { + if (schema is null) return false; return schema.IsExclusiveUnion() && schema.OneOf.Count == 3 && schema.OneOf.Count(static x => isStringType(x) && (x.Enum?.Any() ?? false)) == 1 && diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 46d81499f9..89994dc540 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1190,7 +1190,7 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten } return prop; } - private static readonly HashSet typeNamesToSkip = [JsonSchemaType.Object, JsonSchemaType.Array]; + private static readonly HashSet typeNamesToSkip = [JsonSchemaType.Object, JsonSchemaType.Array, JsonSchemaType.Object | JsonSchemaType.Null, JsonSchemaType.Array | JsonSchemaType.Null]; private static CodeType? GetPrimitiveType(IOpenApiSchema? typeSchema, string? childType = default) { var typeNames = new List { typeSchema?.Items?.Type, typeSchema?.Type }; @@ -1801,7 +1801,7 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo !x.IsArray() && !x.IsReferencedSchema()) ?? false)) && schema.AnyOf?.FirstOrDefault(static x => !string.IsNullOrEmpty(x.GetSchemaName())) is { } targetSchema) - {// once openAPI 3.1 is supported, there will be a third case oneOf with Ref and type null. + { var className = targetSchema.GetSchemaName().CleanupSymbolName(); var shortestNamespace = GetShortestNamespace(codeNamespace, targetSchema); return new CodeType @@ -1852,8 +1852,28 @@ private CodeTypeBase CreateComposedModelDeclaration(OpenApiUrlTreeNode currentNo if (!unionType.ContainsType(declarationType)) unionType.AddType(declarationType); } + if (schema.IsArrayOfTypes()) + { + AddTypeArrayMemberToComposedType(schema, JsonSchemaType.Boolean, unionType); + AddTypeArrayMemberToComposedType(schema, JsonSchemaType.Integer, unionType); + AddTypeArrayMemberToComposedType(schema, JsonSchemaType.Number, unionType); + AddTypeArrayMemberToComposedType(schema, JsonSchemaType.String, unionType); + } return unionType; } + private void AddTypeArrayMemberToComposedType(IOpenApiSchema schema, JsonSchemaType typeToScan, CodeComposedTypeBase codeComposedTypeBase) + { + if (!schema.Type.HasValue || (schema.Type.Value & typeToScan) != typeToScan) return; + + var temporarySchema = new OpenApiSchema { Type = typeToScan, Format = schema.Format }; + if (GetPrimitiveType(temporarySchema) is CodeType primitiveType && !string.IsNullOrEmpty(primitiveType.Name)) + { + if (schema.IsArray()) + primitiveType.CollectionKind = CodeTypeBase.CodeTypeCollectionKind.Complex; + if (!codeComposedTypeBase.ContainsType(primitiveType)) + codeComposedTypeBase.AddType(primitiveType); + } + } private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, IOpenApiSchema schema, OpenApiOperation? operation, CodeElement parentElement, string suffixForInlineSchema, IOpenApiResponse? response = default, string typeNameForInlineSchema = "", bool isRequestBody = false, bool isViaDiscriminator = false) { var (codeNamespace, responseValue, suffix) = schema.IsReferencedSchema() switch diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index 916c79edf3..7c79221912 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -61,6 +61,22 @@ public void Defensive() } [Fact] + public void IsExclusiveUnionMatchesTypeArrays() + { + Assert.True(new OpenApiSchema + { + Type = JsonSchemaType.String | JsonSchemaType.Number + }.IsExclusiveUnion()); + Assert.True(new OpenApiSchema + { + Type = JsonSchemaType.String | JsonSchemaType.Number | JsonSchemaType.Null + }.IsExclusiveUnion()); + Assert.False(new OpenApiSchema + { + Type = JsonSchemaType.Number | JsonSchemaType.Null + }.IsExclusiveUnion()); + } + [Fact] public void ExternalReferencesAreNotSupported() { var mockSchema = new OpenApiSchemaReference("example.json#/path/to/component", null, "http://example.com/example.json"); diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 3bcd84a4c5..265c9ac565 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -4316,6 +4316,48 @@ public void MapsQueryParameterTypes(JsonSchemaType type, string format, string e Assert.True(property.Type.AllTypes.First().IsExternal); } [Fact] + public void MapsArrayOfTypesAsUnionType() + { + var document = new OpenApiDocument + { + Paths = new OpenApiPaths + { + ["primitive"] = new OpenApiPathItem + { + Operations = { + [OperationType.Get] = new OpenApiOperation + { + Responses = new OpenApiResponses + { + ["200"] = new OpenApiResponse { + Content = { + ["application/json"] = new OpenApiMediaType { + Schema = new OpenApiSchema { + Type = JsonSchemaType.Number | JsonSchemaType.String, + } + } + } + }, + } + } + } + } + }, + }; + var mockLogger = new Mock>(); + var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", ApiRootUrl = "https://localhost" }, _httpClient); + var node = builder.CreateUriSpace(document); + var codeModel = builder.CreateSourceModel(node); + var requestBuilder = codeModel.FindChildByName("primitiveRequestBuilder"); + Assert.NotNull(requestBuilder); + var method = requestBuilder.GetChildElements(true).OfType().FirstOrDefault(x => x.IsOfKind(CodeMethodKind.RequestExecutor)); + Assert.NotNull(method); + var unionType = Assert.IsType(method.ReturnType); + Assert.Equal(2, unionType.Types.Count()); + Assert.Contains("string", unionType.Types.Select(static x => x.Name), StringComparer.OrdinalIgnoreCase); + Assert.Contains("double", unionType.Types.Select(static x => x.Name), StringComparer.OrdinalIgnoreCase); + } + [Fact] public void MapsQueryParameterArrayTypes() { var document = new OpenApiDocument From 62e83acd25ed541c7c1730f584cdd15ed2e09d53 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 14 Feb 2025 13:47:37 -0500 Subject: [PATCH 84/96] chore: comment cleanup Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 89994dc540..ba5bc13aa7 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1222,7 +1222,6 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten (JsonSchemaType.Number, _) => new CodeType { Name = "double", IsExternal = true }, (JsonSchemaType.Integer, _) => new CodeType { Name = "integer", IsExternal = true }, (JsonSchemaType.Boolean, _) => new CodeType { Name = "boolean", IsExternal = true }, - //TODO handle the case where we have multiple entries (_, _) when !string.IsNullOrEmpty(childType) => new CodeType { Name = childType, IsExternal = false, }, (_, _) => null, }; From 243168eaa2b68d3298ed06543478856cdad23609 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 14 Feb 2025 14:23:05 -0500 Subject: [PATCH 85/96] feat: adds support for external references Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 5 +- .../Kiota.Builder.Tests/KiotaBuilderTests.cs | 70 +++++++++++++++++++ 2 files changed, 71 insertions(+), 4 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index 8be7af48f3..f7c745a903 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -59,10 +59,7 @@ public static bool IsReferencedSchema(this IOpenApiSchema schema) { return schema switch { - OpenApiSchemaReference reference => reference.Reference.IsExternal ? - // TODO remove this failsafe once we have a test with external documents. - throw new NotSupportedException("External references are not supported in this version of Kiota. While Kiota awaits on OpenAPI.Net to support inlining external references, you can use https://www.nuget.org/packages/Microsoft.OpenApi.Hidi to generate an OpenAPI description with inlined external references and then use this new reference with Kiota.") : - true, + OpenApiSchemaReference => true, _ => false, }; } diff --git a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs index 265c9ac565..0c84c4c754 100644 --- a/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs +++ b/tests/Kiota.Builder.Tests/KiotaBuilderTests.cs @@ -38,6 +38,76 @@ public void Dispose() _httpClient.Dispose(); GC.SuppressFinalize(this); } + [Fact] + public async Task SupportsExternalReferences() + { + var tempFilePathReferee = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); + await File.WriteAllTextAsync(tempFilePathReferee, +""" +openapi: 3.1.1 +info: + title: OData Service for namespace microsoft.graph + description: This OData service is located at https://graph.microsoft.com/v1.0 + version: 1.0.1 +servers: + - url: https://graph.microsoft.com/v1.0 +paths: + /placeholder: + get: + responses: + '200': + content: + application/json: + schema: + type: string +components: + schemas: + MySchema: + type: object + properties: + id: + type: string +"""); + var tempFilePathReferrer = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); + await File.WriteAllTextAsync(tempFilePathReferrer, +$$$""" +openapi: 3.1.1 +info: + title: OData Service for namespace microsoft.graph + description: This OData service is located at https://graph.microsoft.com/v1.0 + version: 1.0.1 +servers: + - url: https://graph.microsoft.com/v1.0 +paths: + /placeholder: + get: + responses: + '200': + content: + application/json: + schema: + $ref: './{{{Path.GetFileName(tempFilePathReferee)}}}#/components/schemas/MySchema' +components: + schemas: + MySchema: + type: object + properties: + id: + type: string +"""); + var mockLogger = new Mock>(); + var builder = new KiotaBuilder(mockLogger.Object, new GenerationConfiguration { ClientClassName = "Graph", OpenAPIFilePath = tempFilePathReferrer, Serializers = ["none"], Deserializers = ["none"] }, _httpClient); + await using var fs = new FileStream(tempFilePathReferrer, FileMode.Open); + var document = await builder.CreateOpenApiDocumentAsync(fs); + var node = builder.CreateUriSpace(document); + builder.SetApiRootUrl(); + var codeModel = builder.CreateSourceModel(node); + var rootNS = codeModel.FindNamespaceByName("ApiSdk"); + Assert.NotNull(rootNS); + var modelClass = rootNS.FindChildByName("MySchema", true); + Assert.NotNull(modelClass); + Assert.Single(modelClass.Properties, static x => x.Name.Equals("id", StringComparison.OrdinalIgnoreCase)); + } [InlineData("https://graph.microsoft.com/description.yaml", "/v1.0", "https://graph.microsoft.com/v1.0")] [InlineData("/home/vsts/a/s/1", "/v1.0", "/v1.0")] [InlineData("https://graph.microsoft.com/docs/description.yaml", "../v1.0", "https://graph.microsoft.com/v1.0")] From b46eb2d42db9ee33c8796f57d63a1159c261fbeb Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 14 Feb 2025 15:13:10 -0500 Subject: [PATCH 86/96] fix: external reference anti-test update Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensionsTests.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index 7c79221912..d35f100426 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -77,10 +77,16 @@ public void IsExclusiveUnionMatchesTypeArrays() }.IsExclusiveUnion()); } [Fact] - public void ExternalReferencesAreNotSupported() + public void ExternalReferencesAreSupported() { var mockSchema = new OpenApiSchemaReference("example.json#/path/to/component", null, "http://example.com/example.json"); - Assert.Throws(() => mockSchema.IsReferencedSchema()); + Assert.True(mockSchema.IsReferencedSchema()); + } + [Fact] + public void SchemasAreNotConsideredReferences() + { + var mockSchema = new OpenApiSchema(); + Assert.False(mockSchema.IsReferencedSchema()); } [Fact] public void LocalReferencesAreSupported() From 61b9cb92056655e0486a97f3191dcf4f496cdeb3 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 17 Feb 2025 08:08:10 -0500 Subject: [PATCH 87/96] chore: bumps openapi deps --- src/Kiota.Builder/Kiota.Builder.csproj | 4 ++-- src/kiota/kiota.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index 776bf5295e..56757f7228 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -39,9 +39,9 @@ - + - + diff --git a/src/kiota/kiota.csproj b/src/kiota/kiota.csproj index 525af4051a..e7450b56da 100644 --- a/src/kiota/kiota.csproj +++ b/src/kiota/kiota.csproj @@ -47,7 +47,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all From e2de4a7386d7d86e03756fb4741c403c70c1e670 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 17 Feb 2025 12:56:26 -0500 Subject: [PATCH 88/96] fix: java issue with base64 types Signed-off-by: Vincent Biret --- src/Kiota.Builder/Writers/Java/JavaConventionService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/Writers/Java/JavaConventionService.cs b/src/Kiota.Builder/Writers/Java/JavaConventionService.cs index 29d4191c63..51e78829e8 100644 --- a/src/Kiota.Builder/Writers/Java/JavaConventionService.cs +++ b/src/Kiota.Builder/Writers/Java/JavaConventionService.cs @@ -86,7 +86,7 @@ public override string TranslateType(CodeType type) "sbyte" => "Short", "decimal" or "Decimal" => "BigDecimal", "void" or "boolean" when !type.IsNullable => type.Name, //little casing hack - "binary" or "base64" or "base64url" or "Base64url" => "byte[]", + "binary" or "Binary" or "base64" or "Base64" or "base64url" or "Base64url" => "byte[]", "Guid" => "UUID", _ when type.Name.Contains('.', StringComparison.OrdinalIgnoreCase) => type.Name, // casing _ => type.Name is string typeName && !string.IsNullOrEmpty(typeName) ? typeName : "Object", From c1aaae06d67f673328a7a4e48e3a2da67d4c10e8 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 17 Feb 2025 13:25:31 -0500 Subject: [PATCH 89/96] fix: do not use null default values Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index ba5bc13aa7..f7179388ee 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1180,7 +1180,8 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten if (kind == CodePropertyKind.Custom && propertySchema?.Default is JsonValue stringDefaultJsonValue && stringDefaultJsonValue.TryGetValue(out var stringDefaultValue) && - !string.IsNullOrEmpty(stringDefaultValue)) + !string.IsNullOrEmpty(stringDefaultValue) && + !"null".Equals(stringDefaultValue, StringComparison.OrdinalIgnoreCase)) prop.DefaultValue = $"\"{stringDefaultValue}\""; if (existingType == null) From 90970141f528c7f980d63074763aedea9db56dda Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 17 Feb 2025 13:52:27 -0500 Subject: [PATCH 90/96] fix: get primitive type for properties should ignore null Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index f7179388ee..1f793f843f 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1932,7 +1932,7 @@ private CodeTypeBase CreateModelDeclarations(OpenApiUrlTreeNode currentNode, IOp return CreateCollectionModelDeclaration(currentNode, schema, operation, codeNamespace, typeNameForInlineSchema, isRequestBody); } - if (schema.Type is not null || !string.IsNullOrEmpty(schema.Format)) + if (schema.Type is not null && (schema.Type & ~JsonSchemaType.Null) != 0 || !string.IsNullOrEmpty(schema.Format)) return GetPrimitiveType(schema) ?? new CodeType { Name = UntypedNodeName, IsExternal = true }; if ((schema.AnyOf.Any() || schema.OneOf.Any() || schema.AllOf.Any()) && (schema.AnyOf.FirstOrDefault(static x => x.IsSemanticallyMeaningful(true)) ?? schema.OneOf.FirstOrDefault(static x => x.IsSemanticallyMeaningful(true)) ?? schema.AllOf.FirstOrDefault(static x => x.IsSemanticallyMeaningful(true))) is { } childSchema) // we have an empty node because of some local override for schema properties and need to unwrap it. From 0b63dd98f3d583a26ffa7923f1acce304f498340 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Mon, 17 Feb 2025 14:20:49 -0500 Subject: [PATCH 91/96] fix: enum defensive statement for primitive types Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index 1f793f843f..f9fcc8ed5e 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -1194,6 +1194,8 @@ openApiExtension is OpenApiPrimaryErrorMessageExtension primaryErrorMessageExten private static readonly HashSet typeNamesToSkip = [JsonSchemaType.Object, JsonSchemaType.Array, JsonSchemaType.Object | JsonSchemaType.Null, JsonSchemaType.Array | JsonSchemaType.Null]; private static CodeType? GetPrimitiveType(IOpenApiSchema? typeSchema, string? childType = default) { + if (typeSchema?.Items?.IsEnum() ?? false) + return null; var typeNames = new List { typeSchema?.Items?.Type, typeSchema?.Type }; if (typeSchema?.AnyOf?.Any() ?? false) typeNames.AddRange(typeSchema.AnyOf.Select(x => x.Type)); // double is sometimes an anyof string, number and enum From 990fd3066a4d0b265cfb0e7aa618d845a137d1b6 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Thu, 20 Feb 2025 08:14:22 -0500 Subject: [PATCH 92/96] chore: linting --- src/Kiota.Builder/Configuration/LanguagesInformation.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Kiota.Builder/Configuration/LanguagesInformation.cs b/src/Kiota.Builder/Configuration/LanguagesInformation.cs index a80f718faf..c96c854d59 100644 --- a/src/Kiota.Builder/Configuration/LanguagesInformation.cs +++ b/src/Kiota.Builder/Configuration/LanguagesInformation.cs @@ -15,7 +15,9 @@ public static LanguagesInformation Parse(JsonObject jsonNode) { var extension = new LanguagesInformation(); foreach (var property in jsonNode.Where(static property => property.Value is JsonObject)) + { extension.Add(property.Key, LanguageInformation.Parse(property.Value!)); + } return extension; } From 5091d00d06b89d3a3a0c9618991c97bf90685326 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 21 Feb 2025 10:07:18 -0500 Subject: [PATCH 93/96] fix: updates to identifier call Signed-off-by: Vincent Biret --- src/Kiota.Builder/KiotaBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Kiota.Builder/KiotaBuilder.cs b/src/Kiota.Builder/KiotaBuilder.cs index f9fcc8ed5e..51f8a6663f 100644 --- a/src/Kiota.Builder/KiotaBuilder.cs +++ b/src/Kiota.Builder/KiotaBuilder.cs @@ -2604,7 +2604,7 @@ private static CodeType GetQueryParameterType(IOpenApiSchema schema) var paramType = GetPrimitiveType(schema) ?? new() { IsExternal = true, - Name = schema.Items is not null && schema.Items.Type.ToIdentifier() is string name ? name : "null", + Name = schema.Items is not null && (schema.Items.Type & ~JsonSchemaType.Null)?.ToIdentifiers().FirstOrDefault() is string name ? name : "null", }; paramType.CollectionKind = schema.IsArray() ? CodeTypeBase.CodeTypeCollectionKind.Array : default; From 13795efe4aeb820abc9be749dfa204765ce6de0d Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 21 Feb 2025 10:16:01 -0500 Subject: [PATCH 94/96] fix: odata types detection Signed-off-by: Vincent Biret --- .../Extensions/OpenApiSchemaExtensions.cs | 2 ++ .../Extensions/OpenApiSchemaExtensionsTests.cs | 14 +++++++------- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs index f7c745a903..0a537d17f0 100644 --- a/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs +++ b/src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs @@ -258,6 +258,8 @@ private static bool IsPowerOfTwo(uint x) private static readonly HashSet oDataTypes = [ JsonSchemaType.Number, JsonSchemaType.Integer, + JsonSchemaType.Number | JsonSchemaType.Null, + JsonSchemaType.Integer | JsonSchemaType.Null, ]; private static readonly Func isODataType = static x => x.Type is not null && oDataTypes.Contains(x.Type.Value); private static readonly Func isStringType = static x => x is { Type: JsonSchemaType.String or (JsonSchemaType.String | JsonSchemaType.Null) }; diff --git a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs index d35f100426..dd5edbd963 100644 --- a/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs +++ b/tests/Kiota.Builder.Tests/Extensions/OpenApiSchemaExtensionsTests.cs @@ -1054,22 +1054,22 @@ public void IsOdataPrimitive() [ new OpenApiSchema() { - Type = JsonSchemaType.Number, + Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double", }, new OpenApiSchema() { - Type = JsonSchemaType.String, + Type = JsonSchemaType.String | JsonSchemaType.Null, }, new OpenApiSchema() { Enum = [ - "INF", + "-INF", "INF", "NaN", ], - Type = JsonSchemaType.String, + Type = JsonSchemaType.String | JsonSchemaType.Null, } ] }; @@ -1084,18 +1084,18 @@ public void IsOdataPrimitiveBackwardCompatible() [ new OpenApiSchema() { - Type = JsonSchemaType.Number, + Type = JsonSchemaType.Number | JsonSchemaType.Null, Format = "double", }, new OpenApiSchema() { - Type = JsonSchemaType.String, + Type = JsonSchemaType.String | JsonSchemaType.Null, }, new OpenApiSchema() { Enum = [ - "INF", + "-INF", "INF", "NaN", ] From 4644138c1b6af6b77561be12197fdab8a9fbb0ea Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 21 Feb 2025 13:58:54 -0500 Subject: [PATCH 95/96] chore: upgrades openapi dependency --- src/Kiota.Builder/Kiota.Builder.csproj | 4 ++-- src/kiota/kiota.csproj | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Kiota.Builder/Kiota.Builder.csproj b/src/Kiota.Builder/Kiota.Builder.csproj index 56757f7228..c2ced0a263 100644 --- a/src/Kiota.Builder/Kiota.Builder.csproj +++ b/src/Kiota.Builder/Kiota.Builder.csproj @@ -39,9 +39,9 @@ - + - + diff --git a/src/kiota/kiota.csproj b/src/kiota/kiota.csproj index e7450b56da..2ca8b2d58a 100644 --- a/src/kiota/kiota.csproj +++ b/src/kiota/kiota.csproj @@ -47,7 +47,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all From a967ef2290cf98a11d44f52b2a0a63e344fa8155 Mon Sep 17 00:00:00 2001 From: Vincent Biret Date: Fri, 21 Feb 2025 14:00:26 -0500 Subject: [PATCH 96/96] docs: adds changelog entry for OAI 3.1 support Signed-off-by: Vincent Biret --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f65217252f..f2ea809c88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Added support for OpenAPI 3.1. [#3914](https://github.com/microsoft/kiota/issues/3914) + ### Changed - Fixed mapping of Binary Types to array buffer in TypeScript. [#6124](https://github.com/microsoft/kiota/issues/6124) @@ -35,7 +37,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed a bug in the VS Code extension deeplink with the API Center extension [#6004](https://github.com/microsoft/kiota/issues/6004) - Drops Python 3.8 support by removing deprecated type aliases from generated code. [microsoft/kiota-python#349](https://github.com/microsoft/kiota-python/issues/349) -- Removes superfluous inline imports in serializer methods in Python Generation. +- Removes superfluous inline imports in serializer methods in Python Generation. ## [1.22.2] @@ -1570,5 +1572,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Initial GitHub release - -