Browse Source

Implement MetadataEvent and re-work the representation of attribute arguments.

pull/1198/head
Daniel Grunwald 7 years ago
parent
commit
ee3012281d
  1. 164
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  2. 53
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 26
      ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
  4. 12
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  5. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  6. 34
      ICSharpCode.Decompiler/Metadata/Dom.cs
  7. 100
      ICSharpCode.Decompiler/Metadata/MethodSemanticsLookup.cs
  8. 7
      ICSharpCode.Decompiler/SRMExtensions.cs
  9. 2
      ICSharpCode.Decompiler/SRMHacks.cs
  10. 2
      ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
  11. 16
      ICSharpCode.Decompiler/TypeSystem/ComHelper.cs
  12. 4
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  13. 6
      ICSharpCode.Decompiler/TypeSystem/IAttribute.cs
  14. 155
      ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
  15. 69
      ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs
  16. 43
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs
  17. 9
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedEvent.cs
  18. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  19. 37
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs
  20. 48
      ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
  21. 147
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataEvent.cs
  22. 60
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  23. 15
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
  24. 23
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs
  25. 41
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
  26. 34
      ICSharpCode.Decompiler/TypeSystem/Implementation/ResolvedAttributeBlob.cs
  27. 13
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedEvent.cs
  28. 3
      ICSharpCode.Decompiler/TypeSystem/Implementation/UnresolvedSecurityDeclarationBlob.cs
  29. 93
      ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs
  30. 10
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

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

@ -18,8 +18,10 @@ @@ -18,8 +18,10 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -32,6 +34,8 @@ using NUnit.Framework; @@ -32,6 +34,8 @@ using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.TypeSystem
{
using AttributeArray = ImmutableArray<CustomAttributeTypedArgument<IType>>;
[TestFixture]
public class TypeSystemLoaderTests
{
@ -87,7 +91,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -87,7 +91,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(c.IsAbstract);
Assert.IsFalse(c.IsSealed);
Assert.IsFalse(c.IsStatic);
Assert.IsFalse(c.IsShadowing);
//Assert.IsFalse(c.IsShadowing);
}
[Test]
@ -158,17 +162,16 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -158,17 +162,16 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{
var attributes = compilation.MainAssembly.AssemblyAttributes;
var typeTest = attributes.Single(a => a.AttributeType.FullName == typeof(TypeTestAttribute).FullName);
Assert.AreEqual(3, typeTest.PositionalArguments.Count);
Assert.AreEqual(3, typeTest.FixedArguments.Length);
// first argument is (int)42
Assert.AreEqual(42, (int)typeTest.PositionalArguments[0].ConstantValue);
Assert.AreEqual(42, (int)typeTest.FixedArguments[0].Value);
// second argument is typeof(System.Action<>)
TypeOfResolveResult rt = (TypeOfResolveResult)typeTest.PositionalArguments[1];
Assert.IsFalse(rt.ReferencedType is ParameterizedType); // rt must not be constructed - it's just an unbound type
Assert.AreEqual("System.Action", rt.ReferencedType.FullName);
Assert.AreEqual(1, rt.ReferencedType.TypeParameterCount);
var ty = (IType)typeTest.FixedArguments[1].Value;
Assert.IsFalse(ty is ParameterizedType); // rt must not be constructed - it's just an unbound type
Assert.AreEqual("System.Action", ty.FullName);
Assert.AreEqual(1, ty.TypeParameterCount);
// third argument is typeof(IDictionary<string, IList<TestAttribute>>)
rt = (TypeOfResolveResult)typeTest.PositionalArguments[2];
ParameterizedType crt = (ParameterizedType)rt.ReferencedType;
var crt = (ParameterizedType)typeTest.FixedArguments[2].Value;
Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName);
Assert.AreEqual("System.String", crt.TypeArguments[0].FullName);
// we know the name for TestAttribute, but not necessarily the namespace, as NUnit is not in the compilation
@ -185,9 +188,9 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -185,9 +188,9 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{
var attributes = compilation.MainAssembly.AssemblyAttributes;
var forwardAttribute = attributes.Single(a => a.AttributeType.FullName == typeof(TypeForwardedToAttribute).FullName);
Assert.AreEqual(1, forwardAttribute.PositionalArguments.Count);
TypeOfResolveResult rt = (TypeOfResolveResult)forwardAttribute.PositionalArguments[0];
Assert.AreEqual("System.Func`2", rt.ReferencedType.ReflectionName);
Assert.AreEqual(1, forwardAttribute.FixedArguments.Length);
var rt = (IType)forwardAttribute.FixedArguments[0].Value;
Assert.AreEqual("System.Func`2", rt.ReflectionName);
}
[Test]
@ -564,19 +567,19 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -564,19 +567,19 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{
IAttribute attr = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Attributes.Single();
Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.FullName);
ResolveResult arg1 = attr.PositionalArguments.Single();
var arg1 = attr.FixedArguments.Single();
Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.Type.FullName);
Assert.AreEqual((int)LayoutKind.Explicit, arg1.ConstantValue);
Assert.AreEqual((int)LayoutKind.Explicit, arg1.Value);
var arg2 = attr.NamedArguments[0];
Assert.AreEqual("CharSet", arg2.Key.Name);
Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Value.Type.FullName);
Assert.AreEqual((int)CharSet.Unicode, arg2.Value.ConstantValue);
Assert.AreEqual("CharSet", arg2.Name);
Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Type.FullName);
Assert.AreEqual((int)CharSet.Unicode, arg2.Value);
var arg3 = attr.NamedArguments[1];
Assert.AreEqual("Pack", arg3.Key.Name);
Assert.AreEqual("System.Int32", arg3.Value.Type.FullName);
Assert.AreEqual(8, arg3.Value.ConstantValue);
Assert.AreEqual("Pack", arg3.Name);
Assert.AreEqual("System.Int32", arg3.Type.FullName);
Assert.AreEqual(8, arg3.Value);
}
[Test]
@ -584,15 +587,15 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -584,15 +587,15 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{
IField field = GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0");
Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.FullName);
ResolveResult arg = field.Attributes.Single().PositionalArguments.Single();
var arg = field.Attributes.Single().FixedArguments.Single();
Assert.AreEqual("System.Int32", arg.Type.FullName);
Assert.AreEqual(0, arg.ConstantValue);
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().PositionalArguments.Single();
arg = field.Attributes.Single().FixedArguments.Single();
Assert.AreEqual("System.Int32", arg.Type.FullName);
Assert.AreEqual(100, arg.ConstantValue);
Assert.AreEqual(100, arg.Value);
}
[Test]
@ -601,8 +604,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -601,8 +604,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IAttribute dllImport = method.Attributes.Single();
Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.FullName);
Assert.AreEqual("unmanaged.dll", dllImport.PositionalArguments[0].ConstantValue);
Assert.AreEqual((int)CharSet.Unicode, dllImport.NamedArguments.Single().Value.ConstantValue);
Assert.AreEqual("unmanaged.dll", dllImport.FixedArguments[0].Value);
Assert.AreEqual((int)CharSet.Unicode, dllImport.NamedArguments.Single().Value);
}
[Test]
@ -621,7 +624,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -621,7 +624,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
{
IMethod method = GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod");
IAttribute marshalAs = method.ReturnTypeAttributes.Single();
Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.PositionalArguments.Single().ConstantValue);
Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.FixedArguments.Single().Value);
}
[Test]
@ -887,65 +890,52 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -887,65 +890,52 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.AreEqual("ICSharpCode.Decompiler.Tests.TypeSystem.OuterGeneric`1[[`0]]", p.Type.ReflectionName);
}
ResolveResult GetParamsAttributeArgument(int index)
CustomAttributeTypedArgument<IType> GetParamsAttributeArgument(int index)
{
ITypeDefinition type = GetTypeDefinition(typeof(ParamsAttribute));
var arr = (ArrayCreateResolveResult)type.Attributes.Single().PositionalArguments.Single();
Assert.AreEqual(5, arr.InitializerElements.Count);
Assert.AreEqual(1, arr.SizeArguments.Count);
Assert.AreEqual(5, arr.SizeArguments[0].ConstantValue);
return arr.InitializerElements[index];
}
ResolveResult Unbox(ResolveResult resolveResult)
{
ConversionResolveResult crr = (ConversionResolveResult)resolveResult;
Assert.AreEqual(TypeKind.Class, crr.Type.Kind);
Assert.AreEqual("System.Object", crr.Type.FullName);
Assert.AreEqual(Conversion.BoxingConversion, crr.Conversion);
return crr.Input;
var arr = (AttributeArray)type.Attributes.Single().FixedArguments.Single().Value;
Assert.AreEqual(5, arr.Length);
return arr[index];
}
[Test]
public void ParamsAttribute_Integer()
{
ResolveResult rr = Unbox(GetParamsAttributeArgument(0));
Assert.AreEqual("System.Int32", rr.Type.FullName);
Assert.AreEqual(1, rr.ConstantValue);
var arg = GetParamsAttributeArgument(0);
Assert.AreEqual("System.Int32", arg.Type.FullName);
Assert.AreEqual(1, arg.Value);
}
[Test]
public void ParamsAttribute_Enum()
{
ResolveResult rr = Unbox(GetParamsAttributeArgument(1));
Assert.AreEqual("System.StringComparison", rr.Type.FullName);
Assert.AreEqual((int)StringComparison.CurrentCulture, rr.ConstantValue);
var arg = GetParamsAttributeArgument(1);
Assert.AreEqual("System.StringComparison", arg.Type.FullName);
Assert.AreEqual((int)StringComparison.CurrentCulture, arg.Value);
}
[Test]
public void ParamsAttribute_NullReference()
{
ResolveResult rr = GetParamsAttributeArgument(2);
Assert.AreEqual("System.Object", rr.Type.FullName);
Assert.IsTrue(rr.IsCompileTimeConstant);
Assert.IsNull(rr.ConstantValue);
var arg = GetParamsAttributeArgument(2);
//Assert.AreEqual("System.Object", arg.Type.FullName);
Assert.IsNull(arg.Value);
}
[Test]
public void ParamsAttribute_Double()
{
ResolveResult rr = Unbox(GetParamsAttributeArgument(3));
Assert.AreEqual("System.Double", rr.Type.FullName);
Assert.AreEqual(4.0, rr.ConstantValue);
var arg = GetParamsAttributeArgument(3);
Assert.AreEqual("System.Double", arg.Type.FullName);
Assert.AreEqual(4.0, arg.Value);
}
[Test]
public void ParamsAttribute_String()
{
ConversionResolveResult rr = (ConversionResolveResult)GetParamsAttributeArgument(4);
Assert.AreEqual("System.Object", rr.Type.FullName);
Assert.AreEqual("System.String", rr.Input.Type.FullName);
Assert.AreEqual("Test", rr.Input.ConstantValue);
var arg = GetParamsAttributeArgument(4);
Assert.AreEqual("System.String", arg.Type.FullName);
Assert.AreEqual("Test", arg.Value);
}
[Test]
@ -956,13 +946,13 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -956,13 +946,13 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
var attr = prop.Attributes.Single();
Assert.AreEqual(type, attr.AttributeType);
var normalArguments = ((ArrayCreateResolveResult)attr.PositionalArguments.Single()).InitializerElements;
Assert.AreEqual(0, normalArguments.Count);
var elements = (AttributeArray)attr.FixedArguments.Single().Value;
Assert.AreEqual(0, elements.Length);
var namedArg = attr.NamedArguments.Single();
Assert.AreEqual(prop, namedArg.Key);
var arrayElements = ((ArrayCreateResolveResult)namedArg.Value).InitializerElements;
Assert.AreEqual(2, arrayElements.Count);
Assert.AreEqual(prop.Name, namedArg.Name);
var arrayElements = (AttributeArray)namedArg.Value;
Assert.AreEqual(2, arrayElements.Length);
}
[Test]
@ -978,9 +968,9 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -978,9 +968,9 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void DoubleAttribute_ImplicitNumericConversion()
{
ITypeDefinition type = GetTypeDefinition(typeof(DoubleAttribute));
var arg = type.Attributes.Single().PositionalArguments.ElementAt(0);
var arg = type.Attributes.Single().FixedArguments.Single();
Assert.AreEqual("System.Double", arg.Type.ReflectionName);
Assert.AreEqual(1.0, arg.ConstantValue);
Assert.AreEqual(1.0, arg.Value);
}
[Test, Ignore("interface impls need redesign")]
@ -1488,25 +1478,22 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -1488,25 +1478,22 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
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");
Assert.AreEqual(42, typeTypeTestAttr.PositionalArguments[0].ConstantValue);
Assert.IsInstanceOf<TypeOfResolveResult>(typeTypeTestAttr.PositionalArguments[1]);
Assert.AreEqual(inner, ((TypeOfResolveResult)typeTypeTestAttr.PositionalArguments[1]).ReferencedType);
Assert.AreEqual(42, typeTypeTestAttr.FixedArguments[0].Value);
Assert.AreEqual(inner, typeTypeTestAttr.FixedArguments[1].Value);
var typeMyAttr = type.Attributes.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");
Assert.AreEqual(42, propTypeTestAttr.PositionalArguments[0].ConstantValue);
Assert.IsInstanceOf<TypeOfResolveResult>(propTypeTestAttr.PositionalArguments[1]);
Assert.AreEqual(inner, ((TypeOfResolveResult)propTypeTestAttr.PositionalArguments[1]).ReferencedType);
Assert.AreEqual(42, propTypeTestAttr.FixedArguments[0].Value);
Assert.AreEqual(inner, propTypeTestAttr.FixedArguments[1].Value);
var propMyAttr = prop.Attributes.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");
Assert.AreEqual(42, innerTypeTestAttr.PositionalArguments[0].ConstantValue);
Assert.IsInstanceOf<TypeOfResolveResult>(innerTypeTestAttr.PositionalArguments[1]);
Assert.AreEqual(inner, ((TypeOfResolveResult)innerTypeTestAttr.PositionalArguments[1]).ReferencedType);
Assert.AreEqual(42, innerTypeTestAttr.FixedArguments[0].Value);
Assert.AreEqual(inner, innerTypeTestAttr.FixedArguments[1].Value);
var innerMyAttr = attributedInner.Attributes.Single(a => a.AttributeType.Name == "MyAttribute");
Assert.AreEqual(myAttribute, innerMyAttr.AttributeType);
@ -1514,9 +1501,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -1514,9 +1501,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
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");
Assert.AreEqual(43, inner2TypeTestAttr.PositionalArguments[0].ConstantValue);
Assert.IsInstanceOf<TypeOfResolveResult>(inner2TypeTestAttr.PositionalArguments[1]);
Assert.AreEqual(inner2, ((TypeOfResolveResult)inner2TypeTestAttr.PositionalArguments[1]).ReferencedType);
Assert.AreEqual(43, inner2TypeTestAttr.FixedArguments[0].Value);
Assert.AreEqual(inner2, inner2TypeTestAttr.FixedArguments[1].Value);
var inner2MyAttr = attributedInner2.Attributes.Single(a => a.AttributeType.Name == "MyAttribute");
Assert.AreEqual(myAttribute2, inner2MyAttr.AttributeType);
}
@ -1633,8 +1619,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -1633,8 +1619,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition();
var attr = c.Attributes.Single(a => a.AttributeType.FullName == "System.SerializableAttribute");
Assert.AreEqual(0, attr.Constructor.Parameters.Count);
Assert.AreEqual(0, attr.PositionalArguments.Count);
Assert.AreEqual(0, attr.NamedArguments.Count);
Assert.AreEqual(0, attr.FixedArguments.Length);
Assert.AreEqual(0, attr.NamedArguments.Length);
}
[Test]
@ -1643,11 +1629,11 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -1643,11 +1629,11 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition();
var attr = c.Attributes.Single(a => a.AttributeType.FullName == "System.Runtime.InteropServices.StructLayoutAttribute");
Assert.AreEqual(1, attr.Constructor.Parameters.Count);
Assert.AreEqual(1, attr.PositionalArguments.Count);
Assert.AreEqual(0, attr.PositionalArguments[0].ConstantValue);
Assert.AreEqual(1, attr.NamedArguments.Count);
Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute.Size", attr.NamedArguments[0].Key.FullName);
Assert.AreEqual(1, attr.NamedArguments[0].Value.ConstantValue);
Assert.AreEqual(1, attr.FixedArguments.Length);
Assert.AreEqual(0, attr.FixedArguments[0].Value);
Assert.AreEqual(1, attr.NamedArguments.Length);
Assert.AreEqual("Size", attr.NamedArguments[0].Name);
Assert.AreEqual(1, attr.NamedArguments[0].Value);
}
[Test]
@ -1656,9 +1642,9 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -1656,9 +1642,9 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
ITypeDefinition c = compilation.FindType(typeof(void)).GetDefinition();
var attr = c.Attributes.Single(a => a.AttributeType.FullName == "System.Runtime.InteropServices.ComVisibleAttribute");
Assert.AreEqual(1, attr.Constructor.Parameters.Count);
Assert.AreEqual(1, attr.PositionalArguments.Count);
Assert.AreEqual(true, attr.PositionalArguments[0].ConstantValue);
Assert.AreEqual(0, attr.NamedArguments.Count);
Assert.AreEqual(1, attr.FixedArguments.Length);
Assert.AreEqual(true, attr.FixedArguments[0].Value);
Assert.AreEqual(0, attr.NamedArguments.Length);
}
[Test]

53
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -371,18 +371,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -371,18 +371,17 @@ namespace ICSharpCode.Decompiler.CSharp
void DoDecompileModuleAndAssemblyAttributes(DecompileRun decompileRun, ITypeResolveContext decompilationContext, SyntaxTree syntaxTree)
{
foreach (var a in typeSystem.Compilation.MainAssembly.AssemblyAttributes) {
decompileRun.Namespaces.Add(a.AttributeType.Namespace);
if (a.AttributeType.FullName == typeof(System.Runtime.CompilerServices.TypeForwardedToAttribute).FullName) {
decompileRun.Namespaces.Add(((TypeOfResolveResult)a.PositionalArguments[0]).ReferencedType.Namespace);
} else {
decompileRun.Namespaces.AddRange(a.PositionalArguments.Select(pa => pa.Type.Namespace));
decompileRun.Namespaces.AddRange(a.NamedArguments.Select(na => na.Value.Type.Namespace));
}
var astBuilder = CreateAstBuilder(decompilationContext);
var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a));
attrSection.AttributeTarget = "assembly";
syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole);
}
foreach (var a in typeSystem.Compilation.MainAssembly.ModuleAttributes) {
var astBuilder = CreateAstBuilder(decompilationContext);
var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a));
attrSection.AttributeTarget = "module";
syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole);
}
}
void DoDecompileTypes(IEnumerable<TypeDefinitionHandle> types, DecompileRun decompileRun, ITypeResolveContext decompilationContext, SyntaxTree syntaxTree)
@ -738,16 +737,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -738,16 +737,16 @@ namespace ICSharpCode.Decompiler.CSharp
}
if (typeDecl.Members.OfType<IndexerDeclaration>().Any(idx => idx.PrivateImplementationType.IsNull)) {
// Remove the [DefaultMember] attribute if the class contains indexers
RemoveAttribute(typeDecl, new TopLevelTypeName("System.Reflection", "DefaultMemberAttribute"));
RemoveAttribute(typeDecl, KnownAttribute.DefaultMember);
}
if (settings.IntroduceRefAndReadonlyModifiersOnStructs && typeDecl.ClassType == ClassType.Struct) {
if (RemoveAttribute(typeDecl, new TopLevelTypeName("System.Runtime.CompilerServices", "IsByRefLikeAttribute"))) {
if (RemoveAttribute(typeDecl, KnownAttribute.IsByRefLike)) {
typeDecl.Modifiers |= Modifiers.Ref;
}
if (RemoveAttribute(typeDecl, new TopLevelTypeName("System.Runtime.CompilerServices", "IsReadOnlyAttribute"))) {
if (RemoveAttribute(typeDecl, KnownAttribute.IsReadOnly)) {
typeDecl.Modifiers |= Modifiers.Readonly;
}
if (FindAttribute(typeDecl, new TopLevelTypeName("System", "ObsoleteAttribute"), out var attr)) {
if (FindAttribute(typeDecl, KnownAttribute.Obsolete, out var attr)) {
if (obsoleteAttributePattern.IsMatch(attr)) {
if (attr.Parent is Syntax.AttributeSection section && section.Attributes.Count == 1)
section.Remove();
@ -880,28 +879,28 @@ namespace ICSharpCode.Decompiler.CSharp @@ -880,28 +879,28 @@ namespace ICSharpCode.Decompiler.CSharp
if (!body.Descendants.Any(d => d is YieldReturnStatement || d is YieldBreakStatement)) {
body.Add(new YieldBreakStatement());
}
RemoveAttribute(entityDecl, new TopLevelTypeName("System.Runtime.CompilerServices", "IteratorStateMachineAttribute"));
RemoveAttribute(entityDecl, KnownAttribute.IteratorStateMachine);
if (function.StateMachineCompiledWithMono) {
RemoveAttribute(entityDecl, new TopLevelTypeName("System.Diagnostics", "DebuggerHiddenAttribute"));
RemoveAttribute(entityDecl, KnownAttribute.DebuggerHidden);
}
}
if (function.IsAsync) {
entityDecl.Modifiers |= Modifiers.Async;
RemoveAttribute(entityDecl, new TopLevelTypeName("System.Runtime.CompilerServices", "AsyncStateMachineAttribute"));
RemoveAttribute(entityDecl, new TopLevelTypeName("System.Diagnostics", "DebuggerStepThroughAttribute"));
RemoveAttribute(entityDecl, KnownAttribute.AsyncStateMachine);
RemoveAttribute(entityDecl, KnownAttribute.DebuggerStepThrough);
}
} catch (Exception innerException) when (!(innerException is OperationCanceledException)) {
throw new DecompilerException(typeSystem.ModuleDefinition, (MethodDefinitionHandle)method.MetadataToken, innerException);
}
}
bool RemoveAttribute(EntityDeclaration entityDecl, FullTypeName attrName)
bool RemoveAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType)
{
bool found = false;
foreach (var section in entityDecl.Attributes) {
foreach (var attr in section.Attributes) {
var symbol = attr.Type.GetSymbol();
if (symbol is ITypeDefinition td && td.FullTypeName == attrName) {
if (symbol is ITypeDefinition td && td.FullTypeName == attributeType.GetTypeName()) {
attr.Remove();
found = true;
}
@ -913,13 +912,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -913,13 +912,13 @@ namespace ICSharpCode.Decompiler.CSharp
return found;
}
bool FindAttribute(EntityDeclaration entityDecl, FullTypeName attrName, out Syntax.Attribute attribute)
bool FindAttribute(EntityDeclaration entityDecl, KnownAttribute attributeType, out Syntax.Attribute attribute)
{
attribute = null;
foreach (var section in entityDecl.Attributes) {
foreach (var attr in section.Attributes) {
var symbol = attr.Type.GetSymbol();
if (symbol is ITypeDefinition td && td.FullTypeName == attrName) {
if (symbol is ITypeDefinition td && td.FullTypeName == attributeType.GetTypeName()) {
attribute = attr;
return true;
}
@ -931,8 +930,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -931,8 +930,8 @@ namespace ICSharpCode.Decompiler.CSharp
void AddDefinesForConditionalAttributes(ILFunction function, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{
foreach (var call in function.Descendants.OfType<CallInstruction>()) {
var attr = call.Method.GetAttribute(new TopLevelTypeName("System.Diagnostics", nameof(ConditionalAttribute)));
var symbolName = attr?.PositionalArguments.FirstOrDefault()?.ConstantValue as string;
var attr = call.Method.GetAttribute(KnownAttribute.Conditional);
var symbolName = attr?.FixedArguments.FirstOrDefault().Value as string;
if (symbolName == null || !decompileRun.DefinedSymbols.Add(symbolName))
continue;
syntaxTree.InsertChildAfter(null, new PreProcessorDirective(PreProcessorDirectiveType.Define, symbolName), Roles.PreProcessorDirective);
@ -977,7 +976,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -977,7 +976,7 @@ namespace ICSharpCode.Decompiler.CSharp
fixedFieldDecl.Variables.Add(new FixedVariableInitializer(field.Name, new PrimitiveExpression(elementCount)));
fixedFieldDecl.Variables.Single().CopyAnnotationsFrom(((FieldDeclaration)fieldDecl).Variables.Single());
fixedFieldDecl.CopyAnnotationsFrom(fieldDecl);
RemoveAttribute(fixedFieldDecl, fixedBufferAttributeTypeName);
RemoveAttribute(fixedFieldDecl, KnownAttribute.FixedBuffer);
return fixedFieldDecl;
}
var fieldDefinition = typeSystem.GetMetadata().GetFieldDefinition((FieldDefinitionHandle)field.MetadataToken);
@ -992,16 +991,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -992,16 +991,14 @@ namespace ICSharpCode.Decompiler.CSharp
return fieldDecl;
}
static readonly FullTypeName fixedBufferAttributeTypeName = new TopLevelTypeName("System.Runtime.CompilerServices", "FixedBufferAttribute");
internal static bool IsFixedField(IField field, out IType type, out int elementCount)
{
type = null;
elementCount = 0;
IAttribute attr = field.GetAttribute(fixedBufferAttributeTypeName, inherit: false);
if (attr != null && attr.PositionalArguments.Count == 2) {
if (attr.PositionalArguments[0] is TypeOfResolveResult trr && attr.PositionalArguments[1].ConstantValue is int length) {
type = trr.ReferencedType;
IAttribute attr = field.GetAttribute(KnownAttribute.FixedBuffer, inherit: false);
if (attr != null && attr.FixedArguments.Length == 2) {
if (attr.FixedArguments[0].Value is IType trr && attr.FixedArguments[1].Value is int length) {
type = trr;
elementCount = length;
return true;
}

26
ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs

@ -24,6 +24,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -24,6 +24,8 @@ namespace ICSharpCode.Decompiler.CSharp
foreach (var type in typeSystem.MainAssembly.TypeDefinitions) {
CollectNamespaces(type, typeSystem, namespaces);
}
HandleAttributes(typeSystem.MainAssembly.AssemblyAttributes, namespaces);
HandleAttributes(typeSystem.MainAssembly.ModuleAttributes, namespaces);
}
public static void CollectNamespaces(IEntity entity, DecompilerTypeSystem typeSystem, HashSet<string> namespaces, bool scanningFullType = false)
@ -138,19 +140,27 @@ namespace ICSharpCode.Decompiler.CSharp @@ -138,19 +140,27 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
static void HandleAttributes(IEnumerable<IAttribute> attributes, HashSet<string> namespaces)
public static void HandleAttributes(IEnumerable<IAttribute> attributes, HashSet<string> namespaces)
{
foreach (var attr in attributes) {
namespaces.Add(attr.AttributeType.Namespace);
foreach (var arg in attr.PositionalArguments) {
namespaces.Add(arg.Type.Namespace);
if (arg is TypeOfResolveResult torr)
namespaces.Add(torr.ReferencedType.Namespace);
foreach (var arg in attr.FixedArguments) {
HandleAttributeValue(arg.Type, arg.Value, namespaces);
}
foreach (var arg in attr.NamedArguments) {
namespaces.Add(arg.Value.Type.Namespace);
if (arg.Value is TypeOfResolveResult torr)
namespaces.Add(torr.ReferencedType.Namespace);
HandleAttributeValue(arg.Type, arg.Value, namespaces);
}
}
}
static void HandleAttributeValue(IType type, object value, HashSet<string> namespaces)
{
CollectNamespacesForTypeReference(type, namespaces);
if (value is IType typeofType)
CollectNamespacesForTypeReference(typeofType, namespaces);
if (value is ImmutableArray<CustomAttributeTypedArgument<IType>> arr) {
foreach (var element in arr) {
HandleAttributeValue(element.Type, element.Value, namespaces);
}
}
}

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

@ -434,15 +434,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -434,15 +434,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} else if (mt != null && mt.MemberName.EndsWith("Attribute", StringComparison.Ordinal)) {
mt.MemberName = mt.MemberName.Substring(0, mt.MemberName.Length - 9);
}
foreach (ResolveResult arg in attribute.PositionalArguments) {
attr.Arguments.Add(ConvertConstantValue(arg));
foreach (var arg in attribute.FixedArguments) {
attr.Arguments.Add(ConvertConstantValue(arg.Type, arg.Value));
}
if (attribute.NamedArguments.Count > 0) {
if (attribute.NamedArguments.Length > 0) {
InitializedObjectResolveResult targetResult = new InitializedObjectResolveResult(attribute.AttributeType);
foreach (var pair in attribute.NamedArguments) {
NamedExpression namedArgument = new NamedExpression(pair.Key.Name, ConvertConstantValue(pair.Value));
foreach (var namedArg in attribute.NamedArguments) {
NamedExpression namedArgument = new NamedExpression(namedArg.Name, ConvertConstantValue(namedArg.Type, namedArg.Value));
if (AddResolveResultAnnotations) {
namedArgument.AddAnnotation(new MemberResolveResult(targetResult, pair.Key));
//namedArgument.AddAnnotation(new MemberResolveResult(targetResult, pair.Key));
}
attr.Arguments.Add(namedArgument);
}

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -292,6 +292,7 @@ @@ -292,6 +292,7 @@
<Compile Include="Metadata\LightJson\Serialization\JsonReader.cs" />
<Compile Include="Metadata\LightJson\Serialization\TextPosition.cs" />
<Compile Include="Metadata\LightJson\Serialization\TextScanner.cs" />
<Compile Include="Metadata\MethodSemanticsLookup.cs" />
<Compile Include="Metadata\OperandType.cs" />
<Compile Include="Metadata\SignatureBlobComparer.cs" />
<Compile Include="Metadata\UniversalAssemblyResolver.cs" />
@ -348,6 +349,7 @@ @@ -348,6 +349,7 @@
<Compile Include="TypeSystem\Implementation\MetadataMethod.cs" />
<Compile Include="TypeSystem\Implementation\MetadataNamespace.cs" />
<Compile Include="TypeSystem\Implementation\MetadataParameter.cs" />
<Compile Include="TypeSystem\Implementation\MetadataEvent.cs" />
<Compile Include="TypeSystem\Implementation\MetadataProperty.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeDefinition.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeParameter.cs" />

34
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -194,6 +194,40 @@ namespace ICSharpCode.Decompiler.Metadata @@ -194,6 +194,40 @@ namespace ICSharpCode.Decompiler.Metadata
return default;
}
Dictionary<FullTypeName, ExportedTypeHandle> typeForwarderLookup;
/// <summary>
/// Finds the type forwarder with the specified name.
/// </summary>
public ExportedTypeHandle GetTypeForwarder(FullTypeName typeName)
{
var lookup = LazyInit.VolatileRead(ref typeForwarderLookup);
if (lookup == null) {
lookup = new Dictionary<FullTypeName, ExportedTypeHandle>();
foreach (var handle in Metadata.ExportedTypes) {
var td = Metadata.GetExportedType(handle);
lookup[td.GetFullTypeName(Metadata)] = handle;
}
lookup = LazyInit.GetOrSet(ref typeForwarderLookup, lookup);
}
if (lookup.TryGetValue(typeName, out var resultHandle))
return resultHandle;
else
return default;
}
MethodSemanticsLookup methodSemanticsLookup;
internal MethodSemanticsLookup MethodSemanticsLookup {
get {
var r = LazyInit.VolatileRead(ref methodSemanticsLookup);
if (r != null)
return r;
else
return LazyInit.GetOrSet(ref methodSemanticsLookup, new MethodSemanticsLookup(Metadata));
}
}
IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
{
return new MetadataAssembly(context.Compilation, this, TypeSystemOptions.Default);

100
ICSharpCode.Decompiler/Metadata/MethodSemanticsLookup.cs

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
// Copyright (c) 2018 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Metadata
{
/// <summary>
/// Lookup structure that, for an accessor, can find the associated property/event.
/// </summary>
class MethodSemanticsLookup
{
const MethodSemanticsAttributes csharpAccessors =
MethodSemanticsAttributes.Getter | MethodSemanticsAttributes.Setter
| MethodSemanticsAttributes.Adder | MethodSemanticsAttributes.Remover;
readonly struct Entry : IComparable<Entry>
{
public readonly MethodSemanticsAttributes Semantics;
public readonly int MethodRowNumber;
public MethodDefinitionHandle Method => MetadataTokens.MethodDefinitionHandle(MethodRowNumber);
public readonly EntityHandle Association;
public Entry(MethodSemanticsAttributes semantics, MethodDefinitionHandle method, EntityHandle association)
{
Semantics = semantics;
MethodRowNumber = MetadataTokens.GetRowNumber(method);
Association = association;
}
public int CompareTo(Entry other)
{
return MethodRowNumber.CompareTo(other.MethodRowNumber);
}
}
// entries, sorted by MethodRowNumber
readonly List<Entry> entries;
public MethodSemanticsLookup(MetadataReader metadata, MethodSemanticsAttributes filter = csharpAccessors)
{
if ((filter & MethodSemanticsAttributes.Other) != 0) {
throw new NotSupportedException("SRM doesn't provide access to 'other' accessors");
}
entries = new List<Entry>(metadata.GetTableRowCount(TableIndex.MethodSemantics));
foreach (var propHandle in metadata.PropertyDefinitions) {
var prop = metadata.GetPropertyDefinition(propHandle);
var accessors = prop.GetAccessors();
AddEntry(MethodSemanticsAttributes.Getter, accessors.Getter, propHandle);
AddEntry(MethodSemanticsAttributes.Setter, accessors.Setter, propHandle);
}
foreach (var eventHandle in metadata.EventDefinitions) {
var ev = metadata.GetEventDefinition(eventHandle);
var accessors = ev.GetAccessors();
AddEntry(MethodSemanticsAttributes.Adder, accessors.Adder, eventHandle);
AddEntry(MethodSemanticsAttributes.Remover, accessors.Remover, eventHandle);
AddEntry(MethodSemanticsAttributes.Raiser, accessors.Raiser, eventHandle);
}
entries.Sort();
void AddEntry(MethodSemanticsAttributes semantics, MethodDefinitionHandle method, EntityHandle association)
{
if ((semantics & filter) == 0 || method.IsNil)
return;
entries.Add(new Entry(semantics, method, association));
}
}
public (EntityHandle, MethodSemanticsAttributes) GetSemantics(MethodDefinitionHandle method)
{
int pos = entries.BinarySearch(new Entry(0, method, default(EntityHandle)));
if (pos >= 0) {
return (entries[pos].Association, entries[pos].Semantics);
} else {
return (default(EntityHandle), 0);
}
}
}
}

7
ICSharpCode.Decompiler/SRMExtensions.cs

@ -227,6 +227,13 @@ namespace ICSharpCode.Decompiler @@ -227,6 +227,13 @@ namespace ICSharpCode.Decompiler
}
}
public static FullTypeName GetFullTypeName(this ExportedType type, MetadataReader metadata)
{
string ns = type.Namespace.IsNil ? "" : metadata.GetString(type.Namespace);
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(type.Name), out int typeParameterCount);
return new TopLevelTypeName(ns, name, typeParameterCount);
}
public static TType DecodeSignature<TType, TGenericContext>(this EventDefinition ev, MetadataReader reader, ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
{
switch (ev.Type.Kind) {

2
ICSharpCode.Decompiler/SRMHacks.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler @@ -44,7 +44,7 @@ namespace ICSharpCode.Decompiler
}
}
return resultBuilder.ToImmutable();
return resultBuilder.MoveToImmutable();
}
/*

2
ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs

@ -152,7 +152,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -152,7 +152,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
Debug.Assert(elementTypes.Count == tupleCardinality);
return new TupleType(
compilation,
elementTypes.ToImmutable(),
elementTypes.MoveToImmutable(),
elementNames,
valueTupleAssembly
);

16
ICSharpCode.Decompiler/TypeSystem/ComHelper.cs

@ -26,11 +26,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -26,11 +26,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
public static class ComHelper
{
static bool IsComAttribute(IAttribute attribute, string name)
{
return attribute.AttributeType.Name == name && attribute.AttributeType.Namespace == "System.Runtime.InteropServices";
}
/// <summary>
/// Gets whether the specified type is imported from COM.
/// </summary>
@ -38,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -38,7 +33,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
return typeDefinition != null
&& typeDefinition.Kind == TypeKind.Interface
&& typeDefinition.Attributes.Any(a => IsComAttribute(a, "ComImportAttribute"));
&& typeDefinition.GetAttributes(KnownAttribute.ComImport, inherit: false) != null;
}
/// <summary>
@ -50,11 +45,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -50,11 +45,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
if (typeDefinition == null)
return SpecialType.UnknownType;
var coClassAttribute = typeDefinition.Attributes.FirstOrDefault(a => IsComAttribute(a, "CoClassAttribute"));
if (coClassAttribute != null && coClassAttribute.PositionalArguments.Count == 1) {
var rr = coClassAttribute.PositionalArguments[0] as TypeOfResolveResult;
if (rr != null)
return rr.ReferencedType;
var coClassAttribute = typeDefinition.GetAttribute(KnownAttribute.CoClass, inherit: false);
if (coClassAttribute != null && coClassAttribute.FixedArguments.Length == 1) {
if (coClassAttribute.FixedArguments[0].Value is IType ty)
return ty;
}
return SpecialType.UnknownType;
}

4
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -58,6 +58,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -58,6 +58,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
ExtensionMethods = 4,
/// <summary>
/// Only load the public API into the type system.
/// </summary>
OnlyPublicAPI = 8,
/// <summary>
/// Default settings: all features enabled.
/// </summary>
Default = Dynamic | Tuple | ExtensionMethods

6
ICSharpCode.Decompiler/TypeSystem/IAttribute.cs

@ -17,6 +17,8 @@ @@ -17,6 +17,8 @@
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Semantics;
namespace ICSharpCode.Decompiler.TypeSystem
@ -53,11 +55,11 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -53,11 +55,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary>
/// Gets the positional arguments.
/// </summary>
IReadOnlyList<ResolveResult> PositionalArguments { get; }
ImmutableArray<CustomAttributeTypedArgument<IType>> FixedArguments { get; }
/// <summary>
/// Gets the named arguments passed to the attribute.
/// </summary>
IReadOnlyList<KeyValuePair<IMember, ResolveResult>> NamedArguments { get; }
ImmutableArray<CustomAttributeNamedArgument<IType>> NamedArguments { get; }
}
}

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

@ -26,6 +26,7 @@ using System.Text; @@ -26,6 +26,7 @@ using System.Text;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.Decompiler.Semantics;
using System.Runtime.InteropServices;
using System.Linq;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
@ -67,33 +68,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -67,33 +68,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
/// </summary>
public void Add(KnownAttribute type, KnownTypeCode argType, object argValue)
{
Add(type, new ConstantResolveResult(assembly.Compilation.FindType(argType), argValue));
Add(type, ImmutableArray.Create(new CustomAttributeTypedArgument<IType>(assembly.Compilation.FindType(argType), argValue)));
}
/// <summary>
/// Construct a builtin attribute.
/// Construct a builtin attribute with a single positional argument of known type.
/// </summary>
public void Add(KnownAttribute type, params ResolveResult[] positionalArguments)
{
Add(new DefaultAttribute(assembly.GetAttributeType(type), positionalArguments));
}
internal KeyValuePair<IMember, ResolveResult> MakeNamedArg(IType attrType, string name, KnownTypeCode valueType, object value)
{
return MakeNamedArg(attrType, name, assembly.Compilation.FindType(valueType), value);
}
internal KeyValuePair<IMember, ResolveResult> MakeNamedArg(IType attrType, string name, IType valueType, object value)
public void Add(KnownAttribute type, TopLevelTypeName argType, object argValue)
{
var rr = new ConstantResolveResult(valueType, value);
return Implementation.CustomAttribute.MakeNamedArg(assembly.Compilation, attrType, name, rr);
Add(type, ImmutableArray.Create(new CustomAttributeTypedArgument<IType>(assembly.Compilation.FindType(argType), argValue)));
}
internal KeyValuePair<IMember, ResolveResult> MakeNamedArg(IType attrType, string name, bool value)
/// <summary>
/// Construct a builtin attribute.
/// </summary>
public void Add(KnownAttribute type, ImmutableArray<CustomAttributeTypedArgument<IType>> fixedArguments)
{
return MakeNamedArg(attrType, name, assembly.Compilation.FindType(KnownTypeCode.Boolean), value);
Add(new DefaultAttribute(assembly.GetAttributeType(type), fixedArguments,
ImmutableArray.Create<CustomAttributeNamedArgument<IType>>()));
}
#region MarshalAsAttribute (ConvertMarshalInfo)
internal void AddMarshalInfo(BlobHandle marshalInfo)
{
@ -106,34 +100,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -106,34 +100,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IAttribute ConvertMarshalInfo(SRM.BlobReader marshalInfo)
{
IType marshalAsAttributeType = assembly.GetAttributeType(KnownAttribute.MarshalAs);
var b = new AttributeBuilder(assembly, KnownAttribute.MarshalAs);
IType unmanagedTypeType = assembly.Compilation.FindType(new TopLevelTypeName(InteropServices, nameof(UnmanagedType)));
int type = marshalInfo.ReadByte();
var positionalArguments = new ResolveResult[] {
new ConstantResolveResult(unmanagedTypeType, type)
};
var namedArguments = new List<KeyValuePair<IMember, ResolveResult>>();
b.AddFixedArg(unmanagedTypeType, type);
int size;
switch (type) {
case 0x1e: // FixedArray
if (!marshalInfo.TryReadCompressedInteger(out size))
size = 0;
namedArguments.Add(MakeNamedArg(marshalAsAttributeType, "SizeConst", KnownTypeCode.Int32, size));
b.AddNamedArg("SizeConst", KnownTypeCode.Int32, size);
if (marshalInfo.RemainingBytes > 0) {
type = marshalInfo.ReadByte();
if (type != 0x66) // None
namedArguments.Add(MakeNamedArg(marshalAsAttributeType, "ArraySubType", unmanagedTypeType, type));
b.AddNamedArg("ArraySubType", unmanagedTypeType, type);
}
break;
case 0x1d: // SafeArray
if (marshalInfo.RemainingBytes > 0) {
VarEnum varType = (VarEnum)marshalInfo.ReadByte();
if (varType != VarEnum.VT_EMPTY) {
var varEnumType = assembly.Compilation.FindType(new TopLevelTypeName(InteropServices, nameof(VarEnum)));
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"SafeArraySubType", varEnumType, (int)varType));
var varEnumType = new TopLevelTypeName(InteropServices, nameof(VarEnum));
b.AddNamedArg("SafeArraySubType", varEnumType, (int)varType);
}
}
break;
@ -144,19 +134,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -144,19 +134,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
type = 0x66; // Cecil uses NativeType.None as default.
}
if (type != 0x50) { // Max
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"ArraySubType", unmanagedTypeType, type));
b.AddNamedArg("ArraySubType", unmanagedTypeType, type);
}
int sizeParameterIndex = marshalInfo.TryReadCompressedInteger(out int value) ? value : -1;
size = marshalInfo.TryReadCompressedInteger(out value) ? value : -1;
int sizeParameterMultiplier = marshalInfo.TryReadCompressedInteger(out value) ? value : -1;
if (size >= 0) {
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"SizeConst", KnownTypeCode.Int32, size));
b.AddNamedArg("SizeConst", KnownTypeCode.Int32, size);
}
if (sizeParameterMultiplier != 0 && sizeParameterIndex >= 0) {
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"SizeParamIndex", KnownTypeCode.Int16, (short)sizeParameterIndex));
b.AddNamedArg("SizeParamIndex", KnownTypeCode.Int16, (short)sizeParameterIndex);
}
break;
case 0x2c: // CustomMarshaler
@ -165,21 +152,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -165,21 +152,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
string managedType = marshalInfo.ReadSerializedString();
string cookie = marshalInfo.ReadSerializedString();
if (managedType != null) {
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"MarshalType", KnownTypeCode.String, managedType));
b.AddNamedArg("MarshalType", KnownTypeCode.String, managedType);
}
if (!string.IsNullOrEmpty(cookie)) {
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"MarshalCookie", KnownTypeCode.String, cookie));
b.AddNamedArg("MarshalCookie", KnownTypeCode.String, cookie);
}
break;
case 0x17: // FixedSysString
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"SizeConst", KnownTypeCode.Int32, marshalInfo.ReadCompressedInteger()));
b.AddNamedArg("SizeConst", KnownTypeCode.Int32, marshalInfo.ReadCompressedInteger());
break;
}
return new DefaultAttribute(marshalAsAttributeType, positionalArguments, namedArguments);
return b.Build();
}
#endregion
@ -239,7 +223,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -239,7 +223,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public void AddSecurityAttributes(DeclarativeSecurityAttribute secDecl)
{
var securityActionType = assembly.Compilation.FindType(new TopLevelTypeName("System.Security.Permissions", "SecurityAction"));
var securityAction = new ConstantResolveResult(securityActionType, (int)secDecl.Action);
var securityAction = new CustomAttributeTypedArgument<IType>(securityActionType, (int)secDecl.Action);
var metadata = assembly.metadata;
var reader = metadata.GetBlobReader(secDecl.PermissionSet);
if (reader.ReadByte() == '.') {
@ -255,20 +239,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -255,20 +239,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
private void ReadXmlSecurityAttribute(ref SRM.BlobReader reader, ConstantResolveResult securityAction)
private void ReadXmlSecurityAttribute(ref SRM.BlobReader reader, CustomAttributeTypedArgument<IType> securityAction)
{
string xml = reader.ReadUTF16(reader.RemainingBytes);
var permissionSetAttributeType = assembly.GetAttributeType(KnownAttribute.PermissionSet);
Add(new DefaultAttribute(
permissionSetAttributeType,
positionalArguments: new ResolveResult[] { securityAction },
namedArguments: new[] {
MakeNamedArg(permissionSetAttributeType, "XML", assembly.Compilation.FindType(KnownTypeCode.String), xml)
}
));
var b = new AttributeBuilder(assembly, KnownAttribute.PermissionSet);
b.AddFixedArg(securityAction);
b.AddNamedArg("XML", KnownTypeCode.String, xml);
}
private IAttribute ReadBinarySecurityAttribute(ref SRM.BlobReader reader, ResolveResult securityActionRR)
private IAttribute ReadBinarySecurityAttribute(ref SRM.BlobReader reader, CustomAttributeTypedArgument<IType> securityAction)
{
string attributeTypeName = reader.ReadSerializedString();
IType attributeType = assembly.Compilation.FindType(new FullTypeName(attributeTypeName));
@ -282,8 +261,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -282,8 +261,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return new DefaultAttribute(
attributeType,
positionalArguments: new ResolveResult[] { securityActionRR },
namedArguments: CustomAttribute.ConvertNamedArguments(assembly.Compilation, attributeType, namedArgs));
fixedArguments: ImmutableArray.Create(securityAction),
namedArguments: namedArgs);
}
#endregion
@ -295,4 +274,70 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -295,4 +274,70 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return attributes.ToArray();
}
}
struct AttributeBuilder
{
readonly ICompilation compilation;
readonly IType attributeType;
ImmutableArray<CustomAttributeTypedArgument<IType>>.Builder fixedArgs;
ImmutableArray<CustomAttributeNamedArgument<IType>>.Builder namedArgs;
public AttributeBuilder(MetadataAssembly assembly, KnownAttribute attributeType)
: this(assembly, assembly.GetAttributeType(attributeType))
{
}
public AttributeBuilder(MetadataAssembly assembly, IType attributeType)
{
this.compilation = assembly.Compilation;
this.attributeType = attributeType;
this.fixedArgs = ImmutableArray.CreateBuilder<CustomAttributeTypedArgument<IType>>();
this.namedArgs = ImmutableArray.CreateBuilder<CustomAttributeNamedArgument<IType>>();
}
public void AddFixedArg(CustomAttributeTypedArgument<IType> arg)
{
fixedArgs.Add(arg);
}
public void AddFixedArg(KnownTypeCode type, object value)
{
AddFixedArg(compilation.FindType(type), value);
}
public void AddFixedArg(TopLevelTypeName type, object value)
{
AddFixedArg(compilation.FindType(type), value);
}
public void AddFixedArg(IType type, object value)
{
fixedArgs.Add(new CustomAttributeTypedArgument<IType>(type, value));
}
public void AddNamedArg(string name, KnownTypeCode type, object value)
{
AddNamedArg(name, compilation.FindType(type), value);
}
public void AddNamedArg(string name, TopLevelTypeName type, object value)
{
AddNamedArg(name, compilation.FindType(type), value);
}
public void AddNamedArg(string name, IType type, object value)
{
CustomAttributeNamedArgumentKind kind;
if (attributeType.GetFields(f => f.Name == name, GetMemberOptions.ReturnMemberDefinitions).Any())
kind = CustomAttributeNamedArgumentKind.Field;
else
kind = CustomAttributeNamedArgumentKind.Property;
namedArgs.Add(new CustomAttributeNamedArgument<IType>(name, kind, type, value));
}
public IAttribute Build()
{
return new DefaultAttribute(attributeType, fixedArgs.ToImmutable(), namedArgs.ToImmutable());
}
}
}

69
ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs

@ -21,7 +21,7 @@ using System.Collections.Generic; @@ -21,7 +21,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
@ -38,8 +38,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -38,8 +38,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IMethod Constructor { get; }
// lazy-loaded:
IReadOnlyList<ResolveResult> positionalArguments;
IReadOnlyList<KeyValuePair<IMember, ResolveResult>> namedArguments;
SRM.CustomAttributeValue<IType> value;
bool valueDecoded;
internal CustomAttribute(MetadataAssembly assembly, IMethod attrCtor, SRM.CustomAttributeHandle handle)
{
@ -53,34 +53,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -53,34 +53,30 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IType AttributeType => Constructor.DeclaringType;
public IReadOnlyList<ResolveResult> PositionalArguments {
public ImmutableArray<CustomAttributeTypedArgument<IType>> FixedArguments {
get {
var args = LazyInit.VolatileRead(ref this.positionalArguments);
if (args != null)
return args;
DecodeValue();
return this.positionalArguments;
return value.FixedArguments;
}
}
public IReadOnlyList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
public ImmutableArray<CustomAttributeNamedArgument<IType>> NamedArguments {
get {
var namedArgs = LazyInit.VolatileRead(ref this.namedArguments);
if (namedArgs != null)
return namedArgs;
DecodeValue();
return this.namedArguments;
return value.NamedArguments;
}
}
void DecodeValue()
{
var metadata = assembly.metadata;
var attr = metadata.GetCustomAttribute(handle);
var attrVal = attr.DecodeValue(assembly.TypeProvider);
LazyInit.GetOrSet(ref this.positionalArguments, ConvertArguments(attrVal.FixedArguments));
LazyInit.GetOrSet(ref this.namedArguments,
ConvertNamedArguments(assembly.Compilation, AttributeType, attrVal.NamedArguments));
lock (this) {
if (!valueDecoded) {
var metadata = assembly.metadata;
var attr = metadata.GetCustomAttribute(handle);
value = attr.DecodeValue(assembly.TypeProvider);
valueDecoded = true;
}
}
}
internal static KeyValuePair<IMember, ResolveResult> MakeNamedArg(ICompilation compilation, IType attrType, string name, ResolveResult rr)
@ -101,21 +97,46 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -101,21 +97,46 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return new KeyValuePair<IMember, ResolveResult>(field, rr);
}
internal static KeyValuePair<IMember, ResolveResult> MakeNamedArg(ICompilation compilation, IType attrType, SRM.CustomAttributeNamedArgumentKind kind, string name, ResolveResult rr)
{
if (kind == CustomAttributeNamedArgumentKind.Field) {
var field = attrType.GetFields(f => f.Name == name).FirstOrDefault();
if (field != null) {
return new KeyValuePair<IMember, ResolveResult>(field, rr);
}
}
if (kind == CustomAttributeNamedArgumentKind.Property) {
var prop = attrType.GetProperties(f => f.Name == name).FirstOrDefault();
if (prop != null) {
return new KeyValuePair<IMember, ResolveResult>(prop, rr);
}
}
var fakeField = new FakeField(compilation) {
DeclaringType = attrType,
Name = name,
ReturnType = rr.Type
};
return new KeyValuePair<IMember, ResolveResult>(fakeField, rr);
}
internal static IReadOnlyList<KeyValuePair<IMember, ResolveResult>> ConvertNamedArguments(
ICompilation compilation, IType attributeType, ImmutableArray<SRM.CustomAttributeNamedArgument<IType>> namedArgs)
{
var arr = new KeyValuePair<IMember, ResolveResult>[namedArgs.Length];
for (int i = 0; i < arr.Length; i++) {
var namedArg = namedArgs[i];
arr[i] = MakeNamedArg(compilation, attributeType, namedArg.Name, ConvertArgument(namedArg.Type, namedArg.Value));
arr[i] = MakeNamedArg(compilation, attributeType, namedArg.Kind, namedArg.Name,
ConvertArgument(compilation, namedArg.Type, namedArg.Value));
}
return arr;
}
private static ResolveResult ConvertArgument(IType type, object value)
private static ResolveResult ConvertArgument(ICompilation compilation, IType type, object value)
{
if (value is ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> arr) {
return new ArrayCreateResolveResult(type, null, ConvertArguments(arr));
var arrSize = new ConstantResolveResult(compilation.FindType(KnownTypeCode.Int32), arr.Length);
return new ArrayCreateResolveResult(type, new[] { arrSize },
ConvertArguments(compilation, type, arr));
} else if (value is IType valueType) {
return new TypeOfResolveResult(type, valueType);
} else {
@ -123,9 +144,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -123,9 +144,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
private static IReadOnlyList<ResolveResult> ConvertArguments(ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> arr)
private static IReadOnlyList<ResolveResult> ConvertArguments(ICompilation compilation, IType type, ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> arr)
{
return arr.SelectArray(arg => ConvertArgument(arg.Type, arg.Value));
return arr.SelectArray(arg => ConvertArgument(compilation, type ?? arg.Type, arg.Value));
}
}
}

43
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultAttribute.cs

@ -18,7 +18,9 @@ @@ -18,7 +18,9 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
@ -30,30 +32,33 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -30,30 +32,33 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public class DefaultAttribute : IAttribute
{
readonly IType attributeType;
readonly IReadOnlyList<ResolveResult> positionalArguments;
readonly IReadOnlyList<KeyValuePair<IMember, ResolveResult>> namedArguments;
volatile IMethod constructor;
public DefaultAttribute(IType attributeType, IReadOnlyList<ResolveResult> positionalArguments = null,
IReadOnlyList<KeyValuePair<IMember, ResolveResult>> namedArguments = null)
public ImmutableArray<CustomAttributeTypedArgument<IType>> FixedArguments { get; }
public ImmutableArray<CustomAttributeNamedArgument<IType>> NamedArguments { get; }
public DefaultAttribute(IType attributeType,
ImmutableArray<CustomAttributeTypedArgument<IType>> fixedArguments,
ImmutableArray<CustomAttributeNamedArgument<IType>> namedArguments)
{
if (attributeType == null)
throw new ArgumentNullException("attributeType");
this.attributeType = attributeType;
this.positionalArguments = positionalArguments ?? EmptyList<ResolveResult>.Instance;
this.namedArguments = namedArguments ?? EmptyList<KeyValuePair<IMember, ResolveResult>>.Instance;
this.FixedArguments = fixedArguments;
this.NamedArguments = namedArguments;
}
public DefaultAttribute(IMethod constructor, IReadOnlyList<ResolveResult> positionalArguments = null,
IReadOnlyList<KeyValuePair<IMember, ResolveResult>> namedArguments = null)
public DefaultAttribute(IMethod constructor,
ImmutableArray<CustomAttributeTypedArgument<IType>> fixedArguments,
ImmutableArray<CustomAttributeNamedArgument<IType>> namedArguments)
{
if (constructor == null)
throw new ArgumentNullException("constructor");
this.constructor = constructor;
this.attributeType = constructor.DeclaringType ?? SpecialType.UnknownType;
this.positionalArguments = positionalArguments ?? EmptyList<ResolveResult>.Instance;
this.namedArguments = namedArguments ?? EmptyList<KeyValuePair<IMember, ResolveResult>>.Instance;
if (this.positionalArguments.Count != constructor.Parameters.Count) {
this.FixedArguments = fixedArguments;
this.NamedArguments = namedArguments;
if (fixedArguments.Length != constructor.Parameters.Count) {
throw new ArgumentException("Positional argument count must match the constructor's parameter count");
}
}
@ -66,8 +71,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -66,8 +71,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get {
IMethod ctor = this.constructor;
if (ctor == null) {
foreach (IMethod candidate in this.AttributeType.GetConstructors(m => m.Parameters.Count == positionalArguments.Count)) {
if (candidate.Parameters.Select(p => p.Type).SequenceEqual(this.PositionalArguments.Select(a => a.Type))) {
foreach (IMethod candidate in this.AttributeType.GetConstructors(m => m.Parameters.Count == FixedArguments.Length)) {
if (candidate.Parameters.Select(p => p.Type).SequenceEqual(this.FixedArguments.Select(a => a.Type))) {
ctor = candidate;
break;
}
@ -77,13 +82,5 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -77,13 +82,5 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return ctor;
}
}
public IReadOnlyList<ResolveResult> PositionalArguments {
get { return positionalArguments; }
}
public IReadOnlyList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
get { return namedArguments; }
}
}
}

9
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedEvent.cs

@ -59,14 +59,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -59,14 +59,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override IMember Specialize(TypeParameterSubstitution substitution)
{
if (TypeParameterSubstitution.Identity.Equals(substitution)
|| DeclaringType.TypeParameterCount == 0)
{
return this;
}
if (substitution.MethodTypeArguments != null && substitution.MethodTypeArguments.Count > 0)
substitution = new TypeParameterSubstitution(substitution.ClassTypeArguments, EmptyList<IType>.Instance);
return new SpecializedEvent(this, substitution);
return SpecializedEvent.Create(this, substitution);
}
}
}

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

@ -385,8 +385,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -385,8 +385,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
from attr in this.AssemblyAttributes
where attr.AttributeType.Name == "InternalsVisibleToAttribute"
&& attr.AttributeType.Namespace == "System.Runtime.CompilerServices"
&& attr.PositionalArguments.Count == 1
select GetShortName(attr.PositionalArguments.Single().ConstantValue as string)
&& attr.FixedArguments.Length == 1
select GetShortName(attr.FixedArguments.Single().Value as string)
).ToArray();
}
return internalsVisibleTo;

37
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAttribute.cs

@ -18,6 +18,8 @@ @@ -18,6 +18,8 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
@ -186,7 +188,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -186,7 +188,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly IReadOnlyList<ResolveResult> positionalArguments;
// cannot use ProjectedList because KeyValuePair is value type
IReadOnlyList<KeyValuePair<IMember, ResolveResult>> namedArguments;
//IReadOnlyList<KeyValuePair<IMember, ResolveResult>> namedArguments;
IMethod constructor;
volatile bool constructorResolved;
@ -231,33 +233,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -231,33 +233,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return null;
}
public IReadOnlyList<ResolveResult> PositionalArguments {
get { return positionalArguments; }
}
public IReadOnlyList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
get {
var namedArgs = LazyInit.VolatileRead(ref this.namedArguments);
if (namedArgs != null) {
return namedArgs;
} else {
var newNamedArgs = new List<KeyValuePair<IMember, ResolveResult>>();
foreach (var pair in unresolved.NamedArguments) {
IMember member = pair.Key.Resolve(context);
if (member != null) {
ResolveResult val = pair.Value.Resolve(context);
newNamedArgs.Add(new KeyValuePair<IMember, ResolveResult>(member, val));
}
}
return LazyInit.GetOrSet(ref this.namedArguments, newNamedArgs);
}
}
}
public ICompilation Compilation {
get { return context.Compilation; }
}
IType IAttribute.AttributeType => throw new NotImplementedException();
IMethod IAttribute.Constructor => throw new NotImplementedException();
ImmutableArray<CustomAttributeTypedArgument<IType>> IAttribute.FixedArguments => throw new NotImplementedException();
ImmutableArray<CustomAttributeNamedArgument<IType>> IAttribute.NamedArguments => throw new NotImplementedException();
public override string ToString()
{
if (positionalArguments.Count == 0)

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

@ -1,14 +1,30 @@ @@ -1,14 +1,30 @@
using System;
using System.Collections.Generic;
// Copyright (c) 2010-2018 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
namespace ICSharpCode.Decompiler.TypeSystem
{
enum KnownAttribute
public enum KnownAttribute
{
/// <summary>
/// Not a known attribute
@ -22,21 +38,32 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -22,21 +38,32 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
Extension,
Dynamic,
TupleElementNames,
Conditional,
Obsolete,
IsReadOnly,
DebuggerHidden,
DebuggerStepThrough,
// Assembly attributes:
AssemblyVersion,
InternalsVisibleTo,
TypeForwardedTo,
// Type attributes:
Serializable,
ComImport,
CoClass,
StructLayout,
DefaultMember,
IsByRefLike,
IteratorStateMachine,
AsyncStateMachine,
// Field attributes:
FieldOffset,
NonSerialized,
DecimalConstant,
FixedBuffer,
// Method attributes:
DllImport,
@ -65,18 +92,29 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -65,18 +92,29 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(ExtensionAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(DynamicAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(TupleElementNamesAttribute)),
new TopLevelTypeName("System.Diagnostics", nameof(ConditionalAttribute)),
new TopLevelTypeName("System", nameof(ObsoleteAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", "IsReadOnlyAttribute"),
new TopLevelTypeName("System.Diagnostics", nameof(DebuggerHiddenAttribute)),
new TopLevelTypeName("System.Diagnostics", nameof(DebuggerStepThroughAttribute)),
// Assembly attributes:
new TopLevelTypeName("System.Reflection", nameof(AssemblyVersionAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(InternalsVisibleToAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(TypeForwardedToAttribute)),
// Type attributes:
new TopLevelTypeName("System", nameof(SerializableAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(ComImportAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(CoClassAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(StructLayoutAttribute)),
new TopLevelTypeName("System.Reflection", nameof(DefaultMemberAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", "IsByRefLikeAttribute"),
new TopLevelTypeName("System.Reflection", nameof(IteratorStateMachineAttribute)),
new TopLevelTypeName("System.Reflection", nameof(AsyncStateMachineAttribute)),
// Field attributes:
new TopLevelTypeName("System.Runtime.InteropServices", nameof(FieldOffsetAttribute)),
new TopLevelTypeName("System", nameof(NonSerializedAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(DecimalConstantAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(FixedBufferAttribute)),
// Method attributes:
new TopLevelTypeName("System.Runtime.InteropServices", nameof(DllImportAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(PreserveSigAttribute)),

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

@ -0,0 +1,147 @@ @@ -0,0 +1,147 @@
// Copyright (c) 2018 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
sealed class MetadataEvent : IEvent
{
readonly MetadataAssembly assembly;
readonly EventDefinitionHandle handle;
readonly EventAccessors accessors;
readonly string name;
// lazy-loaded:
IAttribute[] customAttributes;
IType returnType;
internal MetadataEvent(MetadataAssembly assembly, EventDefinitionHandle handle)
{
Debug.Assert(assembly != null);
Debug.Assert(!handle.IsNil);
this.assembly = assembly;
this.handle = handle;
var metadata = assembly.metadata;
var ev = metadata.GetEventDefinition(handle);
accessors = ev.GetAccessors();
name = metadata.GetString(ev.Name);
}
public EntityHandle MetadataToken => handle;
public string Name => name;
SymbolKind ISymbol.SymbolKind => SymbolKind.Event;
public bool CanAdd => !accessors.Adder.IsNil;
public bool CanRemove => !accessors.Remover.IsNil;
public bool CanInvoke => !accessors.Raiser.IsNil;
public IMethod AddAccessor => assembly.GetDefinition(accessors.Adder);
public IMethod RemoveAccessor => assembly.GetDefinition(accessors.Remover);
public IMethod InvokeAccessor => assembly.GetDefinition(accessors.Raiser);
IMethod AnyAccessor => assembly.GetDefinition(accessors.GetAny());
#region Signature (ReturnType + Parameters)
public IType ReturnType {
get {
var returnType = LazyInit.VolatileRead(ref this.returnType);
if (returnType != null)
return returnType;
var metadata = assembly.metadata;
var ev = metadata.GetEventDefinition(handle);
var context = new GenericContext(DeclaringTypeDefinition?.TypeParameters);
returnType = assembly.ResolveType(ev.Type, context, ev.GetCustomAttributes());
return LazyInit.GetOrSet(ref this.returnType, returnType);
}
}
#endregion
public bool IsExplicitInterfaceImplementation => AnyAccessor?.IsExplicitInterfaceImplementation ?? false;
public IEnumerable<IMember> ImplementedInterfaceMembers => GetInterfaceMembersFromAccessor(AnyAccessor);
internal static IEnumerable<IMember> GetInterfaceMembersFromAccessor(IMethod method)
{
if (method == null)
return EmptyList<IMember>.Instance;
return method.ImplementedInterfaceMembers.Select(m => ((IMethod)m).AccessorOwner).Where(m => m != null);
}
public ITypeDefinition DeclaringTypeDefinition => AnyAccessor?.DeclaringTypeDefinition;
public IType DeclaringType => AnyAccessor?.DeclaringType;
IMember IMember.MemberDefinition => this;
TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity;
#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());
}
}
IAttribute[] DecodeAttributes()
{
var b = new AttributeListBuilder(assembly);
var metadata = assembly.metadata;
var eventDef = metadata.GetEventDefinition(handle);
b.Add(eventDef.GetCustomAttributes());
return b.Build();
}
#endregion
public Accessibility Accessibility => AnyAccessor?.Accessibility ?? Accessibility.None;
public bool IsStatic => AnyAccessor?.IsStatic ?? false;
public bool IsAbstract => AnyAccessor?.IsAbstract ?? false;
public bool IsSealed => AnyAccessor?.IsSealed ?? false;
public bool IsVirtual => AnyAccessor?.IsVirtual ?? false;
public bool IsOverride => AnyAccessor?.IsOverride ?? false;
public bool IsOverridable => AnyAccessor?.IsOverridable ?? false;
bool IEntity.IsShadowing => AnyAccessor?.IsShadowing ?? false;
public IAssembly ParentAssembly => assembly;
public ICompilation Compilation => assembly.Compilation;
public string FullName => $"{DeclaringType?.FullName}.{Name}";
public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}";
public string Namespace => DeclaringType?.Namespace ?? string.Empty;
bool IMember.Equals(IMember obj, TypeVisitor typeNormalization)
{
return this == obj;
}
public IMember Specialize(TypeParameterSubstitution substitution)
{
return SpecializedEvent.Create(this, substitution);
}
}
}

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

@ -39,6 +39,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -39,6 +39,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly MethodAttributes attributes;
readonly SymbolKind symbolKind;
readonly ITypeParameter[] typeParameters;
readonly EntityHandle accessorOwner;
public bool IsExtensionMethod { get; }
// lazy-loaded fields:
@ -61,7 +62,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -61,7 +62,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.attributes = def.Attributes;
this.symbolKind = SymbolKind.Method;
if ((attributes & (MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)) != 0) {
var (accessorOwner, semanticsAttribute) = assembly.PEFile.MethodSemanticsLookup.GetSemantics(handle);
if (semanticsAttribute != 0) {
this.symbolKind = SymbolKind.Accessor;
this.accessorOwner = accessorOwner;
} else if ((attributes & (MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)) != 0) {
string name = this.Name;
if (name == ".cctor" || name == ".ctor")
this.symbolKind = SymbolKind.Constructor;
@ -104,7 +109,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -104,7 +109,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool HasBody => assembly.metadata.GetMethodDefinition(handle).HasBody();
public IMember AccessorOwner => throw new NotImplementedException();
public IMember AccessorOwner {
get {
if (accessorOwner.IsNil)
return null;
if (accessorOwner.Kind == HandleKind.PropertyDefinition)
return assembly.GetDefinition((PropertyDefinitionHandle)accessorOwner);
else if (accessorOwner.Kind == HandleKind.EventDefinition)
return assembly.GetDefinition((EventDefinitionHandle)accessorOwner);
else
return null;
}
}
#region Signature (ReturnType + Parameters)
public IReadOnlyList<IParameter> Parameters {
@ -231,18 +247,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -231,18 +247,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
#region DllImportAttribute
var info = def.GetImport();
if ((attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl && !info.Module.IsNil) {
var dllImportType = assembly.GetAttributeType(KnownAttribute.DllImport);
var positionalArguments = new ResolveResult[] {
new ConstantResolveResult(assembly.Compilation.FindType(KnownTypeCode.String),
metadata.GetString(metadata.GetModuleReference(info.Module).Name))
};
var namedArgs = new List<KeyValuePair<IMember, ResolveResult>>();
var dllImport = new AttributeBuilder(assembly, KnownAttribute.DllImport);
dllImport.AddFixedArg(KnownTypeCode.String,
metadata.GetString(metadata.GetModuleReference(info.Module).Name));
var importAttrs = info.Attributes;
if ((importAttrs & MethodImportAttributes.BestFitMappingDisable) == MethodImportAttributes.BestFitMappingDisable)
namedArgs.Add(b.MakeNamedArg(dllImportType, "BestFitMapping", false));
dllImport.AddNamedArg("BestFitMapping", KnownTypeCode.Boolean, false);
if ((importAttrs & MethodImportAttributes.BestFitMappingEnable) == MethodImportAttributes.BestFitMappingEnable)
namedArgs.Add(b.MakeNamedArg(dllImportType, "BestFitMapping", true));
dllImport.AddNamedArg("BestFitMapping", KnownTypeCode.Boolean, true);
CallingConvention callingConvention;
switch (info.Attributes & MethodImportAttributes.CallingConventionMask) {
@ -270,7 +283,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -270,7 +283,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
if (callingConvention != CallingConvention.Winapi) {
var callingConventionType = FindInteropType(nameof(CallingConvention));
namedArgs.Add(b.MakeNamedArg(dllImportType, "CallingConvention", callingConventionType, (int)callingConvention));
dllImport.AddNamedArg("CallingConvention", callingConventionType, (int)callingConvention);
}
CharSet charSet = CharSet.None;
@ -287,33 +300,32 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -287,33 +300,32 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
if (charSet != CharSet.None) {
var charSetType = FindInteropType(nameof(CharSet));
namedArgs.Add(b.MakeNamedArg(dllImportType, "CharSet", charSetType, (int)charSet));
dllImport.AddNamedArg("CharSet", charSetType, (int)charSet);
}
if (!info.Name.IsNil && info.Name != def.Name) {
namedArgs.Add(b.MakeNamedArg(dllImportType,
"EntryPoint", KnownTypeCode.String, metadata.GetString(info.Name)));
dllImport.AddNamedArg("EntryPoint", KnownTypeCode.String, metadata.GetString(info.Name));
}
if ((info.Attributes & MethodImportAttributes.ExactSpelling) == MethodImportAttributes.ExactSpelling) {
namedArgs.Add(b.MakeNamedArg(dllImportType, "ExactSpelling", true));
dllImport.AddNamedArg("ExactSpelling", KnownTypeCode.Boolean, true);
}
if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) {
implAttributes &= ~MethodImplAttributes.PreserveSig;
} else {
namedArgs.Add(b.MakeNamedArg(dllImportType, "PreserveSig", true));
dllImport.AddNamedArg("PreserveSig", KnownTypeCode.Boolean, true);
}
if ((info.Attributes & MethodImportAttributes.SetLastError) == MethodImportAttributes.SetLastError)
namedArgs.Add(b.MakeNamedArg(dllImportType, "SetLastError", true));
dllImport.AddNamedArg("SetLastError", KnownTypeCode.Boolean, true);
if ((info.Attributes & MethodImportAttributes.ThrowOnUnmappableCharDisable) == MethodImportAttributes.ThrowOnUnmappableCharDisable)
namedArgs.Add(b.MakeNamedArg(dllImportType, "ThrowOnUnmappableChar", false));
dllImport.AddNamedArg("ThrowOnUnmappableChar", KnownTypeCode.Boolean, false);
if ((info.Attributes & MethodImportAttributes.ThrowOnUnmappableCharEnable) == MethodImportAttributes.ThrowOnUnmappableCharEnable)
namedArgs.Add(b.MakeNamedArg(dllImportType, "ThrowOnUnmappableChar", true));
dllImport.AddNamedArg("ThrowOnUnmappableChar", KnownTypeCode.Boolean, true);
b.Add(new DefaultAttribute(dllImportType, positionalArguments, namedArgs));
b.Add(dllImport.Build());
}
#endregion
@ -326,10 +338,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -326,10 +338,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
#region MethodImplAttribute
if (implAttributes != 0) {
b.Add(KnownAttribute.MethodImpl, new ConstantResolveResult(
Compilation.FindType(new TopLevelTypeName("System.Runtime.CompilerServices", nameof(MethodImplOptions))),
b.Add(KnownAttribute.MethodImpl,
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(MethodImplOptions)),
(int)implAttributes
));
);
}
#endregion
@ -392,7 +404,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -392,7 +404,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public bool IsStatic => (attributes & MethodAttributes.Static) != 0;
public bool IsAbstract => (attributes & MethodAttributes.Abstract) != 0;
public bool IsSealed => (attributes & (MethodAttributes.Abstract | MethodAttributes.Final | MethodAttributes.NewSlot | MethodAttributes.Static)) == MethodAttributes.Final;
public bool IsVirtual => (attributes & (MethodAttributes.Abstract | MethodAttributes.Virtual | MethodAttributes.NewSlot)) == (MethodAttributes.Virtual | MethodAttributes.NewSlot);
public bool IsVirtual => (attributes & (MethodAttributes.Abstract | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.Final)) == (MethodAttributes.Virtual | MethodAttributes.NewSlot);
public bool IsOverride => (attributes & (MethodAttributes.NewSlot | MethodAttributes.Virtual)) == MethodAttributes.Virtual;
public bool IsOverridable
=> (attributes & (MethodAttributes.Abstract | MethodAttributes.Virtual)) != 0

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

@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
const ParameterAttributes inOut = ParameterAttributes.In | ParameterAttributes.Out;
public bool IsRef => Type.Kind == TypeKind.ByReference && (attributes & inOut) != ParameterAttributes.Out;
public bool IsOut => Type.Kind == TypeKind.ByReference && (attributes & inOut) == ParameterAttributes.Out;
public bool IsOptional => (attributes & ParameterAttributes.HasDefault) != 0;
public bool IsOptional => (attributes & ParameterAttributes.Optional) != 0;
public bool IsParams {
get {
@ -109,7 +109,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -109,7 +109,18 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool IVariable.IsConst => false;
public object ConstantValue => throw new NotImplementedException();
public object ConstantValue {
get {
var metadata = assembly.metadata;
var propertyDef = metadata.GetParameter(handle);
var constantHandle = propertyDef.GetDefaultValue();
if (constantHandle.IsNil)
return null;
var constant = metadata.GetConstant(constantHandle);
var blobReader = metadata.GetBlobReader(constant.Value);
return blobReader.ReadConstant(constant.TypeCode);
}
}
SymbolKind ISymbol.SymbolKind => SymbolKind.Parameter;

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

@ -75,6 +75,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -75,6 +75,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IMethod Getter => assembly.GetDefinition(getterHandle);
public IMethod Setter => assembly.GetDefinition(setterHandle);
IMethod AnyAccessor => assembly.GetDefinition(getterHandle.IsNil ? setterHandle : getterHandle);
public bool IsIndexer => symbolKind == SymbolKind.Indexer;
public SymbolKind SymbolKind => symbolKind;
@ -118,8 +119,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -118,8 +119,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
#endregion
public bool IsExplicitInterfaceImplementation => (Getter ?? Setter)?.IsExplicitInterfaceImplementation ?? false;
public IEnumerable<IMember> ImplementedInterfaceMembers => GetInterfaceMembersFromAccessor(Getter ?? Setter);
public bool IsExplicitInterfaceImplementation => AnyAccessor?.IsExplicitInterfaceImplementation ?? false;
public IEnumerable<IMember> ImplementedInterfaceMembers => GetInterfaceMembersFromAccessor(AnyAccessor);
internal static IEnumerable<IMember> GetInterfaceMembersFromAccessor(IMethod method)
{
@ -128,8 +129,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -128,8 +129,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return method.ImplementedInterfaceMembers.Select(m => ((IMethod)m).AccessorOwner).Where(m => m != null);
}
public ITypeDefinition DeclaringTypeDefinition => (Getter ?? Setter)?.DeclaringTypeDefinition;
public IType DeclaringType => (Getter ?? Setter)?.DeclaringType;
public ITypeDefinition DeclaringTypeDefinition => AnyAccessor?.DeclaringTypeDefinition;
public IType DeclaringType => AnyAccessor?.DeclaringType;
IMember IMember.MemberDefinition => this;
TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity;
@ -202,14 +203,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -202,14 +203,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
#endregion
public bool IsStatic => (Getter ?? Setter)?.IsStatic ?? false;
public bool IsAbstract => (Getter ?? Setter)?.IsAbstract ?? false;
public bool IsSealed => (Getter ?? Setter)?.IsSealed ?? false;
public bool IsVirtual => (Getter ?? Setter)?.IsVirtual ?? false;
public bool IsOverride => (Getter ?? Setter)?.IsOverride ?? false;
public bool IsOverridable => (Getter ?? Setter)?.IsOverridable ?? false;
public bool IsStatic => AnyAccessor?.IsStatic ?? false;
public bool IsAbstract => AnyAccessor?.IsAbstract ?? false;
public bool IsSealed => AnyAccessor?.IsSealed ?? false;
public bool IsVirtual => AnyAccessor?.IsVirtual ?? false;
public bool IsOverride => AnyAccessor?.IsOverride ?? false;
public bool IsOverridable => AnyAccessor?.IsOverridable ?? false;
bool IEntity.IsShadowing => (Getter ?? Setter)?.IsShadowing ?? false;
bool IEntity.IsShadowing => AnyAccessor?.IsShadowing ?? false;
public IAssembly ParentAssembly => assembly;
public ICompilation Compilation => assembly.Compilation;

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

@ -168,7 +168,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -168,7 +168,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var propertyCollection = metadata.GetTypeDefinition(handle).GetProperties();
var propertyList = new List<IProperty>(propertyCollection.Count);
foreach (PropertyDefinitionHandle h in propertyCollection) {
propertyList.Add(assembly.GetDefinition(h));
var property = metadata.GetPropertyDefinition(h);
var accessors = property.GetAccessors();
bool getterVisible = !accessors.Getter.IsNil && assembly.IsVisible(metadata.GetMethodDefinition(accessors.Getter).Attributes);
bool setterVisible = !accessors.Setter.IsNil && assembly.IsVisible(metadata.GetMethodDefinition(accessors.Setter).Attributes);
if (getterVisible || setterVisible) {
propertyList.Add(assembly.GetDefinition(h));
}
}
return LazyInit.GetOrSet(ref this.properties, propertyList.ToArray());
}
@ -183,7 +189,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -183,7 +189,14 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var eventCollection = metadata.GetTypeDefinition(handle).GetEvents();
var eventList = new List<IEvent>(eventCollection.Count);
foreach (EventDefinitionHandle h in eventCollection) {
eventList.Add(assembly.GetDefinition(h));
var ev = metadata.GetEventDefinition(h);
var accessors = ev.GetAccessors();
if (accessors.Adder.IsNil)
continue;
var addMethod = metadata.GetMethodDefinition(accessors.Adder);
if (assembly.IsVisible(addMethod.Attributes)) {
eventList.Add(assembly.GetDefinition(h));
}
}
return LazyInit.GetOrSet(ref this.events, eventList.ToArray());
}
@ -311,29 +324,21 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -311,29 +324,21 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var layout = typeDefinition.GetLayout();
LayoutKind defaultLayoutKind = Kind == TypeKind.Struct ? LayoutKind.Sequential : LayoutKind.Auto;
if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || layout.PackingSize > 0 || layout.Size > 0) {
var structLayoutAttributeType = Compilation.FindType(KnownAttribute.StructLayout);
var layoutKindType = Compilation.FindType(new TopLevelTypeName("System.Runtime.InteropServices", "LayoutKind"));
var positionalArguments = new ResolveResult[] {
new ConstantResolveResult(layoutKindType, (int)layoutKind)
};
var namedArguments = new List<KeyValuePair<IMember, ResolveResult>>(3);
var structLayout = new AttributeBuilder(assembly, KnownAttribute.StructLayout);
structLayout.AddFixedArg(
new TopLevelTypeName("System.Runtime.InteropServices", "LayoutKind"),
(int)layoutKind);
if (charSet != CharSet.Ansi) {
var charSetType = Compilation.FindType(new TopLevelTypeName("System.Runtime.InteropServices", "CharSet"));
namedArguments.Add(b.MakeNamedArg(structLayoutAttributeType,
"CharSet", charSetType, (int)charSet));
structLayout.AddNamedArg("CharSet", charSetType, (int)charSet);
}
if (layout.PackingSize > 0) {
namedArguments.Add(b.MakeNamedArg(structLayoutAttributeType,
"Pack", KnownTypeCode.Int32, (int)layout.PackingSize));
structLayout.AddNamedArg("Pack", KnownTypeCode.Int32, (int)layout.PackingSize);
}
if (layout.Size > 0) {
namedArguments.Add(b.MakeNamedArg(structLayoutAttributeType,
"Size", KnownTypeCode.Int32, (int)layout.Size));
structLayout.AddNamedArg("Size", KnownTypeCode.Int32, (int)layout.Size);
}
b.Add(new DefaultAttribute(
structLayoutAttributeType,
positionalArguments, namedArguments
));
b.Add(structLayout.Build());
}
#endregion

34
ICSharpCode.Decompiler/TypeSystem/Implementation/ResolvedAttributeBlob.cs

@ -26,7 +26,9 @@ @@ -26,7 +26,9 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection.Metadata;
using System.Threading;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
@ -74,7 +76,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -74,7 +76,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return constructor;
}
}
IType IAttribute.AttributeType => throw new NotImplementedException();
IMethod IAttribute.Constructor => throw new NotImplementedException();
ImmutableArray<CustomAttributeTypedArgument<IType>> IAttribute.FixedArguments => throw new NotImplementedException();
ImmutableArray<CustomAttributeNamedArgument<IType>> IAttribute.NamedArguments => throw new NotImplementedException();
IMethod ResolveConstructor()
{
var parameterTypes = ctorParameterTypes.Resolve(context);
@ -92,28 +102,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -92,28 +102,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return null;
}
public IReadOnlyList<ResolveResult> PositionalArguments {
get {
var result = LazyInit.VolatileRead(ref this.positionalArguments);
if (result != null) {
return result;
}
DecodeBlob();
return positionalArguments;
}
}
public IReadOnlyList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
get {
var result = LazyInit.VolatileRead(ref this.namedArguments);
if (result != null) {
return result;
}
DecodeBlob();
return namedArguments;
}
}
public override string ToString()
{
return "[" + attributeType.ToString() + "(...)]";

13
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedEvent.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
/// <summary>
@ -23,6 +25,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -23,6 +25,17 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
/// </summary>
public class SpecializedEvent : SpecializedMember, IEvent
{
public static IEvent Create(IEvent ev, TypeParameterSubstitution substitution)
{
if (TypeParameterSubstitution.Identity.Equals(substitution)
|| ev.DeclaringType.TypeParameterCount == 0) {
return ev;
}
if (substitution.MethodTypeArguments != null && substitution.MethodTypeArguments.Count > 0)
substitution = new TypeParameterSubstitution(substitution.ClassTypeArguments, EmptyList<IType>.Instance);
return new SpecializedEvent(ev, substitution);
}
readonly IEvent eventDefinition;
public SpecializedEvent(IEvent eventDefinition, TypeParameterSubstitution substitution)

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

@ -108,10 +108,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -108,10 +108,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
namedArgs.Add(namedArg);
}
throw new NotImplementedException(); /*
attributes[i] = new DefaultAttribute(
attributeType,
positionalArguments: new ResolveResult[] { securityActionRR },
namedArguments: namedArgs);
namedArguments: namedArgs);*/
}
}
}

93
ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs

@ -51,6 +51,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -51,6 +51,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
readonly MetadataField[] fieldDefs;
readonly MetadataMethod[] methodDefs;
readonly MetadataProperty[] propertyDefs;
readonly MetadataEvent[] eventDefs;
internal MetadataAssembly(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options)
{
@ -77,6 +78,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -77,6 +78,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
this.fieldDefs = new MetadataField[metadata.FieldDefinitions.Count + 1];
this.methodDefs = new MetadataMethod[metadata.MethodDefinitions.Count + 1];
this.propertyDefs = new MetadataProperty[metadata.PropertyDefinitions.Count + 1];
this.eventDefs = new MetadataEvent[metadata.EventDefinitions.Count + 1];
}
internal string GetString(StringHandle name)
@ -99,6 +101,13 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -99,6 +101,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
{
var typeDefHandle = PEFile.GetTypeDefinition(topLevelTypeName);
if (typeDefHandle.IsNil) {
var forwarderHandle = PEFile.GetTypeForwarder(topLevelTypeName);
if (!forwarderHandle.IsNil) {
var forwarder = metadata.GetExportedType(forwarderHandle);
return ResolveForwardedType(forwarder).GetDefinition();
}
}
return GetDefinition(typeDefHandle);
}
#endregion
@ -109,7 +118,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -109,7 +118,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (this == assembly)
return true;
foreach (string shortName in GetInternalsVisibleTo()) {
if (assembly.AssemblyName == shortName)
if (string.Equals(assembly.AssemblyName, shortName, StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
@ -212,7 +221,14 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -212,7 +221,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
public IEvent GetDefinition(EventDefinitionHandle handle)
{
throw new NotImplementedException();
int row = MetadataTokens.GetRowNumber(handle);
if (row >= methodDefs.Length)
return null;
var ev = LazyInit.VolatileRead(ref eventDefs[row]);
if (ev != null || handle.IsNil)
return ev;
ev = new MetadataEvent(this, handle);
return LazyInit.GetOrSet(ref eventDefs[row], ev);
}
#endregion
@ -431,6 +447,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -431,6 +447,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (assembly.Version != null) {
b.Add(KnownAttribute.AssemblyVersion, KnownTypeCode.String, assembly.Version.ToString());
}
AddTypeForwarderAttributes(ref b);
}
return LazyInit.GetOrSet(ref this.assemblyAttributes, b.Build());
}
@ -446,9 +464,57 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -446,9 +464,57 @@ namespace ICSharpCode.Decompiler.TypeSystem
return attrs;
var b = new AttributeListBuilder(this);
b.Add(metadata.GetCustomAttributes(Handle.ModuleDefinition));
if (!metadata.IsAssembly) {
AddTypeForwarderAttributes(ref b);
}
return LazyInit.GetOrSet(ref this.moduleAttributes, b.Build());
}
}
void AddTypeForwarderAttributes(ref AttributeListBuilder b)
{
foreach (ExportedTypeHandle t in metadata.ExportedTypes) {
var type = metadata.GetExportedType(t);
if (type.IsForwarder) {
b.Add(KnownAttribute.TypeForwardedTo, KnownTypeCode.Type, ResolveForwardedType(type));
}
}
}
IType ResolveForwardedType(ExportedType forwarder)
{
IAssembly assembly;
switch (forwarder.Implementation.Kind) {
case HandleKind.AssemblyFile:
assembly = this;
break;
case HandleKind.ExportedType:
throw new NotImplementedException();
case HandleKind.AssemblyReference:
var asmRef = metadata.GetAssemblyReference((AssemblyReferenceHandle)forwarder.Implementation);
string shortName = metadata.GetString(asmRef.Name);
assembly = null;
foreach (var asm in Compilation.Assemblies) {
if (string.Equals(asm.AssemblyName, shortName, StringComparison.OrdinalIgnoreCase)) {
assembly = asm;
break;
}
}
break;
default:
throw new NotSupportedException();
}
var typeName = forwarder.GetFullTypeName(metadata);
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
var td = assembly.GetTypeDefinition(typeName);
if (td != null) {
return td;
}
}
}
return new UnknownType(typeName);
}
#endregion
#region Attribute Helpers
@ -479,15 +545,32 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -479,15 +545,32 @@ namespace ICSharpCode.Decompiler.TypeSystem
var attr = LazyInit.VolatileRead(ref knownAttributes[(int)type]);
if (attr != null)
return attr;
attr = new DefaultAttribute(GetAttributeType(type));
attr = new DefaultAttribute(GetAttributeType(type),
ImmutableArray.Create<CustomAttributeTypedArgument<IType>>(),
ImmutableArray.Create<CustomAttributeNamedArgument<IType>>());
return LazyInit.GetOrSet(ref knownAttributes[(int)type], attr);
}
#endregion
#region Visibility Filter
internal bool IsVisible(FieldAttributes attributes)
internal bool IncludeInternalMembers => (options & TypeSystemOptions.OnlyPublicAPI) == 0;
internal bool IsVisible(FieldAttributes att)
{
return true;
att &= FieldAttributes.FieldAccessMask;
return IncludeInternalMembers
|| att == FieldAttributes.Public
|| att == FieldAttributes.Family
|| att == FieldAttributes.FamORAssem;
}
internal bool IsVisible(MethodAttributes att)
{
att &= MethodAttributes.MemberAccessMask;
return IncludeInternalMembers
|| att == MethodAttributes.Public
|| att == MethodAttributes.Family
|| att == MethodAttributes.FamORAssem;
}
#endregion
}

10
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -498,7 +498,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -498,7 +498,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// If inherit is true, an from the entity itself will be returned if possible;
/// and the base entity will only be searched if none exists.
/// </returns>
public static IAttribute GetAttribute(this IEntity entity, FullTypeName attributeType, bool inherit = true)
public static IAttribute GetAttribute(this IEntity entity, KnownAttribute attributeType, bool inherit = true)
{
return GetAttributes(entity, attributeType, inherit).FirstOrDefault();
}
@ -516,13 +516,13 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -516,13 +516,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// 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, FullTypeName attributeType, bool inherit = true)
public static IEnumerable<IAttribute> GetAttributes(this IEntity entity, KnownAttribute attributeType, bool inherit = true)
{
if (entity == null)
throw new ArgumentNullException("entity");
return GetAttributes(entity, attrType => {
ITypeDefinition typeDef = attrType.GetDefinition();
return typeDef != null && typeDef.FullTypeName == attributeType;
return typeDef != null && typeDef.FullTypeName == attributeType.GetTypeName();
}, inherit);
}
@ -589,14 +589,12 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -589,14 +589,12 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion
#region IsCompilerGenerated
static readonly FullTypeName compilerGeneratedAttributeTypeName = new FullTypeName("System.Runtime.CompilerServices.CompilerGeneratedAttribute");
public static bool IsCompilerGenereated(this IEntity entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
return entity.GetAttribute(compilerGeneratedAttributeTypeName) != null;
return entity.GetAttribute(KnownAttribute.CompilerGenerated) != null;
}
#endregion

Loading…
Cancel
Save