Skip to content

Commit

Permalink
Moved call to TryLoadGenericMetaTypeNullability (#71851)
Browse files Browse the repository at this point in the history
* Moved call to TryLoadGenericMetaTypeNullability

The TryLoadGenericMetaTypeNullability method was called with the same
member info but varying nullability across the entire nullability
hierarchy. Moved it one level up where nullability and member info are
aligned.
  • Loading branch information
ropufu authored Jul 12, 2022
1 parent 02f875b commit 6cde4be
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,14 @@ private static NotAnnotatedStatus PopulateAnnotationInfo(IList<CustomAttributeDa
private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, NullableAttributeStateParser parser)
{
int index = 0;
return GetNullabilityInfo(memberInfo, type, parser, ref index);
NullabilityInfo nullability = GetNullabilityInfo(memberInfo, type, parser, ref index);

if (!type.IsValueType && nullability.ReadState != NullabilityState.Unknown)
{
TryLoadGenericMetaTypeNullability(memberInfo, nullability);
}

return nullability;
}

private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, NullableAttributeStateParser parser, ref int index)
Expand Down Expand Up @@ -379,14 +386,7 @@ private NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, Nul
}
}

NullabilityInfo nullability = new NullabilityInfo(type, state, state, elementState, genericArgumentsState);

if (!type.IsValueType && state != NullabilityState.Unknown)
{
TryLoadGenericMetaTypeNullability(memberInfo, nullability);
}

return nullability;
return new NullabilityInfo(type, state, state, elementState, genericArgumentsState);
}

private static NullableAttributeStateParser CreateParser(IList<CustomAttributeData> customAttributes)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1089,6 +1089,67 @@ public void TestNestedGenericInheritanceWithMultipleParameters()
Assert.Equal(NullabilityState.NotNull, item3Info.ElementType!.ReadState);
Assert.Equal(NullabilityState.NotNull, item3Info.ElementType.WriteState);
}

[Fact]
[SkipOnMono("Nullability attributes trimmed on Mono")]
public void TestNullabilityInfoCreationOnPropertiesWithNestedGenericTypeArguments()
{
Type type = typeof(TypeWithPropertiesNestingItsGenericTypeArgument<int>);

NullabilityInfo shallow1Info = nullabilityContext.Create(type.GetProperty("Shallow1")!);
NullabilityInfo deep1Info = nullabilityContext.Create(type.GetProperty("Deep1")!);
NullabilityInfo deep2Info = nullabilityContext.Create(type.GetProperty("Deep2")!);
NullabilityInfo deep3Info = nullabilityContext.Create(type.GetProperty("Deep3")!);
NullabilityInfo deep4Info = nullabilityContext.Create(type.GetProperty("Deep4")!);
NullabilityInfo deep5Info = nullabilityContext.Create(type.GetProperty("Deep5")!);

//public Tuple<T>? Shallow1 { get; set; }
NullabilityInfo info = shallow1Info;
Assert.Equal(1, info.GenericTypeArguments.Length);
Assert.Equal(NullabilityState.Nullable, info.GenericTypeArguments[0].ReadState);

//public Tuple<Tuple<T>>? Deep1 { get; set; }
info = deep1Info;
Assert.Equal(1, info.GenericTypeArguments.Length);
Assert.Equal(1, info.GenericTypeArguments[0].GenericTypeArguments.Length);
Assert.Equal(NullabilityState.NotNull, info.GenericTypeArguments[0].ReadState);
Assert.Equal(NullabilityState.Nullable, info.GenericTypeArguments[0].GenericTypeArguments[0].ReadState);

//public Tuple<Tuple<T>, int>? Deep2 { get; set; }
info = deep2Info;
Assert.Equal(2, info.GenericTypeArguments.Length);
Assert.Equal(1, info.GenericTypeArguments[0].GenericTypeArguments.Length);
Assert.Equal(NullabilityState.NotNull, info.GenericTypeArguments[0].ReadState);
Assert.Equal(NullabilityState.NotNull, info.GenericTypeArguments[1].ReadState);
Assert.Equal(NullabilityState.Nullable, info.GenericTypeArguments[0].GenericTypeArguments[0].ReadState);

//public Tuple<int?, Tuple<T>>? Deep3 { get; set; }
info = deep3Info;
Assert.Equal(2, info.GenericTypeArguments.Length);
Assert.Equal(1, info.GenericTypeArguments[1].GenericTypeArguments.Length);
Assert.Equal(NullabilityState.Nullable, info.GenericTypeArguments[0].ReadState);
Assert.Equal(NullabilityState.NotNull, info.GenericTypeArguments[1].ReadState);
Assert.Equal(NullabilityState.Nullable, info.GenericTypeArguments[1].GenericTypeArguments[0].ReadState);

//public Tuple<int, int?, Tuple<T>>? Deep4 { get; set; }
info = deep4Info;
Assert.Equal(3, info.GenericTypeArguments.Length);
Assert.Equal(1, info.GenericTypeArguments[2].GenericTypeArguments.Length);
Assert.Equal(NullabilityState.NotNull, info.GenericTypeArguments[0].ReadState);
Assert.Equal(NullabilityState.Nullable, info.GenericTypeArguments[1].ReadState);
Assert.Equal(NullabilityState.NotNull, info.GenericTypeArguments[2].ReadState);
Assert.Equal(NullabilityState.Nullable, info.GenericTypeArguments[2].GenericTypeArguments[0].ReadState);

//public Tuple<int, int, Tuple<T, int>?>? Deep5 { get; set; }
info = deep5Info;
Assert.Equal(3, info.GenericTypeArguments.Length);
Assert.Equal(2, info.GenericTypeArguments[2].GenericTypeArguments.Length);
Assert.Equal(NullabilityState.NotNull, info.GenericTypeArguments[0].ReadState);
Assert.Equal(NullabilityState.NotNull, info.GenericTypeArguments[1].ReadState);
Assert.Equal(NullabilityState.Nullable, info.GenericTypeArguments[2].ReadState);
Assert.Equal(NullabilityState.Nullable, info.GenericTypeArguments[2].GenericTypeArguments[0].ReadState);
Assert.Equal(NullabilityState.NotNull, info.GenericTypeArguments[2].GenericTypeArguments[1].ReadState);
}
}

#pragma warning disable CS0649, CS0067, CS0414
Expand Down Expand Up @@ -1348,4 +1409,14 @@ public DerivesFromTupleOfNestedGenerics(List<string[]> item1, Dictionary<object[
{
}
}

public class TypeWithPropertiesNestingItsGenericTypeArgument<T>
{
public Tuple<T>? Shallow1 { get; set; }
public Tuple<Tuple<T>>? Deep1 { get; set; }
public Tuple<Tuple<T>, int>? Deep2 { get; set; }
public Tuple<int?, Tuple<T>>? Deep3 { get; set; }
public Tuple<int, int?, Tuple<T?>>? Deep4 { get; set; }
public Tuple<int, int, Tuple<T, int>?>? Deep5 { get; set; }
}
}

0 comments on commit 6cde4be

Please sign in to comment.