Skip to content

[release/10.0-preview4] Update to Microsoft.OpenApi v2.0.0-preview.17 #61675

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion eng/Dependencies.props
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ and are generated based on the last package release.
<LatestPackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing" />
<LatestPackageReference Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing" />
<LatestPackageReference Include="Microsoft.OpenApi" />
<LatestPackageReference Include="Microsoft.OpenApi.Readers" />
<LatestPackageReference Include="Microsoft.OpenApi.YamlReader" />
<LatestPackageReference Include="System.Buffers" />
<LatestPackageReference Include="System.CodeDom" />
<LatestPackageReference Include="System.CommandLine.Experimental" />
Expand Down
4 changes: 2 additions & 2 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,8 @@
<XunitExtensibilityExecutionVersion>$(XunitVersion)</XunitExtensibilityExecutionVersion>
<XUnitRunnerVisualStudioVersion>2.8.2</XUnitRunnerVisualStudioVersion>
<MicrosoftDataSqlClientVersion>5.2.2</MicrosoftDataSqlClientVersion>
<MicrosoftOpenApiVersion>2.0.0-preview.11</MicrosoftOpenApiVersion>
<MicrosoftOpenApiReadersVersion>2.0.0-preview.11</MicrosoftOpenApiReadersVersion>
<MicrosoftOpenApiVersion>2.0.0-preview.17</MicrosoftOpenApiVersion>
<MicrosoftOpenApiYamlReaderVersion>2.0.0-preview.17</MicrosoftOpenApiYamlReaderVersion>
<!-- dotnet tool versions (see also auto-updated DotnetEfVersion property). -->
<DotnetDumpVersion>6.0.322601</DotnetDumpVersion>
<DotnetServeVersion>1.10.93</DotnetServeVersion>
Expand Down
1 change: 0 additions & 1 deletion src/OpenApi/OpenApi.slnf
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"src\\Servers\\Connections.Abstractions\\src\\Microsoft.AspNetCore.Connections.Abstractions.csproj",
"src\\OpenApi\\test\\Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests\\Microsoft.AspNetCore.OpenApi.SourceGenerators.Tests.csproj",
"src\\OpenApi\\test\\Microsoft.AspNetCore.OpenApi.Tests\\Microsoft.AspNetCore.OpenApi.Tests.csproj",
"src\\OpenApi\\sample\\Sample.csproj",
"src\\OpenApi\\perf\\Microbenchmarks\\Microsoft.AspNetCore.OpenApi.Microbenchmarks.csproj"
]
}
Expand Down
35 changes: 31 additions & 4 deletions src/OpenApi/gen/XmlCommentGenerator.Emitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ namespace Microsoft.AspNetCore.OpenApi.Generated
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
using Microsoft.OpenApi.Any;

Expand Down Expand Up @@ -341,9 +342,7 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
var operationParameter = operation.Parameters?.SingleOrDefault(parameter => parameter.Name == parameterComment.Name);
if (operationParameter is not null)
{
var targetOperationParameter = operationParameter is OpenApiParameterReference reference
? reference.Target
: (OpenApiParameter)operationParameter;
var targetOperationParameter = UnwrapOpenApiParameter(operationParameter);
targetOperationParameter.Description = parameterComment.Description;
if (parameterComment.Example is { } jsonString)
{
Expand All @@ -359,7 +358,12 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform
requestBody.Description = parameterComment.Description;
if (parameterComment.Example is { } jsonString)
{
foreach (var mediaType in requestBody.Content.Values)
var content = requestBody?.Content?.Values;
if (content is null)
{
continue;
}
foreach (var mediaType in content)
{
mediaType.Example = jsonString.Parse();
}
Expand All @@ -383,6 +387,29 @@ public Task TransformAsync(OpenApiOperation operation, OpenApiOperationTransform

return Task.CompletedTask;
}

private static OpenApiParameter UnwrapOpenApiParameter(IOpenApiParameter sourceParameter)
{
if (sourceParameter is OpenApiParameterReference parameterReference)
{
if (parameterReference.Target is OpenApiParameter target)
{
return target;
}
else
{
throw new InvalidOperationException($"The input schema must be an {nameof(OpenApiParameter)} or {nameof(OpenApiParameterReference)}.");
}
}
else if (sourceParameter is OpenApiParameter directParameter)
{
return directParameter;
}
else
{
throw new InvalidOperationException($"The input schema must be an {nameof(OpenApiParameter)} or {nameof(OpenApiParameterReference)}.");
}
}
}

{{GeneratedCodeAttribute}}
Expand Down
2 changes: 2 additions & 0 deletions src/OpenApi/perf/Microbenchmarks/TransformersBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ public void SchemaTransformer_Setup()
{
_options.AddSchemaTransformer((schema, context, token) =>
{
schema.Extensions ??= [];
if (context.JsonTypeInfo.Type == typeof(Todo) && context.ParameterDescription != null)
{
schema.Extensions["x-my-extension"] = new OpenApiAny(context.ParameterDescription.Name);
Expand Down Expand Up @@ -175,6 +176,7 @@ private class SchemaTransformer : IOpenApiSchemaTransformer
{
public Task TransformAsync(OpenApiSchema schema, OpenApiSchemaTransformerContext context, CancellationToken cancellationToken)
{
schema.Extensions ??= [];
if (context.JsonTypeInfo.Type == typeof(Todo) && context.ParameterDescription != null)
{
schema.Extensions["x-my-extension"] = new OpenApiAny(context.ParameterDescription.Name);
Expand Down
26 changes: 13 additions & 13 deletions src/OpenApi/src/Extensions/ApiDescriptionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,30 @@
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
using System.Text;
using Microsoft.AspNetCore.Mvc.ApiExplorer;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Routing.Patterns;
using Microsoft.OpenApi.Models;

internal static class ApiDescriptionExtensions
{
/// <summary>
/// Maps the HTTP method of the ApiDescription to the OpenAPI <see cref="OperationType"/> .
/// Maps the HTTP method of the ApiDescription to the HttpMethod.
/// </summary>
/// <param name="apiDescription">The ApiDescription to resolve an operation type from.</param>
/// <returns>The <see cref="OperationType"/> associated with the given <paramref name="apiDescription"/>.</returns>
public static OperationType GetOperationType(this ApiDescription apiDescription) =>
/// <param name="apiDescription">The ApiDescription to resolve an HttpMethod from.</param>
/// <returns>The <see cref="HttpMethod"/> associated with the given <paramref name="apiDescription"/>.</returns>
public static HttpMethod GetHttpMethod(this ApiDescription apiDescription) =>
apiDescription.HttpMethod?.ToUpperInvariant() switch
{
"GET" => OperationType.Get,
"POST" => OperationType.Post,
"PUT" => OperationType.Put,
"DELETE" => OperationType.Delete,
"PATCH" => OperationType.Patch,
"HEAD" => OperationType.Head,
"OPTIONS" => OperationType.Options,
"TRACE" => OperationType.Trace,
"GET" => HttpMethod.Get,
"POST" => HttpMethod.Post,
"PUT" => HttpMethod.Put,
"DELETE" => HttpMethod.Delete,
"PATCH" => HttpMethod.Patch,
"HEAD" => HttpMethod.Head,
"OPTIONS" => HttpMethod.Options,
"TRACE" => HttpMethod.Trace,
_ => throw new InvalidOperationException($"Unsupported HTTP method: {apiDescription.HttpMethod}"),
};

Expand Down
2 changes: 1 addition & 1 deletion src/OpenApi/src/Extensions/JsonNodeSchemaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ internal static void MapPolymorphismOptionsToDiscriminator(this JsonNode schema,
// that we hardcode here. We could use `OpenApiReference` to construct the reference and
// serialize it but we use a hardcoded string here to avoid allocating a new object and
// working around Microsoft.OpenApi's serialization libraries.
mappings[$"{discriminator}"] = $"#/components/schemas/{createSchemaReferenceId(context.TypeInfo)}{createSchemaReferenceId(jsonDerivedType)}";
mappings[$"{discriminator}"] = $"{createSchemaReferenceId(context.TypeInfo)}{createSchemaReferenceId(jsonDerivedType)}";
}
}
schema[OpenApiSchemaKeywords.DiscriminatorKeyword] = polymorphismOptions.TypeDiscriminatorPropertyName;
Expand Down
23 changes: 15 additions & 8 deletions src/OpenApi/src/Schemas/OpenApiJsonSchema.Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.OpenApi;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.Models.Interfaces;
using Microsoft.OpenApi.Models.References;
using OpenApiConstants = Microsoft.AspNetCore.OpenApi.OpenApiConstants;

internal sealed partial class OpenApiJsonSchema
Expand Down Expand Up @@ -256,12 +258,12 @@ public static void ReadProperty(ref Utf8JsonReader reader, string propertyName,
case OpenApiSchemaKeywords.MinimumKeyword:
reader.Read();
var minimum = reader.GetDecimal();
schema.Minimum = minimum;
schema.Minimum = minimum.ToString(CultureInfo.InvariantCulture);
break;
case OpenApiSchemaKeywords.MaximumKeyword:
reader.Read();
var maximum = reader.GetDecimal();
schema.Maximum = maximum;
schema.Maximum = maximum.ToString(CultureInfo.InvariantCulture);
break;
case OpenApiSchemaKeywords.PatternKeyword:
reader.Read();
Expand Down Expand Up @@ -302,25 +304,30 @@ public static void ReadProperty(ref Utf8JsonReader reader, string propertyName,
var mappings = ReadDictionary<string>(ref reader);
if (mappings is not null)
{
schema.Discriminator.Mapping = mappings;
schema.Discriminator ??= new OpenApiDiscriminator();
foreach (var kvp in mappings)
{
schema.Discriminator.Mapping ??= [];
schema.Discriminator.Mapping[kvp.Key] = new OpenApiSchemaReference(kvp.Value);
}
}
break;
case OpenApiConstants.SchemaId:
reader.Read();
schema.Annotations ??= new Dictionary<string, object>();
schema.Annotations.Add(OpenApiConstants.SchemaId, reader.GetString());
schema.Metadata ??= [];
schema.Metadata.Add(OpenApiConstants.SchemaId, reader.GetString() ?? string.Empty);
break;
// OpenAPI does not support the `const` keyword in its schema implementation, so
// we map it to its closest approximation, an enum with a single value, here.
case OpenApiSchemaKeywords.ConstKeyword:
reader.Read();
schema.Enum = [ReadJsonNode(ref reader, out var constType)];
schema.Enum = ReadJsonNode(ref reader, out var constType) is { } jsonNode ? [jsonNode] : [];
schema.Type = constType;
break;
case OpenApiSchemaKeywords.RefKeyword:
reader.Read();
schema.Annotations ??= new Dictionary<string, object>();
schema.Annotations[OpenApiConstants.RefId] = reader.GetString();
schema.Metadata ??= [];
schema.Metadata[OpenApiConstants.RefId] = reader.GetString() ?? string.Empty;
break;
default:
reader.Skip();
Expand Down
24 changes: 12 additions & 12 deletions src/OpenApi/src/Services/OpenApiConstants.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.OpenApi.Models;
using System.Net.Http;

namespace Microsoft.AspNetCore.OpenApi;

Expand All @@ -14,19 +14,19 @@ internal static class OpenApiConstants
internal const string SchemaId = "x-schema-id";
internal const string RefId = "x-ref-id";
internal const string DefaultOpenApiResponseKey = "default";
// Since there's a finite set of operation types that can be included in a given
// OpenApiPaths, we can pre-allocate an array of these types and use a direct
// Since there's a finite set of HTTP methods that can be included in a given
// OpenApiPaths, we can pre-allocate an array of these methods and use a direct
// lookup on the OpenApiPaths dictionary to avoid allocating an enumerator
// over the KeyValuePairs in OpenApiPaths.
internal static readonly OperationType[] OperationTypes = [
OperationType.Get,
OperationType.Post,
OperationType.Put,
OperationType.Delete,
OperationType.Options,
OperationType.Head,
OperationType.Patch,
OperationType.Trace
internal static readonly HttpMethod[] HttpMethods = [
HttpMethod.Get,
HttpMethod.Post,
HttpMethod.Put,
HttpMethod.Delete,
HttpMethod.Options,
HttpMethod.Head,
HttpMethod.Patch,
HttpMethod.Trace
];
// Represents primitive types that should never be represented as
// a schema reference and always inlined.
Expand Down
Loading
Loading