Skip to content

Commit fdb9548

Browse files
authored
Merge pull request #38 from BinkyLabs/copilot/fix-89dde62e-35c4-4c9f-b72a-053e29c52169
feat: Add OpenApiXmlNodeType enum and update OpenApiXml for OAI 3.2.0 support
2 parents c1a3afb + 1b57b16 commit fdb9548

File tree

10 files changed

+249
-31
lines changed

10 files changed

+249
-31
lines changed

src/Microsoft.OpenApi/Models/OpenApiConstants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,11 @@ public static class OpenApiConstants
245245
/// </summary>
246246
public const string Wrapped = "wrapped";
247247

248+
/// <summary>
249+
/// Field: NodeType
250+
/// </summary>
251+
public const string NodeType = "nodeType";
252+
248253
/// <summary>
249254
/// Field: In
250255
/// </summary>

src/Microsoft.OpenApi/Models/OpenApiXml.cs

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,40 @@ public class OpenApiXml : IOpenApiSerializable, IOpenApiExtensible
3030
/// Declares whether the property definition translates to an attribute instead of an element.
3131
/// Default value is false.
3232
/// </summary>
33-
public bool Attribute { get; set; }
33+
[Obsolete("Use NodeType property instead. This property will be removed in a future version.")]
34+
internal bool Attribute
35+
{
36+
get
37+
{
38+
return NodeType == OpenApiXmlNodeType.Attribute;
39+
}
40+
set
41+
{
42+
NodeType = value ? OpenApiXmlNodeType.Attribute : OpenApiXmlNodeType.None;
43+
}
44+
}
3445

3546
/// <summary>
3647
/// Signifies whether the array is wrapped.
3748
/// Default value is false.
3849
/// </summary>
39-
public bool Wrapped { get; set; }
50+
[Obsolete("Use NodeType property instead. This property will be removed in a future version.")]
51+
internal bool Wrapped
52+
{
53+
get
54+
{
55+
return NodeType == OpenApiXmlNodeType.Element;
56+
}
57+
set
58+
{
59+
NodeType = value ? OpenApiXmlNodeType.Element : OpenApiXmlNodeType.None;
60+
}
61+
}
62+
63+
/// <summary>
64+
/// The node type of the XML representation.
65+
/// </summary>
66+
public OpenApiXmlNodeType? NodeType { get; set; }
4067

4168
/// <summary>
4269
/// Specification Extensions.
@@ -56,8 +83,7 @@ public OpenApiXml(OpenApiXml xml)
5683
Name = xml?.Name ?? Name;
5784
Namespace = xml?.Namespace ?? Namespace;
5885
Prefix = xml?.Prefix ?? Prefix;
59-
Attribute = xml?.Attribute ?? Attribute;
60-
Wrapped = xml?.Wrapped ?? Wrapped;
86+
NodeType = xml?.NodeType ?? NodeType;
6187
Extensions = xml?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(xml.Extensions) : null;
6288
}
6389

@@ -108,11 +134,25 @@ private void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)
108134
// prefix
109135
writer.WriteProperty(OpenApiConstants.Prefix, Prefix);
110136

111-
// attribute
112-
writer.WriteProperty(OpenApiConstants.Attribute, Attribute, false);
113-
114-
// wrapped
115-
writer.WriteProperty(OpenApiConstants.Wrapped, Wrapped, false);
137+
// For OpenAPI 3.2.0 and above, serialize nodeType
138+
if (specVersion >= OpenApiSpecVersion.OpenApi3_2)
139+
{
140+
if (NodeType.HasValue)
141+
{
142+
writer.WriteProperty(OpenApiConstants.NodeType, NodeType.Value.GetDisplayName());
143+
}
144+
}
145+
else
146+
{
147+
// For OpenAPI 3.1.0 and below, serialize attribute and wrapped
148+
// Use backing fields if they were set via obsolete properties,
149+
// otherwise derive from NodeType if set
150+
var attribute = NodeType.HasValue && NodeType == OpenApiXmlNodeType.Attribute;
151+
var wrapped = NodeType.HasValue && NodeType == OpenApiXmlNodeType.Element;
152+
153+
writer.WriteProperty(OpenApiConstants.Attribute, attribute, false);
154+
writer.WriteProperty(OpenApiConstants.Wrapped, wrapped, false);
155+
}
116156

117157
// extensions
118158
writer.WriteExtensions(Extensions, specVersion);
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT license.
3+
4+
namespace Microsoft.OpenApi
5+
{
6+
/// <summary>
7+
/// The type of the XML node
8+
/// </summary>
9+
public enum OpenApiXmlNodeType
10+
{
11+
/// <summary>
12+
/// Element node type
13+
/// </summary>
14+
[Display("element")] Element,
15+
16+
/// <summary>
17+
/// Attribute node type
18+
/// </summary>
19+
[Display("attribute")] Attribute,
20+
21+
/// <summary>
22+
/// Text node type
23+
/// </summary>
24+
[Display("text")] Text,
25+
26+
/// <summary>
27+
/// CDATA node type
28+
/// </summary>
29+
[Display("cdata")] Cdata,
30+
31+
/// <summary>
32+
/// None node type
33+
/// </summary>
34+
[Display("none")] None
35+
}
36+
}

src/Microsoft.OpenApi/Reader/V2/OpenApiXmlDeserializer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ internal static partial class OpenApiV2Deserializer
4242
var attribute = n.GetScalarValue();
4343
if (attribute is not null)
4444
{
45+
#pragma warning disable CS0618 // Type or member is obsolete
4546
o.Attribute = bool.Parse(attribute);
47+
#pragma warning restore CS0618 // Type or member is obsolete
4648
}
4749
}
4850
},
@@ -53,7 +55,9 @@ internal static partial class OpenApiV2Deserializer
5355
var wrapped = n.GetScalarValue();
5456
if (wrapped is not null)
5557
{
58+
#pragma warning disable CS0618 // Type or member is obsolete
5659
o.Wrapped = bool.Parse(wrapped);
60+
#pragma warning restore CS0618 // Type or member is obsolete
5761
}
5862
}
5963
},

src/Microsoft.OpenApi/Reader/V3/OpenApiXmlDeserializer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,9 @@ internal static partial class OpenApiV3Deserializer
3939
var attribute = n.GetScalarValue();
4040
if (attribute is not null)
4141
{
42+
#pragma warning disable CS0618 // Type or member is obsolete
4243
o.Attribute = bool.Parse(attribute);
44+
#pragma warning restore CS0618 // Type or member is obsolete
4345
}
4446
}
4547
},
@@ -50,7 +52,9 @@ internal static partial class OpenApiV3Deserializer
5052
var wrapped = n.GetScalarValue();
5153
if (wrapped is not null)
5254
{
55+
#pragma warning disable CS0618 // Type or member is obsolete
5356
o.Wrapped = bool.Parse(wrapped);
57+
#pragma warning restore CS0618 // Type or member is obsolete
5458
}
5559
}
5660
},

src/Microsoft.OpenApi/Reader/V31/OpenApiXmlDeserializer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ internal static partial class OpenApiV31Deserializer
4141
var attribute = n.GetScalarValue();
4242
if (attribute is not null)
4343
{
44+
#pragma warning disable CS0618 // Type or member is obsolete
4445
o.Attribute = bool.Parse(attribute);
46+
#pragma warning restore CS0618 // Type or member is obsolete
4547
}
4648
}
4749
},
@@ -52,7 +54,9 @@ internal static partial class OpenApiV31Deserializer
5254
var wrapped = n.GetScalarValue();
5355
if (wrapped is not null)
5456
{
57+
#pragma warning disable CS0618 // Type or member is obsolete
5558
o.Wrapped = bool.Parse(wrapped);
59+
#pragma warning restore CS0618 // Type or member is obsolete
5660
}
5761
}
5862
}

src/Microsoft.OpenApi/Reader/V32/OpenApiXmlDeserializer.cs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,14 @@ internal static partial class OpenApiV32Deserializer
3535
(o, n, _) => o.Prefix = n.GetScalarValue()
3636
},
3737
{
38-
"attribute",
38+
"nodeType",
3939
(o, n, _) =>
4040
{
41-
var attribute = n.GetScalarValue();
42-
if (attribute is not null)
41+
if (!n.GetScalarValue().TryGetEnumFromDisplayName<OpenApiXmlNodeType>(n.Context, out var nodeType))
4342
{
44-
o.Attribute = bool.Parse(attribute);
45-
}
46-
}
47-
},
48-
{
49-
"wrapped",
50-
(o, n, _) =>
51-
{
52-
var wrapped = n.GetScalarValue();
53-
if (wrapped is not null)
54-
{
55-
o.Wrapped = bool.Parse(wrapped);
43+
return;
5644
}
45+
o.NodeType = nodeType;
5746
}
5847
}
5948
};

test/Microsoft.OpenApi.Readers.Tests/V3Tests/OpenApiXmlTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public async Task ParseBasicXmlShouldSucceed()
2121
var xml = await OpenApiModelFactory.LoadAsync<OpenApiXml>(Resources.GetStream(Path.Combine(SampleFolderPath, "basicXml.yaml")), OpenApiSpecVersion.OpenApi3_0, new(), settings: SettingsFixture.ReaderSettings);
2222

2323
// Assert
24+
#pragma warning disable CS0618 // Type or member is obsolete
2425
Assert.Equivalent(
2526
new OpenApiXml
2627
{
@@ -29,6 +30,7 @@ public async Task ParseBasicXmlShouldSucceed()
2930
Prefix = "samplePrefix",
3031
Wrapped = true
3132
}, xml);
33+
#pragma warning restore CS0618 // Type or member is obsolete
3234
}
3335
}
3436
}

0 commit comments

Comments
 (0)