Browse Source

Don't cache attributes in the type system.

pull/1030/head
Daniel Grunwald 7 years ago
parent
commit
4ec0028356
  1. 81
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  2. 8
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 18
      ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
  4. 5
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs
  5. 29
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpResolver.cs
  6. 13
      ICSharpCode.Decompiler/CSharp/Resolver/ReducedExtensionMethod.cs
  7. 91
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  8. 26
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  9. 5
      ICSharpCode.Decompiler/NRExtensions.cs
  10. 2
      ICSharpCode.Decompiler/TypeSystem/ComHelper.cs
  11. 3
      ICSharpCode.Decompiler/TypeSystem/IEntity.cs
  12. 5
      ICSharpCode.Decompiler/TypeSystem/IMethod.cs
  13. 4
      ICSharpCode.Decompiler/TypeSystem/IParameter.cs
  14. 4
      ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs
  15. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedEntity.cs
  16. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs
  17. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs
  18. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedMethod.cs
  19. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs
  20. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeParameter.cs
  21. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedParameter.cs
  22. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs
  23. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs
  24. 12
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs
  25. 14
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
  26. 24
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  27. 12
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
  28. 12
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs
  29. 12
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
  30. 11
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs
  31. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs
  32. 8
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs
  33. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs
  34. 43
      ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs
  35. 173
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
  36. 11
      ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs

81
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs

@ -106,7 +106,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(method.IsVirtual); Assert.IsFalse(method.IsVirtual);
Assert.IsFalse(method.IsStatic); Assert.IsFalse(method.IsStatic);
Assert.AreEqual(0, method.Parameters.Count); Assert.AreEqual(0, method.Parameters.Count);
Assert.AreEqual(0, method.Attributes.Count); Assert.AreEqual(0, method.GetAttributes().Count());
Assert.IsTrue(method.HasBody); Assert.IsTrue(method.HasBody);
Assert.IsNull(method.AccessorOwner); Assert.IsNull(method.AccessorOwner);
} }
@ -117,7 +117,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest));
Assert.AreEqual(SpecialType.Dynamic, testClass.Fields.Single(f => f.Name == "DynamicField").ReturnType); Assert.AreEqual(SpecialType.Dynamic, testClass.Fields.Single(f => f.Name == "DynamicField").ReturnType);
Assert.AreEqual(SpecialType.Dynamic, testClass.Properties.Single().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] [Test]
@ -153,7 +153,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest)); ITypeDefinition testClass = GetTypeDefinition(typeof(DynamicTest));
IMethod m1 = testClass.Methods.Single(me => me.Name == "DynamicGenerics1"); 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] [Test]
@ -550,7 +550,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
[Test] [Test]
public void SerializableAttribute() public void SerializableAttribute()
{ {
IAttribute attr = GetTypeDefinition(typeof(NonCustomAttributes)).Attributes.Single(); IAttribute attr = GetTypeDefinition(typeof(NonCustomAttributes)).GetAttributes().Single();
Assert.AreEqual("System.SerializableAttribute", attr.AttributeType.FullName); Assert.AreEqual("System.SerializableAttribute", attr.AttributeType.FullName);
} }
@ -558,13 +558,13 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void NonSerializedAttribute() public void NonSerializedAttribute()
{ {
IField field = GetTypeDefinition(typeof(NonCustomAttributes)).Fields.Single(f => f.Name == "NonSerializedField"); 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] [Test]
public void ExplicitStructLayoutAttribute() 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); Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.FullName);
var arg1 = attr.FixedArguments.Single(); var arg1 = attr.FixedArguments.Single();
Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.Type.FullName); Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.Type.FullName);
@ -585,14 +585,14 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void FieldOffsetAttribute() public void FieldOffsetAttribute()
{ {
IField field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0"); IField field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0");
Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.FullName); Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.GetAttributes().Single().AttributeType.FullName);
var arg = field.Attributes.Single().FixedArguments.Single(); var arg = field.GetAttributes().Single().FixedArguments.Single();
Assert.AreEqual("System.Int32", arg.Type.FullName); Assert.AreEqual("System.Int32", arg.Type.FullName);
Assert.AreEqual(0, arg.Value); Assert.AreEqual(0, arg.Value);
field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100"); field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100");
Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.FullName); Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.GetAttributes().Single().AttributeType.FullName);
arg = field.Attributes.Single().FixedArguments.Single(); arg = field.GetAttributes().Single().FixedArguments.Single();
Assert.AreEqual("System.Int32", arg.Type.FullName); Assert.AreEqual("System.Int32", arg.Type.FullName);
Assert.AreEqual(100, arg.Value); Assert.AreEqual(100, arg.Value);
} }
@ -601,7 +601,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void DllImportAttribute() public void DllImportAttribute()
{ {
IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); 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("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.FullName);
Assert.AreEqual("unmanaged.dll", dllImport.FixedArguments[0].Value); Assert.AreEqual("unmanaged.dll", dllImport.FixedArguments[0].Value);
Assert.AreEqual((int)CharSet.Unicode, dllImport.NamedArguments.Single().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(); IParameter p = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod").Parameters.Single();
Assert.IsTrue(p.IsRef); Assert.IsTrue(p.IsRef);
Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsOut);
Assert.AreEqual(2, p.Attributes.Count); var attr = p.GetAttributes().ToList();
Assert.AreEqual("System.Runtime.InteropServices.InAttribute", p.Attributes[0].AttributeType.FullName); Assert.AreEqual(2, attr.Count);
Assert.AreEqual("System.Runtime.InteropServices.OutAttribute", p.Attributes[1].AttributeType.FullName); Assert.AreEqual("System.Runtime.InteropServices.InAttribute", attr[0].AttributeType.FullName);
Assert.AreEqual("System.Runtime.InteropServices.OutAttribute", attr[1].AttributeType.FullName);
} }
[Test] [Test]
public void MarshalAsAttributeOnMethod() public void MarshalAsAttributeOnMethod()
{ {
IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); 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); 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.IsOptional);
Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsRef);
Assert.IsTrue(p.IsOut); Assert.IsTrue(p.IsOut);
Assert.AreEqual(0, p.Attributes.Count); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsTrue(p.Type.Kind == TypeKind.ByReference); Assert.IsTrue(p.Type.Kind == TypeKind.ByReference);
} }
@ -645,7 +646,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsOut);
Assert.IsTrue(p.IsParams); Assert.IsTrue(p.IsParams);
Assert.AreEqual(0, p.Attributes.Count); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsTrue(p.Type.Kind == TypeKind.Array); Assert.IsTrue(p.Type.Kind == TypeKind.Array);
} }
@ -657,7 +658,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.AreEqual(0, p.Attributes.Count); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.AreEqual(4, p.ConstantValue); Assert.AreEqual(4, p.ConstantValue);
} }
@ -670,7 +671,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
// explicit optional parameter appears in type system if it's read from C#, but not when read from IL // 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] [Test]
@ -681,7 +682,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.AreEqual(0, p.Attributes.Count); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, p.ConstantValue); Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, p.ConstantValue);
} }
@ -693,7 +694,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef); Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut); Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams); Assert.IsFalse(p.IsParams);
Assert.AreEqual(0, p.Attributes.Count); Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsNull(p.ConstantValue); Assert.IsNull(p.ConstantValue);
} }
@ -781,7 +782,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
ITypeDefinition type = GetTypeDefinition(typeof(IAssemblyEnum)); ITypeDefinition type = GetTypeDefinition(typeof(IAssemblyEnum));
// [ComImport] // [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(); IMethod m = type.Methods.Single();
Assert.AreEqual("GetNextAssembly", m.Name); Assert.AreEqual("GetNextAssembly", m.Name);
@ -892,7 +893,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
CustomAttributeTypedArgument<IType> GetParamsAttributeArgument(int index) CustomAttributeTypedArgument<IType> GetParamsAttributeArgument(int index)
{ {
ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute)); 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); Assert.AreEqual(5, arr.Length);
return arr[index]; return arr[index];
} }
@ -942,7 +943,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute)); ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute));
IProperty prop = type.Properties.Single(p => p.Name == "Property"); IProperty prop = type.Properties.Single(p => p.Name == "Property");
var attr = prop.Attributes.Single(); var attr = prop.GetAttributes().Single();
Assert.AreEqual(type, attr.AttributeType); Assert.AreEqual(type, attr.AttributeType);
var elements = (AttributeArray)attr.FixedArguments.Single().Value; var elements = (AttributeArray)attr.FixedArguments.Single().Value;
@ -959,15 +960,15 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{ {
ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute)); ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute));
IProperty prop = type.Properties.Single(p => p.Name == "Property"); IProperty prop = type.Properties.Single(p => p.Name == "Property");
Assert.AreEqual(0, prop.Getter.Attributes.Count); Assert.AreEqual(0, prop.Getter.GetAttributes().Count());
Assert.AreEqual(1, prop.Getter.ReturnTypeAttributes.Count); Assert.AreEqual(1, prop.Getter.GetReturnTypeAttributes().Count());
} }
[Test] [Test]
public void DoubleAttribute_ImplicitNumericConversion() public void DoubleAttribute_ImplicitNumericConversion()
{ {
ITypeDefinition type = GetTypeDefinition(typeof(DoubleAttribute)); 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("System.Double", arg.Type.ReflectionName);
Assert.AreEqual(1.0, arg.Value); Assert.AreEqual(1.0, arg.Value);
} }
@ -1397,7 +1398,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
var f = type.GetFields().Single(x => x.Name == name); var f = type.GetFields().Single(x => x.Name == name);
Assert.IsTrue(f.IsConst); Assert.IsTrue(f.IsConst);
Assert.AreEqual(expected, f.ConstantValue); Assert.AreEqual(expected, f.ConstantValue);
Assert.AreEqual(0, f.Attributes.Count); Assert.AreEqual(0, f.GetAttributes().Count());
} }
[Test] [Test]
@ -1518,33 +1519,33 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
var type = GetTypeDefinition(typeof(ClassWithAttributesUsingNestedMembers)); var type = GetTypeDefinition(typeof(ClassWithAttributesUsingNestedMembers));
var inner = type.GetNestedTypes().Single(t => t.Name == "Inner"); var inner = type.GetNestedTypes().Single(t => t.Name == "Inner");
var myAttribute = type.GetNestedTypes().Single(t => t.Name == "MyAttribute"); 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(42, typeTypeTestAttr.FixedArguments[0].Value);
Assert.AreEqual(inner, typeTypeTestAttr.FixedArguments[1].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); Assert.AreEqual(myAttribute, typeMyAttr.AttributeType);
var prop = type.GetProperties().Single(p => p.Name == "P"); 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(42, propTypeTestAttr.FixedArguments[0].Value);
Assert.AreEqual(inner, propTypeTestAttr.FixedArguments[1].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); Assert.AreEqual(myAttribute, propMyAttr.AttributeType);
var attributedInner = (ITypeDefinition)type.GetNestedTypes().Single(t => t.Name == "AttributedInner"); 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(42, innerTypeTestAttr.FixedArguments[0].Value);
Assert.AreEqual(inner, innerTypeTestAttr.FixedArguments[1].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); Assert.AreEqual(myAttribute, innerMyAttr.AttributeType);
var attributedInner2 = (ITypeDefinition)type.GetNestedTypes().Single(t => t.Name == "AttributedInner2"); var attributedInner2 = (ITypeDefinition)type.GetNestedTypes().Single(t => t.Name == "AttributedInner2");
var inner2 = attributedInner2.GetNestedTypes().Single(t => t.Name == "Inner"); var inner2 = attributedInner2.GetNestedTypes().Single(t => t.Name == "Inner");
var myAttribute2 = attributedInner2.GetNestedTypes().Single(t => t.Name == "MyAttribute"); 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(43, inner2TypeTestAttr.FixedArguments[0].Value);
Assert.AreEqual(inner2, inner2TypeTestAttr.FixedArguments[1].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); Assert.AreEqual(myAttribute2, inner2MyAttr.AttributeType);
} }
@ -1552,7 +1553,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void ClassWithAttributeOnTypeParameter() public void ClassWithAttributeOnTypeParameter()
{ {
var tp = GetTypeDefinition(typeof(ClassWithAttributeOnTypeParameter<>)).TypeParameters.Single(); var tp = GetTypeDefinition(typeof(ClassWithAttributeOnTypeParameter<>)).TypeParameters.Single();
var attr = tp.Attributes.Single(); var attr = tp.GetAttributes().Single();
Assert.AreEqual("DoubleAttribute", attr.AttributeType.Name); Assert.AreEqual("DoubleAttribute", attr.AttributeType.Name);
} }
@ -1658,7 +1659,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void Void_SerializableAttribute() public void Void_SerializableAttribute()
{ {
ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); 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.Constructor.Parameters.Count);
Assert.AreEqual(0, attr.FixedArguments.Length); Assert.AreEqual(0, attr.FixedArguments.Length);
Assert.AreEqual(0, attr.NamedArguments.Length); Assert.AreEqual(0, attr.NamedArguments.Length);
@ -1668,7 +1669,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void Void_StructLayoutAttribute() public void Void_StructLayoutAttribute()
{ {
ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); 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.Constructor.Parameters.Count);
Assert.AreEqual(1, attr.FixedArguments.Length); Assert.AreEqual(1, attr.FixedArguments.Length);
Assert.AreEqual(0, attr.FixedArguments[0].Value); Assert.AreEqual(0, attr.FixedArguments[0].Value);
@ -1681,7 +1682,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void Void_ComVisibleAttribute() public void Void_ComVisibleAttribute()
{ {
ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition(); 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.Constructor.Parameters.Count);
Assert.AreEqual(1, attr.FixedArguments.Length); Assert.AreEqual(1, attr.FixedArguments.Length);
Assert.AreEqual(true, attr.FixedArguments[0].Value); Assert.AreEqual(true, attr.FixedArguments[0].Value);

8
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -794,7 +794,7 @@ namespace ICSharpCode.Decompiler.CSharp
EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, PEFile module) EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef, PEFile module)
{ {
if (typeDef.GetAttribute(KnownAttribute.Flags) != null) if (typeDef.HasAttribute(KnownAttribute.Flags, inherit: false))
return EnumValueDisplayMode.All; return EnumValueDisplayMode.All;
bool first = true; bool first = true;
long firstValue = 0, previousValue = 0; long firstValue = 0, previousValue = 0;
@ -997,7 +997,7 @@ namespace ICSharpCode.Decompiler.CSharp
void AddDefinesForConditionalAttributes(ILFunction function, DecompileRun decompileRun, ITypeResolveContext decompilationContext) void AddDefinesForConditionalAttributes(ILFunction function, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
foreach (var call in function.Descendants.OfType<CallInstruction>()) { foreach (var call in function.Descendants.OfType<CallInstruction>()) {
var attr = call.Method.GetAttribute(KnownAttribute.Conditional); var attr = call.Method.GetAttribute(KnownAttribute.Conditional, inherit: true);
var symbolName = attr?.FixedArguments.FirstOrDefault().Value as string; var symbolName = attr?.FixedArguments.FirstOrDefault().Value as string;
if (symbolName == null || !decompileRun.DefinedSymbols.Add(symbolName)) if (symbolName == null || !decompileRun.DefinedSymbols.Add(symbolName))
continue; continue;
@ -1014,12 +1014,12 @@ namespace ICSharpCode.Decompiler.CSharp
long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false); long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false);
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue); enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue);
if (enumDec.Initializer is PrimitiveExpression primitive 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)))) || (initValue > 9 && ((initValue & (initValue - 1)) == 0 || (initValue & (initValue + 1)) == 0))))
{ {
primitive.SetValue(initValue, $"0x{initValue:X}"); 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)); enumDec.AddAnnotation(new MemberResolveResult(null, field));
return enumDec; return enumDec;
} }

18
ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs

@ -40,10 +40,10 @@ namespace ICSharpCode.Decompiler.CSharp
switch (entity) { switch (entity) {
case ITypeDefinition td: case ITypeDefinition td:
namespaces.Add(td.Namespace); namespaces.Add(td.Namespace);
HandleAttributes(td.Attributes, namespaces); HandleAttributes(td.GetAttributes(), namespaces);
foreach (var typeParam in td.TypeParameters) { foreach (var typeParam in td.TypeParameters) {
HandleAttributes(typeParam.Attributes, namespaces); HandleAttributes(typeParam.GetAttributes(), namespaces);
} }
foreach (var baseType in td.DirectBaseTypes) { foreach (var baseType in td.DirectBaseTypes) {
@ -71,19 +71,19 @@ namespace ICSharpCode.Decompiler.CSharp
} }
break; break;
case IField field: case IField field:
HandleAttributes(field.Attributes, namespaces); HandleAttributes(field.GetAttributes(), namespaces);
CollectNamespacesForTypeReference(field.ReturnType, namespaces); CollectNamespacesForTypeReference(field.ReturnType, namespaces);
break; break;
case IMethod method: case IMethod method:
HandleAttributes(method.Attributes, namespaces); HandleAttributes(method.GetAttributes(), namespaces);
HandleAttributes(method.ReturnTypeAttributes, namespaces); HandleAttributes(method.GetReturnTypeAttributes(), namespaces);
CollectNamespacesForTypeReference(method.ReturnType, namespaces); CollectNamespacesForTypeReference(method.ReturnType, namespaces);
foreach (var param in method.Parameters) { foreach (var param in method.Parameters) {
HandleAttributes(param.Attributes, namespaces); HandleAttributes(param.GetAttributes(), namespaces);
CollectNamespacesForTypeReference(param.Type, namespaces); CollectNamespacesForTypeReference(param.Type, namespaces);
} }
foreach (var typeParam in method.TypeParameters) { foreach (var typeParam in method.TypeParameters) {
HandleAttributes(typeParam.Attributes, namespaces); HandleAttributes(typeParam.GetAttributes(), namespaces);
} }
if (!method.MetadataToken.IsNil && method.HasBody) { if (!method.MetadataToken.IsNil && method.HasBody) {
var reader = typeSystem.ModuleDefinition.Reader; var reader = typeSystem.ModuleDefinition.Reader;
@ -93,12 +93,12 @@ namespace ICSharpCode.Decompiler.CSharp
} }
break; break;
case IProperty property: case IProperty property:
HandleAttributes(property.Attributes, namespaces); HandleAttributes(property.GetAttributes(), namespaces);
CollectNamespaces(property.Getter, typeSystem, namespaces); CollectNamespaces(property.Getter, typeSystem, namespaces);
CollectNamespaces(property.Setter, typeSystem, namespaces); CollectNamespaces(property.Setter, typeSystem, namespaces);
break; break;
case IEvent @event: case IEvent @event:
HandleAttributes(@event.Attributes, namespaces); HandleAttributes(@event.GetAttributes(), namespaces);
CollectNamespaces(@event.AddAccessor, typeSystem, namespaces); CollectNamespaces(@event.AddAccessor, typeSystem, namespaces);
CollectNamespaces(@event.RemoveAccessor, typeSystem, namespaces); CollectNamespaces(@event.RemoveAccessor, typeSystem, namespaces);
break; break;

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

@ -150,8 +150,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
get { return SymbolKind.Operator; } get { return SymbolKind.Operator; }
} }
IReadOnlyList<IAttribute> IEntity.Attributes { IEnumerable<IAttribute> IEntity.GetAttributes()
get { return EmptyList<IAttribute>.Instance; } {
return EmptyList<IAttribute>.Instance;
} }
Accessibility IEntity.Accessibility { Accessibility IEntity.Accessibility {

29
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) void CheckForEnumerableInterface(ResolveResult expression, out IType collectionType, out IType enumeratorType, out IType elementType, out ResolveResult getEnumeratorInvocation)
{ {
bool? isGeneric; bool? isGeneric;
elementType = GetElementTypeFromIEnumerable(expression.Type, compilation, false, out isGeneric); elementType = expression.Type.GetElementTypeFromIEnumerable(compilation, false, out isGeneric);
if (isGeneric == true) { if (isGeneric == true) {
ITypeDefinition enumerableOfT = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition(); ITypeDefinition enumerableOfT = compilation.FindType(KnownTypeCode.IEnumerableOfT).GetDefinition();
if (enumerableOfT != null) if (enumerableOfT != null)
@ -1765,33 +1765,6 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
getEnumeratorInvocation = ResolveMemberAccess(getEnumeratorInvocation, "GetEnumerator", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget); getEnumeratorInvocation = ResolveMemberAccess(getEnumeratorInvocation, "GetEnumerator", EmptyList<IType>.Instance, NameLookupMode.InvocationTarget);
getEnumeratorInvocation = ResolveInvocation(getEnumeratorInvocation, new ResolveResult[0]); 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 #endregion
#region GetExtensionMethods #region GetExtensionMethods

13
ICSharpCode.Decompiler/CSharp/Resolver/ReducedExtensionMethod.cs

@ -136,12 +136,6 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
#region IMethod implementation #region IMethod implementation
public IReadOnlyList<IAttribute> ReturnTypeAttributes {
get {
return baseMethod.ReturnTypeAttributes;
}
}
public IReadOnlyList<ITypeParameter> TypeParameters { public IReadOnlyList<ITypeParameter> TypeParameters {
get { get {
return baseMethod.TypeParameters; return baseMethod.TypeParameters;
@ -243,11 +237,8 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
} }
} }
public IReadOnlyList<IAttribute> Attributes { IEnumerable<IAttribute> IEntity.GetAttributes() => baseMethod.GetAttributes();
get { IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes();
return baseMethod.Attributes;
}
}
public bool IsStatic { public bool IsStatic {
get { get {

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

@ -455,7 +455,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
public Attribute ConvertAttribute(IAttribute attribute) public Attribute ConvertAttribute(IAttribute attribute)
{ {
Attribute attr = new Attribute(); Attribute attr = new Attribute();
attr.Type = ConvertType(attribute.AttributeType); attr.Type = ConvertAttributeType(attribute.AttributeType);
SimpleType st = attr.Type as SimpleType; SimpleType st = attr.Type as SimpleType;
MemberType mt = attr.Type as MemberType; MemberType mt = attr.Type as MemberType;
if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) { if (st != null && st.Identifier.EndsWith("Attribute", StringComparison.Ordinal)) {
@ -482,6 +482,18 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
return attr; return attr;
} }
private IEnumerable<AttributeSection> ConvertAttributes(IEnumerable<IAttribute> attibutes)
{
return attibutes.Select(a => new AttributeSection(ConvertAttribute(a)));
}
private IEnumerable<AttributeSection> ConvertAttributes(IEnumerable<IAttribute> attibutes, string target)
{
return attibutes.Select(a => new AttributeSection(ConvertAttribute(a)) {
AttributeTarget = target
});
}
#endregion #endregion
#region Convert Attribute Type #region Convert Attribute Type
@ -495,6 +507,28 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
if (type.Name.Length > 9 && type.Name.EndsWith("Attribute", StringComparison.Ordinal)) { if (type.Name.Length > 9 && type.Name.EndsWith("Attribute", StringComparison.Ordinal)) {
shortName = type.Name.Remove(type.Name.Length - 9); 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) { switch (astType) {
case SimpleType st: case SimpleType st:
ResolveResult shortRR = null; ResolveResult shortRR = null;
@ -529,12 +563,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
break; break;
} }
if (AddTypeReferenceAnnotations)
astType.AddAnnotation(type);
if (AddResolveResultAnnotations)
astType.AddAnnotation(new TypeResolveResult(type));
return astType;
} }
private bool IsAttributeType(IType type) private bool IsAttributeType(IType type)
@ -792,8 +820,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
bool IsFlagsEnum(ITypeDefinition type) bool IsFlagsEnum(ITypeDefinition type)
{ {
IType flagsAttributeType = type.Compilation.FindType(typeof(System.FlagsAttribute)); return type.HasAttribute(KnownAttribute.Flags, inherit: false);
return type.GetAttribute(flagsAttributeType) != null;
} }
Expression ConvertEnumValue(IType type, long val) Expression ConvertEnumValue(IType type, long val)
@ -880,7 +907,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.ParameterModifier = ParameterModifier.Params; decl.ParameterModifier = ParameterModifier.Params;
} }
if (ShowAttributes) { 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) { if (parameter.Type.Kind == TypeKind.ByReference) {
// avoid 'out ref' // avoid 'out ref'
@ -997,7 +1024,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.ClassType = classType; decl.ClassType = classType;
decl.Modifiers = modifiers; decl.Modifiers = modifiers;
if (ShowAttributes) { if (ShowAttributes) {
decl.Attributes.AddRange (typeDefinition.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(typeDefinition.GetAttributes()));
} }
if (AddResolveResultAnnotations) { if (AddResolveResultAnnotations) {
decl.AddAnnotation(new TypeResolveResult(typeDefinition)); decl.AddAnnotation(new TypeResolveResult(typeDefinition));
@ -1034,7 +1061,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
return decl; return decl;
} }
DelegateDeclaration ConvertDelegate(IMethod invokeMethod, Modifiers modifiers) DelegateDeclaration ConvertDelegate(IMethod invokeMethod, Modifiers modifiers)
{ {
ITypeDefinition d = invokeMethod.DeclaringTypeDefinition; ITypeDefinition d = invokeMethod.DeclaringTypeDefinition;
@ -1042,10 +1069,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
DelegateDeclaration decl = new DelegateDeclaration(); DelegateDeclaration decl = new DelegateDeclaration();
decl.Modifiers = modifiers & ~Modifiers.Sealed; decl.Modifiers = modifiers & ~Modifiers.Sealed;
if (ShowAttributes) { if (ShowAttributes) {
decl.Attributes.AddRange (d.Attributes.Select (a => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(d.GetAttributes()));
decl.Attributes.AddRange (invokeMethod.ReturnTypeAttributes.Select ((a) => new AttributeSection (ConvertAttribute (a)) { decl.Attributes.AddRange(ConvertAttributes(invokeMethod.GetReturnTypeAttributes(), "return"));
AttributeTarget = "return"
}));
} }
if (AddResolveResultAnnotations) { if (AddResolveResultAnnotations) {
decl.AddAnnotation(new TypeResolveResult(d)); decl.AddAnnotation(new TypeResolveResult(d));
@ -1091,7 +1116,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.Modifiers = m; decl.Modifiers = m;
} }
if (ShowAttributes) { if (ShowAttributes) {
decl.Attributes.AddRange (field.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(field.GetAttributes()));
} }
if (AddResolveResultAnnotations) { if (AddResolveResultAnnotations) {
decl.AddAnnotation(new MemberResolveResult(null, field)); 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) if (accessor == null)
return Accessor.Null; return Accessor.Null;
@ -1123,14 +1148,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
if (this.ShowAccessibility && accessor.Accessibility != ownerAccessibility) if (this.ShowAccessibility && accessor.Accessibility != ownerAccessibility)
decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility); decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility);
if (ShowAttributes) { if (ShowAttributes) {
decl.Attributes.AddRange (accessor.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(accessor.GetAttributes()));
decl.Attributes.AddRange (accessor.ReturnTypeAttributes.Select ((a) => new AttributeSection (ConvertAttribute (a)) { decl.Attributes.AddRange(ConvertAttributes(accessor.GetReturnTypeAttributes(), "return"));
AttributeTarget = "return" if (addParameterAttribute && accessor.Parameters.Count > 0) {
})); decl.Attributes.AddRange(ConvertAttributes(accessor.Parameters.Last().GetAttributes(), "param"));
if (addParamterAttribute && accessor.Parameters.Count > 0) {
decl.Attributes.AddRange (accessor.Parameters.Last ().Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)) {
AttributeTarget = "param"
}));
} }
} }
if (AddResolveResultAnnotations) { if (AddResolveResultAnnotations) {
@ -1145,7 +1166,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
PropertyDeclaration decl = new PropertyDeclaration(); PropertyDeclaration decl = new PropertyDeclaration();
decl.Modifiers = GetMemberModifiers(property); decl.Modifiers = GetMemberModifiers(property);
if (ShowAttributes) { if (ShowAttributes) {
decl.Attributes.AddRange (property.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(property.GetAttributes()));
} }
if (AddResolveResultAnnotations) { if (AddResolveResultAnnotations) {
decl.AddAnnotation(new MemberResolveResult(null, property)); decl.AddAnnotation(new MemberResolveResult(null, property));
@ -1163,7 +1184,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
IndexerDeclaration decl = new IndexerDeclaration(); IndexerDeclaration decl = new IndexerDeclaration();
decl.Modifiers = GetMemberModifiers(indexer); decl.Modifiers = GetMemberModifiers(indexer);
if (ShowAttributes) { if (ShowAttributes) {
decl.Attributes.AddRange (indexer.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(indexer.GetAttributes()));
} }
if (AddResolveResultAnnotations) { if (AddResolveResultAnnotations) {
decl.AddAnnotation(new MemberResolveResult(null, indexer)); decl.AddAnnotation(new MemberResolveResult(null, indexer));
@ -1184,7 +1205,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
CustomEventDeclaration decl = new CustomEventDeclaration(); CustomEventDeclaration decl = new CustomEventDeclaration();
decl.Modifiers = GetMemberModifiers(ev); decl.Modifiers = GetMemberModifiers(ev);
if (ShowAttributes) { if (ShowAttributes) {
decl.Attributes.AddRange (ev.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(ev.GetAttributes()));
} }
if (AddResolveResultAnnotations) { if (AddResolveResultAnnotations) {
decl.AddAnnotation(new MemberResolveResult(null, ev)); decl.AddAnnotation(new MemberResolveResult(null, ev));
@ -1199,7 +1220,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
EventDeclaration decl = new EventDeclaration(); EventDeclaration decl = new EventDeclaration();
decl.Modifiers = GetMemberModifiers(ev); decl.Modifiers = GetMemberModifiers(ev);
if (ShowAttributes) { if (ShowAttributes) {
decl.Attributes.AddRange (ev.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(ev.GetAttributes()));
} }
if (AddResolveResultAnnotations) { if (AddResolveResultAnnotations) {
decl.AddAnnotation(new MemberResolveResult(null, ev)); decl.AddAnnotation(new MemberResolveResult(null, ev));
@ -1215,10 +1236,8 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
MethodDeclaration decl = new MethodDeclaration(); MethodDeclaration decl = new MethodDeclaration();
decl.Modifiers = GetMemberModifiers(method); decl.Modifiers = GetMemberModifiers(method);
if (ShowAttributes) { if (ShowAttributes) {
decl.Attributes.AddRange (method.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(method.GetAttributes()));
decl.Attributes.AddRange (method.ReturnTypeAttributes.Select ((a) => new AttributeSection (ConvertAttribute (a)) { decl.Attributes.AddRange(ConvertAttributes(method.GetReturnTypeAttributes(), "return"));
AttributeTarget = "return"
}));
} }
if (AddResolveResultAnnotations) { if (AddResolveResultAnnotations) {
decl.AddAnnotation(new MemberResolveResult(null, method)); decl.AddAnnotation(new MemberResolveResult(null, method));
@ -1275,7 +1294,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
ConstructorDeclaration decl = new ConstructorDeclaration(); ConstructorDeclaration decl = new ConstructorDeclaration();
decl.Modifiers = GetMemberModifiers(ctor); decl.Modifiers = GetMemberModifiers(ctor);
if (ShowAttributes) if (ShowAttributes)
decl.Attributes.AddRange (ctor.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(ctor.GetAttributes()));
if (ctor.DeclaringTypeDefinition != null) if (ctor.DeclaringTypeDefinition != null)
decl.Name = ctor.DeclaringTypeDefinition.Name; decl.Name = ctor.DeclaringTypeDefinition.Name;
foreach (IParameter p in ctor.Parameters) { foreach (IParameter p in ctor.Parameters) {
@ -1369,7 +1388,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.Variance = tp.Variance; decl.Variance = tp.Variance;
decl.Name = tp.Name; decl.Name = tp.Name;
if (ShowAttributes) if (ShowAttributes)
decl.Attributes.AddRange (tp.Attributes.Select ((a) => new AttributeSection (ConvertAttribute (a)))); decl.Attributes.AddRange(ConvertAttributes(tp.GetAttributes()));
return decl; return decl;
} }

26
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -507,17 +507,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
propertyDeclaration.Getter.Body = null; propertyDeclaration.Getter.Body = null;
propertyDeclaration.Setter.Body = null; propertyDeclaration.Setter.Body = null;
// Add C# 7.3 attributes on backing field: // Add C# 7.3 attributes on backing field:
var attributes = field.Attributes var attributes = field.GetAttributes()
.Where(a => !attributeTypesToRemoveFromAutoProperties.Any(t => t == a.AttributeType.FullName)) .Where(a => !attributeTypesToRemoveFromAutoProperties.Contains(a.AttributeType.FullName))
.Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray(); .Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray();
if (attributes.Length > 0) { if (attributes.Length > 0) {
var section = new AttributeSection { var section = new AttributeSection {
AttributeTarget = "field" AttributeTarget = "field"
}; };
section.Attributes.AddRange(attributes); section.Attributes.AddRange(attributes);
propertyDeclaration.Attributes.Add(section); propertyDeclaration.Attributes.Add(section);
} }
} }
// Since the property instance is not changed, we can continue in the visitor as usual, so return null // Since the property instance is not changed, we can continue in the visitor as usual, so return null
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(); IField field = eventDef.DeclaringType.GetFields(f => f.Name == ev.Name, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault();
if (field != null) { if (field != null) {
ed.AddAnnotation(field); ed.AddAnnotation(field);
var attributes = field.Attributes var attributes = field.GetAttributes()
.Where(a => !attributeTypesToRemoveFromAutoEvents.Any(t => t == a.AttributeType.FullName)) .Where(a => !attributeTypesToRemoveFromAutoEvents.Contains(a.AttributeType.FullName))
.Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray(); .Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray();
if (attributes.Length > 0) { if (attributes.Length > 0) {
var section = new AttributeSection { var section = new AttributeSection {

5
ICSharpCode.Decompiler/NRExtensions.cs

@ -44,10 +44,7 @@ namespace ICSharpCode.Decompiler
public static bool IsCompilerGenerated(this IEntity entity) public static bool IsCompilerGenerated(this IEntity entity)
{ {
if (entity != null) { if (entity != null) {
foreach (IAttribute a in entity.Attributes) { return entity.HasAttribute(KnownAttribute.CompilerGenerated);
if (a.AttributeType.FullName == "System.Runtime.CompilerServices.CompilerGeneratedAttribute")
return true;
}
} }
return false; return false;
} }

2
ICSharpCode.Decompiler/TypeSystem/ComHelper.cs

@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
return typeDefinition != null return typeDefinition != null
&& typeDefinition.Kind == TypeKind.Interface && typeDefinition.Kind == TypeKind.Interface
&& typeDefinition.GetAttributes(KnownAttribute.ComImport, inherit: false) != null; && typeDefinition.HasAttribute(KnownAttribute.ComImport, inherit: false);
} }
/// <summary> /// <summary>

3
ICSharpCode.Decompiler/TypeSystem/IEntity.cs

@ -123,8 +123,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary> /// <summary>
/// Gets the attributes on this entity. /// Gets the attributes on this entity.
/// Does not include inherited attributes.
/// </summary> /// </summary>
IReadOnlyList<IAttribute> Attributes { get; } IEnumerable<IAttribute> GetAttributes();
/// <summary> /// <summary>
/// Gets the accessibility of this entity. /// Gets the accessibility of this entity.

5
ICSharpCode.Decompiler/TypeSystem/IMethod.cs

@ -79,7 +79,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary> /// <summary>
/// Gets the attributes associated with the return type. (e.g. [return: MarshalAs(...)]) /// Gets the attributes associated with the return type. (e.g. [return: MarshalAs(...)])
/// </summary> /// </summary>
IReadOnlyList<IAttribute> ReturnTypeAttributes { get; } /// <remarks>
/// Does not include inherited attributes.
/// </remarks>
IEnumerable<IAttribute> GetReturnTypeAttributes();
/// <summary> /// <summary>
/// Gets the type parameters of this method; or an empty list if the method is not generic. /// Gets the type parameters of this method; or an empty list if the method is not generic.

4
ICSharpCode.Decompiler/TypeSystem/IParameter.cs

@ -63,9 +63,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
public interface IParameter : IVariable public interface IParameter : IVariable
{ {
/// <summary> /// <summary>
/// Gets the list of attributes. /// Gets the attributes on this parameter.
/// </summary> /// </summary>
IReadOnlyList<IAttribute> Attributes { get; } IEnumerable<IAttribute> GetAttributes();
/// <summary> /// <summary>
/// Gets whether this parameter is a C# 'ref' parameter. /// Gets whether this parameter is a C# 'ref' parameter.

4
ICSharpCode.Decompiler/TypeSystem/ITypeParameter.cs

@ -82,9 +82,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
new string Name { get; } new string Name { get; }
/// <summary> /// <summary>
/// Gets the list of attributes declared on this type parameter. /// Gets the attributes declared on this type parameter.
/// </summary> /// </summary>
IReadOnlyList<IAttribute> Attributes { get; } IEnumerable<IAttribute> GetAttributes();
/// <summary> /// <summary>
/// Gets the variance of this type parameter. /// Gets the variance of this type parameter.

1
ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedEntity.cs

@ -59,6 +59,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
public IReadOnlyList<IAttribute> Attributes { get; protected set; } public IReadOnlyList<IAttribute> Attributes { get; protected set; }
IEnumerable<IAttribute> IEntity.GetAttributes() => Attributes;
public bool IsStatic { get { return unresolved.IsStatic; } } public bool IsStatic { get { return unresolved.IsStatic; } }
public bool IsAbstract { get { return unresolved.IsAbstract; } } public bool IsAbstract { get { return unresolved.IsAbstract; } }

4
ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs

@ -71,8 +71,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public int Index { public int Index {
get { return index; } get { return index; }
} }
public abstract IReadOnlyList<IAttribute> Attributes { get; } public abstract IEnumerable<IAttribute> GetAttributes();
public VarianceModifier Variance { public VarianceModifier Variance {
get { return variance; } get { return variance; }

4
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs

@ -72,9 +72,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return owner; } get { return owner; }
} }
public IReadOnlyList<IAttribute> Attributes { public IEnumerable<IAttribute> GetAttributes() => attributes;
get { return attributes; }
}
public bool IsRef { public bool IsRef {
get { return isRef; } get { return isRef; }

1
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedMethod.cs

@ -170,6 +170,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IReadOnlyList<IParameter> Parameters { get; private set; } public IReadOnlyList<IParameter> Parameters { get; private set; }
public IReadOnlyList<IAttribute> ReturnTypeAttributes { get; private set; } public IReadOnlyList<IAttribute> ReturnTypeAttributes { get; private set; }
IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => ReturnTypeAttributes;
public IReadOnlyList<ITypeParameter> TypeParameters { get; private set; } public IReadOnlyList<ITypeParameter> TypeParameters { get; private set; }
public IReadOnlyList<IType> TypeArguments { public IReadOnlyList<IType> TypeArguments {

4
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs

@ -105,7 +105,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return LazyInit.GetOrSet(ref this.attributes, result); return LazyInit.GetOrSet(ref this.attributes, result);
} }
} }
public IEnumerable<IAttribute> GetAttributes() => Attributes;
public System.Reflection.Metadata.EntityHandle MetadataToken => parts[0].MetadataToken; public System.Reflection.Metadata.EntityHandle MetadataToken => parts[0].MetadataToken;
public SymbolKind SymbolKind { public SymbolKind SymbolKind {

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

@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.attributes = attributes ?? EmptyList<IAttribute>.Instance; this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
} }
public override IReadOnlyList<IAttribute> Attributes => attributes; public override IEnumerable<IAttribute> GetAttributes() => attributes;
public override bool HasValueTypeConstraint => hasValueTypeConstraint; public override bool HasValueTypeConstraint => hasValueTypeConstraint;
public override bool HasReferenceTypeConstraint => hasReferenceTypeConstraint; public override bool HasReferenceTypeConstraint => hasReferenceTypeConstraint;

1
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedParameter.cs

@ -229,6 +229,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IType Type { get; internal set; } public IType Type { get; internal set; }
public string Name { get; internal set; } public string Name { get; internal set; }
public IReadOnlyList<IAttribute> Attributes { get; internal set; } public IReadOnlyList<IAttribute> Attributes { get; internal set; }
public IEnumerable<IAttribute> GetAttributes() => Attributes;
public bool IsRef { get; internal set; } public bool IsRef { get; internal set; }
public bool IsOut { get; internal set; } public bool IsOut { get; internal set; }
public bool IsParams { get; internal set; } public bool IsParams { get; internal set; }

4
ICSharpCode.Decompiler/TypeSystem/Implementation/DummyTypeParameter.cs

@ -141,9 +141,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return index; } get { return index; }
} }
IReadOnlyList<IAttribute> ITypeParameter.Attributes { IEnumerable<IAttribute> ITypeParameter.GetAttributes() =>EmptyList<IAttribute>.Instance;
get { return EmptyList<IAttribute>.Instance; }
}
SymbolKind ITypeParameter.OwnerType { SymbolKind ITypeParameter.OwnerType {
get { return ownerType; } get { return ownerType; }

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

@ -58,7 +58,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IAssembly IEntity.ParentAssembly => DeclaringType?.GetDefinition()?.ParentAssembly; IAssembly IEntity.ParentAssembly => DeclaringType?.GetDefinition()?.ParentAssembly;
IReadOnlyList<IAttribute> IEntity.Attributes => EmptyList<IAttribute>.Instance; IEnumerable<IAttribute> IEntity.GetAttributes() => EmptyList<IAttribute>.Instance;
public Accessibility Accessibility { get; set; } = Accessibility.Public; public Accessibility Accessibility { get; set; } = Accessibility.Public;
@ -130,7 +130,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override SymbolKind SymbolKind => symbolKind; public override SymbolKind SymbolKind => symbolKind;
IReadOnlyList<IAttribute> IMethod.ReturnTypeAttributes => EmptyList<IAttribute>.Instance; IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => EmptyList<IAttribute>.Instance;
public IReadOnlyList<ITypeParameter> TypeParameters { get; set; } = EmptyList<ITypeParameter>.Instance; public IReadOnlyList<ITypeParameter> TypeParameters { get; set; } = EmptyList<ITypeParameter>.Instance;

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

@ -38,7 +38,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly string name; readonly string name;
// lazy-loaded: // lazy-loaded:
IAttribute[] customAttributes;
IType returnType; IType returnType;
internal MetadataEvent(MetadataAssembly assembly, EventDefinitionHandle handle) internal MetadataEvent(MetadataAssembly assembly, EventDefinitionHandle handle)
@ -103,16 +102,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity; TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity;
#region Attributes #region Attributes
public IReadOnlyList<IAttribute> Attributes { public IEnumerable<IAttribute> GetAttributes()
get {
var attr = LazyInit.VolatileRead(ref this.customAttributes);
if (attr != null)
return attr;
return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes());
}
}
IAttribute[] DecodeAttributes()
{ {
var b = new AttributeListBuilder(assembly); var b = new AttributeListBuilder(assembly);
var metadata = assembly.metadata; var metadata = assembly.metadata;

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

@ -43,7 +43,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IType type; IType type;
bool isVolatile; // initialized together with this.type bool isVolatile; // initialized together with this.type
byte decimalConstant; // 0=no, 1=yes, 2=unknown byte decimalConstant; // 0=no, 1=yes, 2=unknown
IAttribute[] customAttributes;
internal MetadataField(MetadataAssembly assembly, FieldDefinitionHandle handle) internal MetadataField(MetadataAssembly assembly, FieldDefinitionHandle handle)
{ {
@ -127,17 +126,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IType DeclaringType => DeclaringTypeDefinition; public IType DeclaringType => DeclaringTypeDefinition;
public IAssembly ParentAssembly => assembly; public IAssembly ParentAssembly => assembly;
public ICompilation Compilation => assembly.Compilation; public ICompilation Compilation => assembly.Compilation;
public IReadOnlyList<IAttribute> Attributes { public IEnumerable<IAttribute> GetAttributes()
get {
var attr = LazyInit.VolatileRead(ref this.customAttributes);
if (attr != null)
return attr;
return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes());
}
}
IAttribute[] DecodeAttributes()
{ {
var b = new AttributeListBuilder(assembly); var b = new AttributeListBuilder(assembly);
var metadata = assembly.metadata; var metadata = assembly.metadata;

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

@ -45,8 +45,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
// lazy-loaded fields: // lazy-loaded fields:
ITypeDefinition declaringType; ITypeDefinition declaringType;
string name; string name;
IAttribute[] customAttributes;
IAttribute[] returnTypeAttributes;
IParameter[] parameters; IParameter[] parameters;
IType returnType; IType returnType;
@ -232,15 +230,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public ICompilation Compilation => assembly.Compilation; public ICompilation Compilation => assembly.Compilation;
#region Attributes #region Attributes
public IReadOnlyList<IAttribute> 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) IType FindInteropType(string name)
{ {
return assembly.Compilation.FindType(new TopLevelTypeName( return assembly.Compilation.FindType(new TopLevelTypeName(
@ -248,7 +237,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
)); ));
} }
IAttribute[] DecodeAttributes() public IEnumerable<IAttribute> GetAttributes()
{ {
var b = new AttributeListBuilder(assembly); var b = new AttributeListBuilder(assembly);
@ -365,16 +354,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
#endregion #endregion
#region Return type attributes #region Return type attributes
public IReadOnlyList<IAttribute> ReturnTypeAttributes { public IEnumerable<IAttribute> GetReturnTypeAttributes()
get {
var attr = LazyInit.VolatileRead(ref this.returnTypeAttributes);
if (attr != null)
return attr;
return LazyInit.GetOrSet(ref this.returnTypeAttributes, DecodeReturnTypeAttributes());
}
}
private IAttribute[] DecodeReturnTypeAttributes()
{ {
var b = new AttributeListBuilder(assembly); var b = new AttributeListBuilder(assembly);
var metadata = assembly.metadata; var metadata = assembly.metadata;

12
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs

@ -37,7 +37,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
// lazy-loaded: // lazy-loaded:
string name; string name;
IAttribute[] customAttributes;
internal MetadataParameter(MetadataAssembly assembly, IParameterizedMember owner, IType type, ParameterHandle handle) internal MetadataParameter(MetadataAssembly assembly, IParameterizedMember owner, IType type, ParameterHandle handle)
{ {
@ -53,16 +52,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public EntityHandle MetadataToken => handle; public EntityHandle MetadataToken => handle;
#region Attributes #region Attributes
public IReadOnlyList<IAttribute> Attributes { public IEnumerable<IAttribute> GetAttributes()
get {
var attr = LazyInit.VolatileRead(ref this.customAttributes);
if (attr != null)
return attr;
return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes());
}
}
IAttribute[] DecodeAttributes()
{ {
var b = new AttributeListBuilder(assembly); var b = new AttributeListBuilder(assembly);
var metadata = assembly.metadata; var metadata = assembly.metadata;

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

@ -42,7 +42,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly SymbolKind symbolKind; readonly SymbolKind symbolKind;
// lazy-loaded: // lazy-loaded:
IAttribute[] customAttributes;
volatile Accessibility cachedAccessiblity = InvalidAccessibility; volatile Accessibility cachedAccessiblity = InvalidAccessibility;
IParameter[] parameters; IParameter[] parameters;
IType returnType; IType returnType;
@ -144,16 +143,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity; TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity;
#region Attributes #region Attributes
public IReadOnlyList<IAttribute> Attributes { public IEnumerable<IAttribute> GetAttributes()
get {
var attr = LazyInit.VolatileRead(ref this.customAttributes);
if (attr != null)
return attr;
return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes());
}
}
IAttribute[] DecodeAttributes()
{ {
var b = new AttributeListBuilder(assembly); var b = new AttributeListBuilder(assembly);
var metadata = assembly.metadata; var metadata = assembly.metadata;

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

@ -51,7 +51,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool HasExtensionMethods { get; } public bool HasExtensionMethods { get; }
// lazy-loaded: // lazy-loaded:
IAttribute[] customAttributes;
IMember[] members; IMember[] members;
IField[] fields; IField[] fields;
IProperty[] properties; IProperty[] properties;
@ -284,16 +283,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IAssembly ParentAssembly => assembly; public IAssembly ParentAssembly => assembly;
#region Type Attributes #region Type Attributes
public IReadOnlyList<IAttribute> Attributes { public IEnumerable<IAttribute> GetAttributes()
get {
var attr = LazyInit.VolatileRead(ref this.customAttributes);
if (attr != null)
return attr;
return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes());
}
}
IAttribute[] DecodeAttributes()
{ {
var b = new AttributeListBuilder(assembly); var b = new AttributeListBuilder(assembly);
var metadata = assembly.metadata; var metadata = assembly.metadata;

11
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs

@ -98,16 +98,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public GenericParameterHandle MetadataToken => handle; public GenericParameterHandle MetadataToken => handle;
public override IReadOnlyList<IAttribute> Attributes { public override IEnumerable<IAttribute> GetAttributes()
get {
var attr = LazyInit.VolatileRead(ref this.customAttributes);
if (attr != null)
return attr;
return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes());
}
}
IAttribute[] DecodeAttributes()
{ {
var metadata = assembly.metadata; var metadata = assembly.metadata;
var gp = metadata.GetGenericParameter(handle); var gp = metadata.GetGenericParameter(handle);

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

@ -150,10 +150,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public ITypeDefinition DeclaringTypeDefinition { public ITypeDefinition DeclaringTypeDefinition {
get { return baseMember.DeclaringTypeDefinition; } get { return baseMember.DeclaringTypeDefinition; }
} }
public IReadOnlyList<IAttribute> Attributes { IEnumerable<IAttribute> IEntity.GetAttributes() => baseMember.GetAttributes();
get { return baseMember.Attributes; }
}
public IEnumerable<IMember> ExplicitlyImplementedInterfaceMembers { public IEnumerable<IMember> ExplicitlyImplementedInterfaceMembers {
get { get {

8
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs

@ -92,10 +92,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IReadOnlyList<IType> TypeArguments { public IReadOnlyList<IType> TypeArguments {
get { return this.Substitution.MethodTypeArguments ?? EmptyList<IType>.Instance; } get { return this.Substitution.MethodTypeArguments ?? EmptyList<IType>.Instance; }
} }
public IReadOnlyList<IAttribute> ReturnTypeAttributes { public IEnumerable<IAttribute> GetReturnTypeAttributes() => methodDefinition.GetReturnTypeAttributes();
get { return methodDefinition.ReturnTypeAttributes; }
}
public IReadOnlyList<ITypeParameter> TypeParameters { public IReadOnlyList<ITypeParameter> TypeParameters {
get { get {
@ -230,7 +228,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.baseTp = baseTp; this.baseTp = baseTp;
} }
public override IReadOnlyList<IAttribute> Attributes => baseTp.Attributes; public override IEnumerable<IAttribute> GetAttributes() => baseTp.GetAttributes();
public override int GetHashCode() public override int GetHashCode()
{ {

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

@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.newOwner = newOwner; this.newOwner = newOwner;
} }
IReadOnlyList<IAttribute> IParameter.Attributes => baseParameter.Attributes; IEnumerable<IAttribute> IParameter.GetAttributes() => baseParameter.GetAttributes();
bool IParameter.IsRef => baseParameter.IsRef; bool IParameter.IsRef => baseParameter.IsRef;
bool IParameter.IsOut => baseParameter.IsOut; bool IParameter.IsOut => baseParameter.IsOut;
bool IParameter.IsParams => baseParameter.IsParams; bool IParameter.IsParams => baseParameter.IsParams;

43
ICSharpCode.Decompiler/TypeSystem/InheritanceHelper.cs

@ -29,7 +29,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{ {
// TODO: maybe these should be extension methods? // TODO: maybe these should be extension methods?
// or even part of the interface itself? (would allow for easy caching) // or even part of the interface itself? (would allow for easy caching)
#region GetBaseMember #region GetBaseMember
/// <summary> /// <summary>
/// Gets the base member that has the same signature. /// Gets the base member that has the same signature.
@ -58,16 +58,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
yield return member; yield return member;
}*/ }*/
} }
// Remove generic specialization // Remove generic specialization
var substitution = member.Substitution; var substitution = member.Substitution;
member = member.MemberDefinition; member = member.MemberDefinition;
if (member.DeclaringTypeDefinition == null) { if (member.DeclaringTypeDefinition == null) {
// For global methods, return empty list. (prevent SharpDevelop UDC crash 4524) // For global methods, return empty list. (prevent SharpDevelop UDC crash 4524)
yield break; yield break;
} }
IEnumerable<IType> allBaseTypes; IEnumerable<IType> allBaseTypes;
if (includeImplementedInterfaces) { if (includeImplementedInterfaces) {
allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes(); allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes();
@ -93,7 +93,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
#endregion #endregion
#region GetDerivedMember #region GetDerivedMember
/// <summary> /// <summary>
/// Finds the member declared in 'derivedType' that has the same signature (could override) 'baseMember'. /// 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"); throw new ArgumentNullException("baseMember");
if (derivedType == null) if (derivedType == null)
throw new ArgumentNullException("derivedType"); throw new ArgumentNullException("derivedType");
if (baseMember.Compilation != derivedType.Compilation) if (baseMember.Compilation != derivedType.Compilation)
throw new ArgumentException("baseMember and derivedType must be from the same compilation"); throw new ArgumentException("baseMember and derivedType must be from the same compilation");
baseMember = baseMember.MemberDefinition; baseMember = baseMember.MemberDefinition;
bool includeInterfaces = baseMember.DeclaringTypeDefinition.Kind == TypeKind.Interface; bool includeInterfaces = baseMember.DeclaringTypeDefinition.Kind == TypeKind.Interface;
IMethod method = baseMember as IMethod; IMethod method = baseMember as IMethod;
@ -147,5 +147,34 @@ namespace ICSharpCode.Decompiler.TypeSystem
return null; return null;
} }
#endregion #endregion
#region Attributes
internal static IEnumerable<IAttribute> 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<IAttribute> GetAttributes(IMember member)
{
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;
}
foreach (var attr in member.GetAttributes()) {
yield return attr;
}
} while (member.IsOverride && (member = InheritanceHelper.GetBaseMember(member)) != null);
}
#endregion
} }
} }

173
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -420,181 +420,70 @@ namespace ICSharpCode.Decompiler.TypeSystem
return null; return null;
} }
#endregion #endregion
#region ITypeReference.Resolve(ICompilation)
/// <summary>
/// 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.
/// </summary>
/// <returns>
/// Returns the resolved type.
/// In case of an error, returns <see cref="SpecialType.UnknownType"/>.
/// Never returns null.
/// </returns>
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
/// <summary> /// <summary>
/// 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).
/// </summary> /// </summary>
/// <param name="entity">The entity on which the attributes are declared.</param> /// <param name="entity">The entity on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param> /// <param name="attributeType">The attribute type to look for.</param>
/// <param name="inherit"> /// <param name="inherit">
/// Specifies whether attributes inherited from base classes and base members (if the given <paramref name="entity"/> in an <c>override</c>) /// Specifies whether attributes inherited from base classes and base members
/// should be returned. The default is <c>true</c>. /// (if the given <paramref name="entity"/> in an <c>override</c>)
/// should be returned.
/// </param> /// </param>
/// <returns> public static bool HasAttribute(this IEntity entity, KnownAttribute attrType, bool inherit=false)
/// Returns the attribute that was found; or <c>null</c> 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>
public static IAttribute GetAttribute(this IEntity entity, IType attributeType, bool inherit = true)
{ {
return GetAttributes(entity, attributeType, inherit).FirstOrDefault(); return GetAttribute(entity, attrType, inherit) != null;
} }
/// <summary>
/// Gets the attributes of the specified attribute type (or derived attribute types).
/// </summary>
/// <param name="entity">The entity on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param>
/// <param name="inherit">
/// Specifies whether attributes inherited from base classes and base members (if the given <paramref name="entity"/> in an <c>override</c>)
/// should be returned. The default is <c>true</c>.
/// </param>
/// <returns>
/// 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.
/// </returns>
public static IEnumerable<IAttribute> 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);
}
/// <summary> /// <summary>
/// Gets the attribute of the specified attribute type (or derived attribute types). /// Gets the attribute of the specified attribute type (or derived attribute types).
/// </summary> /// </summary>
/// <param name="entity">The entity on which the attributes are declared.</param> /// <param name="entity">The entity on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param> /// <param name="attributeType">The attribute type to look for.</param>
/// <param name="inherit"> /// <param name="inherit">
/// Specifies whether attributes inherited from base classes and base members (if the given <paramref name="entity"/> in an <c>override</c>) /// Specifies whether attributes inherited from base classes and base members
/// should be returned. The default is <c>true</c>. /// (if the given <paramref name="entity"/> in an <c>override</c>)
/// should be returned.
/// </param> /// </param>
/// <returns> /// <returns>
/// Returns the attribute that was found; or <c>null</c> if none was found. /// Returns the attribute that was found; or <c>null</c> if none was found.
/// If inherit is true, an from the entity itself will be returned if possible; /// If inherit is true, an from the entity itself will be returned if possible;
/// and the base entity will only be searched if none exists. /// and the base entity will only be searched if none exists.
/// </returns> /// </returns>
public static IAttribute GetAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit = true) public static IAttribute GetAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit=false)
{
return GetAttributes(entity, attributeType, inherit).FirstOrDefault();
}
/// <summary>
/// Gets the attributes of the specified attribute type (or derived attribute types).
/// </summary>
/// <param name="entity">The entity on which the attributes are declared.</param>
/// <param name="attributeType">The attribute type to look for.</param>
/// <param name="inherit">
/// Specifies whether attributes inherited from base classes and base members (if the given <paramref name="entity"/> in an <c>override</c>)
/// should be returned. The default is <c>true</c>.
/// </param>
/// <returns>
/// 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.
/// </returns>
public static IEnumerable<IAttribute> GetAttributes(this IEntity entity, KnownAttribute attributeType, bool inherit = true)
{ {
if (entity == null) return GetAttributes(entity, inherit).FirstOrDefault(a => a.AttributeType.IsKnownType(attributeType));
throw new ArgumentNullException("entity");
return GetAttributes(entity, attrType => {
ITypeDefinition typeDef = attrType.GetDefinition();
return typeDef != null && typeDef.FullTypeName == attributeType.GetTypeName();
}, inherit);
} }
/// <summary> /// <summary>
/// Gets the attribute of the specified attribute type (or derived attribute types). /// Gets the attributes on the entity.
/// </summary> /// </summary>
/// <param name="entity">The entity on which the attributes are declared.</param> /// <param name="entity">The entity on which the attributes are declared.</param>
/// <param name="inherit"> /// <param name="inherit">
/// Specifies whether attributes inherited from base classes and base members (if the given <paramref name="entity"/> in an <c>override</c>) /// Specifies whether attributes inherited from base classes and base members
/// should be returned. The default is <c>true</c>. /// (if the given <paramref name="entity"/> in an <c>override</c>)
/// should be returned.
/// </param> /// </param>
/// <returns> /// <returns>
/// Returns the attribute that was found; or <c>null</c> if none was found. /// Returns the list of attributes that were found.
/// If inherit is true, an from the entity itself will be returned if possible; /// If inherit is true, attributes from the entity itself are returned first;
/// and the base entity will only be searched if none exists. /// followed by attributes inherited from the base entity.
/// </returns> /// </returns>
public static IEnumerable<IAttribute> GetAttributes(this IEntity entity, bool inherit = true) public static IEnumerable<IAttribute> GetAttributes(this IEntity entity, bool inherit)
{ {
if (entity == null) if (inherit) {
throw new ArgumentNullException ("entity"); if (entity is ITypeDefinition td) {
return GetAttributes(entity, a => true, inherit); return InheritanceHelper.GetAttributes(td);
} } else if (entity is IMember m) {
return InheritanceHelper.GetAttributes(m);
static IEnumerable<IAttribute> GetAttributes(IEntity entity, Predicate<IType> attributeTypePredicate, bool inherit) } else {
{ throw new NotSupportedException("Unknown entity type");
if (!inherit) {
foreach (var attr in entity.Attributes) {
if (attributeTypePredicate(attr.AttributeType))
yield return attr;
} }
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<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;
}
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 #endregion

11
ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs

@ -109,10 +109,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
baseMethod.Specialize(substitution), baseMethod.Specialize(substitution),
parameters.Skip(baseMethod.Parameters.Count - 1).Select(p => p.Type.AcceptVisitor(substitution)).ToList()); parameters.Skip(baseMethod.Parameters.Count - 1).Select(p => p.Type.AcceptVisitor(substitution)).ToList());
} }
public IReadOnlyList<IAttribute> ReturnTypeAttributes { IEnumerable<IAttribute> IEntity.GetAttributes() => baseMethod.GetAttributes();
get { return baseMethod.ReturnTypeAttributes; } IEnumerable<IAttribute> IMethod.GetReturnTypeAttributes() => baseMethod.GetReturnTypeAttributes();
}
public IReadOnlyList<ITypeParameter> TypeParameters { public IReadOnlyList<ITypeParameter> TypeParameters {
get { return baseMethod.TypeParameters; } get { return baseMethod.TypeParameters; }
@ -225,10 +224,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return baseMethod.ParentAssembly; } get { return baseMethod.ParentAssembly; }
} }
public IReadOnlyList<IAttribute> Attributes {
get { return baseMethod.Attributes; }
}
public bool IsStatic { public bool IsStatic {
get { return baseMethod.IsStatic; } get { return baseMethod.IsStatic; }
} }

Loading…
Cancel
Save