diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs index 936df3910..cb1620dbd 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs @@ -106,7 +106,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.IsFalse(method.IsVirtual); Assert.IsFalse(method.IsStatic); Assert.AreEqual(0, method.Parameters.Count); - Assert.AreEqual(0, method.Attributes.Count); + Assert.AreEqual(0, method.GetAttributes().Count()); Assert.IsTrue(method.HasBody); Assert.IsNull(method.AccessorOwner); } @@ -117,7 +117,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); Assert.AreEqual(SpecialType.Dynamic, testClass.Fields.Single(f => f.Name == "DynamicField").ReturnType); Assert.AreEqual(SpecialType.Dynamic, testClass.Properties.Single().ReturnType); - Assert.AreEqual(0, testClass.Properties.Single().Attributes.Count); + Assert.AreEqual(0, testClass.Properties.Single().GetAttributes().Count()); } [Test] @@ -153,7 +153,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem { ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1"); - Assert.AreEqual(0, m1.Parameters[0].Attributes.Count); + Assert.AreEqual(0, m1.Parameters[0].GetAttributes().Count()); } [Test] @@ -550,7 +550,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem [Test] public void SerializableAttribute() { - IAttribute attr = GetTypeDefinition(typeof(NonCustomAttributes)).Attributes.Single(); + IAttribute attr = GetTypeDefinition(typeof(NonCustomAttributes)).GetAttributes().Single(); Assert.AreEqual("System.SerializableAttribute", attr.AttributeType.FullName); } @@ -558,13 +558,13 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void NonSerializedAttribute() { IField field = GetTypeDefinition(typeof(NonCustomAttributes)).Fields.Single(f => f.Name == "NonSerializedField"); - Assert.AreEqual("System.NonSerializedAttribute", field.Attributes.Single().AttributeType.FullName); + Assert.AreEqual("System.NonSerializedAttribute", field.GetAttributes().Single().AttributeType.FullName); } [Test] public void ExplicitStructLayoutAttribute() { - IAttribute attr = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Attributes.Single(); + IAttribute attr = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).GetAttributes().Single(); Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.FullName); var arg1 = attr.FixedArguments.Single(); Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.Type.FullName); @@ -585,14 +585,14 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void FieldOffsetAttribute() { IField field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0"); - Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.FullName); - var arg = field.Attributes.Single().FixedArguments.Single(); + Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.GetAttributes().Single().AttributeType.FullName); + var arg = field.GetAttributes().Single().FixedArguments.Single(); Assert.AreEqual("System.Int32", arg.Type.FullName); Assert.AreEqual(0, arg.Value); field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100"); - Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.FullName); - arg = field.Attributes.Single().FixedArguments.Single(); + Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.GetAttributes().Single().AttributeType.FullName); + arg = field.GetAttributes().Single().FixedArguments.Single(); Assert.AreEqual("System.Int32", arg.Type.FullName); Assert.AreEqual(100, arg.Value); } @@ -601,7 +601,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void DllImportAttribute() { IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); - IAttribute dllImport = method.Attributes.Single(); + IAttribute dllImport = method.GetAttributes().Single(); Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.FullName); Assert.AreEqual("unmanaged.dll", dllImport.FixedArguments[0].Value); Assert.AreEqual((int)CharSet.Unicode, dllImport.NamedArguments.Single().Value); @@ -613,16 +613,17 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem IParameter p = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single(); Assert.IsTrue(p.IsRef); Assert.IsFalse(p.IsOut); - Assert.AreEqual(2, p.Attributes.Count); - Assert.AreEqual("System.Runtime.InteropServices.InAttribute", p.Attributes[0].AttributeType.FullName); - Assert.AreEqual("System.Runtime.InteropServices.OutAttribute", p.Attributes[1].AttributeType.FullName); + var attr = p.GetAttributes().ToList(); + Assert.AreEqual(2, attr.Count); + Assert.AreEqual("System.Runtime.InteropServices.InAttribute", attr[0].AttributeType.FullName); + Assert.AreEqual("System.Runtime.InteropServices.OutAttribute", attr[1].AttributeType.FullName); } [Test] public void MarshalAsAttributeOnMethod() { IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); - IAttribute marshalAs = method.ReturnTypeAttributes.Single(); + IAttribute marshalAs = method.GetReturnTypeAttributes().Single(); Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.FixedArguments.Single().Value); } @@ -633,7 +634,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.IsFalse(p.IsOptional); Assert.IsFalse(p.IsRef); Assert.IsTrue(p.IsOut); - Assert.AreEqual(0, p.Attributes.Count); + Assert.AreEqual(0, p.GetAttributes().Count()); Assert.IsTrue(p.Type.Kind == TypeKind.ByReference); } @@ -645,7 +646,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsOut); Assert.IsTrue(p.IsParams); - Assert.AreEqual(0, p.Attributes.Count); + Assert.AreEqual(0, p.GetAttributes().Count()); Assert.IsTrue(p.Type.Kind == TypeKind.Array); } @@ -657,7 +658,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsParams); - Assert.AreEqual(0, p.Attributes.Count); + Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual(4, p.ConstantValue); } @@ -670,7 +671,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsParams); // explicit optional parameter appears in type system if it's read from C#, but not when read from IL - //Assert.AreEqual(1, p.Attributes.Count); + //Assert.AreEqual(1, p.GetAttributes().Count()); } [Test] @@ -681,7 +682,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsParams); - Assert.AreEqual(0, p.Attributes.Count); + Assert.AreEqual(0, p.GetAttributes().Count()); Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, p.ConstantValue); } @@ -693,7 +694,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsParams); - Assert.AreEqual(0, p.Attributes.Count); + Assert.AreEqual(0, p.GetAttributes().Count()); Assert.IsNull(p.ConstantValue); } @@ -781,7 +782,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem { ITypeDefinition type = GetTypeDefinition(typeof(IAssemblyEnum)); // [ComImport] - Assert.AreEqual(1, type.Attributes.Count(a => a.AttributeType.FullName == typeof(ComImportAttribute).FullName)); + Assert.AreEqual(1, type.GetAttributes().Count(a => a.AttributeType.FullName == typeof(ComImportAttribute).FullName)); IMethod m = type.Methods.Single(); Assert.AreEqual("GetNextAssembly", m.Name); @@ -892,7 +893,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem CustomAttributeTypedArgument GetParamsAttributeArgument(int index) { ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute)); - var arr = (AttributeArray)type.Attributes.Single().FixedArguments.Single().Value; + var arr = (AttributeArray)type.GetAttributes().Single().FixedArguments.Single().Value; Assert.AreEqual(5, arr.Length); return arr[index]; } @@ -942,7 +943,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem { ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute)); IProperty prop = type.Properties.Single(p => p.Name == "Property"); - var attr = prop.Attributes.Single(); + var attr = prop.GetAttributes().Single(); Assert.AreEqual(type, attr.AttributeType); var elements = (AttributeArray)attr.FixedArguments.Single().Value; @@ -959,15 +960,15 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem { ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute)); IProperty prop = type.Properties.Single(p => p.Name == "Property"); - Assert.AreEqual(0, prop.Getter.Attributes.Count); - Assert.AreEqual(1, prop.Getter.ReturnTypeAttributes.Count); + Assert.AreEqual(0, prop.Getter.GetAttributes().Count()); + Assert.AreEqual(1, prop.Getter.GetReturnTypeAttributes().Count()); } [Test] public void DoubleAttribute_ImplicitNumericConversion() { ITypeDefinition type = GetTypeDefinition(typeof(DoubleAttribute)); - var arg = type.Attributes.Single().FixedArguments.Single(); + var arg = type.GetAttributes().Single().FixedArguments.Single(); Assert.AreEqual("System.Double", arg.Type.ReflectionName); Assert.AreEqual(1.0, arg.Value); } @@ -1397,7 +1398,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem var f = type.GetFields().Single(x => x.Name == name); Assert.IsTrue(f.IsConst); Assert.AreEqual(expected, f.ConstantValue); - Assert.AreEqual(0, f.Attributes.Count); + Assert.AreEqual(0, f.GetAttributes().Count()); } [Test] @@ -1518,33 +1519,33 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem var type = GetTypeDefinition(typeof(ClassWithAttributesUsingNestedMembers)); var inner = type.GetNestedTypes().Single(t => t.Name == "Inner"); var myAttribute = type.GetNestedTypes().Single(t => t.Name == "MyAttribute"); - var typeTypeTestAttr = type.Attributes.Single(a => a.AttributeType.Name == "TypeTestAttribute"); + var typeTypeTestAttr = type.GetAttributes().Single(a => a.AttributeType.Name == "TypeTestAttribute"); Assert.AreEqual(42, typeTypeTestAttr.FixedArguments[0].Value); Assert.AreEqual(inner, typeTypeTestAttr.FixedArguments[1].Value); - var typeMyAttr = type.Attributes.Single(a => a.AttributeType.Name == "MyAttribute"); + var typeMyAttr = type.GetAttributes().Single(a => a.AttributeType.Name == "MyAttribute"); Assert.AreEqual(myAttribute, typeMyAttr.AttributeType); var prop = type.GetProperties().Single(p => p.Name == "P"); - var propTypeTestAttr = prop.Attributes.Single(a => a.AttributeType.Name == "TypeTestAttribute"); + var propTypeTestAttr = prop.GetAttributes().Single(a => a.AttributeType.Name == "TypeTestAttribute"); Assert.AreEqual(42, propTypeTestAttr.FixedArguments[0].Value); Assert.AreEqual(inner, propTypeTestAttr.FixedArguments[1].Value); - var propMyAttr = prop.Attributes.Single(a => a.AttributeType.Name == "MyAttribute"); + var propMyAttr = prop.GetAttributes().Single(a => a.AttributeType.Name == "MyAttribute"); Assert.AreEqual(myAttribute, propMyAttr.AttributeType); var attributedInner = (ITypeDefinition)type.GetNestedTypes().Single(t => t.Name == "AttributedInner"); - var innerTypeTestAttr = attributedInner.Attributes.Single(a => a.AttributeType.Name == "TypeTestAttribute"); + var innerTypeTestAttr = attributedInner.GetAttributes().Single(a => a.AttributeType.Name == "TypeTestAttribute"); Assert.AreEqual(42, innerTypeTestAttr.FixedArguments[0].Value); Assert.AreEqual(inner, innerTypeTestAttr.FixedArguments[1].Value); - var innerMyAttr = attributedInner.Attributes.Single(a => a.AttributeType.Name == "MyAttribute"); + var innerMyAttr = attributedInner.GetAttributes().Single(a => a.AttributeType.Name == "MyAttribute"); Assert.AreEqual(myAttribute, innerMyAttr.AttributeType); var attributedInner2 = (ITypeDefinition)type.GetNestedTypes().Single(t => t.Name == "AttributedInner2"); var inner2 = attributedInner2.GetNestedTypes().Single(t => t.Name == "Inner"); var myAttribute2 = attributedInner2.GetNestedTypes().Single(t => t.Name == "MyAttribute"); - var inner2TypeTestAttr = attributedInner2.Attributes.Single(a => a.AttributeType.Name == "TypeTestAttribute"); + var inner2TypeTestAttr = attributedInner2.GetAttributes().Single(a => a.AttributeType.Name == "TypeTestAttribute"); Assert.AreEqual(43, inner2TypeTestAttr.FixedArguments[0].Value); Assert.AreEqual(inner2, inner2TypeTestAttr.FixedArguments[1].Value); - var inner2MyAttr = attributedInner2.Attributes.Single(a => a.AttributeType.Name == "MyAttribute"); + var inner2MyAttr = attributedInner2.GetAttributes().Single(a => a.AttributeType.Name == "MyAttribute"); Assert.AreEqual(myAttribute2, inner2MyAttr.AttributeType); } @@ -1552,7 +1553,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void ClassWithAttributeOnTypeParameter() { var tp = GetTypeDefinition(typeof(ClassWithAttributeOnTypeParameter<>)).TypeParameters.Single(); - var attr = tp.Attributes.Single(); + var attr = tp.GetAttributes().Single(); Assert.AreEqual("DoubleAttribute", attr.AttributeType.Name); } @@ -1658,7 +1659,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void Void_SerializableAttribute() { ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); - var attr = c.Attributes.Single(a => a.AttributeType.FullName == "System.SerializableAttribute"); + var attr = c.GetAttributes().Single(a => a.AttributeType.FullName == "System.SerializableAttribute"); Assert.AreEqual(0, attr.Constructor.Parameters.Count); Assert.AreEqual(0, attr.FixedArguments.Length); Assert.AreEqual(0, attr.NamedArguments.Length); @@ -1668,7 +1669,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void Void_StructLayoutAttribute() { ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); - var attr = c.Attributes.Single(a => a.AttributeType.FullName == "System.Runtime.InteropServices.StructLayoutAttribute"); + var attr = c.GetAttributes().Single(a => a.AttributeType.FullName == "System.Runtime.InteropServices.StructLayoutAttribute"); Assert.AreEqual(1, attr.Constructor.Parameters.Count); Assert.AreEqual(1, attr.FixedArguments.Length); Assert.AreEqual(0, attr.FixedArguments[0].Value); @@ -1681,7 +1682,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void Void_ComVisibleAttribute() { ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); - var attr = c.Attributes.Single(a => a.AttributeType.FullName == "System.Runtime.InteropServices.ComVisibleAttribute"); + var attr = c.GetAttributes().Single(a => a.AttributeType.FullName == "System.Runtime.InteropServices.ComVisibleAttribute"); Assert.AreEqual(1, attr.Constructor.Parameters.Count); Assert.AreEqual(1, attr.FixedArguments.Length); Assert.AreEqual(true, attr.FixedArguments[0].Value); diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 36ebde47b..24f460238 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -794,7 +794,7 @@ namespace ICSharpCode.Decompiler.CSharp EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, PEFile module) { - if (typeDef.GetAttribute(KnownAttribute.Flags) != null) + if (typeDef.HasAttribute(KnownAttribute.Flags, inherit: false)) return EnumValueDisplayMode.All; bool first = true; long firstValue = 0, previousValue = 0; @@ -997,7 +997,7 @@ namespace ICSharpCode.Decompiler.CSharp void AddDefinesForConditionalAttributes(ILFunction function, DecompileRun decompileRun, ITypeResolveContext decompilationContext) { foreach (var call in function.Descendants.OfType()) { - var attr = call.Method.GetAttribute(KnownAttribute.Conditional); + var attr = call.Method.GetAttribute(KnownAttribute.Conditional, inherit: true); var symbolName = attr?.FixedArguments.FirstOrDefault().Value as string; if (symbolName == null || !decompileRun.DefinedSymbols.Add(symbolName)) continue; @@ -1014,12 +1014,12 @@ namespace ICSharpCode.Decompiler.CSharp long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false); enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue); if (enumDec.Initializer is PrimitiveExpression primitive - && (decompilationContext.CurrentTypeDefinition.Attributes.Any(a => a.AttributeType.FullName == "System.FlagsAttribute") + && (decompilationContext.CurrentTypeDefinition.HasAttribute(KnownAttribute.Flags) || (initValue > 9 && ((initValue & (initValue - 1)) == 0 || (initValue & (initValue + 1)) == 0)))) { primitive.SetValue(initValue, $"0x{initValue:X}"); } - enumDec.Attributes.AddRange(field.Attributes.Select(a => new AttributeSection(typeSystemAstBuilder.ConvertAttribute(a)))); + enumDec.Attributes.AddRange(field.GetAttributes().Select(a => new AttributeSection(typeSystemAstBuilder.ConvertAttribute(a)))); enumDec.AddAnnotation(new MemberResolveResult(null, field)); return enumDec; } diff --git a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs index ca03abb7a..99c9bbb17 100644 --- a/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs +++ b/ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs @@ -40,10 +40,10 @@ namespace ICSharpCode.Decompiler.CSharp switch (entity) { case ITypeDefinition td: namespaces.Add(td.Namespace); - HandleAttributes(td.Attributes, namespaces); + HandleAttributes(td.GetAttributes(), namespaces); foreach (var typeParam in td.TypeParameters) { - HandleAttributes(typeParam.Attributes, namespaces); + HandleAttributes(typeParam.GetAttributes(), namespaces); } foreach (var baseType in td.DirectBaseTypes) { @@ -71,19 +71,19 @@ namespace ICSharpCode.Decompiler.CSharp } break; case IField field: - HandleAttributes(field.Attributes, namespaces); + HandleAttributes(field.GetAttributes(), namespaces); CollectNamespacesForTypeReference(field.ReturnType, namespaces); break; case IMethod method: - HandleAttributes(method.Attributes, namespaces); - HandleAttributes(method.ReturnTypeAttributes, namespaces); + HandleAttributes(method.GetAttributes(), namespaces); + HandleAttributes(method.GetReturnTypeAttributes(), namespaces); CollectNamespacesForTypeReference(method.ReturnType, namespaces); foreach (var param in method.Parameters) { - HandleAttributes(param.Attributes, namespaces); + HandleAttributes(param.GetAttributes(), namespaces); CollectNamespacesForTypeReference(param.Type, namespaces); } foreach (var typeParam in method.TypeParameters) { - HandleAttributes(typeParam.Attributes, namespaces); + HandleAttributes(typeParam.GetAttributes(), namespaces); } if (!method.MetadataToken.IsNil && method.HasBody) { var reader = typeSystem.ModuleDefinition.Reader; @@ -93,12 +93,12 @@ namespace ICSharpCode.Decompiler.CSharp } break; case IProperty property: - HandleAttributes(property.Attributes, namespaces); + HandleAttributes(property.GetAttributes(), namespaces); CollectNamespaces(property.Getter, typeSystem, namespaces); CollectNamespaces(property.Setter, typeSystem, namespaces); break; case IEvent @event: - HandleAttributes(@event.Attributes, namespaces); + HandleAttributes(@event.GetAttributes(), namespaces); CollectNamespaces(@event.AddAccessor, typeSystem, namespaces); CollectNamespaces(@event.RemoveAccessor, typeSystem, namespaces); break; diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs index eba09ec69..066fe2b51 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs @@ -150,8 +150,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver get { return SymbolKind.Operator; } } - IReadOnlyList IEntity.Attributes { - get { return EmptyList.Instance; } + IEnumerable IEntity.GetAttributes() + { + return EmptyList.Instance; } Accessibility IEntity.Accessibility { diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs index 1a91fc33d..6642448e9 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs @@ -1741,7 +1741,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver void CheckForEnumerableInterface(ResolveResult expression, out IType collectionType, out IType enumeratorType, out IType elementType, out ResolveResult getEnumeratorInvocation) { bool? isGeneric; - elementType = GetElementTypeFromIEnumerable(expression.Type, compilation, false, out isGeneric); + elementType = expression.Type.GetElementTypeFromIEnumerable(compilation, false, out isGeneric); if (isGeneric == true) { ITypeDefinition enumerableOfT = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition(); if (enumerableOfT != null) @@ -1765,33 +1765,6 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver getEnumeratorInvocation = ResolveMemberAccess(getEnumeratorInvocation, "GetEnumerator", EmptyList.Instance, NameLookupMode.InvocationTarget); getEnumeratorInvocation = ResolveInvocation(getEnumeratorInvocation, new ResolveResult[0]); } - - static IType GetElementTypeFromIEnumerable(IType collectionType, ICompilation compilation, bool allowIEnumerator, out bool? isGeneric) - { - bool foundNonGenericIEnumerable = false; - foreach (IType baseType in collectionType.GetAllBaseTypes()) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null) { - KnownTypeCode typeCode = baseTypeDef.KnownTypeCode; - if (typeCode == KnownTypeCode.IEnumerableOfT || (allowIEnumerator && typeCode == KnownTypeCode.IEnumeratorOfT)) { - ParameterizedType pt = baseType as ParameterizedType; - if (pt != null) { - isGeneric = true; - return pt.GetTypeArgument(0); - } - } - if (typeCode == KnownTypeCode.IEnumerable || (allowIEnumerator && typeCode == KnownTypeCode.IEnumerator)) - foundNonGenericIEnumerable = true; - } - } - // System.Collections.IEnumerable found in type hierarchy -> Object is element type. - if (foundNonGenericIEnumerable) { - isGeneric = false; - return compilation.FindType(KnownTypeCode.Object); - } - isGeneric = null; - return SpecialType.UnknownType; - } #endregion #region GetExtensionMethods diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/ReducedExtensionMethod.cs b/ICSharpCode.Decompiler/CSharp/Resolver/ReducedExtensionMethod.cs index f0a37e07a..7ef4758a5 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/ReducedExtensionMethod.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/ReducedExtensionMethod.cs @@ -136,12 +136,6 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver #region IMethod implementation - public IReadOnlyList ReturnTypeAttributes { - get { - return baseMethod.ReturnTypeAttributes; - } - } - public IReadOnlyList TypeParameters { get { return baseMethod.TypeParameters; @@ -243,11 +237,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver } } - public IReadOnlyList Attributes { - get { - return baseMethod.Attributes; - } - } + IEnumerable IEntity.GetAttributes() => baseMethod.GetAttributes(); + IEnumerable IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes(); public bool IsStatic { get { diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 8a5f73eda..796864eb9 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -455,7 +455,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax public Attribute ConvertAttribute(IAttribute attribute) { Attribute attr = new Attribute(); - attr.Type = ConvertType(attribute.AttributeType); + attr.Type = ConvertAttributeType(attribute.AttributeType); SimpleType st = attr.Type as SimpleType; MemberType mt = attr.Type as MemberType; if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) { @@ -482,6 +482,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } return attr; } + + private IEnumerable ConvertAttributes(IEnumerable attibutes) + { + return attibutes.Select(a => new AttributeSection(ConvertAttribute(a))); + } + + private IEnumerable ConvertAttributes(IEnumerable attibutes, string target) + { + return attibutes.Select(a => new AttributeSection(ConvertAttribute(a)) { + AttributeTarget = target + }); + } #endregion #region Convert Attribute Type @@ -495,6 +507,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (type.Name.Length > 9 && type.Name.EndsWith("Attribute", StringComparison.Ordinal)) { shortName = type.Name.Remove(type.Name.Length - 9); } + if (AlwaysUseShortTypeNames) { + switch (astType) { + case SimpleType st: + st.Identifier = shortName; + break; + case MemberType mt: + mt.MemberName = shortName; + break; + } + } else if (resolver != null) { + ApplyShortAttributeNameIfPossible(type, astType, shortName); + } + + if (AddTypeReferenceAnnotations) + astType.AddAnnotation(type); + if (AddResolveResultAnnotations) + astType.AddAnnotation(new TypeResolveResult(type)); + return astType; + } + + private void ApplyShortAttributeNameIfPossible(IType type, AstType astType, string shortName) + { switch (astType) { case SimpleType st: ResolveResult shortRR = null; @@ -529,12 +563,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } break; } - - if (AddTypeReferenceAnnotations) - astType.AddAnnotation(type); - if (AddResolveResultAnnotations) - astType.AddAnnotation(new TypeResolveResult(type)); - return astType; } private bool IsAttributeType(IType type) @@ -792,8 +820,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax bool IsFlagsEnum(ITypeDefinition type) { - IType flagsAttributeType = type.Compilation.FindType(typeof(System.FlagsAttribute)); - return type.GetAttribute(flagsAttributeType) != null; + return type.HasAttribute(KnownAttribute.Flags, inherit: false); } Expression ConvertEnumValue(IType type, long val) @@ -880,7 +907,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax decl.ParameterModifier = ParameterModifier.Params; } if (ShowAttributes) { - decl.Attributes.AddRange (parameter.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); + decl.Attributes.AddRange(ConvertAttributes(parameter.GetAttributes())); } if (parameter.Type.Kind == TypeKind.ByReference) { // avoid 'out ref' @@ -997,7 +1024,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax decl.ClassType = classType; decl.Modifiers = modifiers; if (ShowAttributes) { - decl.Attributes.AddRange (typeDefinition.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); + decl.Attributes.AddRange(ConvertAttributes(typeDefinition.GetAttributes())); } if (AddResolveResultAnnotations) { decl.AddAnnotation(new TypeResolveResult(typeDefinition)); @@ -1034,7 +1061,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } return decl; } - + DelegateDeclaration ConvertDelegate(IMethod invokeMethod, Modifiers modifiers) { ITypeDefinition d = invokeMethod.DeclaringTypeDefinition; @@ -1042,10 +1069,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax DelegateDeclaration decl = new DelegateDeclaration(); decl.Modifiers = modifiers & ~Modifiers.Sealed; if (ShowAttributes) { - decl.Attributes.AddRange (d.Attributes.Select (a => new AttributeSection (ConvertAttribute (a)))); - decl.Attributes.AddRange (invokeMethod.ReturnTypeAttributes.Select ((a) => new AttributeSection (ConvertAttribute (a)) { - AttributeTarget = "return" - })); + decl.Attributes.AddRange(ConvertAttributes(d.GetAttributes())); + decl.Attributes.AddRange(ConvertAttributes(invokeMethod.GetReturnTypeAttributes(), "return")); } if (AddResolveResultAnnotations) { decl.AddAnnotation(new TypeResolveResult(d)); @@ -1091,7 +1116,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax decl.Modifiers = m; } if (ShowAttributes) { - decl.Attributes.AddRange (field.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); + decl.Attributes.AddRange(ConvertAttributes(field.GetAttributes())); } if (AddResolveResultAnnotations) { decl.AddAnnotation(new MemberResolveResult(null, field)); @@ -1115,7 +1140,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax } } - Accessor ConvertAccessor(IMethod accessor, Accessibility ownerAccessibility, bool addParamterAttribute) + Accessor ConvertAccessor(IMethod accessor, Accessibility ownerAccessibility, bool addParameterAttribute) { if (accessor == null) return Accessor.Null; @@ -1123,14 +1148,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax if (this.ShowAccessibility && accessor.Accessibility != ownerAccessibility) decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility); if (ShowAttributes) { - decl.Attributes.AddRange (accessor.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); - decl.Attributes.AddRange (accessor.ReturnTypeAttributes.Select ((a) => new AttributeSection (ConvertAttribute (a)) { - AttributeTarget = "return" - })); - if (addParamterAttribute && accessor.Parameters.Count > 0) { - decl.Attributes.AddRange (accessor.Parameters.Last ().Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)) { - AttributeTarget = "param" - })); + decl.Attributes.AddRange(ConvertAttributes(accessor.GetAttributes())); + decl.Attributes.AddRange(ConvertAttributes(accessor.GetReturnTypeAttributes(), "return")); + if (addParameterAttribute && accessor.Parameters.Count > 0) { + decl.Attributes.AddRange(ConvertAttributes(accessor.Parameters.Last().GetAttributes(), "param")); } } if (AddResolveResultAnnotations) { @@ -1145,7 +1166,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax PropertyDeclaration decl = new PropertyDeclaration(); decl.Modifiers = GetMemberModifiers(property); if (ShowAttributes) { - decl.Attributes.AddRange (property.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); + decl.Attributes.AddRange(ConvertAttributes(property.GetAttributes())); } if (AddResolveResultAnnotations) { decl.AddAnnotation(new MemberResolveResult(null, property)); @@ -1163,7 +1184,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax IndexerDeclaration decl = new IndexerDeclaration(); decl.Modifiers = GetMemberModifiers(indexer); if (ShowAttributes) { - decl.Attributes.AddRange (indexer.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); + decl.Attributes.AddRange(ConvertAttributes(indexer.GetAttributes())); } if (AddResolveResultAnnotations) { decl.AddAnnotation(new MemberResolveResult(null, indexer)); @@ -1184,7 +1205,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax CustomEventDeclaration decl = new CustomEventDeclaration(); decl.Modifiers = GetMemberModifiers(ev); if (ShowAttributes) { - decl.Attributes.AddRange (ev.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); + decl.Attributes.AddRange(ConvertAttributes(ev.GetAttributes())); } if (AddResolveResultAnnotations) { decl.AddAnnotation(new MemberResolveResult(null, ev)); @@ -1199,7 +1220,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax EventDeclaration decl = new EventDeclaration(); decl.Modifiers = GetMemberModifiers(ev); if (ShowAttributes) { - decl.Attributes.AddRange (ev.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); + decl.Attributes.AddRange(ConvertAttributes(ev.GetAttributes())); } if (AddResolveResultAnnotations) { decl.AddAnnotation(new MemberResolveResult(null, ev)); @@ -1215,10 +1236,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax MethodDeclaration decl = new MethodDeclaration(); decl.Modifiers = GetMemberModifiers(method); if (ShowAttributes) { - decl.Attributes.AddRange (method.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); - decl.Attributes.AddRange (method.ReturnTypeAttributes.Select ((a) => new AttributeSection (ConvertAttribute (a)) { - AttributeTarget = "return" - })); + decl.Attributes.AddRange(ConvertAttributes(method.GetAttributes())); + decl.Attributes.AddRange(ConvertAttributes(method.GetReturnTypeAttributes(), "return")); } if (AddResolveResultAnnotations) { decl.AddAnnotation(new MemberResolveResult(null, method)); @@ -1275,7 +1294,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax ConstructorDeclaration decl = new ConstructorDeclaration(); decl.Modifiers = GetMemberModifiers(ctor); if (ShowAttributes) - decl.Attributes.AddRange (ctor.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); + decl.Attributes.AddRange(ConvertAttributes(ctor.GetAttributes())); if (ctor.DeclaringTypeDefinition != null) decl.Name = ctor.DeclaringTypeDefinition.Name; foreach (IParameter p in ctor.Parameters) { @@ -1369,7 +1388,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax decl.Variance = tp.Variance; decl.Name = tp.Name; if (ShowAttributes) - decl.Attributes.AddRange (tp.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); + decl.Attributes.AddRange(ConvertAttributes(tp.GetAttributes())); return decl; } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs index c188a7366..f2efa6d3c 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs @@ -507,17 +507,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms propertyDeclaration.Getter.Body = null; propertyDeclaration.Setter.Body = null; - // Add C# 7.3 attributes on backing field: - var attributes = field.Attributes - .Where(a => !attributeTypesToRemoveFromAutoProperties.Any(t => t == a.AttributeType.FullName)) - .Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray(); - if (attributes.Length > 0) { - var section = new AttributeSection { - AttributeTarget = "field" - }; - section.Attributes.AddRange(attributes); - propertyDeclaration.Attributes.Add(section); - } + // Add C# 7.3 attributes on backing field: + var attributes = field.GetAttributes() + .Where(a => !attributeTypesToRemoveFromAutoProperties.Contains(a.AttributeType.FullName)) + .Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray(); + if (attributes.Length > 0) { + var section = new AttributeSection { + AttributeTarget = "field" + }; + section.Attributes.AddRange(attributes); + propertyDeclaration.Attributes.Add(section); + } } // Since the property instance is not changed, we can continue in the visitor as usual, so return null return null; @@ -788,8 +788,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms IField field = eventDef.DeclaringType.GetFields(f => f.Name == ev.Name, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault(); if (field != null) { ed.AddAnnotation(field); - var attributes = field.Attributes - .Where(a => !attributeTypesToRemoveFromAutoEvents.Any(t => t == a.AttributeType.FullName)) + var attributes = field.GetAttributes() + .Where(a => !attributeTypesToRemoveFromAutoEvents.Contains(a.AttributeType.FullName)) .Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray(); if (attributes.Length > 0) { var section = new AttributeSection { diff --git a/ICSharpCode.Decompiler/NRExtensions.cs b/ICSharpCode.Decompiler/NRExtensions.cs index a2ff9ba22..0a816ad82 100644 --- a/ICSharpCode.Decompiler/NRExtensions.cs +++ b/ICSharpCode.Decompiler/NRExtensions.cs @@ -44,10 +44,7 @@ namespace ICSharpCode.Decompiler public static bool IsCompilerGenerated(this IEntity entity) { if (entity != null) { - foreach (IAttribute a in entity.Attributes) { - if (a.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute") - return true; - } + return entity.HasAttribute(KnownAttribute.CompilerGenerated); } return false; } diff --git a/ICSharpCode.Decompiler/TypeSystem/ComHelper.cs b/ICSharpCode.Decompiler/TypeSystem/ComHelper.cs index 5c646dba2..b0064f746 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ComHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ComHelper.cs @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { return typeDefinition != null && typeDefinition.Kind == TypeKind.Interface - && typeDefinition.GetAttributes(KnownAttribute.ComImport, inherit: false) != null; + && typeDefinition.HasAttribute(KnownAttribute.ComImport, inherit: false); } /// diff --git a/ICSharpCode.Decompiler/TypeSystem/IEntity.cs b/ICSharpCode.Decompiler/TypeSystem/IEntity.cs index 1d6b9db92..fdc1d83f6 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IEntity.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IEntity.cs @@ -123,8 +123,9 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// Gets the attributes on this entity. + /// Does not include inherited attributes. /// - IReadOnlyList Attributes { get; } + IEnumerable GetAttributes(); /// /// Gets the accessibility of this entity. diff --git a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs index 67f982753..d29803a0f 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IMethod.cs @@ -79,7 +79,10 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// Gets the attributes associated with the return type. (e.g. [return: MarshalAs(...)]) /// - IReadOnlyList ReturnTypeAttributes { get; } + /// + /// Does not include inherited attributes. + /// + IEnumerable GetReturnTypeAttributes(); /// /// Gets the type parameters of this method; or an empty list if the method is not generic. diff --git a/ICSharpCode.Decompiler/TypeSystem/IParameter.cs b/ICSharpCode.Decompiler/TypeSystem/IParameter.cs index f5fca79a3..8b6acb8b6 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IParameter.cs @@ -63,9 +63,9 @@ namespace ICSharpCode.Decompiler.TypeSystem public interface IParameter : IVariable { /// - /// Gets the list of attributes. + /// Gets the attributes on this parameter. /// - IReadOnlyList Attributes { get; } + IEnumerable GetAttributes(); /// /// Gets whether this parameter is a C# 'ref' parameter. diff --git a/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs index 78cc617d7..34c530a7b 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs @@ -82,9 +82,9 @@ namespace ICSharpCode.Decompiler.TypeSystem new string Name { get; } /// - /// Gets the list of attributes declared on this type parameter. + /// Gets the attributes declared on this type parameter. /// - IReadOnlyList Attributes { get; } + IEnumerable GetAttributes(); /// /// Gets the variance of this type parameter. diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedEntity.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedEntity.cs index 9c01eb5ff..e7f24cdc7 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedEntity.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedEntity.cs @@ -59,6 +59,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation } public IReadOnlyList Attributes { get; protected set; } + IEnumerable IEntity.GetAttributes() => Attributes; public bool IsStatic { get { return unresolved.IsStatic; } } public bool IsAbstract { get { return unresolved.IsAbstract; } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs index deaf7f4ad..e6c681745 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs @@ -71,8 +71,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public int Index { get { return index; } } - - public abstract IReadOnlyList Attributes { get; } + + public abstract IEnumerable GetAttributes(); public VarianceModifier Variance { get { return variance; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs index 435da9076..28d0873d5 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs @@ -72,9 +72,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation get { return owner; } } - public IReadOnlyList Attributes { - get { return attributes; } - } + public IEnumerable GetAttributes() => attributes; public bool IsRef { get { return isRef; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedMethod.cs index 825fc28a9..e1304b298 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedMethod.cs @@ -170,6 +170,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IReadOnlyList Parameters { get; private set; } public IReadOnlyList ReturnTypeAttributes { get; private set; } + IEnumerable IMethod.GetReturnTypeAttributes() => ReturnTypeAttributes; public IReadOnlyList TypeParameters { get; private set; } public IReadOnlyList TypeArguments { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs index cc4eaa992..a2ca1c902 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs @@ -105,7 +105,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation return LazyInit.GetOrSet(ref this.attributes, result); } } - + + public IEnumerable GetAttributes() => Attributes; + public System.Reflection.Metadata.EntityHandle MetadataToken => parts[0].MetadataToken; public SymbolKind SymbolKind { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeParameter.cs index e6bc15eff..9b7fce095 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeParameter.cs @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.attributes = attributes ?? EmptyList.Instance; } - public override IReadOnlyList Attributes => attributes; + public override IEnumerable GetAttributes() => attributes; public override bool HasValueTypeConstraint => hasValueTypeConstraint; public override bool HasReferenceTypeConstraint => hasReferenceTypeConstraint; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedParameter.cs index 4b7077759..ffe8d0d95 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedParameter.cs @@ -229,6 +229,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IType Type { get; internal set; } public string Name { get; internal set; } public IReadOnlyList Attributes { get; internal set; } + public IEnumerable GetAttributes() => Attributes; public bool IsRef { get; internal set; } public bool IsOut { get; internal set; } public bool IsParams { get; internal set; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs index cb0f2bd71..ed84cb480 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs @@ -141,9 +141,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation get { return index; } } - IReadOnlyList ITypeParameter.Attributes { - get { return EmptyList.Instance; } - } + IEnumerable ITypeParameter.GetAttributes() =>EmptyList.Instance; SymbolKind ITypeParameter.OwnerType { get { return ownerType; } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs index d433148ab..ad3536088 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs @@ -58,7 +58,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IAssembly IEntity.ParentAssembly => DeclaringType?.GetDefinition()?.ParentAssembly; - IReadOnlyList IEntity.Attributes => EmptyList.Instance; + IEnumerable IEntity.GetAttributes() => EmptyList.Instance; public Accessibility Accessibility { get; set; } = Accessibility.Public; @@ -130,7 +130,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override SymbolKind SymbolKind => symbolKind; - IReadOnlyList IMethod.ReturnTypeAttributes => EmptyList.Instance; + IEnumerable IMethod.GetReturnTypeAttributes() => EmptyList.Instance; public IReadOnlyList TypeParameters { get; set; } = EmptyList.Instance; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs index def1c93ad..f7ed937b2 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs @@ -38,7 +38,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation readonly string name; // lazy-loaded: - IAttribute[] customAttributes; IType returnType; internal MetadataEvent(MetadataAssembly assembly, EventDefinitionHandle handle) @@ -103,16 +102,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity; #region Attributes - public IReadOnlyList Attributes { - get { - var attr = LazyInit.VolatileRead(ref this.customAttributes); - if (attr != null) - return attr; - return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes()); - } - } - - IAttribute[] DecodeAttributes() + public IEnumerable GetAttributes() { var b = new AttributeListBuilder(assembly); var metadata = assembly.metadata; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs index 34dc34915..b02f947ca 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs @@ -43,7 +43,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation IType type; bool isVolatile; // initialized together with this.type byte decimalConstant; // 0=no, 1=yes, 2=unknown - IAttribute[] customAttributes; internal MetadataField(MetadataAssembly assembly, FieldDefinitionHandle handle) { @@ -127,17 +126,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IType DeclaringType => DeclaringTypeDefinition; public IAssembly ParentAssembly => assembly; public ICompilation Compilation => assembly.Compilation; - - public IReadOnlyList Attributes { - get { - var attr = LazyInit.VolatileRead(ref this.customAttributes); - if (attr != null) - return attr; - return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes()); - } - } - - IAttribute[] DecodeAttributes() + + public IEnumerable GetAttributes() { var b = new AttributeListBuilder(assembly); var metadata = assembly.metadata; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs index c5a006633..07101b7e3 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs @@ -45,8 +45,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // lazy-loaded fields: ITypeDefinition declaringType; string name; - IAttribute[] customAttributes; - IAttribute[] returnTypeAttributes; IParameter[] parameters; IType returnType; @@ -232,15 +230,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public ICompilation Compilation => assembly.Compilation; #region Attributes - public IReadOnlyList Attributes { - get { - var attr = LazyInit.VolatileRead(ref this.customAttributes); - if (attr != null) - return attr; - return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes()); - } - } - IType FindInteropType(string name) { return assembly.Compilation.FindType(new TopLevelTypeName( @@ -248,7 +237,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation )); } - IAttribute[] DecodeAttributes() + public IEnumerable GetAttributes() { var b = new AttributeListBuilder(assembly); @@ -365,16 +354,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation #endregion #region Return type attributes - public IReadOnlyList ReturnTypeAttributes { - get { - var attr = LazyInit.VolatileRead(ref this.returnTypeAttributes); - if (attr != null) - return attr; - return LazyInit.GetOrSet(ref this.returnTypeAttributes, DecodeReturnTypeAttributes()); - } - } - - private IAttribute[] DecodeReturnTypeAttributes() + public IEnumerable GetReturnTypeAttributes() { var b = new AttributeListBuilder(assembly); var metadata = assembly.metadata; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs index dbf523768..7f2123a34 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs @@ -37,7 +37,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation // lazy-loaded: string name; - IAttribute[] customAttributes; internal MetadataParameter(MetadataAssembly assembly, IParameterizedMember owner, IType type, ParameterHandle handle) { @@ -53,16 +52,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public EntityHandle MetadataToken => handle; #region Attributes - public IReadOnlyList Attributes { - get { - var attr = LazyInit.VolatileRead(ref this.customAttributes); - if (attr != null) - return attr; - return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes()); - } - } - - IAttribute[] DecodeAttributes() + public IEnumerable GetAttributes() { var b = new AttributeListBuilder(assembly); var metadata = assembly.metadata; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs index 2758bf6b2..d2612bd29 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs @@ -42,7 +42,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation readonly SymbolKind symbolKind; // lazy-loaded: - IAttribute[] customAttributes; volatile Accessibility cachedAccessiblity = InvalidAccessibility; IParameter[] parameters; IType returnType; @@ -144,16 +143,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity; #region Attributes - public IReadOnlyList Attributes { - get { - var attr = LazyInit.VolatileRead(ref this.customAttributes); - if (attr != null) - return attr; - return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes()); - } - } - - IAttribute[] DecodeAttributes() + public IEnumerable GetAttributes() { var b = new AttributeListBuilder(assembly); var metadata = assembly.metadata; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs index 548efd109..87de66903 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs @@ -51,7 +51,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public bool HasExtensionMethods { get; } // lazy-loaded: - IAttribute[] customAttributes; IMember[] members; IField[] fields; IProperty[] properties; @@ -284,16 +283,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IAssembly ParentAssembly => assembly; #region Type Attributes - public IReadOnlyList Attributes { - get { - var attr = LazyInit.VolatileRead(ref this.customAttributes); - if (attr != null) - return attr; - return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes()); - } - } - - IAttribute[] DecodeAttributes() + public IEnumerable GetAttributes() { var b = new AttributeListBuilder(assembly); var metadata = assembly.metadata; diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs index 56ea796f9..7aad3675e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs @@ -98,16 +98,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public GenericParameterHandle MetadataToken => handle; - public override IReadOnlyList Attributes { - get { - var attr = LazyInit.VolatileRead(ref this.customAttributes); - if (attr != null) - return attr; - return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes()); - } - } - - IAttribute[] DecodeAttributes() + public override IEnumerable GetAttributes() { var metadata = assembly.metadata; var gp = metadata.GetGenericParameter(handle); diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs index f80927c44..79472bc5d 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs @@ -150,10 +150,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public ITypeDefinition DeclaringTypeDefinition { get { return baseMember.DeclaringTypeDefinition; } } - - public IReadOnlyList Attributes { - get { return baseMember.Attributes; } - } + + IEnumerable IEntity.GetAttributes() => baseMember.GetAttributes(); public IEnumerable ExplicitlyImplementedInterfaceMembers { get { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs index b49fe531a..a215acfe6 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs @@ -92,10 +92,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public IReadOnlyList TypeArguments { get { return this.Substitution.MethodTypeArguments ?? EmptyList.Instance; } } - - public IReadOnlyList ReturnTypeAttributes { - get { return methodDefinition.ReturnTypeAttributes; } - } + + public IEnumerable GetReturnTypeAttributes() => methodDefinition.GetReturnTypeAttributes(); public IReadOnlyList TypeParameters { get { @@ -230,7 +228,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.baseTp = baseTp; } - public override IReadOnlyList Attributes => baseTp.Attributes; + public override IEnumerable GetAttributes() => baseTp.GetAttributes(); public override int GetHashCode() { diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs index eee19f7a6..5e6070f0a 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.newOwner = newOwner; } - IReadOnlyList IParameter.Attributes => baseParameter.Attributes; + IEnumerable IParameter.GetAttributes() => baseParameter.GetAttributes(); bool IParameter.IsRef => baseParameter.IsRef; bool IParameter.IsOut => baseParameter.IsOut; bool IParameter.IsParams => baseParameter.IsParams; diff --git a/ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs b/ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs index 602f5be5e..7ee067de9 100644 --- a/ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.TypeSystem { // TODO: maybe these should be extension methods? // or even part of the interface itself? (would allow for easy caching) - + #region GetBaseMember /// /// Gets the base member that has the same signature. @@ -58,16 +58,16 @@ namespace ICSharpCode.Decompiler.TypeSystem yield return member; }*/ } - + // Remove generic specialization var substitution = member.Substitution; member = member.MemberDefinition; - + if (member.DeclaringTypeDefinition == null) { // For global methods, return empty list. (prevent SharpDevelop UDC crash 4524) yield break; } - + IEnumerable allBaseTypes; if (includeImplementedInterfaces) { allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes(); @@ -93,7 +93,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } } #endregion - + #region GetDerivedMember /// /// Finds the member declared in 'derivedType' that has the same signature (could override) 'baseMember'. @@ -104,10 +104,10 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new ArgumentNullException("baseMember"); if (derivedType == null) throw new ArgumentNullException("derivedType"); - + if (baseMember.Compilation != derivedType.Compilation) throw new ArgumentException("baseMember and derivedType must be from the same compilation"); - + baseMember = baseMember.MemberDefinition; bool includeInterfaces = baseMember.DeclaringTypeDefinition.Kind == TypeKind.Interface; IMethod method = baseMember as IMethod; @@ -147,5 +147,34 @@ namespace ICSharpCode.Decompiler.TypeSystem return null; } #endregion + + #region Attributes + internal static IEnumerable GetAttributes(ITypeDefinition typeDef) + { + foreach (var baseType in typeDef.GetNonInterfaceBaseTypes().Reverse()) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef == null) + continue; + foreach (var attr in baseTypeDef.GetAttributes()) { + yield return attr; + } + } + } + + internal static IEnumerable GetAttributes(IMember member) + { + HashSet visitedMembers = new HashSet(); + 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; + } + foreach (var attr in member.GetAttributes()) { + yield return attr; + } + } while (member.IsOverride && (member = InheritanceHelper.GetBaseMember(member)) != null); + } + #endregion } } diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs index e24a8f910..2d9609490 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs @@ -420,181 +420,70 @@ namespace ICSharpCode.Decompiler.TypeSystem return null; } #endregion - - #region ITypeReference.Resolve(ICompilation) - - /// - /// Resolves a type reference in the compilation's main type resolve context. - /// Some type references require a more specific type resolve context and will not resolve using this method. - /// - /// - /// Returns the resolved type. - /// In case of an error, returns . - /// Never returns null. - /// - public static IType Resolve (this ITypeReference reference, ICompilation compilation) - { - if (reference == null) - throw new ArgumentNullException ("reference"); - if (compilation == null) - throw new ArgumentNullException ("compilation"); - return reference.Resolve (compilation.TypeResolveContext); - } - #endregion - #region ITypeDefinition.GetAttribute + #region IEntity.GetAttribute /// - /// Gets the attribute of the specified attribute type (or derived attribute types). + /// Gets whether the entity has an attribute of the specified attribute type (or derived attribute types). /// /// The entity on which the attributes are declared. /// The attribute type to look for. /// - /// Specifies whether attributes inherited from base classes and base members (if the given in an override) - /// should be returned. The default is true. + /// Specifies whether attributes inherited from base classes and base members + /// (if the given in an override) + /// should be returned. /// - /// - /// Returns the attribute that was found; or null if none was found. - /// 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. - /// - public static IAttribute GetAttribute(this IEntity entity, IType attributeType, bool inherit = true) + public static bool HasAttribute(this IEntity entity, KnownAttribute attrType, bool inherit=false) { - return GetAttributes(entity, attributeType, inherit).FirstOrDefault(); + return GetAttribute(entity, attrType, inherit) != null; } - - /// - /// Gets the attributes of the specified attribute type (or derived attribute types). - /// - /// The entity on which the attributes are declared. - /// The attribute type to look for. - /// - /// Specifies whether attributes inherited from base classes and base members (if the given in an override) - /// should be returned. The default is true. - /// - /// - /// Returns the list of attributes that were found. - /// If inherit is true, attributes from the entity itself are returned first; followed by attributes inherited from the base entity. - /// - public static IEnumerable GetAttributes(this IEntity entity, IType attributeType, bool inherit = true) - { - if (entity == null) - throw new ArgumentNullException("entity"); - if (attributeType == null) - throw new ArgumentNullException("attributeType"); - return GetAttributes(entity, attributeType.Equals, inherit); - } - + /// /// Gets the attribute of the specified attribute type (or derived attribute types). /// /// The entity on which the attributes are declared. /// The attribute type to look for. /// - /// Specifies whether attributes inherited from base classes and base members (if the given in an override) - /// should be returned. The default is true. + /// Specifies whether attributes inherited from base classes and base members + /// (if the given in an override) + /// should be returned. /// /// /// Returns the attribute that was found; or null if none was found. /// 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. /// - public static IAttribute GetAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit = true) - { - return GetAttributes(entity, attributeType, inherit).FirstOrDefault(); - } - - /// - /// Gets the attributes of the specified attribute type (or derived attribute types). - /// - /// The entity on which the attributes are declared. - /// The attribute type to look for. - /// - /// Specifies whether attributes inherited from base classes and base members (if the given in an override) - /// should be returned. The default is true. - /// - /// - /// Returns the list of attributes that were found. - /// If inherit is true, attributes from the entity itself are returned first; followed by attributes inherited from the base entity. - /// - public static IEnumerable GetAttributes(this IEntity entity, KnownAttribute attributeType, bool inherit = true) + public static IAttribute GetAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit=false) { - if (entity == null) - throw new ArgumentNullException("entity"); - return GetAttributes(entity, attrType => { - ITypeDefinition typeDef = attrType.GetDefinition(); - return typeDef != null && typeDef.FullTypeName == attributeType.GetTypeName(); - }, inherit); + return GetAttributes(entity, inherit).FirstOrDefault(a => a.AttributeType.IsKnownType(attributeType)); } /// - /// Gets the attribute of the specified attribute type (or derived attribute types). + /// Gets the attributes on the entity. /// /// The entity on which the attributes are declared. /// - /// Specifies whether attributes inherited from base classes and base members (if the given in an override) - /// should be returned. The default is true. + /// Specifies whether attributes inherited from base classes and base members + /// (if the given in an override) + /// should be returned. /// /// - /// Returns the attribute that was found; or null if none was found. - /// 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 the list of attributes that were found. + /// If inherit is true, attributes from the entity itself are returned first; + /// followed by attributes inherited from the base entity. /// - public static IEnumerable GetAttributes(this IEntity entity, bool inherit = true) - { - if (entity == null) - throw new ArgumentNullException ("entity"); - return GetAttributes(entity, a => true, inherit); - } - - static IEnumerable GetAttributes(IEntity entity, Predicate attributeTypePredicate, bool inherit) - { - if (!inherit) { - foreach (var attr in entity.Attributes) { - if (attributeTypePredicate(attr.AttributeType)) - yield return attr; + public static IEnumerable GetAttributes(this IEntity entity, bool inherit) + { + if (inherit) { + if (entity is ITypeDefinition td) { + return InheritanceHelper.GetAttributes(td); + } else if (entity is IMember m) { + return InheritanceHelper.GetAttributes(m); + } else { + throw new NotSupportedException("Unknown entity type"); } - yield break; + } else { + return entity.GetAttributes(); } - ITypeDefinition typeDef = entity as ITypeDefinition; - if (typeDef != null) { - foreach (var baseType in typeDef.GetNonInterfaceBaseTypes().Reverse()) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef == null) - continue; - foreach (var attr in baseTypeDef.Attributes) { - if (attributeTypePredicate(attr.AttributeType)) - yield return attr; - } - } - yield break; - } - IMember member = entity as IMember; - if (member != null) { - HashSet visitedMembers = new HashSet(); - 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; - } - foreach (var attr in member.Attributes) { - if (attributeTypePredicate(attr.AttributeType)) - yield return attr; - } - } while (member.IsOverride && (member = InheritanceHelper.GetBaseMember(member)) != null); - yield break; - } - throw new NotSupportedException("Unknown entity type"); - } - #endregion - - #region IsCompilerGenerated - public static bool IsCompilerGenereated(this IEntity entity) - { - if (entity == null) - throw new ArgumentNullException(nameof(entity)); - - return entity.GetAttribute(KnownAttribute.CompilerGenerated) != null; } #endregion diff --git a/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs b/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs index 38180810b..96e3375d8 100644 --- a/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs +++ b/ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs @@ -109,10 +109,9 @@ namespace ICSharpCode.Decompiler.TypeSystem baseMethod.Specialize(substitution), parameters.Skip(baseMethod.Parameters.Count - 1).Select(p => p.Type.AcceptVisitor(substitution)).ToList()); } - - public IReadOnlyList ReturnTypeAttributes { - get { return baseMethod.ReturnTypeAttributes; } - } + + IEnumerable IEntity.GetAttributes() => baseMethod.GetAttributes(); + IEnumerable IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes(); public IReadOnlyList TypeParameters { get { return baseMethod.TypeParameters; } @@ -225,10 +224,6 @@ namespace ICSharpCode.Decompiler.TypeSystem get { return baseMethod.ParentAssembly; } } - public IReadOnlyList Attributes { - get { return baseMethod.Attributes; } - } - public bool IsStatic { get { return baseMethod.IsStatic; } }