Browse Source

Work on #1204: Add optimized implementation of HasAttribute and GetAttribute to IEntity.

pull/2765/head
Siegfried Pammer 3 years ago
parent
commit
583f661153
  1. 4
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 7
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs
  3. 2
      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 @@ -1491,7 +1491,7 @@ namespace ICSharpCode.Decompiler.CSharp
EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, PEFile module)
{
if (typeDef.HasAttribute(KnownAttribute.Flags, inherit: false))
if (typeDef.HasAttribute(KnownAttribute.Flags))
return EnumValueDisplayMode.AllHex;
bool first = true;
long firstValue = 0, previousValue = 0;
@ -1917,7 +1917,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1917,7 +1917,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
type = null;
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.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 @@ -156,10 +156,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return SymbolKind.Operator; }
}
IEnumerable<IAttribute> IEntity.GetAttributes()
{
return EmptyList<IAttribute>.Instance;
}
IEnumerable<IAttribute> IEntity.GetAttributes() => EmptyList<IAttribute>.Instance;
bool IEntity.HasAttribute(KnownAttribute attribute) => false;
IAttribute? IEntity.GetAttribute(KnownAttribute attribute) => null;
Accessibility IEntity.Accessibility {
get { return Accessibility.Public; }

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

@ -1196,7 +1196,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1196,7 +1196,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
bool IsFlagsEnum(ITypeDefinition type)
{
return type.HasAttribute(KnownAttribute.Flags, inherit: false);
return type.HasAttribute(KnownAttribute.Flags);
}
Expression ConvertEnumValue(IType type, long val)

4
ICSharpCode.Decompiler/TypeSystem/ComHelper.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
return typeDefinition != null
&& typeDefinition.Kind == TypeKind.Interface
&& typeDefinition.HasAttribute(KnownAttribute.ComImport, inherit: false);
&& typeDefinition.HasAttribute(KnownAttribute.ComImport);
}
/// <summary>
@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -46,7 +46,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
if (typeDefinition == null)
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.FixedArguments[0].Value is IType ty)

4
ICSharpCode.Decompiler/TypeSystem/IEntity.cs

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

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

@ -190,7 +190,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -190,7 +190,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
foreach (var handle in attributes)
{
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 type = ctor.DeclaringType;
if (IgnoreAttribute(type, target))
@ -205,6 +205,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -205,6 +205,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
if (attributeType.DeclaringType != null || attributeType.TypeParameterCount != 0)
return false;
return IgnoreAttribute(new TopLevelTypeName(attributeType.Namespace, attributeType.Name), target);
}
internal bool IgnoreAttribute(TopLevelTypeName attributeType, SymbolKind target)
{
switch (attributeType.Namespace)
{
case "System.Runtime.CompilerServices":
@ -259,6 +264,39 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -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)
{
return kind switch {

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

@ -61,6 +61,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -61,6 +61,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IModule IEntity.ParentModule => DeclaringType?.GetDefinition()?.ParentModule;
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;

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

@ -107,7 +107,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -107,7 +107,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
PreserveBaseOverrides,
}
static class KnownAttributes
public static class KnownAttributes
{
internal const int Count = (int)KnownAttribute.PreserveBaseOverrides + 1;
@ -197,5 +197,30 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -197,5 +197,30 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
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 @@ -145,6 +145,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IType DeclaringType => baseMethod.DeclaringType;
public IModule ParentModule => baseMethod.ParentModule;
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();
bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly;
bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly;

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

@ -123,6 +123,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -123,6 +123,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Add(eventDef.GetCustomAttributes(), SymbolKind.Event);
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
public Accessibility Accessibility => AnyAccessor?.Accessibility ?? Accessibility.None;

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

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
@ -164,6 +165,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -164,6 +165,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
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 ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}";
public string Namespace => DeclaringType?.Namespace ?? string.Empty;

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

@ -463,6 +463,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -463,6 +463,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
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
#region Return type attributes

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

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
const Accessibility InvalidAccessibility = (Accessibility)0xff;
readonly MetadataModule module;
readonly PropertyDefinitionHandle propertyHandle;
readonly PropertyDefinitionHandle handle;
readonly IMethod getter;
readonly IMethod setter;
readonly string name;
@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -49,7 +49,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
Debug.Assert(module != null);
Debug.Assert(!handle.IsNil);
this.module = module;
this.propertyHandle = handle;
this.handle = handle;
var metadata = module.metadata;
var prop = metadata.GetPropertyDefinition(handle);
@ -83,10 +83,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -83,10 +83,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
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 bool CanGet => getter != null;
@ -122,14 +122,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -122,14 +122,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool ReturnTypeIsRefReadOnly {
get {
var propertyDef = module.metadata.GetPropertyDefinition(propertyHandle);
var propertyDef = module.metadata.GetPropertyDefinition(handle);
return propertyDef.GetCustomAttributes().HasKnownAttribute(module.metadata, KnownAttribute.IsReadOnly);
}
}
private void DecodeSignature()
{
var propertyDef = module.metadata.GetPropertyDefinition(propertyHandle);
var propertyDef = module.metadata.GetPropertyDefinition(handle);
var genericContext = new GenericContext(DeclaringType.TypeParameters);
IType returnType;
IParameter[] parameters;
@ -201,7 +201,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -201,7 +201,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
var b = new AttributeListBuilder(module);
var metadata = module.metadata;
var propertyDef = metadata.GetPropertyDefinition(propertyHandle);
var propertyDef = metadata.GetPropertyDefinition(handle);
if (IsIndexer && Name != "Item" && !IsExplicitInterfaceImplementation)
{
b.Add(KnownAttribute.IndexerName, KnownTypeCode.String, Name);
@ -216,6 +216,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -216,6 +216,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Add(propertyDef.GetCustomAttributes(), symbolKind);
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
#region Accessibility
@ -278,14 +302,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -278,14 +302,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
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;
}
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)

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

@ -432,6 +432,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -432,6 +432,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
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 {
get {
string defaultMemberName = LazyInit.VolatileRead(ref this.defaultMemberName);

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

@ -258,10 +258,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -258,10 +258,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return EmptyList<IMethod>.Instance;
}
IEnumerable<IAttribute> IEntity.GetAttributes()
{
return EmptyList<IAttribute>.Instance;
}
IEnumerable<IAttribute> IEntity.GetAttributes() => EmptyList<IAttribute>.Instance;
bool IEntity.HasAttribute(KnownAttribute attribute) => false;
IAttribute IEntity.GetAttribute(KnownAttribute attribute) => null;
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 @@ -162,6 +162,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
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 {
get {

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

@ -126,6 +126,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -126,6 +126,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
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();

32
ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs

@ -185,6 +185,20 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -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)
{
HashSet<IMember> visitedMembers = new HashSet<IMember>();
@ -202,6 +216,24 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -202,6 +216,24 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
} 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
}
}

35
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -485,7 +485,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -485,7 +485,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region IEntity.GetAttribute
/// <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>
/// <param name="entity">The entity on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param>
@ -494,13 +494,16 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -494,13 +494,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// (if the given <paramref name="entity"/> in an <c>override</c>)
/// should be returned.
/// </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;
}
/// <summary>
/// Gets the attribute of the specified attribute type (or derived attribute types).
/// Gets the attribute of the specified attribute type.
/// </summary>
/// <param name="entity">The entity on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param>
@ -514,9 +517,27 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -514,9 +517,27 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// 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.
/// </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>
@ -559,7 +580,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -559,7 +580,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
#region IParameter.GetAttribute
/// <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>
/// <param name="parameter">The parameter on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param>
@ -569,7 +590,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -569,7 +590,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
/// <summary>
/// Gets the attribute of the specified attribute type (or derived attribute types).
/// Gets the attribute of the specified attribute type.
/// </summary>
/// <param name="parameter">The parameter on which the attributes are declared.</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 @@ -118,6 +118,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
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();
bool IMethod.ReturnTypeIsRefReadOnly => baseMethod.ReturnTypeIsRefReadOnly;
bool IMethod.ThisIsRefReadOnly => baseMethod.ThisIsRefReadOnly;

21
ILSpy/Analyzers/Builtin/AttributeAppliedToAnalyzer.cs

@ -51,26 +51,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin @@ -51,26 +51,7 @@ namespace ICSharpCode.ILSpy.Analyzers.Builtin
bool IsBuiltinAttribute(ITypeDefinition attributeType, out KnownAttribute knownAttribute)
{
knownAttribute = attributeType.IsBuiltinAttribute();
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:
return true;
default:
return false;
}
return !knownAttribute.IsCustomAttribute();
}
IEnumerable<IEnumerable<ISymbol>> HandleBuiltinAttribute(KnownAttribute attribute, AnalyzerScope scope, CancellationToken ct)

Loading…
Cancel
Save