Browse Source

Fix #3094: look for `[NullableAttribute]` both on the property getter and property itself

pull/3111/head
Daniel Grunwald 2 years ago
parent
commit
a14cc0234e
  1. 25
      ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
  2. 14
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  3. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs

25
ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs

@ -40,7 +40,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -40,7 +40,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
SRM.MetadataReader metadata,
TypeSystemOptions options,
Nullability nullableContext,
bool typeChildrenOnly = false)
bool typeChildrenOnly = false,
SRM.CustomAttributeHandleCollection? additionalAttributes = null)
{
bool hasDynamicAttribute = false;
bool[] dynamicAttributeData = null;
@ -57,10 +58,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -57,10 +58,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
nullability = Nullability.Oblivious;
}
const TypeSystemOptions relevantOptions = TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple | TypeSystemOptions.NullabilityAnnotations | TypeSystemOptions.NativeIntegers;
if (attributes != null && (options & relevantOptions) != 0)
{
foreach (var attrHandle in attributes.Value)
void ProcessAttribute(SRM.CustomAttributeHandle attrHandle)
{
var attr = metadata.GetCustomAttribute(attrHandle);
var attrType = attr.GetAttributeType(metadata);
@ -123,6 +122,22 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -123,6 +122,22 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
}
}
const TypeSystemOptions relevantOptions = TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple | TypeSystemOptions.NullabilityAnnotations | TypeSystemOptions.NativeIntegers;
if (attributes != null && (options & relevantOptions) != 0)
{
foreach (var attrHandle in attributes.Value)
{
ProcessAttribute(attrHandle);
}
}
if (additionalAttributes != null && (options & relevantOptions) != 0)
{
// Note: additional attributes will override the values from the normal attributes.
foreach (var attrHandle in additionalAttributes.Value)
{
ProcessAttribute(attrHandle);
}
}
if (hasDynamicAttribute || hasNativeIntegersAttribute || nullability != Nullability.Oblivious || nullableAttributeData != null
|| (options & (TypeSystemOptions.Tuple | TypeSystemOptions.KeepModifiers)) != TypeSystemOptions.KeepModifiers)

14
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs

@ -209,13 +209,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -209,13 +209,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
MetadataModule module, IParameterizedMember owner,
MethodSignature<IType> signature, ParameterHandleCollection? parameterHandles,
Nullability nullableContext, TypeSystemOptions typeSystemOptions,
CustomAttributeHandleCollection? returnTypeAttributes = null)
CustomAttributeHandleCollection? additionalReturnTypeAttributes = null)
{
var metadata = module.metadata;
int i = 0;
IParameter[] parameters = new IParameter[signature.RequiredParameterCount
+ (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs ? 1 : 0)];
IType parameterType;
CustomAttributeHandleCollection? returnTypeAttributes = null;
if (parameterHandles != null)
{
foreach (var parameterHandle in parameterHandles)
@ -225,14 +226,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -225,14 +226,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
// "parameter" holds return type attributes.
// Note: for properties, the attributes normally stored on a method's return type
// are instead stored as normal attributes on the property.
// So MetadataProperty provides a non-null value for returnTypeAttributes,
// which then should be preferred over the attributes on the accessor's parameters.
if (returnTypeAttributes == null)
{
// are instead typically stored as normal attributes on the property.
// So MetadataProperty provides a non-null value for additionalReturnTypeAttributes,
// which then will be preferred over the attributes on the accessor's parameters.
// However if an attribute only exists on the accessor's parameters, we still want
// to process it here.
returnTypeAttributes = par.GetCustomAttributes();
}
}
else if (i < par.SequenceNumber && par.SequenceNumber <= signature.RequiredParameterCount)
{
// "Successive rows of the Param table that are owned by the same method shall be

2
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs

@ -169,7 +169,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -169,7 +169,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
(returnType, parameters, _) = MetadataMethod.DecodeSignature(
module, this, signature,
parameterHandles, nullableContext, typeOptions,
returnTypeAttributes: propertyDef.GetCustomAttributes());
additionalReturnTypeAttributes: propertyDef.GetCustomAttributes());
}
catch (BadImageFormatException)
{

Loading…
Cancel
Save