Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

adds support for OpenAPI 3.1 descriptions #5936

Draft
wants to merge 100 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
85194e4
fix: oas extensions parsing
baywet Oct 14, 2024
d83bc2f
fix: multiple NRE
baywet Oct 14, 2024
99623e1
fix: additional NRE
baywet Oct 14, 2024
8392023
chore: updates reference to oai.net preview
baywet Nov 12, 2024
25e4511
fix: additional 3.1 NRT and type reference fixes
baywet Nov 12, 2024
99dcbfb
fix: additional 3.1 NRT and type reference fixes
baywet Nov 12, 2024
6422b45
fix: wrong value comparison
baywet Nov 12, 2024
4bff227
fix: additional type and NRT fixes
baywet Nov 12, 2024
229a425
fix: main project builds
baywet Nov 12, 2024
193a7b9
fix: all validation tests migrated to the new OAI.net object model
baywet Nov 12, 2024
294d80e
fix: openapi extension migrated to new OAI.net model
baywet Nov 12, 2024
2d87938
fix: main tests build
baywet Nov 12, 2024
453bf9d
Merge branch 'main' into feat/OAI-3-1
baywet Nov 25, 2024
57c7cb9
fix: parsing of dependencies
baywet Nov 25, 2024
5db7ad0
fix: aligns dependencies versions
baywet Nov 25, 2024
2360204
Merge branch 'main' into feat/OAI-3-1
baywet Nov 27, 2024
4c1866d
chore: upgrades additional code
baywet Nov 27, 2024
291db8a
Merge branch 'main' into feat/OAI-3-1
baywet Dec 20, 2024
4daed72
chore: upgrades to OAI.net preview3
baywet Dec 20, 2024
9c9f988
fix: registers missing reader
baywet Dec 20, 2024
9cebd6c
fix: bad boolean algebra
baywet Dec 20, 2024
893a5ae
chore: linting
baywet Dec 20, 2024
c1e21aa
fix: class naming for discriminator mapping
baywet Dec 20, 2024
5f7e287
fix: further fix of missing reference ids
baywet Dec 20, 2024
77f3a55
fix: wrong method overload use
baywet Dec 20, 2024
66641be
fix: wrong test data
baywet Dec 20, 2024
52ede22
fix: missing readers
baywet Dec 20, 2024
85c67cd
fix: form encoded validation rule
baywet Dec 20, 2024
bc64b83
fix: validation rules registration
baywet Dec 20, 2024
21c607f
Merge branch 'main' into feat/OAI-3-1
baywet Dec 23, 2024
f5b95b7
fix: rules disablement did not work anymore
baywet Dec 23, 2024
c539330
fix: invalid payload for unit test
baywet Dec 23, 2024
c1cbea9
chore: improves validation tests performance for API export
baywet Dec 23, 2024
3cdd3d4
fix: document path for manifest generation tests
baywet Dec 23, 2024
99c4675
fix: invalid type for test data
baywet Dec 23, 2024
1886d77
chore: linting removes unnecessary string interpolation
baywet Dec 23, 2024
7f16e6b
fix: navigation properties type generation
baywet Dec 23, 2024
118e524
fix: binary and byte format mapping
baywet Dec 23, 2024
8782bd6
fix: enum values number parsing
baywet Dec 23, 2024
3caf91e
Merge branch 'main' into feat/OAI-3-1
baywet Dec 24, 2024
1ca8341
chore: bumps oai.net preview version
baywet Dec 24, 2024
7a7ca1a
fix: tolerate more than strings for comparisons
baywet Jan 2, 2025
55015ff
Merge branch 'main' into feat/OAI-3-1
baywet Jan 2, 2025
f54ee9e
chore: updates api manifest reference
baywet Jan 2, 2025
3fe0294
fix: references to schema type after merge
baywet Jan 2, 2025
68308ee
Merge branch 'main' into feat/OAI-3-1
baywet Jan 3, 2025
6608a8d
Merge branch 'main' into feat/OAI-3-1
baywet Jan 8, 2025
fbfd05d
chore; upgrades plugin manifest lib to align oai.net versions
baywet Jan 8, 2025
e2a6e20
fix: adds missing serialization settings to get schemas inlined
baywet Jan 8, 2025
f507645
fix: updates to latest OAI.net async changes
baywet Jan 8, 2025
c7390c5
Merge branch 'main' into feat/OAI-3-1
baywet Jan 16, 2025
269ff50
Merge branch 'main' into feat/OAI-3-1
baywet Jan 20, 2025
a4e0a0f
fix: defensive programming
baywet Jan 20, 2025
c9e3ea7
Merge branch 'main' into feat/OAI-3-1
baywet Jan 21, 2025
3010bf2
chore: bumps to latest oai.net preview
baywet Jan 21, 2025
86e5b39
Merge branch 'main' into feat/OAI-3-1
baywet Jan 31, 2025
0a54809
fix: updates reference code for preview6 in main projects
baywet Feb 3, 2025
40300e8
Merge branch 'main' into feat/OAI-3-1
baywet Feb 3, 2025
eaa16e4
fix: first batch of unit test reference fixes
baywet Feb 3, 2025
18722f3
fix: removes nullable references
baywet Feb 3, 2025
054c53a
Merge branch 'main' into feat/OAI-3-1
baywet Feb 4, 2025
f3ec848
fix: schema reference mutation
baywet Feb 4, 2025
510ebcf
Merge branch 'main' into feat/OAI-3-1
baywet Feb 5, 2025
13937bf
Merge branch 'main' into feat/OAI-3-1
baywet Feb 6, 2025
ca80001
chore: bumps all openapi deps to 2.X line
baywet Feb 6, 2025
fbc9d63
fix: first batch of broken references in unit tests
baywet Feb 6, 2025
2169848
Merge branch 'main' into feat/OAI-3-1
baywet Feb 7, 2025
1e91b2c
fix: additional batch of reference fixes
baywet Feb 7, 2025
88f3d6f
chore: updates plugin manifest reference
baywet Feb 7, 2025
9005646
chore: updates plugins manifest namespace
baywet Feb 7, 2025
12fae11
fix: additional batch of reference fixes
baywet Feb 7, 2025
0912d64
Merge branch 'main' into feat/OAI-3-1
baywet Feb 10, 2025
457a810
fix: final batch of reference updates
baywet Feb 10, 2025
baa762c
fix: reference request body generation
baywet Feb 10, 2025
356b40f
fix: schema type for deprecation information
baywet Feb 10, 2025
7bf177e
fix: schema type for multipart detection
baywet Feb 10, 2025
e550ce6
fix: schema type for merging schemas
baywet Feb 10, 2025
1c0b027
fix: schema type for model generation
baywet Feb 10, 2025
d302dbf
fix: schema type for validation rules
baywet Feb 10, 2025
32b91fc
fix: typo in reference conversion
baywet Feb 10, 2025
dd4ddca
Merge branch 'main' into feat/OAI-3-1
baywet Feb 11, 2025
a9aa5a5
fix: removes duplicated usings
baywet Feb 11, 2025
6c65988
chore: code linting
baywet Feb 11, 2025
ff7f180
Merge branch 'main' into feat/OAI-3-1
baywet Feb 12, 2025
32756de
Merge branch 'feat/OAI-3-1' of https://github.com/microsoft/kiota int…
baywet Feb 12, 2025
ffbc12c
fix: discriminator inherited class creation
baywet Feb 12, 2025
5abacaa
chore: code linting
baywet Feb 12, 2025
698963c
chore; code linting
baywet Feb 12, 2025
4e438dd
fix: schema all of merging causes side effects
baywet Feb 12, 2025
fc4fed8
fix: deprecation information propagation
baywet Feb 12, 2025
d72898e
chore: makes test non order specific
baywet Feb 12, 2025
9f01860
chore: code linting
baywet Feb 12, 2025
97e91ba
fix: nullable conversion derails primitive types
baywet Feb 12, 2025
e7f1da8
chore: code linting
baywet Feb 12, 2025
acdfe74
fix: merging logic should use target
baywet Feb 12, 2025
a4eccd6
fix: description taken from all of inline entry
baywet Feb 12, 2025
a88dca3
Merge branch 'main' into feat/OAI-3-1
baywet Feb 13, 2025
a666b61
fix: set both discriminator property and mapping when available
baywet Feb 13, 2025
53d8536
chore: additional validation
baywet Feb 13, 2025
3fc3a49
fix: missing discriminator information
baywet Feb 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 18 additions & 16 deletions src/Kiota.Builder/Configuration/LanguagesInformation.cs
Original file line number Diff line number Diff line change
@@ -1,31 +1,22 @@
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;

namespace Kiota.Builder.Configuration;

public class LanguagesInformation : Dictionary<string, LanguageInformation>, 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;
}

Expand All @@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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<OpenApiSchema>
internal class OpenApiSchemaReferenceComparer(StringComparer? stringComparer = null) : IEqualityComparer<IOpenApiSchema>
{
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -12,38 +13,36 @@ 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();
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<OpenApiSchema>()
.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<OpenApiSchema>()
.Where(static x => !x.IsReferencedSchema())
.Select(static x => x.GetDeprecationInformation())
.FirstOrDefault(static x => x.IsDeprecated) is DeprecationInformation requestDeprecationInformation)
return requestDeprecationInformation;
Expand Down
5 changes: 3 additions & 2 deletions src/Kiota.Builder/Extensions/OpenApiDocumentExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<OpenApiSchemaReference>())
{
var dependents = inheritanceIndex.GetOrAdd(allOfEntry.Reference.Id, new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase));
dependents.TryAdd(entry.Key, false);
Expand All @@ -31,7 +32,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()
Expand Down
16 changes: 9 additions & 7 deletions src/Kiota.Builder/Extensions/OpenApiOperationExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -21,21 +22,22 @@ private static string vendorSpecificCleanup(string input)
/// <summary>
/// cleans application/vnd.github.mercy-preview+json to application/json
/// </summary>
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<OpenApiSchema> GetResponseSchemas(this OpenApiOperation operation, HashSet<string> successCodesToUse, StructuredMimeTypesCollection structuredMimeTypes)
internal static IEnumerable<IOpenApiSchema> GetResponseSchemas(this OpenApiOperation operation, HashSet<string> 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)
.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
Expand All @@ -44,7 +46,7 @@ internal static IEnumerable<OpenApiSchema> GetResponseSchemas(this OpenApiOperat
private static readonly StructuredMimeTypesCollection multipartMimeTypes = new(["multipart/form-data"]);
internal static bool IsMultipartFormDataSchema(this IDictionary<string, OpenApiMediaType> 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<string, OpenApiMediaType> source, StructuredMimeTypesCollection structuredMimeTypes)
Expand All @@ -56,7 +58,7 @@ internal static bool IsMultipartTopMimeType(this IDictionary<string, OpenApiMedi
if (source.Count == 1 || !source.Keys.Where(static x => !multipartMimeTypes.Contains(x)).Any(structuredMimeTypes.Contains)) return true;
return structuredMimeTypes.First() == multipartMimeTypes.First();
}
internal static IEnumerable<OpenApiSchema> GetValidSchemas(this IDictionary<string, OpenApiMediaType> source, StructuredMimeTypesCollection structuredMimeTypes)
internal static IEnumerable<IOpenApiSchema> GetValidSchemas(this IDictionary<string, OpenApiMediaType> source, StructuredMimeTypesCollection structuredMimeTypes)
{
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(structuredMimeTypes);
Expand All @@ -67,9 +69,9 @@ internal static IEnumerable<OpenApiSchema> GetValidSchemas(this IDictionary<stri
.Select(static c => (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<IOpenApiSchema>();
}
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();
Expand Down
12 changes: 0 additions & 12 deletions src/Kiota.Builder/Extensions/OpenApiReferenceExtensions.cs

This file was deleted.

Loading
Loading