Browse Source

Merge pull request #2765 from icsharpcode/issue/1204

pull/2768/head
Siegfried Pammer 3 years ago committed by GitHub
parent
commit
d2cc9e0989
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 7
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs
  3. 4
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  4. 4
      ICSharpCode.Decompiler/TypeSystem/ComHelper.cs
  5. 4
      ICSharpCode.Decompiler/TypeSystem/IEntity.cs
  6. 40
      ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
  7. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs
  8. 27
      ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
  9. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/LocalFunctionMethod.cs
  10. 24
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs
  11. 25
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
  12. 24
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  13. 42
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs
  14. 24
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
  15. 7
      ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs
  16. 3
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs
  17. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/SyntheticRangeIndexer.cs
  18. 32
      ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs
  19. 35
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
  20. 3
      ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs
  21. 21
      ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs

4
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1491,7 +1491,7 @@ namespace ICSharpCode.Decompiler.CSharp
EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, PEFile module) EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, PEFile module)
{ {
if (typeDef.HasAttribute(KnownAttribute.Flags, inherit: false)) if (typeDef.HasAttribute(KnownAttribute.Flags))
return EnumValueDisplayMode.AllHex; return EnumValueDisplayMode.AllHex;
bool first = true; bool first = true;
long firstValue = 0, previousValue = 0; long firstValue = 0, previousValue = 0;
@ -1917,7 +1917,7 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
type = null; type = null;
elementCount = 0; elementCount = 0;
IAttribute attr = field.GetAttribute(KnownAttribute.FixedBuffer, inherit: false); IAttribute attr = field.GetAttribute(KnownAttribute.FixedBuffer);
if (attr != null && attr.FixedArguments.Length == 2) if (attr != null && attr.FixedArguments.Length == 2)
{ {
if (attr.FixedArguments[0].Value is IType trr && attr.FixedArguments[1].Value is int length) if (attr.FixedArguments[0].Value is IType trr && attr.FixedArguments[1].Value is int length)

7
ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs

@ -156,10 +156,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return SymbolKind.Operator; } get { return SymbolKind.Operator; }
} }
IEnumerable<IAttribute> IEntity.GetAttributes() IEnumerable<IAttribute> IEntity.GetAttributes() => EmptyList<IAttribute>.Instance;
{ bool IEntity.HasAttribute(KnownAttribute attribute) => false;
return EmptyList<IAttribute>.Instance; IAttribute? IEntity.GetAttribute(KnownAttribute attribute) => null;
}
Accessibility IEntity.Accessibility { Accessibility IEntity.Accessibility {
get { return Accessibility.Public; } get { return Accessibility.Public; }

4
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -1154,7 +1154,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return true; return true;
} }
Dictionary<object, (KnownTypeCode Type, string Member)> specialConstants = new Dictionary<object, (KnownTypeCode Type, string Member)>() { static readonly Dictionary<object, (KnownTypeCode Type, string Member)> specialConstants = new Dictionary<object, (KnownTypeCode Type, string Member)>() {
// byte: // byte:
{ byte.MaxValue, (KnownTypeCode.Byte, "MaxValue") }, { byte.MaxValue, (KnownTypeCode.Byte, "MaxValue") },
// sbyte: // sbyte:
@ -1196,7 +1196,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
bool IsFlagsEnum(ITypeDefinition type) bool IsFlagsEnum(ITypeDefinition type)
{ {
return type.HasAttribute(KnownAttribute.Flags, inherit: false); return type.HasAttribute(KnownAttribute.Flags);
} }
Expression ConvertEnumValue(IType type, long val) Expression ConvertEnumValue(IType type, long val)

4
ICSharpCode.Decompiler/TypeSystem/ComHelper.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
return typeDefinition != null return typeDefinition != null
&& typeDefinition.Kind == TypeKind.Interface && typeDefinition.Kind == TypeKind.Interface
&& typeDefinition.HasAttribute(KnownAttribute.ComImport, inherit: false); && typeDefinition.HasAttribute(KnownAttribute.ComImport);
} }
/// <summary> /// <summary>
@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
if (typeDefinition == null) if (typeDefinition == null)
return SpecialType.UnknownType; return SpecialType.UnknownType;
var coClassAttribute = typeDefinition.GetAttribute(KnownAttribute.CoClass, inherit: false); var coClassAttribute = typeDefinition.GetAttribute(KnownAttribute.CoClass);
if (coClassAttribute != null && coClassAttribute.FixedArguments.Length == 1) if (coClassAttribute != null && coClassAttribute.FixedArguments.Length == 1)
{ {
if (coClassAttribute.FixedArguments[0].Value is IType ty) if (coClassAttribute.FixedArguments[0].Value is IType ty)

4
ICSharpCode.Decompiler/TypeSystem/IEntity.cs

@ -68,6 +68,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
IEnumerable<IAttribute> GetAttributes(); IEnumerable<IAttribute> GetAttributes();
bool HasAttribute(KnownAttribute attribute);
IAttribute? GetAttribute(KnownAttribute attribute);
/// <summary> /// <summary>
/// Gets the accessibility of this entity. /// Gets the accessibility of this entity.
/// </summary> /// </summary>

40
ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs

@ -190,7 +190,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
foreach (var handle in attributes) foreach (var handle in attributes)
{ {
var attribute = metadata.GetCustomAttribute(handle); var attribute = metadata.GetCustomAttribute(handle);
// Attribute types shouldn't be generic (and certainly not open), so we don't need a generic context. // Attribute types shouldn't be open generic, so we don't need a generic context.
var ctor = module.ResolveMethod(attribute.Constructor, new GenericContext()); var ctor = module.ResolveMethod(attribute.Constructor, new GenericContext());
var type = ctor.DeclaringType; var type = ctor.DeclaringType;
if (IgnoreAttribute(type, target)) if (IgnoreAttribute(type, target))
@ -205,6 +205,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{ {
if (attributeType.DeclaringType != null || attributeType.TypeParameterCount != 0) if (attributeType.DeclaringType != null || attributeType.TypeParameterCount != 0)
return false; return false;
return IgnoreAttribute(new TopLevelTypeName(attributeType.Namespace, attributeType.Name), target);
}
internal bool IgnoreAttribute(TopLevelTypeName attributeType, SymbolKind target)
{
switch (attributeType.Namespace) switch (attributeType.Namespace)
{ {
case "System.Runtime.CompilerServices": case "System.Runtime.CompilerServices":
@ -259,6 +264,39 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
} }
internal bool HasAttribute(MetadataReader metadata, CustomAttributeHandleCollection customAttributes, KnownAttribute attribute, SymbolKind symbolKind)
{
Debug.Assert(attribute.IsCustomAttribute());
foreach (var h in customAttributes)
{
var attr = metadata.GetCustomAttribute(h);
if (attr.IsKnownAttribute(metadata, attribute))
{
return !IgnoreAttribute(attribute.GetTypeName(), symbolKind);
}
}
return false;
}
internal IAttribute GetAttribute(MetadataReader metadata, CustomAttributeHandleCollection customAttributes, KnownAttribute attribute, SymbolKind symbolKind)
{
Debug.Assert(attribute.IsCustomAttribute());
foreach (var h in customAttributes)
{
var attr = metadata.GetCustomAttribute(h);
if (attr.IsKnownAttribute(metadata, attribute)
&& !IgnoreAttribute(attribute.GetTypeName(), symbolKind))
{
// Attribute types shouldn't be open generic, so we don't need a generic context.
var ctor = module.ResolveMethod(attr.Constructor, new GenericContext());
return new CustomAttribute(module, ctor, h);
}
}
return null;
}
static bool IsMethodLike(SymbolKind kind) static bool IsMethodLike(SymbolKind kind)
{ {
return kind switch { return kind switch {

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

@ -61,6 +61,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IModule IEntity.ParentModule => DeclaringType?.GetDefinition()?.ParentModule; IModule IEntity.ParentModule => DeclaringType?.GetDefinition()?.ParentModule;
IEnumerable<IAttribute> IEntity.GetAttributes() => EmptyList<IAttribute>.Instance; IEnumerable<IAttribute> IEntity.GetAttributes() => EmptyList<IAttribute>.Instance;
bool IEntity.HasAttribute(KnownAttribute attribute) => false;
IAttribute IEntity.GetAttribute(KnownAttribute attribute) => null;
public Accessibility Accessibility { get; set; } = Accessibility.Public; public Accessibility Accessibility { get; set; } = Accessibility.Public;

27
ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs

@ -107,7 +107,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
PreserveBaseOverrides, PreserveBaseOverrides,
} }
static class KnownAttributes public static class KnownAttributes
{ {
internal const int Count = (int)KnownAttribute.PreserveBaseOverrides + 1; internal const int Count = (int)KnownAttribute.PreserveBaseOverrides + 1;
@ -197,5 +197,30 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
return KnownAttribute.None; return KnownAttribute.None;
} }
public static bool IsCustomAttribute(this KnownAttribute knownAttribute)
{
switch (knownAttribute)
{
case KnownAttribute.Serializable:
case KnownAttribute.ComImport:
case KnownAttribute.StructLayout:
case KnownAttribute.DllImport:
case KnownAttribute.PreserveSig:
case KnownAttribute.MethodImpl:
case KnownAttribute.FieldOffset:
case KnownAttribute.NonSerialized:
case KnownAttribute.MarshalAs:
case KnownAttribute.PermissionSet:
case KnownAttribute.Optional:
case KnownAttribute.In:
case KnownAttribute.Out:
case KnownAttribute.IndexerName:
case KnownAttribute.SpecialName:
return false;
default:
return true;
}
}
} }
} }

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

@ -145,6 +145,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IType DeclaringType => baseMethod.DeclaringType; public IType DeclaringType => baseMethod.DeclaringType;
public IModule ParentModule => baseMethod.ParentModule; public IModule ParentModule => baseMethod.ParentModule;
IEnumerable<IAttribute> IEntity.GetAttributes() => baseMethod.GetAttributes(); IEnumerable<IAttribute> IEntity.GetAttributes() => baseMethod.GetAttributes();
bool IEntity.HasAttribute(KnownAttribute attribute) => baseMethod.HasAttribute(attribute);
IAttribute IEntity.GetAttribute(KnownAttribute attribute) => baseMethod.GetAttribute(attribute);
IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes(); IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes();
bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly; bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly;
bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly; bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly;

24
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs

@ -123,6 +123,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Add(eventDef.GetCustomAttributes(), SymbolKind.Event); b.Add(eventDef.GetCustomAttributes(), SymbolKind.Event);
return b.Build(); return b.Build();
} }
public bool HasAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().Any(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetEventDefinition(handle);
return b.HasAttribute(metadata, def.GetCustomAttributes(), attribute, SymbolKind.Event);
}
public IAttribute GetAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().FirstOrDefault(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetEventDefinition(handle);
return b.GetAttribute(metadata, def.GetCustomAttributes(), attribute, SymbolKind.Event);
}
#endregion #endregion
public Accessibility Accessibility => AnyAccessor?.Accessibility ?? Accessibility.None; public Accessibility Accessibility => AnyAccessor?.Accessibility ?? Accessibility.None;

25
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
@ -164,6 +165,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return b.Build(); return b.Build();
} }
public bool HasAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().Any(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetFieldDefinition(handle);
return b.HasAttribute(metadata, def.GetCustomAttributes(), attribute, SymbolKind.Field);
}
public IAttribute GetAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().FirstOrDefault(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetFieldDefinition(handle);
return b.GetAttribute(metadata, def.GetCustomAttributes(), attribute, SymbolKind.Field);
}
public string FullName => $"{DeclaringType?.FullName}.{Name}"; public string FullName => $"{DeclaringType?.FullName}.{Name}";
public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}"; public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}";
public string Namespace => DeclaringType?.Namespace ?? string.Empty; public string Namespace => DeclaringType?.Namespace ?? string.Empty;

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

@ -463,6 +463,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return b.Build(); return b.Build();
} }
public bool HasAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().Any(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetMethodDefinition(handle);
return b.HasAttribute(metadata, def.GetCustomAttributes(), attribute, symbolKind);
}
public IAttribute GetAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().FirstOrDefault(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetMethodDefinition(handle);
return b.GetAttribute(metadata, def.GetCustomAttributes(), attribute, symbolKind);
}
#endregion #endregion
#region Return type attributes #region Return type attributes

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

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
const Accessibility InvalidAccessibility = (Accessibility)0xff; const Accessibility InvalidAccessibility = (Accessibility)0xff;
readonly MetadataModule module; readonly MetadataModule module;
readonly PropertyDefinitionHandle propertyHandle; readonly PropertyDefinitionHandle handle;
readonly IMethod getter; readonly IMethod getter;
readonly IMethod setter; readonly IMethod setter;
readonly string name; readonly string name;
@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
Debug.Assert(module != null); Debug.Assert(module != null);
Debug.Assert(!handle.IsNil); Debug.Assert(!handle.IsNil);
this.module = module; this.module = module;
this.propertyHandle = handle; this.handle = handle;
var metadata = module.metadata; var metadata = module.metadata;
var prop = metadata.GetPropertyDefinition(handle); var prop = metadata.GetPropertyDefinition(handle);
@ -83,10 +83,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override string ToString() public override string ToString()
{ {
return $"{MetadataTokens.GetToken(propertyHandle):X8} {DeclaringType?.ReflectionName}.{Name}"; return $"{MetadataTokens.GetToken(handle):X8} {DeclaringType?.ReflectionName}.{Name}";
} }
public EntityHandle MetadataToken => propertyHandle; public EntityHandle MetadataToken => handle;
public string Name => name; public string Name => name;
public bool CanGet => getter != null; public bool CanGet => getter != null;
@ -122,14 +122,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool ReturnTypeIsRefReadOnly { public bool ReturnTypeIsRefReadOnly {
get { get {
var propertyDef = module.metadata.GetPropertyDefinition(propertyHandle); var propertyDef = module.metadata.GetPropertyDefinition(handle);
return propertyDef.GetCustomAttributes().HasKnownAttribute(module.metadata, KnownAttribute.IsReadOnly); return propertyDef.GetCustomAttributes().HasKnownAttribute(module.metadata, KnownAttribute.IsReadOnly);
} }
} }
private void DecodeSignature() private void DecodeSignature()
{ {
var propertyDef = module.metadata.GetPropertyDefinition(propertyHandle); var propertyDef = module.metadata.GetPropertyDefinition(handle);
var genericContext = new GenericContext(DeclaringType.TypeParameters); var genericContext = new GenericContext(DeclaringType.TypeParameters);
IType returnType; IType returnType;
IParameter[] parameters; IParameter[] parameters;
@ -201,7 +201,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{ {
var b = new AttributeListBuilder(module); var b = new AttributeListBuilder(module);
var metadata = module.metadata; var metadata = module.metadata;
var propertyDef = metadata.GetPropertyDefinition(propertyHandle); var propertyDef = metadata.GetPropertyDefinition(handle);
if (IsIndexer && Name != "Item" && !IsExplicitInterfaceImplementation) if (IsIndexer && Name != "Item" && !IsExplicitInterfaceImplementation)
{ {
b.Add(KnownAttribute.IndexerName, KnownTypeCode.String, Name); b.Add(KnownAttribute.IndexerName, KnownTypeCode.String, Name);
@ -216,6 +216,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Add(propertyDef.GetCustomAttributes(), symbolKind); b.Add(propertyDef.GetCustomAttributes(), symbolKind);
return b.Build(); return b.Build();
} }
public bool HasAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().Any(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetPropertyDefinition(handle);
return b.HasAttribute(metadata, def.GetCustomAttributes(), attribute, symbolKind);
}
public IAttribute GetAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().FirstOrDefault(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetPropertyDefinition(handle);
return b.GetAttribute(metadata, def.GetCustomAttributes(), attribute, symbolKind);
}
#endregion #endregion
#region Accessibility #region Accessibility
@ -278,14 +302,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{ {
if (obj is MetadataProperty p) if (obj is MetadataProperty p)
{ {
return propertyHandle == p.propertyHandle && module.PEFile == p.module.PEFile; return handle == p.handle && module.PEFile == p.module.PEFile;
} }
return false; return false;
} }
public override int GetHashCode() public override int GetHashCode()
{ {
return 0x32b6a76c ^ module.PEFile.GetHashCode() ^ propertyHandle.GetHashCode(); return 0x32b6a76c ^ module.PEFile.GetHashCode() ^ handle.GetHashCode();
} }
bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) bool IMember.Equals(IMember obj, TypeVisitor typeNormalization)

24
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs

@ -432,6 +432,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return b.Build(); return b.Build();
} }
public bool HasAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().Any(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetTypeDefinition(handle);
return b.HasAttribute(metadata, def.GetCustomAttributes(), attribute, SymbolKind.TypeDefinition);
}
public IAttribute GetAttribute(KnownAttribute attribute)
{
if (!attribute.IsCustomAttribute())
{
return GetAttributes().FirstOrDefault(attr => attr.AttributeType.IsKnownType(attribute));
}
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var def = metadata.GetTypeDefinition(handle);
return b.GetAttribute(metadata, def.GetCustomAttributes(), attribute, SymbolKind.TypeDefinition);
}
public string DefaultMemberName { public string DefaultMemberName {
get { get {
string defaultMemberName = LazyInit.VolatileRead(ref this.defaultMemberName); string defaultMemberName = LazyInit.VolatileRead(ref this.defaultMemberName);

7
ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs

@ -258,10 +258,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return EmptyList<IMethod>.Instance; return EmptyList<IMethod>.Instance;
} }
IEnumerable<IAttribute> IEntity.GetAttributes() IEnumerable<IAttribute> IEntity.GetAttributes() => EmptyList<IAttribute>.Instance;
{ bool IEntity.HasAttribute(KnownAttribute attribute) => false;
return EmptyList<IAttribute>.Instance; IAttribute IEntity.GetAttribute(KnownAttribute attribute) => null;
}
IEnumerable<IMethod> IType.GetConstructors(Predicate<IMethod> filter, GetMemberOptions options) IEnumerable<IMethod> IType.GetConstructors(Predicate<IMethod> filter, GetMemberOptions options)
{ {

3
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs

@ -162,6 +162,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
IEnumerable<IAttribute> IEntity.GetAttributes() => baseMember.GetAttributes(); IEnumerable<IAttribute> IEntity.GetAttributes() => baseMember.GetAttributes();
bool IEntity.HasAttribute(KnownAttribute attribute) => baseMember.HasAttribute(attribute);
IAttribute IEntity.GetAttribute(KnownAttribute attribute) => baseMember.GetAttribute(attribute);
public IEnumerable<IMember> ExplicitlyImplementedInterfaceMembers { public IEnumerable<IMember> ExplicitlyImplementedInterfaceMembers {
get { get {

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

@ -126,6 +126,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
IEnumerable<IAttribute> IEntity.GetAttributes() => underlyingMethod.GetAttributes(); IEnumerable<IAttribute> IEntity.GetAttributes() => underlyingMethod.GetAttributes();
bool IEntity.HasAttribute(KnownAttribute attribute) => underlyingMethod.HasAttribute(attribute);
IAttribute IEntity.GetAttribute(KnownAttribute attribute) => underlyingMethod.GetAttribute(attribute);
IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => underlyingMethod.GetReturnTypeAttributes(); IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => underlyingMethod.GetReturnTypeAttributes();

32
ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs

@ -185,6 +185,20 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
internal static IAttribute GetAttribute(ITypeDefinition typeDef, KnownAttribute attributeType)
{
foreach (var baseType in typeDef.GetNonInterfaceBaseTypes().Reverse())
{
ITypeDefinition baseTypeDef = baseType.GetDefinition();
if (baseTypeDef == null)
continue;
var attr = baseTypeDef.GetAttribute(attributeType);
if (attr != null)
return attr;
}
return null;
}
internal static IEnumerable<IAttribute> GetAttributes(IMember member) internal static IEnumerable<IAttribute> GetAttributes(IMember member)
{ {
HashSet<IMember> visitedMembers = new HashSet<IMember>(); HashSet<IMember> visitedMembers = new HashSet<IMember>();
@ -202,6 +216,24 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} while (member.IsOverride && (member = InheritanceHelper.GetBaseMember(member)) != null); } while (member.IsOverride && (member = InheritanceHelper.GetBaseMember(member)) != null);
} }
internal static IAttribute GetAttribute(IMember member, KnownAttribute attributeType)
{
HashSet<IMember> visitedMembers = new HashSet<IMember>();
do
{
member = member.MemberDefinition; // it's sufficient to look at the definitions
if (!visitedMembers.Add(member))
{
// abort if we seem to be in an infinite loop (cyclic inheritance)
break;
}
var attr = member.GetAttribute(attributeType);
if (attr != null)
return attr;
} while (member.IsOverride && (member = InheritanceHelper.GetBaseMember(member)) != null);
return null;
}
#endregion #endregion
} }
} }

35
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -485,7 +485,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region IEntity.GetAttribute #region IEntity.GetAttribute
/// <summary> /// <summary>
/// Gets whether the entity has an attribute of the specified attribute type (or derived attribute types). /// Gets whether the entity has an attribute of the specified attribute type.
/// </summary> /// </summary>
/// <param name="entity">The entity on which the attributes are declared.</param> /// <param name="entity">The entity on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param> /// <param name="attributeType">The attribute type to look for.</param>
@ -494,13 +494,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// (if the given <paramref name="entity"/> in an <c>override</c>) /// (if the given <paramref name="entity"/> in an <c>override</c>)
/// should be returned. /// should be returned.
/// </param> /// </param>
public static bool HasAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit = false) public static bool HasAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit)
{ {
if (!inherit)
return entity.HasAttribute(attributeType);
return GetAttribute(entity, attributeType, inherit) != null; return GetAttribute(entity, attributeType, inherit) != null;
} }
/// <summary> /// <summary>
/// Gets the attribute of the specified attribute type (or derived attribute types). /// Gets the attribute of the specified attribute type.
/// </summary> /// </summary>
/// <param name="entity">The entity on which the attributes are declared.</param> /// <param name="entity">The entity on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param> /// <param name="attributeType">The attribute type to look for.</param>
@ -514,9 +517,27 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// If inherit is true, an from the entity itself will be returned if possible; /// If inherit is true, an from the entity itself will be returned if possible;
/// and the base entity will only be searched if none exists. /// and the base entity will only be searched if none exists.
/// </returns> /// </returns>
public static IAttribute GetAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit = false) public static IAttribute GetAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit)
{ {
return GetAttributes(entity, inherit).FirstOrDefault(a => a.AttributeType.IsKnownType(attributeType)); if (inherit)
{
if (entity is ITypeDefinition td)
{
return InheritanceHelper.GetAttribute(td, attributeType);
}
else if (entity is IMember m)
{
return InheritanceHelper.GetAttribute(m, attributeType);
}
else
{
throw new NotSupportedException("Unknown entity type");
}
}
else
{
return entity.GetAttribute(attributeType);
}
} }
/// <summary> /// <summary>
@ -559,7 +580,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region IParameter.GetAttribute #region IParameter.GetAttribute
/// <summary> /// <summary>
/// Gets whether the parameter has an attribute of the specified attribute type (or derived attribute types). /// Gets whether the parameter has an attribute of the specified attribute type.
/// </summary> /// </summary>
/// <param name="parameter">The parameter on which the attributes are declared.</param> /// <param name="parameter">The parameter on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param> /// <param name="attributeType">The attribute type to look for.</param>
@ -569,7 +590,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
/// <summary> /// <summary>
/// Gets the attribute of the specified attribute type (or derived attribute types). /// Gets the attribute of the specified attribute type.
/// </summary> /// </summary>
/// <param name="parameter">The parameter on which the attributes are declared.</param> /// <param name="parameter">The parameter on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param> /// <param name="attributeType">The attribute type to look for.</param>

3
ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs

@ -118,6 +118,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
IEnumerable<IAttribute> IEntity.GetAttributes() => baseMethod.GetAttributes(); IEnumerable<IAttribute> IEntity.GetAttributes() => baseMethod.GetAttributes();
bool IEntity.HasAttribute(KnownAttribute attribute) => baseMethod.HasAttribute(attribute);
IAttribute IEntity.GetAttribute(KnownAttribute attribute) => baseMethod.GetAttribute(attribute);
IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes(); IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes();
bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly; bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly;
bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly; bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly;

21
ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs

@ -51,26 +51,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
bool IsBuiltinAttribute(ITypeDefinition attributeType, out KnownAttribute knownAttribute) bool IsBuiltinAttribute(ITypeDefinition attributeType, out KnownAttribute knownAttribute)
{ {
knownAttribute = attributeType.IsBuiltinAttribute(); knownAttribute = attributeType.IsBuiltinAttribute();
switch (knownAttribute) return !knownAttribute.IsCustomAttribute();
{
case KnownAttribute.Serializable:
case KnownAttribute.ComImport:
case KnownAttribute.StructLayout:
case KnownAttribute.DllImport:
case KnownAttribute.PreserveSig:
case KnownAttribute.MethodImpl:
case KnownAttribute.FieldOffset:
case KnownAttribute.NonSerialized:
case KnownAttribute.MarshalAs:
case KnownAttribute.PermissionSet:
case KnownAttribute.Optional:
case KnownAttribute.In:
case KnownAttribute.Out:
case KnownAttribute.IndexerName:
return true;
default:
return false;
}
} }
IEnumerable<IEnumerable<ISymbol>> HandleBuiltinAttribute(KnownAttribute attribute, AnalyzerScope scope, CancellationToken ct) IEnumerable<IEnumerable<ISymbol>> HandleBuiltinAttribute(KnownAttribute attribute, AnalyzerScope scope, CancellationToken ct)

Loading…
Cancel
Save