Skip to content

Commit

Permalink
NullableContextAttribute can no longer appear at module level
Browse files Browse the repository at this point in the history
As per dotnet/roslyn#37610, the compiler will
no longer emit nullability context attributes at the module level,
only at the type and method level.

Simplify our non-nullability detection convention.

Part of dotnet#16440
  • Loading branch information
roji committed Aug 1, 2019
1 parent 0b9205b commit 822ca94
Showing 1 changed file with 18 additions and 41 deletions.
59 changes: 18 additions & 41 deletions src/EFCore/Metadata/Conventions/NonNullableConventionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,6 @@ protected NonNullableConventionBase([NotNull] ProviderConventionSetBuilderDepend
/// </summary>
protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; }

private byte? GetNullabilityContextFlag(NonNullabilityConventionState state, Attribute[] attributes)
{
if (attributes.FirstOrDefault(a => a.GetType().FullName == NullableContextAttributeFullName) is Attribute attribute)
{
var attributeType = attribute.GetType();

if (attributeType != state.NullableContextAttrType)
{
state.NullableContextFlagFieldInfo = attributeType.GetField("Flag");
state.NullableContextAttrType = attributeType;
}

if (state.NullableContextFlagFieldInfo?.GetValue(attribute) is byte flag)
{
return flag;
}
}

return null;
}

/// <summary>
/// Returns a value indicating whether the member type is a non-nullable reference type.
/// </summary>
Expand Down Expand Up @@ -103,33 +82,32 @@ protected virtual bool IsNonNullableRefType(
var type = memberInfo.DeclaringType;
if (type != null)
{
if (state.TypeNonNullabilityContextCache.TryGetValue(type, out var cachedTypeNonNullable))
if (state.TypeCache.TryGetValue(type, out var cachedTypeNonNullable))
{
return cachedTypeNonNullable;
}

var typeContextFlag = GetNullabilityContextFlag(state, Attribute.GetCustomAttributes(type));
if (typeContextFlag.HasValue)
if (Attribute.GetCustomAttributes(type)
.FirstOrDefault(a => a.GetType().FullName == NullableContextAttributeFullName) is Attribute contextAttr)
{
return state.TypeNonNullabilityContextCache[type] = typeContextFlag.Value == 1;
var attributeType = contextAttr.GetType();

if (attributeType != state.NullableContextAttrType)
{
state.NullableContextFlagFieldInfo = attributeType.GetField("Flag");
state.NullableContextAttrType = attributeType;
}

if (state.NullableContextFlagFieldInfo?.GetValue(contextAttr) is byte flag)
{
return state.TypeCache[type] = flag == 1;
}
}
}

// Not found at the type level, try at the module level
var module = memberInfo.Module;
if (!state.ModuleNonNullabilityContextCache.TryGetValue(module, out var moduleNonNullable))
{
var moduleContextFlag = GetNullabilityContextFlag(state, Attribute.GetCustomAttributes(memberInfo.Module));
moduleNonNullable = state.ModuleNonNullabilityContextCache[module] =
moduleContextFlag.HasValue && moduleContextFlag == 1;
}

if (type != null)
{
state.TypeNonNullabilityContextCache[type] = moduleNonNullable;
return state.TypeCache[type] = false;
}

return moduleNonNullable;
return false;
}

private NonNullabilityConventionState GetOrInitializeState(IConventionModelBuilder modelBuilder)
Expand All @@ -152,8 +130,7 @@ private class NonNullabilityConventionState
public Type NullableContextAttrType;
public FieldInfo NullableFlagsFieldInfo;
public FieldInfo NullableContextFlagFieldInfo;
public Dictionary<Type, bool> TypeNonNullabilityContextCache { get; } = new Dictionary<Type, bool>();
public Dictionary<Module, bool> ModuleNonNullabilityContextCache { get; } = new Dictionary<Module, bool>();
public Dictionary<Type, bool> TypeCache { get; } = new Dictionary<Type, bool>();
}
}
}

0 comments on commit 822ca94

Please sign in to comment.