Skip to content

Commit c1f6733

Browse files
authored
Merge pull request #2109 from microsoft/fix/tag-reference
fix/tag reference
2 parents 5071753 + e147e72 commit c1f6733

12 files changed

+95
-148
lines changed

src/Microsoft.OpenApi/Models/Interfaces/IOpenApiDescribedElement.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,15 @@ public interface IOpenApiDescribedElement : IOpenApiElement
1313
/// </summary>
1414
public string Description { get; set; }
1515
}
16+
17+
/// <summary>
18+
/// Describes an element that has a description.
19+
/// </summary>
20+
public interface IOpenApiReadOnlyDescribedElement : IOpenApiElement
21+
{
22+
/// <summary>
23+
/// Long description for the example.
24+
/// CommonMark syntax MAY be used for rich text representation.
25+
/// </summary>
26+
public string Description { get; }
27+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Microsoft.OpenApi.Interfaces;
2+
3+
namespace Microsoft.OpenApi.Models.Interfaces;
4+
5+
/// <summary>
6+
/// Defines the base properties for the path item object.
7+
/// This interface is provided for type assertions but should not be implemented by package consumers beyond automatic mocking.
8+
/// </summary>
9+
public interface IOpenApiTag : IOpenApiSerializable, IOpenApiReadOnlyExtensible, IOpenApiReadOnlyDescribedElement
10+
{
11+
/// <summary>
12+
/// The name of the tag.
13+
/// </summary>
14+
public string Name { get; }
15+
16+
/// <summary>
17+
/// Additional external documentation for this tag.
18+
/// </summary>
19+
public OpenApiExternalDocs ExternalDocs { get; }
20+
}

src/Microsoft.OpenApi/Models/OpenApiTag.cs

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,61 +4,48 @@
44
using System;
55
using System.Collections.Generic;
66
using Microsoft.OpenApi.Interfaces;
7+
using Microsoft.OpenApi.Models.Interfaces;
78
using Microsoft.OpenApi.Writers;
89

910
namespace Microsoft.OpenApi.Models
1011
{
1112
/// <summary>
1213
/// Tag Object.
1314
/// </summary>
14-
public class OpenApiTag : IOpenApiReferenceable, IOpenApiExtensible
15+
public class OpenApiTag : IOpenApiExtensible, IOpenApiReferenceable, IOpenApiTag, IOpenApiDescribedElement
1516
{
16-
/// <summary>
17-
/// The name of the tag.
18-
/// </summary>
19-
public virtual string Name { get; set; }
17+
/// <inheritdoc/>
18+
public string Name { get; set; }
2019

21-
/// <summary>
22-
/// A short description for the tag.
23-
/// </summary>
24-
public virtual string Description { get; set; }
20+
/// <inheritdoc/>
21+
public string Description { get; set; }
2522

26-
/// <summary>
27-
/// Additional external documentation for this tag.
28-
/// </summary>
29-
public virtual OpenApiExternalDocs ExternalDocs { get; set; }
23+
/// <inheritdoc/>
24+
public OpenApiExternalDocs ExternalDocs { get; set; }
3025

31-
/// <summary>
32-
/// This object MAY be extended with Specification Extensions.
33-
/// </summary>
34-
public virtual IDictionary<string, IOpenApiExtension> Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
35-
36-
/// <summary>
37-
/// Indicates if object is populated with data or is just a reference to the data
38-
/// </summary>
39-
public bool UnresolvedReference { get; set; }
26+
/// <inheritdoc/>
27+
public IDictionary<string, IOpenApiExtension> Extensions { get; set; } = new Dictionary<string, IOpenApiExtension>();
4028

4129
/// <summary>
4230
/// Parameterless constructor
4331
/// </summary>
4432
public OpenApiTag() { }
4533

4634
/// <summary>
47-
/// Initializes a copy of an <see cref="OpenApiTag"/> object
35+
/// Initializes a copy of an <see cref="IOpenApiTag"/> object
4836
/// </summary>
49-
public OpenApiTag(OpenApiTag tag)
37+
public OpenApiTag(IOpenApiTag tag)
5038
{
5139
Name = tag?.Name ?? Name;
5240
Description = tag?.Description ?? Description;
5341
ExternalDocs = tag?.ExternalDocs != null ? new(tag.ExternalDocs) : null;
5442
Extensions = tag?.Extensions != null ? new Dictionary<string, IOpenApiExtension>(tag.Extensions) : null;
55-
UnresolvedReference = tag?.UnresolvedReference ?? UnresolvedReference;
5643
}
5744

5845
/// <summary>
5946
/// Serialize <see cref="OpenApiTag"/> to Open Api v3.1
6047
/// </summary>
61-
public virtual void SerializeAsV31(IOpenApiWriter writer)
48+
public void SerializeAsV31(IOpenApiWriter writer)
6249
{
6350
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_1,
6451
(writer, element) => element.SerializeAsV31(writer));
@@ -67,13 +54,13 @@ public virtual void SerializeAsV31(IOpenApiWriter writer)
6754
/// <summary>
6855
/// Serialize <see cref="OpenApiTag"/> to Open Api v3.0
6956
/// </summary>
70-
public virtual void SerializeAsV3(IOpenApiWriter writer)
57+
public void SerializeAsV3(IOpenApiWriter writer)
7158
{
7259
SerializeInternal(writer, OpenApiSpecVersion.OpenApi3_0,
7360
(writer, element) => element.SerializeAsV3(writer));
7461
}
7562

76-
internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
63+
internal void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersion version,
7764
Action<IOpenApiWriter, IOpenApiSerializable> callback)
7865
{
7966
writer.WriteStartObject();
@@ -96,7 +83,7 @@ internal virtual void SerializeInternal(IOpenApiWriter writer, OpenApiSpecVersio
9683
/// <summary>
9784
/// Serialize <see cref="OpenApiTag"/> to Open Api v2.0
9885
/// </summary>
99-
public virtual void SerializeAsV2(IOpenApiWriter writer)
86+
public void SerializeAsV2(IOpenApiWriter writer)
10087
{
10188
writer.WriteStartObject();
10289

src/Microsoft.OpenApi/Models/References/BaseOpenApiReferenceHolder.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ namespace Microsoft.OpenApi.Models.References;
1010
/// <typeparam name="V">The interface type for the model.</typeparam>
1111
public abstract class BaseOpenApiReferenceHolder<T, V> : IOpenApiReferenceHolder<T, V> where T : class, IOpenApiReferenceable, V where V : IOpenApiSerializable
1212
{
13-
private T _target;
13+
/// <summary>
14+
/// The resolved target object.
15+
/// </summary>
16+
protected T _target;
1417
/// <inheritdoc/>
15-
public T Target
18+
public virtual T Target
1619
{
1720
get
1821
{

src/Microsoft.OpenApi/Models/References/OpenApiTagReference.cs

Lines changed: 13 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,19 @@
55
using System.Collections.Generic;
66
using System.Linq;
77
using Microsoft.OpenApi.Interfaces;
8-
using Microsoft.OpenApi.Writers;
8+
using Microsoft.OpenApi.Models.Interfaces;
99

1010
namespace Microsoft.OpenApi.Models.References
1111
{
1212
/// <summary>
1313
/// Tag Object Reference
1414
/// </summary>
15-
public class OpenApiTagReference : OpenApiTag, IOpenApiReferenceHolder<OpenApiTag>
15+
public class OpenApiTagReference : BaseOpenApiReferenceHolder<OpenApiTag, IOpenApiTag>, IOpenApiTag
1616
{
17-
internal OpenApiTag _target;
18-
19-
/// <summary>
20-
/// Reference.
21-
/// </summary>
22-
public OpenApiReference Reference { get; set; }
23-
2417
/// <summary>
2518
/// Resolved target of the reference.
2619
/// </summary>
27-
public OpenApiTag Target
20+
public override OpenApiTag Target
2821
{
2922
get
3023
{
@@ -38,85 +31,32 @@ public OpenApiTag Target
3831
/// </summary>
3932
/// <param name="referenceId">The reference Id.</param>
4033
/// <param name="hostDocument">The host OpenAPI document.</param>
41-
public OpenApiTagReference(string referenceId, OpenApiDocument hostDocument)
34+
public OpenApiTagReference(string referenceId, OpenApiDocument hostDocument):base(referenceId, hostDocument, ReferenceType.Tag)
4235
{
43-
Utils.CheckArgumentNullOrEmpty(referenceId);
44-
45-
Reference = new OpenApiReference()
46-
{
47-
Id = referenceId,
48-
HostDocument = hostDocument,
49-
Type = ReferenceType.Tag
50-
};
5136
}
5237

53-
/// <summary>
54-
/// Copy Constructor
55-
/// </summary>
56-
/// <param name="source">The source to copy information from.</param>
57-
public OpenApiTagReference(OpenApiTagReference source):base()
38+
internal OpenApiTagReference(OpenApiTag target, string referenceId):base(target, referenceId, ReferenceType.Tag)
5839
{
59-
Reference = source?.Reference != null ? new(source.Reference) : null;
60-
_target = source?._target;
6140
}
6241

63-
private const string ReferenceErrorMessage = "Setting the value from the reference is not supported, use the target property instead.";
6442
/// <inheritdoc/>
65-
public override string Description { get => Target.Description; set => throw new InvalidOperationException(ReferenceErrorMessage); }
66-
67-
/// <inheritdoc/>
68-
public override OpenApiExternalDocs ExternalDocs { get => Target.ExternalDocs; set => throw new InvalidOperationException(ReferenceErrorMessage); }
69-
70-
/// <inheritdoc/>
71-
public override IDictionary<string, IOpenApiExtension> Extensions { get => Target.Extensions; set => throw new InvalidOperationException(ReferenceErrorMessage); }
72-
73-
/// <inheritdoc/>
74-
public override string Name { get => Target.Name; set => throw new InvalidOperationException(ReferenceErrorMessage); }
75-
76-
/// <inheritdoc/>
77-
public override void SerializeAsV3(IOpenApiWriter writer)
43+
public string Description
7844
{
79-
if (!writer.GetSettings().ShouldInlineReference(Reference))
80-
{
81-
Reference.SerializeAsV3(writer);
82-
}
83-
else
84-
{
85-
SerializeInternal(writer);
86-
}
45+
get => string.IsNullOrEmpty(Reference?.Description) ? Target?.Description : Reference.Description;
8746
}
8847

8948
/// <inheritdoc/>
90-
public override void SerializeAsV31(IOpenApiWriter writer)
91-
{
92-
if (!writer.GetSettings().ShouldInlineReference(Reference))
93-
{
94-
Reference.SerializeAsV31(writer);
95-
}
96-
else
97-
{
98-
SerializeInternal(writer);
99-
}
100-
}
49+
public OpenApiExternalDocs ExternalDocs { get => Target?.ExternalDocs; }
10150

10251
/// <inheritdoc/>
103-
public override void SerializeAsV2(IOpenApiWriter writer)
104-
{
105-
if (!writer.GetSettings().ShouldInlineReference(Reference))
106-
{
107-
Reference.SerializeAsV2(writer);
108-
}
109-
else
110-
{
111-
SerializeInternal(writer);
112-
}
113-
}
52+
public IDictionary<string, IOpenApiExtension> Extensions { get => Target?.Extensions; }
11453

11554
/// <inheritdoc/>
116-
private void SerializeInternal(IOpenApiWriter writer)
55+
public string Name { get => Target?.Name; }
56+
/// <inheritdoc/>
57+
public override IOpenApiTag CopyReferenceAsTargetElementWithOverrides(IOpenApiTag source)
11758
{
118-
Utils.CheckArgumentNull(writer);
119-
writer.WriteValue(Name);
59+
return source is OpenApiTag ? new OpenApiTag(this) : source;
12060
}
12161
}
12262
}

test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt

Lines changed: 0 additions & 9 deletions
This file was deleted.

test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV2JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=False.verified.txt

Lines changed: 0 additions & 9 deletions
This file was deleted.

test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.SerializeAdvancedTagAsV3JsonWithoutReferenceWorksAsync_produceTerseOutput=True.verified.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

test/Microsoft.OpenApi.Tests/Models/OpenApiTagTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Threading.Tasks;
88
using Microsoft.OpenApi.Interfaces;
99
using Microsoft.OpenApi.Models;
10+
using Microsoft.OpenApi.Models.Interfaces;
1011
using Microsoft.OpenApi.Models.References;
1112
using Microsoft.OpenApi.Writers;
1213
using VerifyXunit;
@@ -30,7 +31,7 @@ public class OpenApiTagTests
3031
}
3132
};
3233

33-
public static OpenApiTag ReferencedTag = new OpenApiTagReference("pet", null);
34+
public static IOpenApiTag ReferencedTag = new OpenApiTagReference(AdvancedTag, "pet");
3435

3536
[Theory]
3637
[InlineData(true)]

0 commit comments

Comments
 (0)