Skip to content

Commit 2348814

Browse files
Merge branch 'dev' into fix/enum-parsing
2 parents fd25660 + e9e214f commit 2348814

File tree

58 files changed

+488
-435
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+488
-435
lines changed

src/Microsoft.OpenApi.Hidi/OpenApiService.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ public static async Task TransformOpenApiDocumentAsync(HidiOptions options, ILog
113113
var walker = new OpenApiWalker(powerShellFormatter);
114114
walker.Walk(document);
115115
}
116-
WriteOpenApi(options, openApiFormat, openApiVersion, document, logger);
116+
await WriteOpenApiAsync(options, openApiFormat, openApiVersion, document, logger, cancellationToken).ConfigureAwait(false);
117117
}
118118
catch (TaskCanceledException)
119119
{
@@ -191,7 +191,7 @@ private static OpenApiDocument ApplyFilters(HidiOptions options, ILogger logger,
191191
return document;
192192
}
193193

194-
private static void WriteOpenApi(HidiOptions options, OpenApiFormat openApiFormat, OpenApiSpecVersion openApiVersion, OpenApiDocument document, ILogger logger)
194+
private static async Task WriteOpenApiAsync(HidiOptions options, OpenApiFormat openApiFormat, OpenApiSpecVersion openApiVersion, OpenApiDocument document, ILogger logger, CancellationToken cancellationToken)
195195
{
196196
using (logger.BeginScope("Output"))
197197
{
@@ -216,11 +216,11 @@ private static void WriteOpenApi(HidiOptions options, OpenApiFormat openApiForma
216216

217217
var stopwatch = new Stopwatch();
218218
stopwatch.Start();
219-
document.Serialize(writer, openApiVersion);
219+
await document.SerializeAsync(writer, openApiVersion, cancellationToken).ConfigureAwait(false);
220220
stopwatch.Stop();
221221

222222
logger.LogTrace("Finished serializing in {ElapsedMilliseconds}ms", stopwatch.ElapsedMilliseconds);
223-
textWriter.Flush();
223+
await textWriter.FlushAsync(cancellationToken).ConfigureAwait(false);
224224
}
225225
}
226226

@@ -769,7 +769,7 @@ internal static async Task PluginManifestAsync(HidiOptions options, ILogger logg
769769
// Write OpenAPI to Output folder
770770
options.Output = new(Path.Combine(options.OutputFolder, "openapi.json"));
771771
options.TerseOutput = true;
772-
WriteOpenApi(options, OpenApiFormat.Json, OpenApiSpecVersion.OpenApi3_1, document, logger);
772+
await WriteOpenApiAsync(options, OpenApiFormat.Json, OpenApiSpecVersion.OpenApi3_1, document, logger, cancellationToken).ConfigureAwait(false);
773773

774774
// Create OpenAIPluginManifest from ApiDependency and OpenAPI document
775775
var manifest = new OpenAIPluginManifest(document.Info?.Title ?? "Title", document.Info?.Title ?? "Title", "https://go.microsoft.com/fwlink/?LinkID=288890", document.Info?.Contact?.Email ?? "[email protected]", document.Info?.License?.Url.ToString() ?? "https://placeholderlicenseurl.com")

src/Microsoft.OpenApi.Workbench/MainModel.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ internal async Task ParseDocumentAsync()
270270

271271
stopwatch.Reset();
272272
stopwatch.Start();
273-
Output = WriteContents(document);
273+
Output = await WriteContentsAsync(document);
274274
stopwatch.Stop();
275275

276276
RenderTime = $"{stopwatch.ElapsedMilliseconds} ms";
@@ -299,23 +299,23 @@ internal async Task ParseDocumentAsync()
299299
/// <summary>
300300
/// Write content from the given document based on the format and version set in this class.
301301
/// </summary>
302-
private string WriteContents(OpenApiDocument document)
302+
private async Task<string> WriteContentsAsync(OpenApiDocument document)
303303
{
304304
var outputStream = new MemoryStream();
305305

306-
document.Serialize(
306+
await document.SerializeAsync(
307307
outputStream,
308308
Version,
309309
Format,
310-
new()
310+
(Writers.OpenApiWriterSettings)new()
311311
{
312312
InlineLocalReferences = InlineLocal,
313313
InlineExternalReferences = InlineExternal
314314
});
315315

316316
outputStream.Position = 0;
317317

318-
return new StreamReader(outputStream).ReadToEnd();
318+
return await new StreamReader(outputStream).ReadToEndAsync();
319319
}
320320

321321
private static MemoryStream CreateStream(string text)

src/Microsoft.OpenApi/Extensions/OpenApiSerializableExtensions.cs

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
using System.Globalization;
55
using System.IO;
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using Microsoft.OpenApi.Exceptions;
79
using Microsoft.OpenApi.Interfaces;
810
using Microsoft.OpenApi.Properties;
@@ -22,10 +24,11 @@ public static class OpenApiSerializableExtensions
2224
/// <param name="element">The Open API element.</param>
2325
/// <param name="stream">The output stream.</param>
2426
/// <param name="specVersion">The Open API specification version.</param>
25-
public static void SerializeAsJson<T>(this T element, Stream stream, OpenApiSpecVersion specVersion)
27+
/// <param name="cancellationToken">The cancellation token.</param>
28+
public static Task SerializeAsJsonAsync<T>(this T element, Stream stream, OpenApiSpecVersion specVersion, CancellationToken cancellationToken = default)
2629
where T : IOpenApiSerializable
2730
{
28-
element.Serialize(stream, specVersion, OpenApiFormat.Json);
31+
return element.SerializeAsync(stream, specVersion, OpenApiFormat.Json, cancellationToken);
2932
}
3033

3134
/// <summary>
@@ -35,10 +38,11 @@ public static void SerializeAsJson<T>(this T element, Stream stream, OpenApiSpec
3538
/// <param name="element">The Open API element.</param>
3639
/// <param name="stream">The output stream.</param>
3740
/// <param name="specVersion">The Open API specification version.</param>
38-
public static void SerializeAsYaml<T>(this T element, Stream stream, OpenApiSpecVersion specVersion)
41+
/// <param name="cancellationToken">The cancellation token.</param>
42+
public static Task SerializeAsYamlAsync<T>(this T element, Stream stream, OpenApiSpecVersion specVersion, CancellationToken cancellationToken = default)
3943
where T : IOpenApiSerializable
4044
{
41-
element.Serialize(stream, specVersion, OpenApiFormat.Yaml);
45+
return element.SerializeAsync(stream, specVersion, OpenApiFormat.Yaml, cancellationToken);
4246
}
4347

4448
/// <summary>
@@ -50,14 +54,16 @@ public static void SerializeAsYaml<T>(this T element, Stream stream, OpenApiSpec
5054
/// <param name="stream">The given stream.</param>
5155
/// <param name="specVersion">The Open API specification version.</param>
5256
/// <param name="format">The output format (JSON or YAML).</param>
53-
public static void Serialize<T>(
57+
/// <param name="cancellationToken">The cancellation token.</param>
58+
public static Task SerializeAsync<T>(
5459
this T element,
5560
Stream stream,
5661
OpenApiSpecVersion specVersion,
57-
OpenApiFormat format)
62+
OpenApiFormat format,
63+
CancellationToken cancellationToken = default)
5864
where T : IOpenApiSerializable
5965
{
60-
element.Serialize(stream, specVersion, format, null);
66+
return element.SerializeAsync(stream, specVersion, format, null, cancellationToken);
6167
}
6268

6369
/// <summary>
@@ -70,12 +76,14 @@ public static void Serialize<T>(
7076
/// <param name="specVersion">The Open API specification version.</param>
7177
/// <param name="format">The output format (JSON or YAML).</param>
7278
/// <param name="settings">Provide configuration settings for controlling writing output</param>
73-
public static void Serialize<T>(
79+
/// <param name="cancellationToken">The cancellation token.</param>
80+
public static Task SerializeAsync<T>(
7481
this T element,
7582
Stream stream,
7683
OpenApiSpecVersion specVersion,
7784
OpenApiFormat format,
78-
OpenApiWriterSettings settings)
85+
OpenApiWriterSettings settings,
86+
CancellationToken cancellationToken = default)
7987
where T : IOpenApiSerializable
8088
{
8189
Utils.CheckArgumentNull(stream);
@@ -88,7 +96,7 @@ public static void Serialize<T>(
8896
OpenApiFormat.Yaml => new OpenApiYamlWriter(streamWriter, settings),
8997
_ => throw new OpenApiException(string.Format(SRResource.OpenApiFormatNotSupported, format)),
9098
};
91-
element.Serialize(writer, specVersion);
99+
return element.SerializeAsync(writer, specVersion, cancellationToken);
92100
}
93101

94102
/// <summary>
@@ -98,7 +106,8 @@ public static void Serialize<T>(
98106
/// <param name="element">The Open API element.</param>
99107
/// <param name="writer">The output writer.</param>
100108
/// <param name="specVersion">Version of the specification the output should conform to</param>
101-
public static void Serialize<T>(this T element, IOpenApiWriter writer, OpenApiSpecVersion specVersion)
109+
/// <param name="cancellationToken">The cancellation token.</param>
110+
public static Task SerializeAsync<T>(this T element, IOpenApiWriter writer, OpenApiSpecVersion specVersion, CancellationToken cancellationToken = default)
102111
where T : IOpenApiSerializable
103112
{
104113
Utils.CheckArgumentNull(element);
@@ -122,7 +131,7 @@ public static void Serialize<T>(this T element, IOpenApiWriter writer, OpenApiSp
122131
throw new OpenApiException(string.Format(SRResource.OpenApiSpecVersionNotSupported, specVersion));
123132
}
124133

125-
writer.Flush();
134+
return writer.FlushAsync(cancellationToken);
126135
}
127136

128137
/// <summary>
@@ -131,12 +140,14 @@ public static void Serialize<T>(this T element, IOpenApiWriter writer, OpenApiSp
131140
/// <typeparam name="T">the <see cref="IOpenApiSerializable"/></typeparam>
132141
/// <param name="element">The Open API element.</param>
133142
/// <param name="specVersion">The Open API specification version.</param>
134-
public static string SerializeAsJson<T>(
143+
/// <param name="cancellationToken">The cancellation token.</param>
144+
public static Task<string> SerializeAsJsonAsync<T>(
135145
this T element,
136-
OpenApiSpecVersion specVersion)
146+
OpenApiSpecVersion specVersion,
147+
CancellationToken cancellationToken = default)
137148
where T : IOpenApiSerializable
138149
{
139-
return element.Serialize(specVersion, OpenApiFormat.Json);
150+
return element.SerializeAsync(specVersion, OpenApiFormat.Json, cancellationToken);
140151
}
141152

142153
/// <summary>
@@ -145,12 +156,14 @@ public static string SerializeAsJson<T>(
145156
/// <typeparam name="T">the <see cref="IOpenApiSerializable"/></typeparam>
146157
/// <param name="element">The Open API element.</param>
147158
/// <param name="specVersion">The Open API specification version.</param>
148-
public static string SerializeAsYaml<T>(
159+
/// <param name="cancellationToken">The cancellation token.</param>
160+
public static Task<string> SerializeAsYamlAsync<T>(
149161
this T element,
150-
OpenApiSpecVersion specVersion)
162+
OpenApiSpecVersion specVersion,
163+
CancellationToken cancellationToken = default)
151164
where T : IOpenApiSerializable
152165
{
153-
return element.Serialize(specVersion, OpenApiFormat.Yaml);
166+
return element.SerializeAsync(specVersion, OpenApiFormat.Yaml, cancellationToken);
154167
}
155168

156169
/// <summary>
@@ -160,20 +173,26 @@ public static string SerializeAsYaml<T>(
160173
/// <param name="element">The Open API element.</param>
161174
/// <param name="specVersion">The Open API specification version.</param>
162175
/// <param name="format">Open API document format.</param>
163-
public static string Serialize<T>(
176+
/// <param name="cancellationToken">The cancellation token.</param>
177+
public static async Task<string> SerializeAsync<T>(
164178
this T element,
165179
OpenApiSpecVersion specVersion,
166-
OpenApiFormat format)
180+
OpenApiFormat format,
181+
CancellationToken cancellationToken = default)
167182
where T : IOpenApiSerializable
168183
{
169184
Utils.CheckArgumentNull(element);
170185

171186
using var stream = new MemoryStream();
172-
element.Serialize(stream, specVersion, format);
187+
await element.SerializeAsync(stream, specVersion, format, cancellationToken).ConfigureAwait(false);
173188
stream.Position = 0;
174189

175190
using var streamReader = new StreamReader(stream);
176-
return streamReader.ReadToEnd();
191+
#if NET7_0_OR_GREATER
192+
return await streamReader.ReadToEndAsync(cancellationToken).ConfigureAwait(false);
193+
#else
194+
return await streamReader.ReadToEndAsync().ConfigureAwait(false);
195+
#endif
177196
}
178197
}
179198
}

src/Microsoft.OpenApi/Microsoft.OpenApi.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFramework>netstandard2.0</TargetFramework>
3+
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
44
<LangVersion>Latest</LangVersion>
55
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
66
<Version>2.0.0-preview4</Version>

src/Microsoft.OpenApi/Models/OpenApiComponents.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ private void RenderComponents(IOpenApiWriter writer, Action<IOpenApiWriter, IOpe
318318
{
319319
var loops = writer.GetSettings().LoopDetector.Loops;
320320
writer.WriteStartObject();
321-
if (loops.TryGetValue(typeof(OpenApiSchema), out List<object> schemas))
321+
if (loops.TryGetValue(typeof(OpenApiSchema), out var schemas))
322322
{
323323
writer.WriteOptionalMap(OpenApiConstants.Schemas, Schemas, callback);
324324
}

src/Microsoft.OpenApi/Models/OpenApiDocument.cs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,6 @@ public class OpenApiDocument : IOpenApiSerializable, IOpenApiExtensible, IOpenAp
8383
/// </summary>
8484
public IDictionary<string, IOpenApiExtension>? Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
8585

86-
/// <summary>
87-
/// The unique hash code of the generated OpenAPI document
88-
/// </summary>
89-
public string HashCode => GenerateHashValue(this);
90-
9186
/// <inheritdoc />
9287
public IDictionary<string, object>? Annotations { get; set; }
9388

@@ -243,7 +238,7 @@ public void SerializeAsV2(IOpenApiWriter writer)
243238
{
244239
var loops = writer.GetSettings().LoopDetector.Loops;
245240

246-
if (loops.TryGetValue(typeof(OpenApiSchema), out List<object> schemas))
241+
if (loops.TryGetValue(typeof(OpenApiSchema), out var schemas))
247242
{
248243
var openApiSchemas = schemas.Cast<OpenApiSchema>().Distinct().ToList()
249244
.ToDictionary<OpenApiSchema, string>(k => k.Reference.Id);
@@ -414,14 +409,15 @@ private static void WriteHostInfoV2(IOpenApiWriter writer, IList<OpenApiServer>?
414409
return url;
415410
})
416411
.Where(
417-
u => Uri.Compare(
412+
u => u is not null &&
413+
Uri.Compare(
418414
u,
419415
firstServerUrl,
420416
UriComponents.Host | UriComponents.Port | UriComponents.Path,
421417
UriFormat.SafeUnescaped,
422418
StringComparison.OrdinalIgnoreCase) ==
423419
0 && u.IsAbsoluteUri)
424-
.Select(u => u.Scheme)
420+
.Select(u => u!.Scheme)
425421
.Distinct()
426422
.ToList();
427423

@@ -457,22 +453,24 @@ public void SetReferenceHostDocument()
457453
/// <summary>
458454
/// Takes in an OpenApi document instance and generates its hash value
459455
/// </summary>
460-
/// <param name="doc">The OpenAPI description to hash.</param>
456+
/// <param name="cancellationToken">Propagates notification that operations should be canceled.</param>
461457
/// <returns>The hash value.</returns>
462-
public static string GenerateHashValue(OpenApiDocument doc)
458+
public async Task<string> GetHashCodeAsync(CancellationToken cancellationToken = default)
463459
{
464460
using HashAlgorithm sha = SHA512.Create();
465461
using var cryptoStream = new CryptoStream(Stream.Null, sha, CryptoStreamMode.Write);
466462
using var streamWriter = new StreamWriter(cryptoStream);
467463

468464
var openApiJsonWriter = new OpenApiJsonWriter(streamWriter, new() { Terse = true });
469-
doc.SerializeAsV3(openApiJsonWriter);
470-
openApiJsonWriter.Flush();
465+
SerializeAsV3(openApiJsonWriter);
466+
await openApiJsonWriter.FlushAsync(cancellationToken).ConfigureAwait(false);
471467

468+
#if NET5_0_OR_GREATER
469+
await cryptoStream.FlushFinalBlockAsync(cancellationToken).ConfigureAwait(false);
470+
#else
472471
cryptoStream.FlushFinalBlock();
473-
var hash = sha.Hash;
474-
475-
return ConvertByteArrayToString(hash);
472+
#endif
473+
return ConvertByteArrayToString(sha.Hash ?? []);
476474
}
477475

478476
private static string ConvertByteArrayToString(byte[] hash)

src/Microsoft.OpenApi/Models/OpenApiOperation.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,11 @@ public void SerializeAsV2(IOpenApiWriter writer)
283283
{
284284
var produces = Responses
285285
.Where(static r => r.Value.Content != null)
286-
.SelectMany(static r => r.Value.Content?.Keys)
286+
.SelectMany(static r => r.Value.Content?.Keys ?? [])
287287
.Concat(
288288
Responses
289289
.Where(static r => r.Value.Reference is {HostDocument: not null})
290-
.SelectMany(static r => r.Value.Content?.Keys))
290+
.SelectMany(static r => r.Value.Content?.Keys ?? []))
291291
.Distinct(StringComparer.OrdinalIgnoreCase)
292292
.ToArray();
293293

src/Microsoft.OpenApi/Reader/OpenApiModelFactory.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,11 @@ public static async Task<ReadResult> LoadAsync(Stream input, string format = nul
129129
var result = await InternalLoadAsync(preparedStream, format, settings, cancellationToken).ConfigureAwait(false);
130130
if (!settings.LeaveStreamOpen)
131131
{
132+
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP || NET5_0_OR_GREATER
133+
await input.DisposeAsync().ConfigureAwait(false);
134+
#else
132135
input.Dispose();
136+
#endif
133137
}
134138
return result;
135139
}

src/Microsoft.OpenApi/Writers/IOpenApiWriter.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT license.
33

4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
47
namespace Microsoft.OpenApi.Writers
58
{
69
/// <summary>
@@ -71,6 +74,7 @@ public interface IOpenApiWriter
7174
/// <summary>
7275
/// Flush the writer.
7376
/// </summary>
74-
void Flush();
77+
/// <param name="cancellationToken">The cancellation token.</param>
78+
Task FlushAsync(CancellationToken cancellationToken = default);
7579
}
7680
}

0 commit comments

Comments
 (0)