Skip to content

Commit

Permalink
Prevent ArgumentOutOfRangeException when handling nested generic types (
Browse files Browse the repository at this point in the history
dotnet#59201)

* Add unit test for the issue

* Fix typo

* Fix bug

* More efficient check with a better variable name
  • Loading branch information
sander1095 authored Dec 16, 2024
1 parent 8bbe9e3 commit 726b484
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/OpenApi/src/Extensions/JsonTypeInfoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ internal static class JsonTypeInfoExtensions
}

// Although arrays are enumerable types they are not encoded correctly
// with JsonTypeInfoKind.Enumerable so we handle the Enumerble type
// with JsonTypeInfoKind.Enumerable so we handle the Enumerable type
// case here.
if (jsonTypeInfo is JsonTypeInfo { Kind: JsonTypeInfoKind.Enumerable } || type.IsArray)
{
Expand Down Expand Up @@ -104,7 +104,13 @@ internal static string GetSchemaReferenceId(this Type type, JsonSerializerOption
// Generic types become a concatenation of the generic type name and the type arguments
if (type.IsGenericType)
{
var genericTypeName = type.Name[..type.Name.LastIndexOf('`')];
// We need to handle the case where the generic type is a nested type,
// so we check if the name contains a backtick already.
// For more information: https://github.com/dotnet/aspnetcore/issues/59092
var backtickIndex = type.Name.LastIndexOf('`');
var isNestedGenericType = backtickIndex == -1;

var genericTypeName = isNestedGenericType ? type.Name : type.Name[..backtickIndex];
var genericArguments = type.GetGenericArguments();
var argumentNames = string.Join("And", genericArguments.Select(arg => arg.GetSchemaReferenceId(options)));
return $"{genericTypeName}Of{argumentNames}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,21 @@ private class Container
internal delegate void ContainedTestDelegate(int x, int y);
}

/// <remarks>
/// https://github.com/dotnet/aspnetcore/issues/59092
/// </remarks>
public static class Foo<T>
{
public static class Bar<TT>
{
public class Baz
{
public required T One { get; set; }
public required TT Two { get; set; }
}
}
}

/// <summary>
/// This data is used to test the <see cref="TypeExtensions.GetSchemaReferenceId"/> method
/// which is used to generate reference IDs for OpenAPI schemas in the OpenAPI document.
Expand Down Expand Up @@ -58,6 +73,7 @@ private class Container
[typeof(Dictionary<string, string[]>), null],
[typeof(Dictionary<string, List<string[]>>), null],
[typeof(Dictionary<string, IEnumerable<string[]>>), null],
[typeof(Foo<int>.Bar<string>.Baz), "BazOfintAndstring"],
];

[Theory]
Expand Down

0 comments on commit 726b484

Please sign in to comment.