Skip to content

Commit ad5b91b

Browse files
committed
Merge branch 'support/v2' into fix/tags-order-to-v3
Signed-off-by: Vincent Biret <vibiret@microsoft.com>
2 parents 6ad5d02 + 56446a6 commit ad5b91b

File tree

3 files changed

+95
-3
lines changed

3 files changed

+95
-3
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@
5656

5757
* adds support for OpenAPI 3.2.0 ([765a8dd](https://github.com/microsoft/OpenAPI.NET/commit/765a8dd4d6efd1a31b6a76d282ccffa5877a845a))
5858

59+
## [2.4.3](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.2...v2.4.3) (2026-01-16)
60+
61+
## Bug Fixes
62+
63+
* Support custom tag ordering ([008576c](https://github.com/microsoft/OpenAPI.NET/commit/008576c31f8dcecf59363c9c2f85d691601faa73))
64+
* Support custom tag ordering ([7610d07](https://github.com/microsoft/OpenAPI.NET/commit/7610d07bd11a99a4ce1cc31338d180dbd764d952))
65+
5966
## [2.4.2](https://github.com/microsoft/OpenAPI.NET/compare/v2.4.1...v2.4.2) (2025-12-22)
6067

6168

src/Microsoft.OpenApi/Models/OpenApiDocument.cs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
using System;
55
using System.Collections.Generic;
6+
#if NET
7+
using System.Collections.Immutable;
8+
#endif
69
using System.IO;
710
using System.Linq;
811
using System.Security.Cryptography;
@@ -88,9 +91,15 @@ public ISet<OpenApiTag>? Tags
8891
{
8992
return;
9093
}
91-
_tags = value is HashSet<OpenApiTag> tags && tags.Comparer is OpenApiTagComparer ?
92-
tags :
93-
new HashSet<OpenApiTag>(value, OpenApiTagComparer.Instance);
94+
_tags = value switch
95+
{
96+
HashSet<OpenApiTag> tags when tags.Comparer != EqualityComparer<OpenApiTag>.Default => value,
97+
SortedSet<OpenApiTag> => value,
98+
#if NET
99+
ImmutableSortedSet<OpenApiTag> => value,
100+
#endif
101+
_ => new HashSet<OpenApiTag>(value, OpenApiTagComparer.Instance),
102+
};
94103
}
95104
}
96105

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

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Collections.Immutable;
7+
using System.Diagnostics.CodeAnalysis;
68
using System.Globalization;
79
using System.IO;
10+
using System.Linq;
811
using System.Net.Http;
912
using System.Threading.Tasks;
1013
using VerifyXunit;
@@ -2126,6 +2129,79 @@ public void DeduplicatesTags()
21262129
Assert.Contains(document.Tags, t => t.Name == "tag2");
21272130
}
21282131

2132+
[Fact]
2133+
public void TagsSupportsCustomComparer()
2134+
{
2135+
var document = new OpenApiDocument
2136+
{
2137+
Tags = new HashSet<OpenApiTag>(new CaseInsensitiveOpenApiTagEqualityComparer()),
2138+
};
2139+
2140+
Assert.True(document.Tags.Add(new OpenApiTag { Name = "Tag1" }));
2141+
Assert.False(document.Tags.Add(new OpenApiTag { Name = "tag1" }));
2142+
Assert.True(document.Tags.Add(new OpenApiTag { Name = "tag2" }));
2143+
Assert.False(document.Tags.Add(new OpenApiTag { Name = "TAG1" }));
2144+
Assert.Equal(2, document.Tags.Count);
2145+
}
2146+
2147+
private sealed class CaseInsensitiveOpenApiTagEqualityComparer : IEqualityComparer<OpenApiTag>
2148+
{
2149+
public bool Equals(OpenApiTag x, OpenApiTag y)
2150+
{
2151+
return string.Equals(x.Name, y.Name, StringComparison.OrdinalIgnoreCase);
2152+
}
2153+
2154+
public int GetHashCode([DisallowNull] OpenApiTag obj)
2155+
{
2156+
return obj.Name.GetHashCode(StringComparison.OrdinalIgnoreCase);
2157+
}
2158+
}
2159+
2160+
[Fact]
2161+
public void TagsSupportsSortedSets()
2162+
{
2163+
var document = new OpenApiDocument
2164+
{
2165+
Tags = new SortedSet<OpenApiTag>(new DescendingOpenApiTagComparer())
2166+
{
2167+
new OpenApiTag { Name = "tagB" },
2168+
new OpenApiTag { Name = "tagA" },
2169+
new OpenApiTag { Name = "tagC" },
2170+
}
2171+
};
2172+
2173+
var names = document.Tags.Select(t => t.Name);
2174+
Assert.Equal(["tagC", "tagB", "tagA"], names);
2175+
Assert.IsType<SortedSet<OpenApiTag>>(document.Tags);
2176+
}
2177+
2178+
private sealed class DescendingOpenApiTagComparer : IComparer<OpenApiTag>
2179+
{
2180+
public int Compare(OpenApiTag x, OpenApiTag y)
2181+
{
2182+
return string.Compare(y?.Name, x?.Name, StringComparison.Ordinal);
2183+
}
2184+
}
2185+
2186+
[Fact]
2187+
public void TagsSupportsImmutableSortedSets()
2188+
{
2189+
var document = new OpenApiDocument
2190+
{
2191+
Tags = ImmutableSortedSet.Create(
2192+
new DescendingOpenApiTagComparer(),
2193+
[
2194+
new OpenApiTag { Name = "tagB" },
2195+
new OpenApiTag { Name = "tagA" },
2196+
new OpenApiTag { Name = "tagC" },
2197+
]),
2198+
};
2199+
2200+
var names = document.Tags.Select(t => t.Name);
2201+
Assert.Equal(["tagC", "tagB", "tagA"], names);
2202+
Assert.IsType<ImmutableSortedSet<OpenApiTag>>(document.Tags);
2203+
}
2204+
21292205
public static TheoryData<OpenApiSpecVersion> OpenApiSpecVersions()
21302206
{
21312207
var values = new TheoryData<OpenApiSpecVersion>();

0 commit comments

Comments
 (0)