Skip to content

Commit 78b8d88

Browse files
Merge branch 'main' into feat/enable-NRT
2 parents ea5c389 + 85c3a4e commit 78b8d88

Some content is hidden

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

41 files changed

+516
-196
lines changed

.release-please-manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
{
2-
".": "2.0.0-preview7"
2+
".": "2.0.0-preview8"
33
}

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## [2.0.0-preview8](https://github.com/microsoft/OpenAPI.NET/compare/v2.0.0-preview7...v2.0.0-preview8) (2025-02-17)
4+
5+
6+
### Bug Fixes
7+
8+
* a bug where external reference loading for local files would not work on linux ([df99a00](https://github.com/microsoft/OpenAPI.NET/commit/df99a00010001b35b34f9b74bbf12437f90b6b18))
9+
* add meaningful exception message during validation ([4a6547d](https://github.com/microsoft/OpenAPI.NET/commit/4a6547d08c86194e1783ce7f52e8248ca15556e0))
10+
* add meaningful exception message during validation ([74d20ed](https://github.com/microsoft/OpenAPI.NET/commit/74d20edebb6c5ee6150e8e03a42a40ed8c01d1da))
11+
* adds a cancellation token argument to external document loading ([a5ffab1](https://github.com/microsoft/OpenAPI.NET/commit/a5ffab1e77c19987fe468b9297e19e8f4c48f47a))
12+
* parsing failure on nodes set to null ([20aacc1](https://github.com/microsoft/OpenAPI.NET/commit/20aacc1a21510dbfe8cb21fb6ec2fc8b7720f2aa))
13+
* parsing failure on nodes set to null ([4245de9](https://github.com/microsoft/OpenAPI.NET/commit/4245de9ff333a1d34e125ba72c543b6e78db6980))
14+
315
## [2.0.0-preview7](https://github.com/microsoft/OpenAPI.NET/compare/v2.0.0-preview6...v2.0.0-preview7) (2025-02-06)
416

517

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<PackageProjectUrl>https://github.com/Microsoft/OpenAPI.NET</PackageProjectUrl>
1313
<Copyright>© Microsoft Corporation. All rights reserved.</Copyright>
1414
<PackageTags>OpenAPI .NET</PackageTags>
15-
<Version>2.0.0-preview7</Version>
15+
<Version>2.0.0-preview8</Version>
1616
</PropertyGroup>
1717
<!-- https://github.com/clairernovotny/DeterministicBuilds#deterministic-builds -->
1818
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">

src/Microsoft.OpenApi.Hidi/Extensions/OpenApiExtensibleExtensions.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Microsoft.OpenApi.Any;
22
using Microsoft.OpenApi.Interfaces;
33
using System.Collections.Generic;
4+
using System.Text.Json.Nodes;
45

56
namespace Microsoft.OpenApi.Hidi.Extensions
67
{
@@ -14,9 +15,9 @@ internal static class OpenApiExtensibleExtensions
1415
/// <returns>A <see cref="string"/> value matching the provided extensionKey. Return null when extensionKey is not found. </returns>
1516
internal static string GetExtension(this IDictionary<string, IOpenApiExtension> extensions, string extensionKey)
1617
{
17-
if (extensions.TryGetValue(extensionKey, out var value) && value is OpenApiAny castValue && castValue.Node is not null)
18+
if (extensions.TryGetValue(extensionKey, out var value) && value is OpenApiAny { Node: JsonValue castValue } && castValue.TryGetValue<string>(out var stringValue))
1819
{
19-
return castValue.Node.GetValue<string>();
20+
return stringValue;
2021
}
2122
return string.Empty;
2223
}

src/Microsoft.OpenApi.Hidi/Microsoft.OpenApi.Hidi.csproj

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
3131
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.2" />
3232
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.2" />
33-
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0" />
33+
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.2" />
3434
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.2" />
3535
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.13.2">
3636
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -39,12 +39,8 @@
3939
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
4040
<PackageReference Include="Microsoft.OData.Edm" Version="8.2.3" />
4141
<PackageReference Include="Microsoft.OpenApi.OData" Version="2.0.0-preview8" />
42-
<PackageReference Include="Microsoft.OpenApi.ApiManifest" Version="0.5.6-preview" />
42+
<PackageReference Include="Microsoft.OpenApi.ApiManifest" Version="2.0.0-preview1" />
4343
<PackageReference Include="System.CommandLine.Hosting" Version="0.4.0-alpha.22272.1" />
44-
<!--STJ
45-
required until Microsoft.Extensions.Logging.Console and Microsoft.Extensions.Configuration.Json
46-
update their dependencies -->
47-
<PackageReference Include="System.Text.Json" Version="9.0.0" />
4844
</ItemGroup>
4945

5046
<ItemGroup>

src/Microsoft.OpenApi.Workbench/MainModel.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,6 @@ internal async Task ParseDocumentAsync()
236236

237237
var settings = new OpenApiReaderSettings
238238
{
239-
ReferenceResolution = ResolveExternal ? ReferenceResolutionSetting.ResolveAllReferences : ReferenceResolutionSetting.ResolveLocalReferences,
240239
RuleSet = ValidationRuleSet.GetDefaultRuleSet()
241240
};
242241
if (ResolveExternal && !string.IsNullOrWhiteSpace(_inputFile))

src/Microsoft.OpenApi.Workbench/Microsoft.OpenApi.Workbench.csproj

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@
99
<NoWarn>NU1903</NoWarn>
1010
</PropertyGroup>
1111
<ItemGroup>
12-
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.12.19">
12+
<PackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.13.2">
1313
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1414
<PrivateAssets>all</PrivateAssets>
1515
</PackageReference>
16-
<PackageReference Include="Microsoft.Windows.Compatibility" Version="9.0.1" />
17-
<!-- Microsoft.Windows.Compatibility 8.0.8 depends on 8.0.0 this dependency can be removed once they update theirs -->
18-
<PackageReference Include="System.Formats.Asn1" Version="9.0.1" />
16+
<PackageReference Include="Microsoft.Windows.Compatibility" Version="9.0.2" />
1917
</ItemGroup>
2018
<ItemGroup>
2119
<Resource Include="Themes\Metro\HowToApplyTheme.txt" />

src/Microsoft.OpenApi/Extensions/OpenApiTypeMapper.cs

Lines changed: 91 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Linq;
67
using Microsoft.OpenApi.Exceptions;
78
using Microsoft.OpenApi.Models;
89

@@ -19,34 +20,61 @@ public static class OpenApiTypeMapper
1920
/// </summary>
2021
/// <param name="schemaType"></param>
2122
/// <returns></returns>
22-
public static string? ToIdentifier(this JsonSchemaType? schemaType)
23+
public static string[]? ToIdentifiers(this JsonSchemaType? schemaType)
2324
{
2425
if (schemaType is null)
2526
{
2627
return null;
2728
}
28-
return schemaType.Value.ToIdentifier();
29+
return schemaType.Value.ToIdentifiers();
2930
}
3031

3132
/// <summary>
3233
/// Maps a JsonSchema data type to an identifier.
3334
/// </summary>
3435
/// <param name="schemaType"></param>
3536
/// <returns></returns>
36-
public static string? ToIdentifier(this JsonSchemaType schemaType)
37+
public static string[] ToIdentifiers(this JsonSchemaType schemaType)
3738
{
38-
return schemaType switch
39-
{
40-
JsonSchemaType.Null => "null",
41-
JsonSchemaType.Boolean => "boolean",
42-
JsonSchemaType.Integer => "integer",
43-
JsonSchemaType.Number => "number",
44-
JsonSchemaType.String => "string",
45-
JsonSchemaType.Array => "array",
46-
JsonSchemaType.Object => "object",
47-
_ => null,
48-
};
39+
return schemaType.ToIdentifiersInternal().ToArray();
40+
}
41+
42+
private static readonly Dictionary<JsonSchemaType, string> allSchemaTypes = new()
43+
{
44+
{ JsonSchemaType.Boolean, "boolean" },
45+
{ JsonSchemaType.Integer, "integer" },
46+
{ JsonSchemaType.Number, "number" },
47+
{ JsonSchemaType.String, "string" },
48+
{ JsonSchemaType.Object, "object" },
49+
{ JsonSchemaType.Array, "array" },
50+
{ JsonSchemaType.Null, "null" }
51+
};
52+
53+
private static IEnumerable<string> ToIdentifiersInternal(this JsonSchemaType schemaType)
54+
{
55+
return allSchemaTypes.Where(kvp => schemaType.HasFlag(kvp.Key)).Select(static kvp => kvp.Value);
56+
}
57+
58+
/// <summary>
59+
/// Returns the first identifier from a string array.
60+
/// </summary>
61+
/// <param name="schemaType"></param>
62+
/// <returns></returns>
63+
internal static string ToFirstIdentifier(this JsonSchemaType schemaType)
64+
{
65+
return schemaType.ToIdentifiersInternal().First();
66+
}
67+
68+
/// <summary>
69+
/// Returns a single identifier from an array with only one item.
70+
/// </summary>
71+
/// <param name="schemaType"></param>
72+
/// <returns></returns>
73+
internal static string ToSingleIdentifier(this JsonSchemaType schemaType)
74+
{
75+
return schemaType.ToIdentifiersInternal().Single();
4976
}
77+
5078
#nullable restore
5179

5280
/// <summary>
@@ -70,6 +98,26 @@ public static JsonSchemaType ToJsonSchemaType(this string identifier)
7098
};
7199
}
72100

101+
/// <summary>
102+
/// Converts a schema type's identifier into the enum equivalent
103+
/// </summary>
104+
/// <param name="identifier"></param>
105+
/// <returns></returns>
106+
public static JsonSchemaType? ToJsonSchemaType(this string[] identifier)
107+
{
108+
if (identifier == null)
109+
{
110+
return null;
111+
}
112+
113+
JsonSchemaType type = 0;
114+
foreach (var id in identifier)
115+
{
116+
type |= id.ToJsonSchemaType();
117+
}
118+
return type;
119+
}
120+
73121
private static readonly Dictionary<Type, Func<OpenApiSchema>> _simpleTypeToOpenApiSchema = new()
74122
{
75123
[typeof(bool)] = () => new() { Type = JsonSchemaType.Boolean },
@@ -141,7 +189,7 @@ public static OpenApiSchema MapTypeToOpenApiPrimitiveType(this Type type)
141189
}
142190

143191
/// <summary>
144-
/// Maps an JsonSchema data type and format to a simple type.
192+
/// Maps a JsonSchema data type and format to a simple type.
145193
/// </summary>
146194
/// <param name="schema">The OpenApi data type</param>
147195
/// <returns>The simple type</returns>
@@ -153,37 +201,36 @@ public static Type MapOpenApiPrimitiveTypeToSimpleType(this OpenApiSchema schema
153201
throw new ArgumentNullException(nameof(schema));
154202
}
155203

156-
var type = ((schema.Type & ~JsonSchemaType.Null).ToIdentifier(), schema.Format?.ToLowerInvariant(), schema.Type & JsonSchemaType.Null) switch
204+
var type = (schema.Type, schema.Format?.ToLowerInvariant()) switch
157205
{
158-
("integer" or "number", "int32", JsonSchemaType.Null) => typeof(int?),
159-
("integer" or "number", "int64", JsonSchemaType.Null) => typeof(long?),
160-
("integer", null, JsonSchemaType.Null) => typeof(long?),
161-
("number", "float", JsonSchemaType.Null) => typeof(float?),
162-
("number", "double", JsonSchemaType.Null) => typeof(double?),
163-
("number", null, JsonSchemaType.Null) => typeof(double?),
164-
("number", "decimal", JsonSchemaType.Null) => typeof(decimal?),
165-
("string", "byte", JsonSchemaType.Null) => typeof(byte?),
166-
("string", "date-time", JsonSchemaType.Null) => typeof(DateTimeOffset?),
167-
("string", "uuid", JsonSchemaType.Null) => typeof(Guid?),
168-
("string", "char", JsonSchemaType.Null) => typeof(char?),
169-
("boolean", null, JsonSchemaType.Null) => typeof(bool?),
170-
("boolean", null, _) => typeof(bool),
206+
(JsonSchemaType.Integer | JsonSchemaType.Null or JsonSchemaType.Number | JsonSchemaType.Null, "int32") => typeof(int?),
207+
(JsonSchemaType.Integer | JsonSchemaType.Null or JsonSchemaType.Number | JsonSchemaType.Null, "int64") => typeof(long?),
208+
(JsonSchemaType.Integer | JsonSchemaType.Null, null) => typeof(long?),
209+
(JsonSchemaType.Number | JsonSchemaType.Null, "float") => typeof(float?),
210+
(JsonSchemaType.Number | JsonSchemaType.Null, "double") => typeof(double?),
211+
(JsonSchemaType.Number | JsonSchemaType.Null, null) => typeof(double?),
212+
(JsonSchemaType.Number | JsonSchemaType.Null, "decimal") => typeof(decimal?),
213+
(JsonSchemaType.String | JsonSchemaType.Null, "byte") => typeof(byte?),
214+
(JsonSchemaType.String | JsonSchemaType.Null, "date-time") => typeof(DateTimeOffset?),
215+
(JsonSchemaType.String | JsonSchemaType.Null, "uuid") => typeof(Guid?),
216+
(JsonSchemaType.String | JsonSchemaType.Null, "char") => typeof(char?),
217+
(JsonSchemaType.Boolean | JsonSchemaType.Null, null) => typeof(bool?),
218+
(JsonSchemaType.Boolean, null) => typeof(bool),
171219
// integer is technically not valid with format, but we must provide some compatibility
172-
("integer" or "number", "int32", _) => typeof(int),
173-
("integer" or "number", "int64", _) => typeof(long),
174-
("integer", null, _) => typeof(long),
175-
("number", "float", _) => typeof(float),
176-
("number", "double", _) => typeof(double),
177-
("number", "decimal", _) => typeof(decimal),
178-
("number", null, _) => typeof(double),
179-
("string", "byte", _) => typeof(byte),
180-
("string", "date-time", _) => typeof(DateTimeOffset),
181-
("string", "uuid", _) => typeof(Guid),
182-
("string", "duration", _) => typeof(TimeSpan),
183-
("string", "char", _) => typeof(char),
184-
("string", null, _) => typeof(string),
185-
("object", null, _) => typeof(object),
186-
("string", "uri", _) => typeof(Uri),
220+
(JsonSchemaType.Integer or JsonSchemaType.Number, "int32") => typeof(int),
221+
(JsonSchemaType.Integer or JsonSchemaType.Number, "int64") => typeof(long),
222+
(JsonSchemaType.Integer, null) => typeof(long),
223+
(JsonSchemaType.Number, "float") => typeof(float),
224+
(JsonSchemaType.Number, "double") => typeof(double),
225+
(JsonSchemaType.Number, "decimal") => typeof(decimal),
226+
(JsonSchemaType.Number, null) => typeof(double),
227+
(JsonSchemaType.String, "byte") => typeof(byte),
228+
(JsonSchemaType.String, "date-time") => typeof(DateTimeOffset),
229+
(JsonSchemaType.String, "uuid") => typeof(Guid),
230+
(JsonSchemaType.String, "char") => typeof(char),
231+
(JsonSchemaType.String, null) => typeof(string),
232+
(JsonSchemaType.Object, null) => typeof(object),
233+
(JsonSchemaType.String, "uri") => typeof(Uri),
187234
_ => typeof(string),
188235
};
189236

src/Microsoft.OpenApi/Interfaces/IStreamLoader.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.IO;
6+
using System.Threading;
67
using System.Threading.Tasks;
78
using Microsoft.OpenApi.Models;
89

@@ -17,7 +18,8 @@ public interface IStreamLoader
1718
/// Use Uri to locate data and convert into an input object.
1819
/// </summary>
1920
/// <param name="uri">Identifier of some source of an OpenAPI Description</param>
21+
/// <param name="cancellationToken">The cancellation token.</param>
2022
/// <returns>A data object that can be processed by a reader to generate an <see cref="OpenApiDocument"/></returns>
21-
Task<Stream> LoadAsync(Uri uri);
23+
Task<Stream> LoadAsync(Uri uri, CancellationToken cancellationToken = default);
2224
}
2325
}

src/Microsoft.OpenApi/MicrosoftExtensions/OpenApiDeprecationExtension.cs

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
using Microsoft.OpenApi.Interfaces;
1010
using Microsoft.OpenApi.Writers;
1111
using System.Text.Json.Nodes;
12+
using System.Text.Json;
13+
using System.Globalization;
1214

1315
namespace Microsoft.OpenApi.MicrosoftExtensions;
1416

@@ -71,6 +73,35 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
7173
writer.WriteEndObject();
7274
}
7375
}
76+
private static readonly DateTimeStyles datesStyle = DateTimeStyles.AssumeUniversal | DateTimeStyles.RoundtripKind;
77+
private static DateTimeOffset? GetDateTimeOffsetValue(string propertyName, JsonObject rawObject)
78+
{
79+
if (!rawObject.TryGetPropertyValue(propertyName.ToFirstCharacterLowerCase(), out var jsonNode) ||
80+
jsonNode is not JsonValue jsonValue ||
81+
jsonNode.GetValueKind() is not JsonValueKind.String)
82+
return null;
83+
84+
if (jsonValue.TryGetValue<string>(out var strValue) &&
85+
DateTimeOffset.TryParse(strValue, CultureInfo.InvariantCulture, datesStyle, out var parsedValue))
86+
{
87+
return parsedValue;
88+
}
89+
if (jsonValue.TryGetValue<DateTimeOffset>(out var returnedDto))
90+
{
91+
return returnedDto;
92+
}
93+
if (jsonValue.TryGetValue<DateTime>(out var returnedDt))
94+
{
95+
return new DateTimeOffset(returnedDt, TimeSpan.FromHours(0));
96+
}
97+
#if NET6_0_OR_GREATER
98+
if (jsonValue.TryGetValue<DateOnly>(out var returnedDo))
99+
{
100+
return new(returnedDo.Year, returnedDo.Month, returnedDo.Day, 0, 0, 0, TimeSpan.FromHours(0));
101+
}
102+
#endif
103+
return null;
104+
}
74105
/// <summary>
75106
/// Parses the <see cref="OpenApiAny"/> to <see cref="OpenApiDeprecationExtension"/>.
76107
/// </summary>
@@ -80,15 +111,15 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
80111
public static OpenApiDeprecationExtension Parse(JsonNode source)
81112
{
82113
if (source is not JsonObject rawObject) throw new ArgumentOutOfRangeException(nameof(source));
83-
var extension = new OpenApiDeprecationExtension();
84-
if (rawObject.TryGetPropertyValue(nameof(RemovalDate).ToFirstCharacterLowerCase(), out var removalDate) && removalDate is JsonNode removalDateValue)
85-
extension.RemovalDate = removalDateValue.GetValue<DateTimeOffset>();
86-
if (rawObject.TryGetPropertyValue(nameof(Date).ToFirstCharacterLowerCase(), out var date) && date is JsonNode dateValue)
87-
extension.Date = dateValue.GetValue<DateTimeOffset>();
88-
if (rawObject.TryGetPropertyValue(nameof(Version).ToFirstCharacterLowerCase(), out var version) && version is JsonNode versionValue)
89-
extension.Version = versionValue.GetValue<string>();
90-
if (rawObject.TryGetPropertyValue(nameof(Description).ToFirstCharacterLowerCase(), out var description) && description is JsonNode descriptionValue)
91-
extension.Description = descriptionValue.GetValue<string>();
114+
var extension = new OpenApiDeprecationExtension
115+
{
116+
RemovalDate = GetDateTimeOffsetValue(nameof(RemovalDate), rawObject),
117+
Date = GetDateTimeOffsetValue(nameof(Date), rawObject)
118+
};
119+
if (rawObject.TryGetPropertyValue(nameof(Version).ToFirstCharacterLowerCase(), out var version) && version is JsonValue versionValue && versionValue.TryGetValue<string>(out var versionStr))
120+
extension.Version = versionStr;
121+
if (rawObject.TryGetPropertyValue(nameof(Description).ToFirstCharacterLowerCase(), out var description) && description is JsonValue descriptionValue && descriptionValue.TryGetValue<string>(out var descriptionStr))
122+
extension.Description = descriptionStr;
92123
return extension;
93124
}
94125
}

0 commit comments

Comments
 (0)