diff --git a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/MemberInfoExtensions.cs b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/MemberInfoExtensions.cs
index 34f9a51e28..574c305f32 100644
--- a/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/MemberInfoExtensions.cs
+++ b/src/Swashbuckle.AspNetCore.SwaggerGen/SchemaGenerator/MemberInfoExtensions.cs
@@ -61,6 +61,23 @@ public static bool IsNonNullableReferenceType(this MemberInfo memberInfo)
public static bool IsDictionaryValueNonNullable(this MemberInfo memberInfo)
{
+#if NET6_0_OR_GREATER
+ var context = new NullabilityInfoContext();
+ var nullableInfo = memberInfo.MemberType == MemberTypes.Field
+ ? context.Create((FieldInfo)memberInfo)
+ : context.Create((PropertyInfo)memberInfo);
+
+ if (nullableInfo.GenericTypeArguments.Length != 2)
+ {
+ var length = nullableInfo.GenericTypeArguments.Length;
+ var type = nullableInfo.Type.FullName;
+ var container = memberInfo.DeclaringType.FullName;
+ var member = memberInfo.Name;
+ throw new InvalidOperationException($"Expected Dictionary to have two generic type arguments but it had {length}. Member: {container}.{member} Type: {type}.");
+ }
+
+ return nullableInfo.GenericTypeArguments[1].ReadState == NullabilityState.NotNull;
+#else
var memberType = memberInfo.MemberType == MemberTypes.Field
? ((FieldInfo)memberInfo).FieldType
: ((PropertyInfo)memberInfo).PropertyType;
@@ -104,6 +121,7 @@ public static bool IsDictionaryValueNonNullable(this MemberInfo memberInfo)
}
return false;
+#endif
}
private static object GetNullableAttribute(this MemberInfo memberInfo)
diff --git a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs
index 1aaaa43d31..88e20d03f9 100644
--- a/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs
+++ b/test/Swashbuckle.AspNetCore.SwaggerGen.Test/SchemaGenerator/JsonSerializerSchemaGeneratorTests.cs
@@ -5,6 +5,7 @@
using System.Dynamic;
using System.Linq;
using System.Net;
+using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http;
@@ -670,15 +671,65 @@ public void GenerateSchema_SupportsOption_UseInlineDefinitionsForEnums()
Assert.NotNull(schema.Enum);
}
+ [Fact]
+ public void TypeWithNullableContextAnnotated_IsAnnotated()
+ {
+ // This is a sanity check to ensure that TypeWithNullableContextAnnotated
+ // is annotated with NullableContext(Flag=2) by the compiler. If this is no
+ // longer the case, you may need to add more of the Dummy properties to
+ // coerce the compiler.
+
+ const string Name = "System.Runtime.CompilerServices.NullableContextAttribute";
+
+ var nullableContext = typeof(TypeWithNullableContextAnnotated)
+ .GetCustomAttributes()
+ .FirstOrDefault(attr => string.Equals(attr.GetType().FullName, Name));
+
+ Assert.NotNull(nullableContext);
+
+ var flag = nullableContext?.GetType().GetField("Flag")?.GetValue(nullableContext);
+
+ Assert.Equal((byte)2, flag);
+ }
+
+ [Fact]
+ public void TypeWithNullableContextNotAnnotated_IsNotAnnotated()
+ {
+ // This is a sanity check to ensure that TypeWithNullableContextNotAnnotated
+ // is annotated with NullableContext(Flag=1) by the compiler. If this is no
+ // longer the case, you may need to add more of the Dummy properties to
+ // coerce the compiler.
+
+ const string Name = "System.Runtime.CompilerServices.NullableContextAttribute";
+
+ var nullableContext = typeof(TypeWithNullableContextNotAnnotated)
+ .GetCustomAttributes()
+ .FirstOrDefault(attr => string.Equals(attr.GetType().FullName, Name));
+
+ Assert.NotNull(nullableContext);
+
+ var flag = nullableContext?.GetType().GetField("Flag")?.GetValue(nullableContext);
+
+ Assert.Equal((byte)1, flag);
+ }
+
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableInt), true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableInt), false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableString), true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableString), false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableArray), true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableArray), false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableList), true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableList), false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableInt), true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableInt), false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableString), true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableString), false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableArray), true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableArray), false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableList), true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableList), false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableInt), true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableInt), false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableString), true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableString), false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableArray), true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableArray), false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableList), true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableList), false)]
public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes(
Type declaringType,
string propertyName,
@@ -696,10 +747,14 @@ public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes(
}
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableDictionaryInNonNullableContent), true, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableDictionaryInNonNullableContent), false, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableDictionaryInNullableContent), false, true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableDictionaryInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableDictionaryInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableDictionaryInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableDictionaryInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableDictionaryInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableDictionaryInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableDictionaryInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableDictionaryInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableDictionaryInNullableContent), true, true)]
public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_NullableAttribute_Compiler_Optimizations_Situations_Dictionary(
Type declaringType,
string propertyName,
@@ -720,10 +775,14 @@ public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_Nulla
}
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableIDictionaryInNonNullableContent), true, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableIDictionaryInNonNullableContent), false, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableIDictionaryInNullableContent), false, true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableIDictionaryInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableIDictionaryInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableIDictionaryInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableIDictionaryInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableIDictionaryInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableIDictionaryInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableIDictionaryInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableIDictionaryInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableIDictionaryInNullableContent), true, true)]
public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_NullableAttribute_Compiler_Optimizations_Situations_IDictionary(
Type declaringType,
string propertyName,
@@ -744,10 +803,14 @@ public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_Nulla
}
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableIReadOnlyDictionaryInNonNullableContent), true, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableIReadOnlyDictionaryInNonNullableContent), false, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableIReadOnlyDictionaryInNullableContent), false, true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableIReadOnlyDictionaryInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableIReadOnlyDictionaryInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableIReadOnlyDictionaryInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableIReadOnlyDictionaryInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableIReadOnlyDictionaryInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableIReadOnlyDictionaryInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableIReadOnlyDictionaryInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableIReadOnlyDictionaryInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableIReadOnlyDictionaryInNullableContent), true, true)]
public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_NullableAttribute_Compiler_Optimizations_Situations_IReadOnlyDictionary(
Type declaringType,
string propertyName,
@@ -768,10 +831,14 @@ public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_Nulla
}
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableDictionaryWithValueTypeInNonNullableContent), true, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableDictionaryWithValueTypeInNonNullableContent), false, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableDictionaryWithValueTypeInNullableContent), false, true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableDictionaryWithValueTypeInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableDictionaryWithValueTypeInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableDictionaryWithValueTypeInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableDictionaryWithValueTypeInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableDictionaryWithValueTypeInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableDictionaryWithValueTypeInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableDictionaryWithValueTypeInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableDictionaryWithValueTypeInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableDictionaryWithValueTypeInNullableContent), true, true)]
public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_NullableAttribute_Compiler_Optimizations_Situations_DictionaryWithValueType(
Type declaringType,
string propertyName,
@@ -792,10 +859,14 @@ public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_Nulla
}
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableIDictionaryWithValueTypeInNonNullableContent), true, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableIDictionaryWithValueTypeInNonNullableContent), false, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableIDictionaryWithValueTypeInNullableContent), false, true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableIDictionaryWithValueTypeInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableIDictionaryWithValueTypeInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableIDictionaryWithValueTypeInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableIDictionaryWithValueTypeInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableIDictionaryWithValueTypeInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableIDictionaryWithValueTypeInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableIDictionaryWithValueTypeInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableIDictionaryWithValueTypeInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableIDictionaryWithValueTypeInNullableContent), true, true)]
public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_NullableAttribute_Compiler_Optimizations_Situations_IDictionaryWithValueType(
Type declaringType,
string propertyName,
@@ -816,10 +887,14 @@ public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_Nulla
}
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableIReadOnlyDictionaryWithValueTypeInNonNullableContent), true, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableIReadOnlyDictionaryWithValueTypeInNonNullableContent), false, false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NonNullableIReadOnlyDictionaryWithValueTypeInNullableContent), false, true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.NullableIReadOnlyDictionaryWithValueTypeInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableIReadOnlyDictionaryWithValueTypeInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableIReadOnlyDictionaryWithValueTypeInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NonNullableIReadOnlyDictionaryWithValueTypeInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.NullableIReadOnlyDictionaryWithValueTypeInNullableContent), true, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableIReadOnlyDictionaryWithValueTypeInNonNullableContent), true, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableIReadOnlyDictionaryWithValueTypeInNonNullableContent), false, false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NonNullableIReadOnlyDictionaryWithValueTypeInNullableContent), false, true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.NullableIReadOnlyDictionaryWithValueTypeInNullableContent), true, true)]
public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_NullableAttribute_Compiler_Optimizations_Situations_IReadOnlyDictionaryWithValueType(
Type declaringType,
string propertyName,
@@ -840,8 +915,10 @@ public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypes_Nulla
}
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.SubTypeWithOneNullableContent), nameof(TypeWithNullableContext.NullableString), true)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContext.NonNullableString), false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.SubTypeWithOneNullableContent), nameof(TypeWithNullableContextAnnotated.NullableString), true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContextAnnotated.NonNullableString), false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.SubTypeWithOneNullableContent), nameof(TypeWithNullableContextNotAnnotated.NullableString), true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContextNotAnnotated.NonNullableString), false)]
public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypesInDictionary_NullableAttribute_Compiler_Optimizations_Situations(
Type declaringType,
string subType,
@@ -860,8 +937,10 @@ public void GenerateSchema_SupportsOption_SupportNonNullableReferenceTypesInDict
}
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.SubTypeWithOneNullableContent), nameof(TypeWithNullableContext.NullableString), false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContext.NonNullableString), true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.SubTypeWithOneNullableContent), nameof(TypeWithNullableContextAnnotated.NullableString), false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContextAnnotated.NonNullableString), true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.SubTypeWithOneNullableContent), nameof(TypeWithNullableContextNotAnnotated.NullableString), false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContextNotAnnotated.NonNullableString), true)]
public void GenerateSchema_SupportsOption_NonNullableReferenceTypesAsRequired_RequiredAttribute_Compiler_Optimizations_Situations(
Type declaringType,
string subType,
@@ -880,8 +959,10 @@ public void GenerateSchema_SupportsOption_NonNullableReferenceTypesAsRequired_Re
}
[Theory]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContext.NonNullableString), false)]
- [InlineData(typeof(TypeWithNullableContext), nameof(TypeWithNullableContext.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContext.NonNullableString), true)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContextAnnotated.NonNullableString), false)]
+ [InlineData(typeof(TypeWithNullableContextAnnotated), nameof(TypeWithNullableContextAnnotated.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContextAnnotated.NonNullableString), true)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContextNotAnnotated.NonNullableString), false)]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated), nameof(TypeWithNullableContextNotAnnotated.SubTypeWithOneNonNullableContent), nameof(TypeWithNullableContextNotAnnotated.NonNullableString), true)]
public void GenerateSchema_SupportsOption_SuppressImplicitRequiredAttributeForNonNullableReferenceTypes(
Type declaringType,
string subType,
@@ -900,8 +981,10 @@ public void GenerateSchema_SupportsOption_SuppressImplicitRequiredAttributeForNo
Assert.Equal(!suppress, propertyIsRequired);
}
- [Fact]
- public void GenerateSchema_Works_IfNotProvidingMvcOptions()
+ [Theory]
+ [InlineData(typeof(TypeWithNullableContextAnnotated))]
+ [InlineData(typeof(TypeWithNullableContextNotAnnotated))]
+ public void GenerateSchema_Works_IfNotProvidingMvcOptions(Type type)
{
var generatorOptions = new SchemaGeneratorOptions
{
@@ -913,10 +996,10 @@ public void GenerateSchema_Works_IfNotProvidingMvcOptions()
var subject = new SchemaGenerator(generatorOptions, new JsonSerializerDataContractResolver(serializerOptions));
var schemaRepository = new SchemaRepository();
- subject.GenerateSchema(typeof(TypeWithNullableContext), schemaRepository);
+ subject.GenerateSchema(type, schemaRepository);
- var subType = nameof(TypeWithNullableContext.SubTypeWithOneNonNullableContent);
- var propertyName = nameof(TypeWithNullableContext.NonNullableString);
+ var subType = nameof(TypeWithNullableContextAnnotated.SubTypeWithOneNonNullableContent);
+ var propertyName = nameof(TypeWithNullableContextAnnotated.NonNullableString);
var propertyIsRequired = schemaRepository.Schemas[subType].Required.Contains(propertyName);
Assert.True(propertyIsRequired);
}
diff --git a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithNullableContext.cs b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithNullableContext.cs
index 481b950dc5..81cf7dcb5c 100644
--- a/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithNullableContext.cs
+++ b/test/Swashbuckle.AspNetCore.TestSupport/Fixtures/TypeWithNullableContext.cs
@@ -3,8 +3,42 @@
namespace Swashbuckle.AspNetCore.TestSupport
{
#nullable enable
- public class TypeWithNullableContext
+
+ // These types are used to test our handling of nullable references types.
+ // NRT results in NullableContextAttribute and NullableAttribute being placed on
+ // types and members by the compiler.
+
+ // Remember to mirror both types and use both types in tests.
+
+ ///
+ /// We expect this type to receive NullableContext(Flag=1) (NotAnnotated) from the compiler.
+ ///
+ public class TypeWithNullableContextNotAnnotated
{
+ // Dummy properties to affect the NullableContextAttribute placed on the type.
+ // It seems to default to the most common nullable state, so we overwhelm
+ // it with non-nullable properties in order to coerce it.
+ public string Dummy1 { get; } = default!;
+ public string Dummy2 { get; } = default!;
+ public string Dummy3 { get; } = default!;
+ public string Dummy4 { get; } = default!;
+ public string Dummy5 { get; } = default!;
+ public string Dummy6 { get; } = default!;
+ public string Dummy7 { get; } = default!;
+ public string Dummy8 { get; } = default!;
+ public string Dummy9 { get; } = default!;
+ public string Dummy10 { get; } = default!;
+ public string Dummy11 { get; set; } = default!;
+ public string Dummy12 { get; set; } = default!;
+ public string Dummy13 { get; set; } = default!;
+ public string Dummy14 { get; set; } = default!;
+ public string Dummy15 { get; set; } = default!;
+ public string Dummy16 { get; set; } = default!;
+ public string Dummy17 { get; set; } = default!;
+ public string Dummy18 { get; set; } = default!;
+ public string Dummy19 { get; set; } = default!;
+ public string Dummy20 { get; set; } = default!;
+
public int? NullableInt { get; set; }
public int NonNullableInt { get; set; }
public string? NullableString { get; set; }
@@ -54,8 +88,86 @@ public class SubTypeWithOneNonNullableContent
{
public string NonNullableString { get; set; } = default!;
}
+ }
+
+ ///
+ /// We expect this type to receive NullableContext(Flag=2) (Annotated) from the compiler.
+ ///
+ public class TypeWithNullableContextAnnotated
+ {
+ // Dummy properties to affect the NullableContextAttribute placed on the type.
+ // It seems to default to the most common nullable state, so we overwhelm
+ // it with nullable properties in order to coerce it.
+ public string? Dummy1 { get; set; }
+ public string? Dummy2 { get; set; }
+ public string? Dummy3 { get; set; }
+ public string? Dummy4 { get; set; }
+ public string? Dummy5 { get; set; }
+ public string? Dummy6 { get; set; }
+ public string? Dummy7 { get; set; }
+ public string? Dummy8 { get; set; }
+ public string? Dummy9 { get; set; }
+ public string? Dummy10 { get; set; }
+ public string? Dummy11 { get; set; }
+ public string? Dummy12 { get; set; }
+ public string? Dummy13 { get; set; }
+ public string? Dummy14 { get; set; }
+ public string? Dummy15 { get; set; }
+ public string? Dummy16 { get; set; }
+ public string? Dummy17 { get; set; }
+ public string? Dummy18 { get; set; }
+ public string? Dummy19 { get; set; }
+ public string? Dummy20 { get; set; }
+
+ public int? NullableInt { get; set; }
+ public int NonNullableInt { get; set; }
+ public string? NullableString { get; set; }
+ public string NonNullableString { get; set; } = default!;
+ public int[]? NullableArray { get; set; }
+ public int[] NonNullableArray { get; set; } = default!;
+ public List? NullableList { get; set; }
+ public List NonNullableList { get; set; } = default!;
+
+ public Dictionary? NullableDictionaryInNonNullableContent { get; set; }
+ public Dictionary NonNullableDictionaryInNonNullableContent { get; set; } = default!;
+ public Dictionary NonNullableDictionaryInNullableContent { get; set; } = default!;
+ public Dictionary? NullableDictionaryInNullableContent { get; set; }
+ public IDictionary? NullableIDictionaryInNonNullableContent { get; set; }
+ public IDictionary NonNullableIDictionaryInNonNullableContent { get; set; } = default!;
+ public IDictionary NonNullableIDictionaryInNullableContent { get; set; } = default!;
+ public IDictionary? NullableIDictionaryInNullableContent { get; set; }
+
+ public IReadOnlyDictionary? NullableIReadOnlyDictionaryInNonNullableContent { get; set; }
+ public IReadOnlyDictionary NonNullableIReadOnlyDictionaryInNonNullableContent { get; set; } = default!;
+ public IReadOnlyDictionary NonNullableIReadOnlyDictionaryInNullableContent { get; set; } = default!;
+ public IReadOnlyDictionary? NullableIReadOnlyDictionaryInNullableContent { get; set; }
+
+ public Dictionary? NullableDictionaryWithValueTypeInNonNullableContent { get; set; }
+ public Dictionary NonNullableDictionaryWithValueTypeInNonNullableContent { get; set; } = default!;
+ public Dictionary NonNullableDictionaryWithValueTypeInNullableContent { get; set; } = default!;
+ public Dictionary? NullableDictionaryWithValueTypeInNullableContent { get; set; }
+
+ public IDictionary? NullableIDictionaryWithValueTypeInNonNullableContent { get; set; }
+ public IDictionary NonNullableIDictionaryWithValueTypeInNonNullableContent { get; set; } = default!;
+ public IDictionary NonNullableIDictionaryWithValueTypeInNullableContent { get; set; } = default!;
+ public IDictionary? NullableIDictionaryWithValueTypeInNullableContent { get; set; }
+
+ public IReadOnlyDictionary? NullableIReadOnlyDictionaryWithValueTypeInNonNullableContent { get; set; }
+ public IReadOnlyDictionary NonNullableIReadOnlyDictionaryWithValueTypeInNonNullableContent { get; set; } = default!;
+ public IReadOnlyDictionary NonNullableIReadOnlyDictionaryWithValueTypeInNullableContent { get; set; } = default!;
+ public IReadOnlyDictionary? NullableIReadOnlyDictionaryWithValueTypeInNullableContent { get; set; }
+
+ public class SubTypeWithOneNullableContent
+ {
+ public string? NullableString { get; set; }
+ }
+
+ public class SubTypeWithOneNonNullableContent
+ {
+ public string NonNullableString { get; set; } = default!;
+ }
}
#nullable restore
}