Browse Source

Started work on new resolved TS implementation that directly uses SRM.

This is a work-in-progress; ILSpy is not functional with this commit.
The old code path still exists but is broken because some classes were modified for the new system.
The new system is still highly incomplete (types only have fields, but no methods).
pull/1198/head
Daniel Grunwald 7 years ago
parent
commit
0f8c310de2
  1. 1
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 6
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  3. 38
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.cs
  4. 110
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.il
  5. 107
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.il
  6. 111
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.roslyn.il
  7. 114
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.roslyn.il
  8. 26
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  9. 2
      ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
  10. 8
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  11. 121
      ICSharpCode.Decompiler/CSharp/TypeSystem/MethodTypeParameterWithInheritedConstraints.cs
  12. 16
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  13. 12
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  14. 5
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
  15. 217
      ICSharpCode.Decompiler/Metadata/CustomAttributeDecoder.cs
  16. 37
      ICSharpCode.Decompiler/Metadata/Dom.cs
  17. 28
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  18. 11
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  19. 83
      ICSharpCode.Decompiler/SRMExtensions.cs
  20. 6
      ICSharpCode.Decompiler/Semantics/ArrayCreateResolveResult.cs
  21. 9
      ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs
  22. 58
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  23. 4
      ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs
  24. 63
      ICSharpCode.Decompiler/TypeSystem/GenericContext.cs
  25. 9
      ICSharpCode.Decompiler/TypeSystem/IAssembly.cs
  26. 5
      ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs
  27. 20
      ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs
  28. 293
      ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
  29. 131
      ICSharpCode.Decompiler/TypeSystem/Implementation/CustomAttribute.cs
  30. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs
  31. 185
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedTypeParameter.cs
  32. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultUnresolvedAssembly.cs
  33. 92
      ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
  34. 215
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
  35. 99
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataNamespace.cs
  36. 487
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
  37. 124
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeParameter.cs
  38. 24
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeReference.cs
  39. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/SimpleCompilation.cs
  40. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs
  41. 4
      ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
  42. 2
      ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs
  43. 290
      ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs
  44. 48
      ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs
  45. 130
      ICSharpCode.Decompiler/TypeSystem/ModifiedType.cs
  46. 2
      ICSharpCode.Decompiler/TypeSystem/TopLevelTypeName.cs
  47. 10
      ICSharpCode.Decompiler/TypeSystem/TypeKind.cs
  48. 39
      ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs
  49. 37
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
  50. 13
      ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs
  51. 3
      ILSpy/Languages/CSharpLanguage.cs
  52. 2
      ILSpy/SearchPane.cs

1
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -68,6 +68,7 @@ @@ -68,6 +68,7 @@
<Compile Include="DataFlowTest.cs" />
<Compile Include="TestCases\Correctness\RefLocalsAndReturns.cs" />
<Compile Include="TestCases\Pretty\Issue1080.cs" />
<Compile Include="TestCases\Pretty\MemberTests.cs" />
<Compile Include="TestCases\Pretty\NamedArguments.cs" />
<Compile Include="TestCases\Pretty\QualifierTests.cs" />
<Compile Include="TestCases\Pretty\RefLocalsAndReturns.cs" />

6
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -297,6 +297,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -297,6 +297,12 @@ namespace ICSharpCode.Decompiler.Tests
RunForLibrary(cscOptions: cscOptions);
}
[Test]
public void MemberTests([ValueSource("defaultOptions")] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions);
}
void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CSharpCompilerOptions cscOptions = CSharpCompilerOptions.None, DecompilerSettings decompilerSettings = null)
{
Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CSharpCompilerOptions.Library, decompilerSettings);

38
ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.cs

@ -0,0 +1,38 @@ @@ -0,0 +1,38 @@
// Copyright (c) 2008 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;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
internal class MemberTests
{
public const int IntConstant = 1;
public const decimal DecimalConstant = 2m;
private volatile int volatileField = 3;
private static volatile int staticVolatileField = 4;
public void UseVolatileFields()
{
Console.WriteLine(volatileField + staticVolatileField);
volatileField++;
staticVolatileField++;
}
}
}

110
ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.il

@ -0,0 +1,110 @@ @@ -0,0 +1,110 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly MemberTests
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module MemberTests.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests
extends [mscorlib]System.Object
{
.field public static literal int32 IntConstant = int32(0x00000001)
.field public static initonly valuetype [mscorlib]System.Decimal DecimalConstant
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00
00 00 )
.field private int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) volatileField
.field private static int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) staticVolatileField
.method public hidebysig instance void
UseVolatileFields() cil managed
{
// Code size 58 (0x3a)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: volatile.
IL_0004: ldfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0009: volatile.
IL_000b: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0010: add
IL_0011: call void [mscorlib]System.Console::WriteLine(int32)
IL_0016: nop
IL_0017: ldarg.0
IL_0018: dup
IL_0019: volatile.
IL_001b: ldfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0020: ldc.i4.1
IL_0021: add
IL_0022: volatile.
IL_0024: stfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0029: volatile.
IL_002b: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0030: ldc.i4.1
IL_0031: add
IL_0032: volatile.
IL_0034: stsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0039: ret
} // end of method MemberTests::UseVolatileFields
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.3
IL_0002: volatile.
IL_0004: stfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0009: ldarg.0
IL_000a: call instance void [mscorlib]System.Object::.ctor()
IL_000f: nop
IL_0010: ret
} // end of method MemberTests::.ctor
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 20 (0x14)
.maxstack 8
IL_0000: ldc.i4.2
IL_0001: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0006: stsfld valuetype [mscorlib]System.Decimal ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::DecimalConstant
IL_000b: ldc.i4.4
IL_000c: volatile.
IL_000e: stsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0013: ret
} // end of method MemberTests::.cctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

107
ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.il

@ -0,0 +1,107 @@ @@ -0,0 +1,107 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly MemberTests.opt
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module MemberTests.opt.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests
extends [mscorlib]System.Object
{
.field public static literal int32 IntConstant = int32(0x00000001)
.field public static initonly valuetype [mscorlib]System.Decimal DecimalConstant
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00
00 00 )
.field private int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) volatileField
.field private static int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) staticVolatileField
.method public hidebysig instance void
UseVolatileFields() cil managed
{
// Code size 56 (0x38)
.maxstack 8
IL_0000: ldarg.0
IL_0001: volatile.
IL_0003: ldfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0008: volatile.
IL_000a: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_000f: add
IL_0010: call void [mscorlib]System.Console::WriteLine(int32)
IL_0015: ldarg.0
IL_0016: dup
IL_0017: volatile.
IL_0019: ldfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_001e: ldc.i4.1
IL_001f: add
IL_0020: volatile.
IL_0022: stfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0027: volatile.
IL_0029: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_002e: ldc.i4.1
IL_002f: add
IL_0030: volatile.
IL_0032: stsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0037: ret
} // end of method MemberTests::UseVolatileFields
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 16 (0x10)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.3
IL_0002: volatile.
IL_0004: stfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0009: ldarg.0
IL_000a: call instance void [mscorlib]System.Object::.ctor()
IL_000f: ret
} // end of method MemberTests::.ctor
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 20 (0x14)
.maxstack 8
IL_0000: ldc.i4.2
IL_0001: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0006: stsfld valuetype [mscorlib]System.Decimal ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::DecimalConstant
IL_000b: ldc.i4.4
IL_000c: volatile.
IL_000e: stsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0013: ret
} // end of method MemberTests::.cctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

111
ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.opt.roslyn.il

@ -0,0 +1,111 @@ @@ -0,0 +1,111 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly MemberTests
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 02 00 00 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module MemberTests.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests
extends [mscorlib]System.Object
{
.field public static literal int32 IntConstant = int32(0x00000001)
.field public static initonly valuetype [mscorlib]System.Decimal DecimalConstant
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00
00 00 )
.field private int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) volatileField
.field private static int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) staticVolatileField
.method public hidebysig instance void
UseVolatileFields() cil managed
{
// Code size 56 (0x38)
.maxstack 8
IL_0000: ldarg.0
IL_0001: volatile.
IL_0003: ldfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0008: volatile.
IL_000a: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_000f: add
IL_0010: call void [mscorlib]System.Console::WriteLine(int32)
IL_0015: ldarg.0
IL_0016: ldarg.0
IL_0017: volatile.
IL_0019: ldfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_001e: ldc.i4.1
IL_001f: add
IL_0020: volatile.
IL_0022: stfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0027: volatile.
IL_0029: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_002e: ldc.i4.1
IL_002f: add
IL_0030: volatile.
IL_0032: stsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0037: ret
} // end of method MemberTests::UseVolatileFields
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 16 (0x10)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.3
IL_0002: volatile.
IL_0004: stfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0009: ldarg.0
IL_000a: call instance void [mscorlib]System.Object::.ctor()
IL_000f: ret
} // end of method MemberTests::.ctor
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 20 (0x14)
.maxstack 8
IL_0000: ldc.i4.2
IL_0001: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0006: stsfld valuetype [mscorlib]System.Decimal ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::DecimalConstant
IL_000b: ldc.i4.4
IL_000c: volatile.
IL_000e: stsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0013: ret
} // end of method MemberTests::.cctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

114
ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.roslyn.il

@ -0,0 +1,114 @@ @@ -0,0 +1,114 @@
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly MemberTests
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 07 01 00 00 00 00 )
.permissionset reqmin
= {[mscorlib]System.Security.Permissions.SecurityPermissionAttribute = {property bool 'SkipVerification' = bool(true)}}
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module MemberTests.dll
.custom instance void [mscorlib]System.Security.UnverifiableCodeAttribute::.ctor() = ( 01 00 00 00 )
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// =============== CLASS MEMBERS DECLARATION ===================
.class private auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests
extends [mscorlib]System.Object
{
.field public static literal int32 IntConstant = int32(0x00000001)
.field public static initonly valuetype [mscorlib]System.Decimal DecimalConstant
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32) = ( 01 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00
00 00 )
.field private int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) volatileField
.field private static int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) staticVolatileField
.method public hidebysig instance void
UseVolatileFields() cil managed
{
// Code size 58 (0x3a)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: volatile.
IL_0004: ldfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0009: volatile.
IL_000b: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0010: add
IL_0011: call void [mscorlib]System.Console::WriteLine(int32)
IL_0016: nop
IL_0017: ldarg.0
IL_0018: ldarg.0
IL_0019: volatile.
IL_001b: ldfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0020: ldc.i4.1
IL_0021: add
IL_0022: volatile.
IL_0024: stfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0029: volatile.
IL_002b: ldsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0030: ldc.i4.1
IL_0031: add
IL_0032: volatile.
IL_0034: stsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0039: ret
} // end of method MemberTests::UseVolatileFields
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldc.i4.3
IL_0002: volatile.
IL_0004: stfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::volatileField
IL_0009: ldarg.0
IL_000a: call instance void [mscorlib]System.Object::.ctor()
IL_000f: nop
IL_0010: ret
} // end of method MemberTests::.ctor
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 20 (0x14)
.maxstack 8
IL_0000: ldc.i4.2
IL_0001: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0006: stsfld valuetype [mscorlib]System.Decimal ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::DecimalConstant
IL_000b: ldc.i4.4
IL_000c: volatile.
IL_000e: stsfld int32 modreq([mscorlib]System.Runtime.CompilerServices.IsVolatile) ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests::staticVolatileField
IL_0013: ret
} // end of method MemberTests::.cctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Pretty.MemberTests
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

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

@ -18,10 +18,13 @@ @@ -18,10 +18,13 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
@ -32,24 +35,29 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -32,24 +35,29 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
[TestFixture]
public class TypeSystemLoaderTests
{
static readonly Lazy<IUnresolvedAssembly> mscorlib = new Lazy<IUnresolvedAssembly>(
static PEFile LoadAssembly(string filename)
{
return new PEFile(filename, new FileStream(filename, FileMode.Open, FileAccess.Read));
}
static readonly Lazy<PEFile> mscorlib = new Lazy<PEFile>(
delegate {
return new MetadataLoader().LoadAssemblyFile(typeof(object).Assembly.Location);
return LoadAssembly(typeof(object).Assembly.Location);
});
static readonly Lazy<IUnresolvedAssembly> systemCore = new Lazy<IUnresolvedAssembly>(
static readonly Lazy<PEFile> systemCore = new Lazy<PEFile>(
delegate {
return new MetadataLoader().LoadAssemblyFile(typeof(System.Linq.Enumerable).Assembly.Location);
return LoadAssembly(typeof(System.Linq.Enumerable).Assembly.Location);
});
static readonly Lazy<IUnresolvedAssembly> testAssembly = new Lazy<IUnresolvedAssembly>(
static readonly Lazy<PEFile> testAssembly = new Lazy<PEFile>(
delegate {
return new MetadataLoader { IncludeInternalMembers = true }.LoadAssemblyFile(typeof(SimplePublicClass).Assembly.Location);
return LoadAssembly(typeof(SimplePublicClass).Assembly.Location);
});
public static IUnresolvedAssembly Mscorlib { get { return mscorlib.Value; } }
public static IUnresolvedAssembly SystemCore { get { return systemCore.Value; } }
public static IUnresolvedAssembly TestAssembly { get { return testAssembly.Value; } }
public static PEFile Mscorlib { get { return mscorlib.Value; } }
public static PEFile SystemCore { get { return systemCore.Value; } }
public static PEFile TestAssembly { get { return testAssembly.Value; } }
[OneTimeSetUp]
public void FixtureSetUp()

2
ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs

@ -21,7 +21,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -21,7 +21,7 @@ namespace ICSharpCode.Decompiler.CSharp
{
public static void CollectNamespaces(DecompilerTypeSystem typeSystem, HashSet<string> namespaces)
{
foreach (var type in typeSystem.MainAssembly.GetAllTypeDefinitions()) {
foreach (var type in typeSystem.MainAssembly.TypeDefinitions) {
CollectNamespaces(type, typeSystem, namespaces);
}
}

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

@ -437,12 +437,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -437,12 +437,16 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
foreach (ResolveResult arg in attribute.PositionalArguments) {
attr.Arguments.Add(ConvertConstantValue(arg));
}
if (attribute.NamedArguments.Count > 0) {
InitializedObjectResolveResult targetResult = new InitializedObjectResolveResult(attribute.AttributeType);
foreach (var pair in attribute.NamedArguments) {
NamedExpression namedArgument = new NamedExpression(pair.Key.Name, ConvertConstantValue(pair.Value));
if (AddResolveResultAnnotations)
namedArgument.AddAnnotation(new MemberResolveResult(new InitializedObjectResolveResult(attribute.AttributeType), pair.Key));
if (AddResolveResultAnnotations) {
namedArgument.AddAnnotation(new MemberResolveResult(targetResult, pair.Key));
}
attr.Arguments.Add(namedArgument);
}
}
return attr;
}
#endregion

121
ICSharpCode.Decompiler/CSharp/TypeSystem/MethodTypeParameterWithInheritedConstraints.cs

@ -1,121 +0,0 @@ @@ -1,121 +0,0 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// 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.Linq;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.CSharp.TypeSystem
{
[Serializable]
public sealed class MethodTypeParameterWithInheritedConstraints : DefaultUnresolvedTypeParameter
{
public MethodTypeParameterWithInheritedConstraints(int index, string name)
: base(SymbolKind.Method, index, name)
{
}
static ITypeParameter ResolveBaseTypeParameter(IMethod parentMethod, int index)
{
IMethod baseMethod = null;
if (parentMethod.IsOverride) {
foreach (IMethod m in InheritanceHelper.GetBaseMembers(parentMethod, false).OfType<IMethod>()) {
if (!m.IsOverride) {
baseMethod = m;
break;
}
}
} else if (parentMethod.IsExplicitInterfaceImplementation && parentMethod.ImplementedInterfaceMembers.Count == 1) {
baseMethod = parentMethod.ImplementedInterfaceMembers[0] as IMethod;
}
if (baseMethod != null && index < baseMethod.TypeParameters.Count)
return baseMethod.TypeParameters[index];
else
return null;
}
public override ITypeParameter CreateResolvedTypeParameter(ITypeResolveContext context)
{
if (context.CurrentMember is IMethod) {
return new ResolvedMethodTypeParameterWithInheritedConstraints(this, context);
} else {
return base.CreateResolvedTypeParameter(context);
}
}
sealed class ResolvedMethodTypeParameterWithInheritedConstraints : AbstractTypeParameter
{
volatile ITypeParameter baseTypeParameter;
public ResolvedMethodTypeParameterWithInheritedConstraints(MethodTypeParameterWithInheritedConstraints unresolved, ITypeResolveContext context)
: base(context.CurrentMember, unresolved.Index, unresolved.Name, unresolved.Variance,
unresolved.Attributes.CreateResolvedAttributes(context))
{
}
ITypeParameter GetBaseTypeParameter()
{
ITypeParameter baseTP = this.baseTypeParameter;
if (baseTP == null) {
// ResolveBaseTypeParameter() is idempotent, so this is thread-safe.
this.baseTypeParameter = baseTP = ResolveBaseTypeParameter((IMethod)this.Owner, this.Index);
}
return baseTP;
}
public override bool HasValueTypeConstraint {
get {
ITypeParameter baseTP = GetBaseTypeParameter();
return baseTP != null ? baseTP.HasValueTypeConstraint : false;
}
}
public override bool HasReferenceTypeConstraint {
get {
ITypeParameter baseTP = GetBaseTypeParameter();
return baseTP != null ? baseTP.HasReferenceTypeConstraint : false;
}
}
public override bool HasDefaultConstructorConstraint {
get {
ITypeParameter baseTP = GetBaseTypeParameter();
return baseTP != null ? baseTP.HasDefaultConstructorConstraint : false;
}
}
public override IEnumerable<IType> DirectBaseTypes {
get {
ITypeParameter baseTP = GetBaseTypeParameter();
if (baseTP != null) {
// Substitute occurrences of the base method's type parameters in the constraints
// with the type parameters from the
IMethod owner = (IMethod)this.Owner;
var substitution = new TypeParameterSubstitution(null, owner.TypeParameters);
return baseTP.DirectBaseTypes.Select(t => t.AcceptVisitor(substitution));
} else {
return EmptyList<IType>.Instance;
}
}
}
}
}
}

16
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -285,6 +285,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -285,6 +285,9 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine();
}
foreach (var p in methodDefinition.GetGenericParameters()) {
WriteGenericParameterAttributes(module, p);
}
foreach (var p in methodDefinition.GetParameters()) {
WriteParameterAttributes(module, p);
}
@ -940,6 +943,17 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -940,6 +943,17 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
void WriteGenericParameterAttributes(PEFile module, GenericParameterHandle handle)
{
var metadata = module.Metadata;
var p = metadata.GetGenericParameter(handle);
if (p.GetCustomAttributes().Count == 0)
return;
output.Write(".param type {0}", metadata.GetString(p.Name));
output.WriteLine();
WriteAttributes(module, p.GetCustomAttributes());
}
void WriteParameterAttributes(PEFile module, ParameterHandle handle)
{
var metadata = module.Metadata;
@ -1576,7 +1590,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1576,7 +1590,7 @@ namespace ICSharpCode.Decompiler.Disassembler
public void WriteModuleContents(PEFile module)
{
foreach (var handle in module.TypeDefinitions) {
foreach (var handle in module.TopLevelTypeDefinitions) {
DisassembleType(handle);
output.WriteLine();
}

12
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -240,7 +240,6 @@ @@ -240,7 +240,6 @@
<Compile Include="CSharp\TypeSystem\AliasNamespaceReference.cs" />
<Compile Include="CSharp\TypeSystem\CSharpTypeResolveContext.cs" />
<Compile Include="CSharp\TypeSystem\MemberTypeOrNamespaceReference.cs" />
<Compile Include="CSharp\TypeSystem\MethodTypeParameterWithInheritedConstraints.cs" />
<Compile Include="CSharp\TypeSystem\ResolvedUsingScope.cs" />
<Compile Include="CSharp\TypeSystem\SimpleTypeOrNamespaceReference.cs" />
<Compile Include="CSharp\TypeSystem\TypeOrNamespaceReference.cs" />
@ -280,6 +279,7 @@ @@ -280,6 +279,7 @@
<Compile Include="IL\ControlFlow\AsyncAwaitDecompiler.cs" />
<Compile Include="IL\ControlFlow\AwaitInCatchTransform.cs" />
<Compile Include="IL\ControlFlow\YieldReturnDecompiler.cs" />
<Compile Include="Metadata\CustomAttributeDecoder.cs" />
<Compile Include="Metadata\Dom.cs" />
<Compile Include="Metadata\MetadataResolver.cs" />
<Compile Include="Metadata\DotNetCorePathFinder.cs" />
@ -339,8 +339,18 @@ @@ -339,8 +339,18 @@
<Compile Include="SRMExtensions.cs" />
<Compile Include="SRMHacks.cs" />
<Compile Include="TypeSystem\ApplyAttributeTypeVisitor.cs" />
<Compile Include="TypeSystem\GenericContext.cs" />
<Compile Include="TypeSystem\Implementation\AttributeListBuilder.cs" />
<Compile Include="TypeSystem\Implementation\CustomAttribute.cs" />
<Compile Include="TypeSystem\Implementation\FakeMember.cs" />
<Compile Include="TypeSystem\Implementation\KnownAttributes.cs" />
<Compile Include="TypeSystem\Implementation\MetadataField.cs" />
<Compile Include="TypeSystem\Implementation\MetadataNamespace.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeDefinition.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeReference.cs" />
<Compile Include="TypeSystem\MetadataAssembly.cs" />
<Compile Include="TypeSystem\ModifiedType.cs" />
<Compile Include="TypeSystem\Implementation\TypeSpecification.cs" />
<Compile Include="Metadata\MetadataExtensions.cs" />
<Compile Include="Semantics\TupleResolveResult.cs" />

5
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -359,10 +359,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -359,10 +359,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
static string GetNameByType(IType type)
{
var git = type as ParameterizedType;
if (git != null && git.FullName == "System.Nullable`1" && git.TypeArguments.Count == 1) {
type = git.TypeArguments[0];
}
type = NullableType.GetUnderlyingType(type);
string name;
if (type is ArrayType) {

217
ICSharpCode.Decompiler/Metadata/CustomAttributeDecoder.cs

@ -0,0 +1,217 @@ @@ -0,0 +1,217 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.Metadata
{
/// <summary>
/// Decodes custom attribute blobs.
/// </summary>
internal readonly struct CustomAttributeDecoder<TType>
{
// This is a stripped-down copy of SRM's internal CustomAttributeDecoder.
// We need it to decode security declarations.
private readonly ICustomAttributeTypeProvider<TType> _provider;
private readonly MetadataReader _reader;
public CustomAttributeDecoder(ICustomAttributeTypeProvider<TType> provider, MetadataReader reader)
{
_reader = reader;
_provider = provider;
}
public ImmutableArray<CustomAttributeNamedArgument<TType>> DecodeNamedArguments(ref BlobReader valueReader, int count)
{
var arguments = ImmutableArray.CreateBuilder<CustomAttributeNamedArgument<TType>>(count);
for (int i = 0; i < count; i++) {
CustomAttributeNamedArgumentKind kind = (CustomAttributeNamedArgumentKind)valueReader.ReadSerializationTypeCode();
if (kind != CustomAttributeNamedArgumentKind.Field && kind != CustomAttributeNamedArgumentKind.Property) {
throw new BadImageFormatException();
}
ArgumentTypeInfo info = DecodeNamedArgumentType(ref valueReader);
string name = valueReader.ReadSerializedString();
CustomAttributeTypedArgument<TType> argument = DecodeArgument(ref valueReader, info);
arguments.Add(new CustomAttributeNamedArgument<TType>(name, kind, argument.Type, argument.Value));
}
return arguments.MoveToImmutable();
}
private struct ArgumentTypeInfo
{
public TType Type;
public TType ElementType;
public SerializationTypeCode TypeCode;
public SerializationTypeCode ElementTypeCode;
}
private ArgumentTypeInfo DecodeNamedArgumentType(ref BlobReader valueReader, bool isElementType = false)
{
var info = new ArgumentTypeInfo {
TypeCode = valueReader.ReadSerializationTypeCode(),
};
switch (info.TypeCode) {
case SerializationTypeCode.Boolean:
case SerializationTypeCode.Byte:
case SerializationTypeCode.Char:
case SerializationTypeCode.Double:
case SerializationTypeCode.Int16:
case SerializationTypeCode.Int32:
case SerializationTypeCode.Int64:
case SerializationTypeCode.SByte:
case SerializationTypeCode.Single:
case SerializationTypeCode.String:
case SerializationTypeCode.UInt16:
case SerializationTypeCode.UInt32:
case SerializationTypeCode.UInt64:
info.Type = _provider.GetPrimitiveType((PrimitiveTypeCode)info.TypeCode);
break;
case SerializationTypeCode.Type:
info.Type = _provider.GetSystemType();
break;
case SerializationTypeCode.TaggedObject:
info.Type = _provider.GetPrimitiveType(PrimitiveTypeCode.Object);
break;
case SerializationTypeCode.SZArray:
if (isElementType) {
// jagged arrays are not allowed.
throw new BadImageFormatException();
}
var elementInfo = DecodeNamedArgumentType(ref valueReader, isElementType: true);
info.ElementType = elementInfo.Type;
info.ElementTypeCode = elementInfo.TypeCode;
info.Type = _provider.GetSZArrayType(info.ElementType);
break;
case SerializationTypeCode.Enum:
string typeName = valueReader.ReadSerializedString();
info.Type = _provider.GetTypeFromSerializedName(typeName);
info.TypeCode = (SerializationTypeCode)_provider.GetUnderlyingEnumType(info.Type);
break;
default:
throw new BadImageFormatException();
}
return info;
}
private CustomAttributeTypedArgument<TType> DecodeArgument(ref BlobReader valueReader, ArgumentTypeInfo info)
{
if (info.TypeCode == SerializationTypeCode.TaggedObject) {
info = DecodeNamedArgumentType(ref valueReader);
}
// PERF_TODO: https://github.com/dotnet/corefx/issues/6533
// Cache /reuse common arguments to avoid boxing (small integers, true, false).
object value;
switch (info.TypeCode) {
case SerializationTypeCode.Boolean:
value = valueReader.ReadBoolean();
break;
case SerializationTypeCode.Byte:
value = valueReader.ReadByte();
break;
case SerializationTypeCode.Char:
value = valueReader.ReadChar();
break;
case SerializationTypeCode.Double:
value = valueReader.ReadDouble();
break;
case SerializationTypeCode.Int16:
value = valueReader.ReadInt16();
break;
case SerializationTypeCode.Int32:
value = valueReader.ReadInt32();
break;
case SerializationTypeCode.Int64:
value = valueReader.ReadInt64();
break;
case SerializationTypeCode.SByte:
value = valueReader.ReadSByte();
break;
case SerializationTypeCode.Single:
value = valueReader.ReadSingle();
break;
case SerializationTypeCode.UInt16:
value = valueReader.ReadUInt16();
break;
case SerializationTypeCode.UInt32:
value = valueReader.ReadUInt32();
break;
case SerializationTypeCode.UInt64:
value = valueReader.ReadUInt64();
break;
case SerializationTypeCode.String:
value = valueReader.ReadSerializedString();
break;
case SerializationTypeCode.Type:
string typeName = valueReader.ReadSerializedString();
value = _provider.GetTypeFromSerializedName(typeName);
break;
case SerializationTypeCode.SZArray:
value = DecodeArrayArgument(ref valueReader, info);
break;
default:
throw new BadImageFormatException();
}
return new CustomAttributeTypedArgument<TType>(info.Type, value);
}
private ImmutableArray<CustomAttributeTypedArgument<TType>>? DecodeArrayArgument(ref BlobReader blobReader, ArgumentTypeInfo info)
{
int count = blobReader.ReadInt32();
if (count == -1) {
return null;
}
if (count == 0) {
return ImmutableArray<CustomAttributeTypedArgument<TType>>.Empty;
}
if (count < 0) {
throw new BadImageFormatException();
}
var elementInfo = new ArgumentTypeInfo {
Type = info.ElementType,
TypeCode = info.ElementTypeCode,
};
var array = ImmutableArray.CreateBuilder<CustomAttributeTypedArgument<TType>>(count);
for (int i = 0; i < count; i++) {
array.Add(DecodeArgument(ref blobReader, elementInfo));
}
return array.MoveToImmutable();
}
}
}

37
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -92,7 +92,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -92,7 +92,7 @@ namespace ICSharpCode.Decompiler.Metadata
Net_4_0
}
public class PEFile : IDisposable
public class PEFile : IDisposable, TypeSystem.IAssemblyReference
{
public string FileName { get; }
public PEReader Reader { get; }
@ -150,7 +150,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -150,7 +150,7 @@ namespace ICSharpCode.Decompiler.Metadata
public ImmutableArray<AssemblyReference> AssemblyReferences => Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray();
public ImmutableArray<ModuleReferenceHandle> ModuleReferences => Metadata.GetModuleReferences().ToImmutableArray();
public ImmutableArray<TypeDefinition> TypeDefinitions => Metadata.GetTopLevelTypeDefinitions().Select(t => new TypeDefinition(this, t)).ToImmutableArray();
public ImmutableArray<TypeDefinition> TopLevelTypeDefinitions => Metadata.GetTopLevelTypeDefinitions().Select(t => new TypeDefinition(this, t)).ToImmutableArray();
public ImmutableArray<Resource> Resources => GetResources().ToImmutableArray();
IEnumerable<Resource> GetResources()
@ -165,6 +165,39 @@ namespace ICSharpCode.Decompiler.Metadata @@ -165,6 +165,39 @@ namespace ICSharpCode.Decompiler.Metadata
{
Reader.Dispose();
}
Dictionary<TopLevelTypeName, TypeDefinitionHandle> typeLookup;
/// <summary>
/// Finds the top-level-type with the specified name.
/// </summary>
public TypeDefinitionHandle GetTypeDefinition(TopLevelTypeName typeName)
{
var lookup = LazyInit.VolatileRead(ref typeLookup);
if (lookup == null) {
lookup = new Dictionary<TopLevelTypeName, TypeDefinitionHandle>();
foreach (var handle in Metadata.TypeDefinitions) {
var td = Metadata.GetTypeDefinition(handle);
if (!td.GetDeclaringType().IsNil) {
continue; // nested type
}
var nsHandle = td.Namespace;
string ns = nsHandle.IsNil ? string.Empty : Metadata.GetString(nsHandle);
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(Metadata.GetString(td.Name), out int typeParameterCount);
lookup[new TopLevelTypeName(ns, name, typeParameterCount)] = handle;
}
lookup = LazyInit.GetOrSet(ref typeLookup, lookup);
}
if (lookup.TryGetValue(typeName, out var resultHandle))
return resultHandle;
else
return default;
}
IAssembly TypeSystem.IAssemblyReference.Resolve(ITypeResolveContext context)
{
return new MetadataAssembly(context.Compilation, this, TypeSystemOptions.Default);
}
}
public enum ResourceType

28
ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -64,29 +64,9 @@ namespace ICSharpCode.Decompiler.Metadata @@ -64,29 +64,9 @@ namespace ICSharpCode.Decompiler.Metadata
public static IEnumerable<TypeDefinitionHandle> GetTopLevelTypeDefinitions(this MetadataReader reader)
{
unsafe HashSet<uint> GetNestedTypes()
{
byte* startPointer = reader.MetadataPointer;
int offset = reader.GetTableMetadataOffset(TableIndex.NestedClass);
int rowSize = reader.GetTableRowSize(TableIndex.NestedClass);
int rowCount = reader.GetTableRowCount(TableIndex.NestedClass);
var typeDefSize = reader.GetReferenceSize(TableIndex.TypeDef);
var set = new HashSet<uint>();
for (int row = 0; row < rowCount; row++) {
byte* ptr = startPointer + offset + rowSize * row;
uint currentTypeRow = typeDefSize == 2 ? *(ushort*)ptr : *(uint*)ptr;
set.Add(currentTypeRow);
}
return set;
}
HashSet<uint> nestedTypes = GetNestedTypes();
foreach (var handle in reader.TypeDefinitions) {
if (!nestedTypes.Contains((uint)reader.GetRowNumber(handle)))
var td = reader.GetTypeDefinition(handle);
if (td.GetDeclaringType().IsNil)
yield return handle;
}
}
@ -171,7 +151,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -171,7 +151,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
internal static readonly TypeProvider minimalCorlibTypeProvider =
new TypeProvider(MinimalCorlib.Instance.CreateCompilation().MainAssembly);
new TypeProvider(MinimalCorlib.Instance.CreateCompilation());
/// <summary>
/// An attribute type provider that can be used to decode attribute signatures
@ -187,7 +167,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -187,7 +167,7 @@ namespace ICSharpCode.Decompiler.Metadata
foreach (var h in td.GetCustomAttributes()) {
var ca = reader.GetCustomAttribute(h);
if (ca.GetAttributeType(reader).IsTopLevelType(reader, "System.Reflection", "DefaultMemberAttribute")) {
if (ca.IsKnownAttribute(reader, KnownAttribute.DefaultMember)) {
var decodedValues = ca.DecodeValue(minimalCorlibTypeProvider);
if (decodedValues.FixedArguments.Length == 1 && decodedValues.FixedArguments[0].Value is string value) {
defaultMemberAttribute = h;

11
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -25,6 +25,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax; @@ -25,6 +25,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler
{
@ -106,15 +107,15 @@ namespace ICSharpCode.Decompiler @@ -106,15 +107,15 @@ namespace ICSharpCode.Decompiler
var definition = type.GetDefinition();
if (definition == null)
return null;
return new TypeDefinition(typeSystem.GetModuleDefinition(definition.ParentAssembly), (System.Reflection.Metadata.TypeDefinitionHandle)definition.MetadataToken);
return new TypeDefinition(typeSystem.GetModuleDefinition(definition.ParentAssembly), (SRM.TypeDefinitionHandle)definition.MetadataToken);
case IMethod method:
return new MethodDefinition(typeSystem.GetModuleDefinition(method.ParentAssembly), (System.Reflection.Metadata.MethodDefinitionHandle)method.MetadataToken);
return new MethodDefinition(typeSystem.GetModuleDefinition(method.ParentAssembly), (SRM.MethodDefinitionHandle)method.MetadataToken);
case IProperty property:
return new PropertyDefinition(typeSystem.GetModuleDefinition(property.ParentAssembly), (System.Reflection.Metadata.PropertyDefinitionHandle)property.MetadataToken);
return new PropertyDefinition(typeSystem.GetModuleDefinition(property.ParentAssembly), (SRM.PropertyDefinitionHandle)property.MetadataToken);
case IEvent @event:
return new EventDefinition(typeSystem.GetModuleDefinition(@event.ParentAssembly), (System.Reflection.Metadata.EventDefinitionHandle)@event.MetadataToken);
return new EventDefinition(typeSystem.GetModuleDefinition(@event.ParentAssembly), (SRM.EventDefinitionHandle)@event.MetadataToken);
case IField field:
return new FieldDefinition(typeSystem.GetModuleDefinition(field.ParentAssembly), (System.Reflection.Metadata.FieldDefinitionHandle)field.MetadataToken);
return new FieldDefinition(typeSystem.GetModuleDefinition(field.ParentAssembly), (SRM.FieldDefinitionHandle)field.MetadataToken);
default:
return null;
}

83
ICSharpCode.Decompiler/SRMExtensions.cs

@ -4,8 +4,10 @@ using System.Collections.Immutable; @@ -4,8 +4,10 @@ using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using SRM = System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler
@ -29,13 +31,15 @@ namespace ICSharpCode.Decompiler @@ -29,13 +31,15 @@ namespace ICSharpCode.Decompiler
public static bool IsValueType(this TypeDefinition typeDefinition, MetadataReader reader)
{
if (typeDefinition.BaseType.IsNil)
var baseType = typeDefinition.BaseType;
if (baseType.IsNil)
return false;
var baseType = typeDefinition.BaseType.GetFullTypeName(reader).ToString();
if (baseType == "System.Enum")
if (baseType.IsKnownType(reader, KnownTypeCode.Enum))
return true;
var thisType = typeDefinition.GetFullTypeName(reader).ToString();
return baseType == "System.ValueType" && thisType != "System.Enum";
if (!baseType.IsKnownType(reader, KnownTypeCode.ValueType))
return false;
var thisType = typeDefinition.GetFullTypeName(reader);
return !thisType.IsKnownType(KnownTypeCode.Enum);
}
public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader)
@ -47,7 +51,7 @@ namespace ICSharpCode.Decompiler @@ -47,7 +51,7 @@ namespace ICSharpCode.Decompiler
{
if (typeDefinition.BaseType.IsNil)
return false;
return typeDefinition.BaseType.GetFullTypeName(reader).ToString() == "System.Enum";
return typeDefinition.BaseType.IsKnownType(reader, KnownTypeCode.Enum);
}
public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader, out PrimitiveTypeCode underlyingType)
@ -60,7 +64,7 @@ namespace ICSharpCode.Decompiler @@ -60,7 +64,7 @@ namespace ICSharpCode.Decompiler
underlyingType = 0;
if (typeDefinition.BaseType.IsNil)
return false;
if (typeDefinition.BaseType.GetFullTypeName(reader).ToString() != "System.Enum")
if (!typeDefinition.BaseType.IsKnownType(reader, KnownTypeCode.Enum))
return false;
var field = reader.GetFieldDefinition(typeDefinition.GetFields().First());
var blob = reader.GetBlobReader(field.Signature);
@ -78,13 +82,13 @@ namespace ICSharpCode.Decompiler @@ -78,13 +82,13 @@ namespace ICSharpCode.Decompiler
public static bool IsDelegate(this TypeDefinition typeDefinition, MetadataReader reader)
{
var baseType = typeDefinition.BaseType;
return !baseType.IsNil && baseType.GetFullTypeName(reader).ToString() == typeof(MulticastDelegate).FullName;
return !baseType.IsNil && baseType.IsKnownType(reader, KnownTypeCode.MulticastDelegate);
}
public static bool IsExtensionMethod(this MethodDefinition methodDefinition, MetadataReader reader)
{
if (methodDefinition.HasFlag(MethodAttributes.Static)) {
return methodDefinition.GetCustomAttributes().HasAttributeOfType<System.Runtime.CompilerServices.ExtensionAttribute>(reader);
return methodDefinition.GetCustomAttributes().HasKnownAttribute(reader, KnownAttribute.Extension);
}
return false;
}
@ -92,22 +96,16 @@ namespace ICSharpCode.Decompiler @@ -92,22 +96,16 @@ namespace ICSharpCode.Decompiler
public static bool HasBody(this MethodDefinitionHandle handle, MetadataReader reader)
{
var methodDefinition = reader.GetMethodDefinition(handle);
return (methodDefinition.Attributes & MethodAttributes.Abstract) == 0 &&
(methodDefinition.Attributes & MethodAttributes.PinvokeImpl) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.InternalCall) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Native) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Unmanaged) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Runtime) == 0;
return methodDefinition.HasBody();
}
public static bool HasBody(this MethodDefinition methodDefinition)
{
return (methodDefinition.Attributes & MethodAttributes.Abstract) == 0 &&
(methodDefinition.Attributes & MethodAttributes.PinvokeImpl) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.InternalCall) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Native) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Unmanaged) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Runtime) == 0;
const MethodAttributes noBodyAttrs = MethodAttributes.Abstract | MethodAttributes.PinvokeImpl;
const MethodImplAttributes noBodyImplAttrs = MethodImplAttributes.InternalCall
| MethodImplAttributes.Native | MethodImplAttributes.Unmanaged | MethodImplAttributes.Runtime;
return (methodDefinition.Attributes & noBodyAttrs) == 0 &&
(methodDefinition.ImplAttributes & noBodyImplAttrs) == 0;
}
public static int GetCodeSize(this MethodBodyBlock body)
@ -183,14 +181,14 @@ namespace ICSharpCode.Decompiler @@ -183,14 +181,14 @@ namespace ICSharpCode.Decompiler
}
}
public static bool IsTopLevelType(this EntityHandle handle, MetadataReader reader, string namespaceName, string name, int typeParameterCount = 0)
public static bool IsKnownType(this EntityHandle handle, MetadataReader reader, KnownTypeCode knownType)
{
return GetFullTypeName(handle, reader) == new TopLevelTypeName(namespaceName, name, typeParameterCount);
return GetFullTypeName(handle, reader) == KnownTypeReference.Get(knownType).TypeName;
}
public static bool IsAttributeType(this CustomAttribute attr, MetadataReader reader, string namespaceName, string name)
internal static bool IsKnownType(this EntityHandle handle, MetadataReader reader, KnownAttribute knownType)
{
return attr.GetAttributeType(reader).IsTopLevelType(reader, namespaceName, name);
return GetFullTypeName(handle, reader) == knownType.GetTypeName();
}
public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader)
@ -296,7 +294,7 @@ namespace ICSharpCode.Decompiler @@ -296,7 +294,7 @@ namespace ICSharpCode.Decompiler
public static bool IsCompilerGenerated(this MethodDefinition method, MetadataReader metadata)
{
return method.GetCustomAttributes().HasCompilerGeneratedAttribute(metadata);
return method.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
}
public static bool IsCompilerGenerated(this FieldDefinitionHandle handle, MetadataReader metadata)
@ -306,7 +304,7 @@ namespace ICSharpCode.Decompiler @@ -306,7 +304,7 @@ namespace ICSharpCode.Decompiler
public static bool IsCompilerGenerated(this FieldDefinition field, MetadataReader metadata)
{
return field.GetCustomAttributes().HasCompilerGeneratedAttribute(metadata);
return field.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
}
public static bool IsCompilerGenerated(this TypeDefinitionHandle handle, MetadataReader metadata)
@ -316,7 +314,7 @@ namespace ICSharpCode.Decompiler @@ -316,7 +314,7 @@ namespace ICSharpCode.Decompiler
public static bool IsCompilerGenerated(this TypeDefinition type, MetadataReader metadata)
{
return type.GetCustomAttributes().HasCompilerGeneratedAttribute(metadata);
return type.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated);
}
#endregion
@ -325,7 +323,7 @@ namespace ICSharpCode.Decompiler @@ -325,7 +323,7 @@ namespace ICSharpCode.Decompiler
/// <summary>
/// Gets the type of the attribute.
/// </summary>
public static EntityHandle GetAttributeType(this CustomAttribute attribute, MetadataReader reader)
public static EntityHandle GetAttributeType(this SRM.CustomAttribute attribute, MetadataReader reader)
{
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
@ -339,40 +337,23 @@ namespace ICSharpCode.Decompiler @@ -339,40 +337,23 @@ namespace ICSharpCode.Decompiler
}
}
public static bool HasCompilerGeneratedAttribute(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata)
{
return customAttributes.HasAttributeOfType<System.Runtime.CompilerServices.CompilerGeneratedAttribute>(metadata);
}
public static bool HasParamArrayAttribute(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata)
{
return customAttributes.HasAttributeOfType<System.ParamArrayAttribute>(metadata);
}
public static bool HasDefaultMemberAttribute(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata)
{
return customAttributes.HasAttributeOfType<System.Reflection.DefaultMemberAttribute>(metadata);
}
public static bool HasAttributeOfType(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata, Type type)
internal static bool HasKnownAttribute(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata, KnownAttribute type)
{
var typeName = type.FullName;
foreach (var handle in customAttributes) {
var customAttribute = metadata.GetCustomAttribute(handle);
var attributeTypeName = customAttribute.GetAttributeType(metadata).GetFullTypeName(metadata).ToString();
if (typeName == attributeTypeName)
if (customAttribute.IsKnownAttribute(metadata, type))
return true;
}
return false;
}
public static bool HasAttributeOfType<TAttribute>(this CustomAttributeHandleCollection customAttributes, MetadataReader metadata) where TAttribute : Attribute
internal static bool IsKnownAttribute(this SRM.CustomAttribute attr, MetadataReader metadata, KnownAttribute attrType)
{
return HasAttributeOfType(customAttributes, metadata, typeof(TAttribute));
return attr.GetAttributeType(metadata).IsKnownType(metadata, attrType);
}
#endregion
public static unsafe BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile)
public static unsafe SRM.BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile)
{
if (!field.HasFlag(FieldAttributes.HasFieldRVA) || field.GetRelativeVirtualAddress() == 0)
return default;

6
ICSharpCode.Decompiler/Semantics/ArrayCreateResolveResult.cs

@ -31,15 +31,15 @@ namespace ICSharpCode.Decompiler.Semantics @@ -31,15 +31,15 @@ namespace ICSharpCode.Decompiler.Semantics
/// <summary>
/// Gets the size arguments.
/// </summary>
public readonly IList<ResolveResult> SizeArguments;
public readonly IReadOnlyList<ResolveResult> SizeArguments;
/// <summary>
/// Gets the initializer elements.
/// This field may be null if no initializer was specified.
/// </summary>
public readonly IList<ResolveResult> InitializerElements;
public readonly IReadOnlyList<ResolveResult> InitializerElements;
public ArrayCreateResolveResult(IType arrayType, IList<ResolveResult> sizeArguments, IList<ResolveResult> initializerElements)
public ArrayCreateResolveResult(IType arrayType, IReadOnlyList<ResolveResult> sizeArguments, IReadOnlyList<ResolveResult> initializerElements)
: base(arrayType)
{
if (sizeArguments == null)

9
ICSharpCode.Decompiler/TypeSystem/ApplyAttributeTypeVisitor.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
@ -40,16 +41,16 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -40,16 +41,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
if ((options & (TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple)) == TypeSystemOptions.None) {
return inputType;
}
bool useDynamicType = (options & TypeSystemOptions.Dynamic) != 0;
bool useTupleTypes = (options & TypeSystemOptions.Tuple) != 0;
bool hasDynamicAttribute = false;
bool[] dynamicAttributeData = null;
bool useTupleTypes = (options & TypeSystemOptions.Tuple) != 0;
string[] tupleElementNames = null;
if (attributes != null) {
foreach (var attrHandle in attributes.Value) {
var attr = metadata.GetCustomAttribute(attrHandle);
var attrType = attr.GetAttributeType(metadata);
if ((options & TypeSystemOptions.Dynamic) != 0
&& attrType.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "DynamicAttribute")) {
if (useDynamicType && attrType.IsKnownType(metadata, KnownAttribute.Dynamic)) {
hasDynamicAttribute = true;
var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider);
if (ctor.FixedArguments.Length == 1) {
@ -59,7 +60,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -59,7 +60,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
dynamicAttributeData = values.SelectArray(v => (bool)v.Value);
}
}
} else if (useTupleTypes && attrType.IsTopLevelType(metadata, "System.Runtime.CompilerServices", "TupleElementNamesAttribute")) {
} else if (useTupleTypes && attrType.IsKnownType(metadata, KnownAttribute.TupleElementNames)) {
var ctor = attr.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider);
if (ctor.FixedArguments.Length == 1) {
var arg = ctor.FixedArguments[0];

58
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -75,6 +75,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -75,6 +75,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
readonly ICompilation compilation;
readonly ITypeResolveContext context;
readonly TypeSystemOptions typeSystemOptions;
readonly MetadataAssembly mainAssembly;
Dictionary<SRM.EntityHandle, IField> fieldLookupCache = new Dictionary<SRM.EntityHandle, IField>();
Dictionary<SRM.EntityHandle, IProperty> propertyLookupCache = new Dictionary<SRM.EntityHandle, IProperty>();
@ -141,8 +142,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -141,8 +142,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return compilation; }
}
public IAssembly MainAssembly {
get { return compilation.MainAssembly; }
public MetadataAssembly MainAssembly {
get { return mainAssembly; }
}
public Metadata.PEFile ModuleDefinition {
@ -153,11 +154,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -153,11 +154,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
public Metadata.PEFile GetModuleDefinition(IAssembly assembly)
{
if (assembly == MainAssembly)
return ModuleDefinition;
if (!moduleLookup.TryGetValue(assembly.UnresolvedAssembly, out var file))
if (assembly is MetadataAssembly asm) {
return asm.PEFile;
}
return null;
return file;
}
public IMember ResolveAsMember(SRM.EntityHandle memberReference)
@ -193,7 +193,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -193,7 +193,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
return MetadataTypeReference.Resolve(
typeReference,
moduleDefinition.Metadata,
context,
mainAssembly.TypeProvider,
new GenericContext(),
typeSystemOptions
);
}
@ -204,7 +205,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -204,7 +205,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
return MetadataTypeReference.Resolve(
declaringTypeReference,
moduleDefinition.Metadata,
context,
mainAssembly.TypeProvider,
new GenericContext(context),
typeSystemOptions & ~(TypeSystemOptions.Dynamic | TypeSystemOptions.Tuple)
);
}
@ -216,8 +218,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -216,8 +218,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (standaloneSignature.GetKind() != SRM.StandaloneSignatureKind.Method)
throw new InvalidOperationException("Expected Method signature");
return standaloneSignature.DecodeMethodSignature(
new TypeProvider(compilation.MainAssembly),
context
mainAssembly.TypeProvider,
new GenericContext(context)
);
}
@ -227,8 +229,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -227,8 +229,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (standaloneSignature.GetKind() != SRM.StandaloneSignatureKind.LocalVariables)
throw new InvalidOperationException("Expected Local signature");
return standaloneSignature.DecodeLocalSignature(
new TypeProvider(compilation.MainAssembly),
context
mainAssembly.TypeProvider,
new GenericContext(context)
);
}
@ -294,7 +296,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -294,7 +296,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
return field;
}
}
var returnType = memberRef.DecodeFieldSignature(new TypeProvider(context.CurrentAssembly), context);
var returnType = memberRef.DecodeFieldSignature(mainAssembly.TypeProvider, new GenericContext(context));
return new FakeField(compilation) {
DeclaringType = declaringType,
Name = name,
@ -322,7 +324,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -322,7 +324,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
break;
case SRM.HandleKind.MethodSpecification:
var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference);
var methodTypeArgs = methodSpec.DecodeSignature(new TypeProvider(context.CurrentAssembly), context);
var methodTypeArgs = methodSpec.DecodeSignature(mainAssembly.TypeProvider, new GenericContext(context));
if (methodSpec.Method.Kind == SRM.HandleKind.MethodDefinition) {
// generic instance of a methoddef (=generic method in non-generic class in current assembly)
method = ResolveMethodDefinition(metadata, (SRM.MethodDefinitionHandle)methodSpec.Method);
@ -342,27 +344,9 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -342,27 +344,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
IMethod ResolveMethodDefinition(SRM.MetadataReader metadata, SRM.MethodDefinitionHandle methodDefHandle, bool expandVarArgs = true)
{
var methodDef = metadata.GetMethodDefinition(methodDefHandle);
var declaringType = ResolveDeclaringType(methodDef.GetDeclaringType());
var declaringTypeDefinition = declaringType.GetDefinition();
string name = metadata.GetString(methodDef.Name);
IMethod method;
if (declaringTypeDefinition != null) {
if (name == ".ctor") {
method = declaringTypeDefinition.GetConstructors(m => m.MetadataToken == methodDefHandle, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
} else if (name == ".cctor") {
method = declaringTypeDefinition.Methods.FirstOrDefault(m => m.MetadataToken == methodDefHandle);
} else {
method = declaringTypeDefinition.GetMethods(m => m.MetadataToken == methodDefHandle, GetMemberOptions.IgnoreInheritedMembers)
.Concat(declaringTypeDefinition.GetAccessors(m => m.MetadataToken == methodDefHandle, GetMemberOptions.IgnoreInheritedMembers)).FirstOrDefault();
}
} else {
method = null;
}
var method = mainAssembly.GetDefinition(methodDefHandle);
if (method == null) {
var signature = methodDef.DecodeSignature(new TypeProvider(context.CurrentAssembly),
context.WithCurrentTypeDefinition(declaringTypeDefinition));
method = CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), signature);
throw new NotImplementedException();
}
if (expandVarArgs && method.Parameters.LastOrDefault()?.Type.Kind == TypeKind.ArgList) {
method = new VarArgInstanceMethod(method, EmptyList<IType>.Instance);
@ -386,7 +370,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -386,7 +370,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
IMethod method;
if (memberRef.Parent.Kind == SRM.HandleKind.MethodDefinition) {
method = ResolveMethodDefinition(metadata, (SRM.MethodDefinitionHandle)memberRef.Parent, expandVarArgs: false);
signature = memberRef.DecodeMethodSignature(new TypeProvider(context.CurrentAssembly), context);
signature = memberRef.DecodeMethodSignature(mainAssembly.TypeProvider, new GenericContext(context));
} else {
var declaringType = ResolveDeclaringType(memberRef.Parent);
var declaringTypeDefinition = declaringType.GetDefinition();
@ -396,8 +380,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -396,8 +380,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
// Note: declaringType might be parameterized, but the signature is for the original method definition.
// We'll have to search the member directly on declaringTypeDefinition.
string name = metadata.GetString(memberRef.Name);
signature = memberRef.DecodeMethodSignature(new TypeProvider(context.CurrentAssembly),
context.WithCurrentTypeDefinition(declaringTypeDefinition));
signature = memberRef.DecodeMethodSignature(mainAssembly.TypeProvider,
new GenericContext(declaringTypeDefinition?.TypeParameters));
if (declaringTypeDefinition != null) {
// Find the set of overloads to search:
IEnumerable<IMethod> methods;

4
ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs

@ -34,10 +34,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -34,10 +34,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <c>NamespaceName '.' TopLevelTypeName ['`'#] { '+' NestedTypeName ['`'#] }</c>
/// </remarks>
[Serializable]
public struct FullTypeName : IEquatable<FullTypeName>
public readonly struct FullTypeName : IEquatable<FullTypeName>
{
[Serializable]
struct NestedTypeName
readonly struct NestedTypeName
{
public readonly string Name;
public readonly int AdditionalTypeParameterCount;

63
ICSharpCode.Decompiler/TypeSystem/GenericContext.cs

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
// 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.Collections.Generic;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler.TypeSystem
{
public readonly struct GenericContext
{
public readonly IReadOnlyList<ITypeParameter> ClassTypeParameters;
public readonly IReadOnlyList<ITypeParameter> MethodTypeParameters;
public GenericContext(IReadOnlyList<ITypeParameter> classTypeParameters)
{
this.ClassTypeParameters = classTypeParameters;
this.MethodTypeParameters = null;
}
public GenericContext(IReadOnlyList<ITypeParameter> classTypeParameters, IReadOnlyList<ITypeParameter> methodTypeParameters)
{
this.ClassTypeParameters = classTypeParameters;
this.MethodTypeParameters = methodTypeParameters;
}
internal GenericContext(ITypeResolveContext context)
{
this.ClassTypeParameters = context.CurrentTypeDefinition?.TypeParameters;
this.MethodTypeParameters = (context.CurrentMember as IMethod)?.TypeParameters;
}
public ITypeParameter GetClassTypeParameter(int index)
{
if (index < ClassTypeParameters?.Count)
return ClassTypeParameters[index];
else
return DummyTypeParameter.GetClassTypeParameter(index);
}
public ITypeParameter GetMethodTypeParameter(int index)
{
if (index < MethodTypeParameters?.Count)
return MethodTypeParameters[index];
else
return DummyTypeParameter.GetMethodTypeParameter(index);
}
}
}

9
ICSharpCode.Decompiler/TypeSystem/IAssembly.cs

@ -65,11 +65,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -65,11 +65,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
public interface IAssembly : ICompilationProvider
{
/// <summary>
/// Gets the original unresolved assembly.
/// </summary>
IUnresolvedAssembly UnresolvedAssembly { get; }
/// <summary>
/// Gets whether this assembly is the main assembly of the compilation.
/// </summary>
@ -120,8 +115,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -120,8 +115,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
IEnumerable<ITypeDefinition> TopLevelTypeDefinitions { get; }
/// <summary>
/// Gets the type definition from the metadata token, or null if not found.
/// Gets all types in the assembly, including nested types.
/// </summary>
ITypeDefinition ResolveTypeDefToken(TypeDefinitionHandle token);
IEnumerable<ITypeDefinition> TypeDefinitions { get; }
}
}

5
ICSharpCode.Decompiler/TypeSystem/ITypeDefinition.cs

@ -132,11 +132,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -132,11 +132,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <remarks>This property is used to speed up the search for extension methods.</remarks>
bool HasExtensionMethods { get; }
/// <summary>
/// Gets whether this type definition is made up of one or more partial classes.
/// </summary>
bool IsPartial { get; }
/// <summary>
/// Determines how this type is implementing the specified interface member.
/// </summary>

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

@ -31,10 +31,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -31,10 +31,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly IEntity owner;
readonly int index;
readonly string name;
readonly IReadOnlyList<IAttribute> attributes;
readonly VarianceModifier variance;
protected AbstractTypeParameter(IEntity owner, int index, string name, VarianceModifier variance, IReadOnlyList<IAttribute> attributes)
protected AbstractTypeParameter(IEntity owner, int index, string name, VarianceModifier variance)
{
if (owner == null)
throw new ArgumentNullException("owner");
@ -43,11 +42,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -43,11 +42,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.ownerType = owner.SymbolKind;
this.index = index;
this.name = name ?? ((this.OwnerType == SymbolKind.Method ? "!!" : "!") + index.ToString(CultureInfo.InvariantCulture));
this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
this.variance = variance;
}
protected AbstractTypeParameter(ICompilation compilation, SymbolKind ownerType, int index, string name, VarianceModifier variance, IReadOnlyList<IAttribute> attributes)
protected AbstractTypeParameter(ICompilation compilation, SymbolKind ownerType, int index, string name, VarianceModifier variance)
{
if (compilation == null)
throw new ArgumentNullException("compilation");
@ -55,7 +53,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -55,7 +53,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.ownerType = ownerType;
this.index = index;
this.name = name ?? ((this.OwnerType == SymbolKind.Method ? "!!" : "!") + index.ToString(CultureInfo.InvariantCulture));
this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
this.variance = variance;
}
@ -75,9 +72,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -75,9 +72,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return index; }
}
public IReadOnlyList<IAttribute> Attributes {
get { return attributes; }
}
public abstract IReadOnlyList<IAttribute> Attributes { get; }
public VarianceModifier Variance {
get { return variance; }
@ -247,11 +242,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -247,11 +242,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return this;
}
public ITypeReference ToTypeReference()
{
return TypeParameterReference.Create(this.OwnerType, this.Index);
}
IEnumerable<IType> IType.GetNestedTypes(Predicate<ITypeDefinition> filter, GetMemberOptions options)
{
return EmptyList<IType>.Instance;
@ -333,12 +323,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -333,12 +323,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return GetMembersHelper.GetAccessors(this, FilterNonStatic(filter), options);
}
public TypeParameterSubstitution GetSubstitution()
TypeParameterSubstitution IType.GetSubstitution()
{
return TypeParameterSubstitution.Identity;
}
public TypeParameterSubstitution GetSubstitution(IReadOnlyList<IType> methodTypeArguments)
TypeParameterSubstitution IType.GetSubstitution(IReadOnlyList<IType> methodTypeArguments)
{
return TypeParameterSubstitution.Identity;
}

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

@ -0,0 +1,293 @@ @@ -0,0 +1,293 @@
// 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.Collections.Immutable;
using System.Diagnostics;
using System.Reflection.Metadata;
using SRM = System.Reflection.Metadata;
using System.Text;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.Decompiler.Semantics;
using System.Runtime.InteropServices;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
readonly struct AttributeListBuilder
{
readonly MetadataAssembly assembly;
readonly List<IAttribute> attributes;
public AttributeListBuilder(MetadataAssembly assembly)
{
Debug.Assert(assembly != null);
this.assembly = assembly;
this.attributes = new List<IAttribute>();
}
public AttributeListBuilder(MetadataAssembly assembly, int capacity)
{
Debug.Assert(assembly != null);
this.assembly = assembly;
this.attributes = new List<IAttribute>(capacity);
}
public void Add(IAttribute attr)
{
attributes.Add(attr);
}
/// <summary>
/// Add a builtin attribute without any arguments.
/// </summary>
public void Add(KnownAttribute type)
{
// use the assemblies' cache for simple attributes
Add(assembly.MakeAttribute(type));
}
/// <summary>
/// Construct a builtin attribute with a single positional argument of known type.
/// </summary>
public void Add(KnownAttribute type, KnownTypeCode argType, object argValue)
{
Add(type, new ConstantResolveResult(assembly.Compilation.FindType(argType), argValue));
}
/// <summary>
/// Construct a builtin attribute.
/// </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)
{
var rr = new ConstantResolveResult(valueType, value);
return Implementation.CustomAttribute.MakeNamedArg(assembly.Compilation, attrType, name, rr);
}
#region MarshalAsAttribute (ConvertMarshalInfo)
internal void AddMarshalInfo(BlobHandle marshalInfo)
{
if (marshalInfo.IsNil) return;
var metadata = assembly.metadata;
Add(ConvertMarshalInfo(metadata.GetBlobReader(marshalInfo)));
}
const string InteropServices = "System.Runtime.InteropServices";
IAttribute ConvertMarshalInfo(SRM.BlobReader marshalInfo)
{
IType marshalAsAttributeType = assembly.GetAttributeType(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>>();
int size;
switch (type) {
case 0x1e: // FixedArray
if (!marshalInfo.TryReadCompressedInteger(out size))
size = 0;
namedArguments.Add(MakeNamedArg(marshalAsAttributeType, "SizeConst", KnownTypeCode.Int32, size));
if (marshalInfo.RemainingBytes > 0) {
type = marshalInfo.ReadByte();
if (type != 0x66) // None
namedArguments.Add(MakeNamedArg(marshalAsAttributeType, "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));
}
}
break;
case 0x2a: // NATIVE_TYPE_ARRAY
if (marshalInfo.RemainingBytes > 0) {
type = marshalInfo.ReadByte();
} else {
type = 0x66; // Cecil uses NativeType.None as default.
}
if (type != 0x50) { // Max
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"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));
}
if (sizeParameterMultiplier != 0 && sizeParameterIndex >= 0) {
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"SizeParamIndex", KnownTypeCode.Int16, (short)sizeParameterIndex));
}
break;
case 0x2c: // CustomMarshaler
string guidValue = marshalInfo.ReadSerializedString();
string unmanagedType = marshalInfo.ReadSerializedString();
string managedType = marshalInfo.ReadSerializedString();
string cookie = marshalInfo.ReadSerializedString();
if (managedType != null) {
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"MarshalType", KnownTypeCode.String, managedType));
}
if (!string.IsNullOrEmpty(cookie)) {
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"MarshalCookie", KnownTypeCode.String, cookie));
}
break;
case 0x17: // FixedSysString
namedArguments.Add(MakeNamedArg(marshalAsAttributeType,
"SizeConst", KnownTypeCode.Int32, marshalInfo.ReadCompressedInteger()));
break;
}
return new DefaultAttribute(marshalAsAttributeType, positionalArguments, namedArguments);
}
#endregion
#region Custom Attributes (ReadAttribute)
public void Add(CustomAttributeHandleCollection attributes)
{
var metadata = assembly.metadata;
foreach (var handle in attributes) {
var attribute = metadata.GetCustomAttribute(handle);
var ctor = assembly.ResolveMethod(attribute.Constructor);
var type = ctor.DeclaringType;
if (IgnoreAttribute(type)) {
continue;
}
Add(new CustomAttribute(assembly, ctor, handle));
}
}
bool IgnoreAttribute(IType attributeType)
{
if (attributeType.DeclaringType != null || attributeType.TypeParameterCount != 0)
return false;
switch (attributeType.Namespace) {
case "System.Runtime.CompilerServices":
var options = assembly.TypeSystemOptions;
switch (attributeType.Name) {
case "DynamicAttribute":
return (options & TypeSystemOptions.Dynamic) != 0;
case "TupleElementNamesAttribute":
return (options & TypeSystemOptions.Tuple) != 0;
case "ExtensionAttribute":
return (options & TypeSystemOptions.ExtensionMethods) != 0;
case "DecimalConstantAttribute":
return true;
default:
return false;
}
case "System":
return attributeType.Name == "ParamArrayAttribute";
default:
return false;
}
}
#endregion
#region Security Attributes
public void AddSecurityAttributes(DeclarativeSecurityAttributeHandleCollection securityDeclarations)
{
var metadata = assembly.metadata;
foreach (var secDecl in securityDeclarations) {
if (secDecl.IsNil)
continue;
AddSecurityAttributes(metadata.GetDeclarativeSecurityAttribute(secDecl));
}
}
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 metadata = assembly.metadata;
var reader = metadata.GetBlobReader(secDecl.PermissionSet);
if (reader.ReadByte() == '.') {
// binary attribute
int attributeCount = reader.ReadCompressedInteger();
for (int i = 0; i < attributeCount; i++) {
Add(ReadBinarySecurityAttribute(ref reader, securityAction));
}
} else {
// for backward compatibility with .NET 1.0: XML-encoded attribute
reader.Reset();
ReadXmlSecurityAttribute(ref reader, securityAction);
}
}
private void ReadXmlSecurityAttribute(ref SRM.BlobReader reader, ConstantResolveResult 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)
}
));
}
private IAttribute ReadBinarySecurityAttribute(ref SRM.BlobReader reader, ResolveResult securityActionRR)
{
string attributeTypeName = reader.ReadSerializedString();
IType attributeType = assembly.Compilation.FindType(new FullTypeName(attributeTypeName));
reader.ReadCompressedInteger(); // ??
// The specification seems to be incorrect here, so I'm using the logic from Cecil instead.
int numNamed = reader.ReadCompressedInteger();
var decoder = new Metadata.CustomAttributeDecoder<IType>(assembly.TypeProvider, assembly.metadata);
var namedArgs = decoder.DecodeNamedArguments(ref reader, numNamed);
return new DefaultAttribute(
attributeType,
positionalArguments: new ResolveResult[] { securityActionRR },
namedArguments: CustomAttribute.ConvertNamedArguments(assembly.Compilation, attributeType, namedArgs));
}
#endregion
public IAttribute[] Build()
{
if (attributes.Count == 0)
return Empty<IAttribute>.Array;
else
return attributes.ToArray();
}
}
}

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

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
// 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.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
/// <summary>
/// Custom attribute loaded from metadata.
/// </summary>
sealed class CustomAttribute : IAttribute
{
readonly MetadataAssembly assembly;
readonly SRM.CustomAttributeHandle handle;
public IMethod Constructor { get; }
// lazy-loaded:
IReadOnlyList<ResolveResult> positionalArguments;
IReadOnlyList<KeyValuePair<IMember, ResolveResult>> namedArguments;
internal CustomAttribute(MetadataAssembly assembly, IMethod attrCtor, SRM.CustomAttributeHandle handle)
{
Debug.Assert(assembly != null);
Debug.Assert(attrCtor != null);
Debug.Assert(!handle.IsNil);
this.assembly = assembly;
this.Constructor = attrCtor;
this.handle = handle;
}
public IType AttributeType => Constructor.DeclaringType;
public IReadOnlyList<ResolveResult> PositionalArguments {
get {
var args = LazyInit.VolatileRead(ref this.positionalArguments);
if (args != null)
return args;
DecodeValue();
return this.positionalArguments;
}
}
public IReadOnlyList<KeyValuePair<IMember, ResolveResult>> NamedArguments {
get {
var namedArgs = LazyInit.VolatileRead(ref this.namedArguments);
if (namedArgs != null)
return namedArgs;
DecodeValue();
return this.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));
}
internal static KeyValuePair<IMember, ResolveResult> MakeNamedArg(ICompilation compilation, IType attrType, string name, ResolveResult rr)
{
var field = attrType.GetFields(f => f.Name == name).FirstOrDefault();
if (field != null) {
return new KeyValuePair<IMember, ResolveResult>(field, rr);
}
var prop = attrType.GetProperties(f => f.Name == name).FirstOrDefault();
if (prop != null) {
return new KeyValuePair<IMember, ResolveResult>(prop, rr);
}
field = new FakeField(compilation) {
DeclaringType = attrType,
Name = name,
ReturnType = rr.Type
};
return new KeyValuePair<IMember, ResolveResult>(field, 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));
}
return arr;
}
private static ResolveResult ConvertArgument(IType type, object value)
{
if (value is ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> arr) {
return new ArrayCreateResolveResult(type, null, ConvertArguments(arr));
} else if (value is IType valueType) {
return new TypeOfResolveResult(type, valueType);
} else {
return new ConstantResolveResult(type, value);
}
}
private static IReadOnlyList<ResolveResult> ConvertArguments(ImmutableArray<SRM.CustomAttributeTypedArgument<IType>> arr)
{
return arr.SelectArray(arg => ConvertArgument(arg.Type, arg.Value));
}
}
}

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

@ -436,7 +436,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -436,7 +436,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
switch (this.Kind) {
case TypeKind.Class:
case TypeKind.Interface:
case TypeKind.Module:
case TypeKind.Delegate:
return true;
case TypeKind.Struct:

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

@ -27,6 +27,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -27,6 +27,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly bool hasReferenceTypeConstraint;
readonly bool hasDefaultConstructorConstraint;
readonly IReadOnlyList<IType> constraints;
readonly IReadOnlyList<IAttribute> attributes;
public DefaultTypeParameter(
IEntity owner,
@ -35,12 +36,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -35,12 +36,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IReadOnlyList<IAttribute> attributes = null,
bool hasValueTypeConstraint = false, bool hasReferenceTypeConstraint = false, bool hasDefaultConstructorConstraint = false,
IReadOnlyList<IType> constraints = null)
: base(owner, index, name, variance, attributes)
: base(owner, index, name, variance)
{
this.hasValueTypeConstraint = hasValueTypeConstraint;
this.hasReferenceTypeConstraint = hasReferenceTypeConstraint;
this.hasDefaultConstructorConstraint = hasDefaultConstructorConstraint;
this.constraints = constraints ?? EmptyList<IType>.Instance;
this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
}
public DefaultTypeParameter(
@ -50,25 +52,20 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -50,25 +52,20 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
IReadOnlyList<IAttribute> attributes = null,
bool hasValueTypeConstraint = false, bool hasReferenceTypeConstraint = false, bool hasDefaultConstructorConstraint = false,
IReadOnlyList<IType> constraints = null)
: base(compilation, ownerType, index, name, variance, attributes)
: base(compilation, ownerType, index, name, variance)
{
this.hasValueTypeConstraint = hasValueTypeConstraint;
this.hasReferenceTypeConstraint = hasReferenceTypeConstraint;
this.hasDefaultConstructorConstraint = hasDefaultConstructorConstraint;
this.constraints = constraints ?? EmptyList<IType>.Instance;
this.attributes = attributes ?? EmptyList<IAttribute>.Instance;
}
public override bool HasValueTypeConstraint {
get { return hasValueTypeConstraint; }
}
public override bool HasReferenceTypeConstraint {
get { return hasReferenceTypeConstraint; }
}
public override IReadOnlyList<IAttribute> Attributes => attributes;
public override bool HasDefaultConstructorConstraint {
get { return hasDefaultConstructorConstraint; }
}
public override bool HasValueTypeConstraint => hasValueTypeConstraint;
public override bool HasReferenceTypeConstraint => hasReferenceTypeConstraint;
public override bool HasDefaultConstructorConstraint => hasDefaultConstructorConstraint;
public override IEnumerable<IType> DirectBaseTypes {
get {
@ -85,168 +82,4 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -85,168 +82,4 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
}
/*
/// <summary>
/// Default implementation of <see cref="ITypeParameter"/>.
/// </summary>
[Serializable]
public sealed class DefaultTypeParameter : AbstractTypeParameter
{
IList<ITypeReference> constraints;
BitVector16 flags;
const ushort FlagReferenceTypeConstraint = 0x0001;
const ushort FlagValueTypeConstraint = 0x0002;
const ushort FlagDefaultConstructorConstraint = 0x0004;
protected override void FreezeInternal()
{
constraints = FreezeList(constraints);
base.FreezeInternal();
}
public DefaultTypeParameter(SymbolKind ownerType, int index, string name)
: base(ownerType, index, name)
{
}
public IList<ITypeReference> Constraints {
get {
if (constraints == null)
constraints = new List<ITypeReference>();
return constraints;
}
}
public bool HasDefaultConstructorConstraint {
get { return flags[FlagDefaultConstructorConstraint]; }
set {
CheckBeforeMutation();
flags[FlagDefaultConstructorConstraint] = value;
}
}
public bool HasReferenceTypeConstraint {
get { return flags[FlagReferenceTypeConstraint]; }
set {
CheckBeforeMutation();
flags[FlagReferenceTypeConstraint] = value;
}
}
public bool HasValueTypeConstraint {
get { return flags[FlagValueTypeConstraint]; }
set {
CheckBeforeMutation();
flags[FlagValueTypeConstraint] = value;
}
}
public override bool? IsReferenceType(ITypeResolveContext context)
{
switch (flags.Data & (FlagReferenceTypeConstraint | FlagValueTypeConstraint)) {
case FlagReferenceTypeConstraint:
return true;
case FlagValueTypeConstraint:
return false;
}
return base.IsReferenceTypeHelper(GetEffectiveBaseClass(context));
}
public override IType GetEffectiveBaseClass(ITypeResolveContext context)
{
// protect against cyclic type parameters
using (var busyLock = BusyManager.Enter(this)) {
if (!busyLock.Success)
return SpecialTypes.UnknownType;
if (HasValueTypeConstraint)
return context.GetTypeDefinition("System", "ValueType", 0, StringComparer.Ordinal) ?? SpecialTypes.UnknownType;
List<IType> classTypeConstraints = new List<IType>();
foreach (ITypeReference constraintRef in this.Constraints) {
IType constraint = constraintRef.Resolve(context);
if (constraint.Kind == TypeKind.Class) {
classTypeConstraints.Add(constraint);
} else if (constraint.Kind == TypeKind.TypeParameter) {
IType baseClass = ((ITypeParameter)constraint).GetEffectiveBaseClass(context);
if (baseClass.Kind == TypeKind.Class)
classTypeConstraints.Add(baseClass);
}
}
if (classTypeConstraints.Count == 0)
return KnownTypeReference.Object.Resolve(context);
// Find the derived-most type in the resulting set:
IType result = classTypeConstraints[0];
for (int i = 1; i < classTypeConstraints.Count; i++) {
if (classTypeConstraints[i].GetDefinition().IsDerivedFrom(result.GetDefinition(), context))
result = classTypeConstraints[i];
}
return result;
}
}
public override IEnumerable<IType> GetEffectiveInterfaceSet(ITypeResolveContext context)
{
List<IType> result = new List<IType>();
// protect against cyclic type parameters
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
foreach (ITypeReference constraintRef in this.Constraints) {
IType constraint = constraintRef.Resolve(context);
if (constraint.Kind == TypeKind.Interface) {
result.Add(constraint);
} else if (constraint.Kind == TypeKind.TypeParameter) {
result.AddRange(((ITypeParameter)constraint).GetEffectiveInterfaceSet(context));
}
}
}
}
return result.Distinct();
}
public override ITypeParameterConstraints GetConstraints(ITypeResolveContext context)
{
return new DefaultTypeParameterConstraints(
this.Constraints.Select(c => c.Resolve(context)),
this.HasDefaultConstructorConstraint, this.HasReferenceTypeConstraint, this.HasValueTypeConstraint);
}
/*
* Interning for type parameters is disabled; we can't intern cyclic structures as might
* occur in the constraints, and incomplete interning is dangerous for type parameters
* as we use reference equality.
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
// protect against cyclic constraints
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
constraints = provider.InternList(constraints);
base.PrepareForInterning(provider);
}
}
}
int ISupportsInterning.GetHashCodeForInterning()
{
unchecked {
int hashCode = base.GetHashCodeForInterning();
if (constraints != null)
hashCode += constraints.GetHashCode();
hashCode += 771 * flags.Data;
return hashCode;
}
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
DefaultTypeParameter o = other as DefaultTypeParameter;
return base.EqualsForInterning(o)
&& this.constraints == o.constraints
&& this.flags == o.flags;
}
}*/
}

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

@ -443,6 +443,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -443,6 +443,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
public IEnumerable<ITypeDefinition> TypeDefinitions {
get {
return TreeTraversal.PreOrder(TopLevelTypeDefinitions, td => td.NestedTypes);
}
}
public ITypeDefinition ResolveTypeDefToken(System.Reflection.Metadata.TypeDefinitionHandle token)
{
var td = unresolvedAssembly.GetTypeDefByToken(token);

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

@ -0,0 +1,92 @@ @@ -0,0 +1,92 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
enum KnownAttribute
{
/// <summary>
/// Not a known attribute
/// </summary>
None,
CompilerGenerated,
/// <summary>
/// Marks a method as extension method; or a class as containing extension methods.
/// </summary>
Extension,
Dynamic,
TupleElementNames,
// Assembly attributes:
AssemblyVersion,
InternalsVisibleTo,
// Type attributes:
Serializable,
ComImport,
StructLayout,
DefaultMember,
// Field attributes:
FieldOffset,
NonSerialized,
// Method attributes:
// Parameter attributes:
ParamArray,
// Marshalling attributes:
MarshalAs,
// Security attributes:
PermissionSet,
}
static class KnownAttributes
{
internal const int Count = (int)KnownAttribute.PermissionSet + 1;
static readonly TopLevelTypeName[] typeNames = new TopLevelTypeName[Count]{
default,
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CompilerGeneratedAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(ExtensionAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(DynamicAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(TupleElementNamesAttribute)),
// Assembly attributes:
new TopLevelTypeName("System.Reflection", nameof(AssemblyVersionAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(InternalsVisibleToAttribute)),
// Type attributes:
new TopLevelTypeName("System", nameof(SerializableAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(ComImportAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(StructLayoutAttribute)),
new TopLevelTypeName("System.Runtime", nameof(DefaultMemberAttribute)),
// Field attributes:
new TopLevelTypeName("System.Runtime.InteropServices", nameof(FieldOffsetAttribute)),
new TopLevelTypeName("System", nameof(NonSerializedAttribute)),
// Parameter attributes:
new TopLevelTypeName("System", nameof(ParamArrayAttribute)),
// Marshalling attributes:
new TopLevelTypeName("System.Runtime.InteropServices", nameof(MarshalAsAttribute)),
// Security attributes:
new TopLevelTypeName("System.Security", "PermissionSetAttribute"),
};
public static ref readonly TopLevelTypeName GetTypeName(this KnownAttribute attr)
{
Debug.Assert(attr != KnownAttribute.None);
return ref typeNames[(int)attr];
}
public static IType FindType(this ICompilation compilation, KnownAttribute attrType)
{
return compilation.FindType(attrType.GetTypeName());
}
}

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

@ -0,0 +1,215 @@ @@ -0,0 +1,215 @@
// 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.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.InteropServices;
using System.Threading;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
/// <summary>
/// Field definition backed by System.Reflection.Metadata
/// </summary>
class MetadataField : IField
{
readonly MetadataAssembly assembly;
readonly FieldDefinitionHandle handle;
readonly FieldAttributes attributes;
// lazy-loaded fields:
ITypeDefinition declaringType;
string name;
object constantValue;
IType type;
bool isVolatile; // initialized together with this.type
IAttribute[] customAttributes;
internal MetadataField(MetadataAssembly assembly, FieldDefinitionHandle handle)
{
Debug.Assert(assembly != null);
Debug.Assert(!handle.IsNil);
this.assembly = assembly;
this.handle = handle;
var def = assembly.metadata.GetFieldDefinition(handle);
this.attributes = def.Attributes;
}
public EntityHandle MetadataToken => handle;
public override string ToString()
{
return $"{MetadataTokens.GetToken(handle):X8} {DeclaringType?.ReflectionName}.{Name}";
}
public string Name {
get {
string name = LazyInit.VolatileRead(ref this.name);
if (name != null)
return name;
var metadata = assembly.metadata;
var fieldDef = metadata.GetFieldDefinition(handle);
return LazyInit.GetOrSet(ref this.name, metadata.GetString(fieldDef.Name));
}
}
public Accessibility Accessibility => MetadataLoader.GetAccessibility(attributes);
public bool IsReadOnly => (attributes & FieldAttributes.InitOnly) != 0;
public bool IsStatic => (attributes & FieldAttributes.Static) != 0;
// not sure if we need IsFixed anywhere...
public bool IsFixed => throw new NotImplementedException();
// Do we still want IsShadowing in the TS?
// We never set it for assemblies loaded from disk; only for those parsed from C#...
bool IEntity.IsShadowing => throw new NotImplementedException();
SymbolKind ISymbol.SymbolKind => SymbolKind.Field;
IMember IMember.MemberDefinition => this;
TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity;
// Fields can't implement interfaces:
IReadOnlyList<IMember> IMember.ImplementedInterfaceMembers => EmptyList<IMember>.Instance;
bool IMember.IsExplicitInterfaceImplementation => false;
bool IMember.IsVirtual => false;
bool IMember.IsOverride => false;
bool IMember.IsOverridable => false;
bool IEntity.IsAbstract => false;
bool IEntity.IsSealed => false;
public ITypeDefinition DeclaringTypeDefinition {
get {
var declType = LazyInit.VolatileRead(ref this.declaringType);
if (declType != null) {
return declType;
} else {
var def = assembly.metadata.GetFieldDefinition(handle);
return LazyInit.GetOrSet(ref this.declaringType,
assembly.GetDefinition(def.GetDeclaringType()));
}
}
}
public IType DeclaringType => DeclaringTypeDefinition;
public IAssembly ParentAssembly => assembly;
public ICompilation Compilation => assembly.Compilation;
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 fieldDef = metadata.GetFieldDefinition(handle);
// FieldOffsetAttribute
int offset = fieldDef.GetOffset();
if (offset != -1) {
b.Add(KnownAttribute.FieldOffset, KnownTypeCode.Int32, offset);
}
// NonSerializedAttribute
if ((fieldDef.Attributes & FieldAttributes.NotSerialized) != 0) {
b.Add(KnownAttribute.NonSerialized);
}
b.AddMarshalInfo(fieldDef.GetMarshallingDescriptor());
b.Add(fieldDef.GetCustomAttributes());
return b.Build();
}
public string FullName => $"{DeclaringType?.FullName}.{Name}";
public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}";
public string Namespace => DeclaringType?.Namespace;
public bool IsVolatile {
get {
if (LazyInit.VolatileRead(ref this.type) == null) {
DecodeTypeAndVolatileFlag();
}
return this.isVolatile;
}
}
IType IMember.ReturnType => Type;
public IType Type {
get {
var ty = LazyInit.VolatileRead(ref this.type);
if (ty != null) {
return ty;
}
return DecodeTypeAndVolatileFlag();
}
}
private IType DecodeTypeAndVolatileFlag()
{
var metadata = assembly.metadata;
var fieldDef = metadata.GetFieldDefinition(handle);
var ty = fieldDef.DecodeSignature(assembly.TypeProvider, new GenericContext(DeclaringType?.TypeParameters));
if (ty is ModifiedType mod && mod.Modifier.Name == "IsVolatile" && mod.Modifier.Namespace == "System.Runtime.CompilerServices") {
Volatile.Write(ref this.isVolatile, true);
ty = mod.ElementType;
}
return LazyInit.GetOrSet(ref this.type, ty);
}
// TODO: decimal constants
public bool IsConst => (attributes & FieldAttributes.Literal) != 0;
public object ConstantValue {
get {
object val = LazyInit.VolatileRead(ref this.constantValue);
if (val != null)
return val;
var metadata = assembly.metadata;
var fieldDef = metadata.GetFieldDefinition(handle);
var constantHandle = fieldDef.GetDefaultValue();
if (constantHandle.IsNil)
return null;
var constant = metadata.GetConstant(constantHandle);
var blobReader = metadata.GetBlobReader(constant.Value);
val = blobReader.ReadConstant(constant.TypeCode);
return LazyInit.GetOrSet(ref this.constantValue, val);
}
}
public bool Equals(IMember obj, TypeVisitor typeNormalization)
{
return this == obj;
}
public IMember Specialize(TypeParameterSubstitution substitution)
{
return SpecializedField.Create(this, substitution);
}
}
}

99
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataNamespace.cs

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
// 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.Reflection.Metadata;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
sealed class MetadataNamespace : INamespace
{
readonly MetadataAssembly assembly;
readonly NamespaceDefinition ns;
public INamespace ParentNamespace { get; }
public string FullName { get; }
public string Name { get; }
public MetadataNamespace(MetadataAssembly assembly, INamespace parent, string fullName, NamespaceDefinition ns)
{
Debug.Assert(assembly != null);
Debug.Assert(fullName != null);
this.assembly = assembly;
this.ParentNamespace = parent;
this.ns = ns;
this.FullName = fullName;
this.Name = assembly.GetString(ns.Name);
}
string INamespace.ExternAlias => string.Empty;
INamespace[] childNamespaces;
public IEnumerable<INamespace> ChildNamespaces {
get {
var children = LazyInit.VolatileRead(ref childNamespaces);
if (children != null) {
return children;
}
var nsDefs = ns.NamespaceDefinitions;
children = new INamespace[nsDefs.Length];
for (int i = 0; i < children.Length; i++) {
var nsHandle = nsDefs[i];
string fullName = assembly.metadata.GetString(nsHandle);
children[i] = new MetadataNamespace(assembly, this, fullName,
assembly.metadata.GetNamespaceDefinition(nsHandle));
}
return LazyInit.GetOrSet(ref childNamespaces, children);
}
}
IEnumerable<ITypeDefinition> INamespace.Types {
get {
foreach (var typeHandle in ns.TypeDefinitions) {
var def = assembly.GetDefinition(typeHandle);
if (def != null)
yield return def;
}
}
}
IEnumerable<IAssembly> INamespace.ContributingAssemblies => new[] { assembly };
SymbolKind ISymbol.SymbolKind => SymbolKind.Namespace;
ICompilation ICompilationProvider.Compilation => assembly.Compilation;
INamespace INamespace.GetChildNamespace(string name)
{
foreach (var ns in ChildNamespaces) {
if (ns.Name == name)
return ns;
}
return null;
}
ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount)
{
return assembly.GetTypeDefinition(FullName, name, typeParameterCount);
}
}
}

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

@ -0,0 +1,487 @@ @@ -0,0 +1,487 @@
// 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.InteropServices;
using System.Text;
using System.Threading;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
/// <summary>
/// Type definition backed by System.Reflection.Metadata
/// </summary>
sealed class MetadataTypeDefinition : ITypeDefinition
{
readonly MetadataAssembly assembly;
readonly TypeDefinitionHandle handle;
// eagerly loaded:
readonly FullTypeName fullTypeName;
readonly TypeAttributes attributes;
public TypeKind Kind { get; }
public ITypeDefinition DeclaringTypeDefinition { get; }
public IReadOnlyList<ITypeParameter> TypeParameters { get; }
public KnownTypeCode KnownTypeCode { get; }
public IType EnumUnderlyingType { get; }
// lazy-loaded:
IAttribute[] customAttributes;
internal MetadataTypeDefinition(MetadataAssembly assembly, TypeDefinitionHandle handle)
{
Debug.Assert(assembly != null);
Debug.Assert(!handle.IsNil);
this.assembly = assembly;
this.handle = handle;
var metadata = assembly.metadata;
var td = metadata.GetTypeDefinition(handle);
this.attributes = td.Attributes;
this.fullTypeName = td.GetFullTypeName(metadata);
// Find DeclaringType + KnownTypeCode:
if (fullTypeName.IsNested) {
this.DeclaringTypeDefinition = assembly.GetDefinition(td.GetDeclaringType());
} else {
var topLevelTypeName = fullTypeName.TopLevelTypeName;
for (int i = 0; i < KnownTypeReference.KnownTypeCodeCount; i++) {
var ktr = KnownTypeReference.Get((KnownTypeCode)i);
if (ktr != null && ktr.TypeName == topLevelTypeName) {
this.KnownTypeCode = (KnownTypeCode)i;
break;
}
}
}
// Find type kind:
if ((attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface) {
this.Kind = TypeKind.Interface;
} else if (td.IsEnum(metadata, out var underlyingType)) {
this.Kind = TypeKind.Enum;
this.EnumUnderlyingType = assembly.Compilation.FindType(underlyingType.ToKnownTypeCode());
} else if (td.IsValueType(metadata)) {
this.Kind = TypeKind.Struct;
} else if (td.IsDelegate(metadata)) {
this.Kind = TypeKind.Delegate;
} else {
this.Kind = TypeKind.Class;
}
// Create type parameters:
this.TypeParameters = MetadataTypeParameter.Create(assembly, this, td.GetGenericParameters());
}
public override string ToString()
{
return $"{MetadataTokens.GetToken(handle):X8} {fullTypeName}";
}
public IReadOnlyList<ITypeDefinition> NestedTypes => throw new NotImplementedException();
IMember[] members;
public IReadOnlyList<IMember> Members {
get {
var members = LazyInit.VolatileRead(ref this.members);
if (members != null)
return members;
members = this.Fields.Concat<IMember>(this.Methods).Concat(this.Properties).Concat(this.Events).ToArray();
return LazyInit.GetOrSet(ref this.members, members);
}
}
IField[] fields;
public IEnumerable<IField> Fields {
get {
var fields = LazyInit.VolatileRead(ref this.fields);
if (fields != null)
return fields;
var metadata = assembly.metadata;
var fieldCollection = metadata.GetTypeDefinition(handle).GetFields();
var fieldList = new List<IField>(fieldCollection.Count);
foreach (FieldDefinitionHandle h in fieldCollection) {
var field = metadata.GetFieldDefinition(h);
var attr = field.Attributes;
if (assembly.IsVisible(attr) && (attr & FieldAttributes.SpecialName) == 0) {
fieldList.Add(assembly.GetDefinition(h));
}
}
return LazyInit.GetOrSet(ref this.fields, fieldList.ToArray());
}
}
public IEnumerable<IMethod> Methods => throw new NotImplementedException();
public IEnumerable<IProperty> Properties => throw new NotImplementedException();
public IEnumerable<IEvent> Events => throw new NotImplementedException();
public IType DeclaringType => DeclaringTypeDefinition;
public bool HasExtensionMethods => throw new NotImplementedException();
public bool? IsReferenceType {
get {
switch (Kind) {
case TypeKind.Struct:
case TypeKind.Enum:
case TypeKind.Void:
return false;
default:
return true;
}
}
}
public int TypeParameterCount => TypeParameters.Count;
IReadOnlyList<IType> IType.TypeArguments => TypeParameters;
public IEnumerable<IType> DirectBaseTypes => throw new NotImplementedException();
public EntityHandle MetadataToken => handle;
public FullTypeName FullTypeName => fullTypeName;
public string Name => fullTypeName.Name;
public IAssembly ParentAssembly => assembly;
#region Type 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 typeDefinition = metadata.GetTypeDefinition(handle);
// SerializableAttribute
if ((typeDefinition.Attributes & TypeAttributes.Serializable) != 0)
b.Add(KnownAttribute.Serializable);
// ComImportAttribute
if ((typeDefinition.Attributes & TypeAttributes.Import) != 0)
b.Add(KnownAttribute.ComImport);
#region StructLayoutAttribute
LayoutKind layoutKind = LayoutKind.Auto;
switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) {
case TypeAttributes.SequentialLayout:
layoutKind = LayoutKind.Sequential;
break;
case TypeAttributes.ExplicitLayout:
layoutKind = LayoutKind.Explicit;
break;
}
CharSet charSet = CharSet.None;
switch (typeDefinition.Attributes & TypeAttributes.StringFormatMask) {
case TypeAttributes.AnsiClass:
charSet = CharSet.Ansi;
break;
case TypeAttributes.AutoClass:
charSet = CharSet.Auto;
break;
case TypeAttributes.UnicodeClass:
charSet = CharSet.Unicode;
break;
}
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);
if (charSet != CharSet.Ansi) {
var charSetType = Compilation.FindType(new TopLevelTypeName("System.Runtime.InteropServices", "CharSet"));
namedArguments.Add(b.MakeNamedArg(structLayoutAttributeType,
"CharSet", charSetType, (int)charSet));
}
if (layout.PackingSize > 0) {
namedArguments.Add(b.MakeNamedArg(structLayoutAttributeType,
"Pack", KnownTypeCode.Int32, (int)layout.PackingSize));
}
if (layout.Size > 0) {
namedArguments.Add(b.MakeNamedArg(structLayoutAttributeType,
"Size", KnownTypeCode.Int32, (int)layout.Size));
}
b.Add(new DefaultAttribute(
structLayoutAttributeType,
positionalArguments, namedArguments
));
}
#endregion
b.Add(typeDefinition.GetCustomAttributes());
b.AddSecurityAttributes(typeDefinition.GetDeclarativeSecurityAttributes());
return b.Build();
}
#endregion
public Accessibility Accessibility {
get {
switch (attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.NotPublic:
case TypeAttributes.NestedAssembly:
return Accessibility.Internal;
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
return Accessibility.Public;
case TypeAttributes.NestedPrivate:
return Accessibility.Private;
case TypeAttributes.NestedFamily:
return Accessibility.Protected;
case TypeAttributes.NestedFamANDAssem:
return Accessibility.ProtectedAndInternal;
case TypeAttributes.NestedFamORAssem:
return Accessibility.ProtectedOrInternal;
default:
return Accessibility.None;
}
}
}
public bool IsStatic => (attributes & (TypeAttributes.Abstract | TypeAttributes.Sealed)) == (TypeAttributes.Abstract | TypeAttributes.Sealed);
public bool IsAbstract => (attributes & TypeAttributes.Abstract) != 0;
public bool IsSealed => (attributes & TypeAttributes.Sealed) != 0;
bool IEntity.IsShadowing => throw new NotImplementedException();
public SymbolKind SymbolKind => SymbolKind.TypeDefinition;
public ICompilation Compilation => assembly.Compilation;
public string FullName => throw new NotImplementedException();
public string ReflectionName => fullTypeName.ReflectionName;
public string Namespace => fullTypeName.TopLevelTypeName.Namespace;
ITypeDefinition IType.GetDefinition() => this;
TypeParameterSubstitution IType.GetSubstitution() => TypeParameterSubstitution.Identity;
TypeParameterSubstitution IType.GetSubstitution(IReadOnlyList<IType> methodTypeArguments) => TypeParameterSubstitution.Identity;
public IType AcceptVisitor(TypeVisitor visitor)
{
return visitor.VisitTypeDefinition(this);
}
IType IType.VisitChildren(TypeVisitor visitor)
{
return this;
}
bool IEquatable<IType>.Equals(IType other)
{
return this == other;
}
#region GetNestedTypes
public IEnumerable<IType> GetNestedTypes(Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
const GetMemberOptions opt = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions;
if ((options & opt) == opt) {
return GetFiltered(this.NestedTypes, filter);
} else {
return GetMembersHelper.GetNestedTypes(this, filter, options);
}
}
public IEnumerable<IType> GetNestedTypes(IReadOnlyList<IType> typeArguments, Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return GetMembersHelper.GetNestedTypes(this, typeArguments, filter, options);
}
#endregion
#region GetMembers()
IEnumerable<T> GetFiltered<T>(IEnumerable<T> input, Predicate<T> filter) where T : class
{
if (filter == null)
return input;
else
return ApplyFilter(input, filter);
}
IEnumerable<T> ApplyFilter<T>(IEnumerable<T> input, Predicate<T> filter) where T : class
{
foreach (var member in input) {
if (filter(member))
yield return member;
}
}
public IEnumerable<IMethod> GetMethods(Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Methods, ExtensionMethods.And(m => !m.IsConstructor, filter));
} else {
return GetMembersHelper.GetMethods(this, filter, options);
}
}
public IEnumerable<IMethod> GetMethods(IReadOnlyList<IType> typeArguments, Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return GetMembersHelper.GetMethods(this, typeArguments, filter, options);
}
public IEnumerable<IMethod> GetConstructors(Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers)
{
if (ComHelper.IsComImport(this)) {
IType coClass = ComHelper.GetCoClass(this);
using (var busyLock = BusyManager.Enter(this)) {
if (busyLock.Success) {
return coClass.GetConstructors(filter, options)
.Select(m => new SpecializedMethod(m, m.Substitution) { DeclaringType = this });
}
}
return EmptyList<IMethod>.Instance;
}
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Methods, ExtensionMethods.And(m => m.IsConstructor && !m.IsStatic, filter));
} else {
return GetMembersHelper.GetConstructors(this, filter, options);
}
}
public IEnumerable<IProperty> GetProperties(Predicate<IProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Properties, filter);
} else {
return GetMembersHelper.GetProperties(this, filter, options);
}
}
public IEnumerable<IField> GetFields(Predicate<IField> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Fields, filter);
} else {
return GetMembersHelper.GetFields(this, filter, options);
}
}
public IEnumerable<IEvent> GetEvents(Predicate<IEvent> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Events, filter);
} else {
return GetMembersHelper.GetEvents(this, filter, options);
}
}
public IEnumerable<IMember> GetMembers(Predicate<IMember> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFiltered(this.Members, filter);
} else {
return GetMembersHelper.GetMembers(this, filter, options);
}
}
public IEnumerable<IMethod> GetAccessors(Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFilteredAccessors(filter);
} else {
return GetMembersHelper.GetAccessors(this, filter, options);
}
}
IEnumerable<IMethod> GetFilteredAccessors(Predicate<IMethod> filter)
{
foreach (var prop in this.Properties) {
var getter = prop.Getter;
if (getter != null && (filter == null || filter(getter)))
yield return getter;
var setter = prop.Setter;
if (setter != null && (filter == null || filter(setter)))
yield return setter;
}
foreach (var ev in this.Events) {
var adder = ev.AddAccessor;
if (adder != null && (filter == null || filter(adder)))
yield return adder;
var remover = ev.RemoveAccessor;
if (remover != null && (filter == null || filter(remover)))
yield return remover;
var invoker = ev.InvokeAccessor;
if (invoker != null && (filter == null || filter(invoker)))
yield return remover;
}
}
#endregion
#region GetInterfaceImplementation
public IMember GetInterfaceImplementation(IMember interfaceMember)
{
return GetInterfaceImplementation(new[] { interfaceMember })[0];
}
public IReadOnlyList<IMember> GetInterfaceImplementation(IReadOnlyList<IMember> interfaceMembers)
{
// TODO: review the subtle rules for interface reimplementation,
// write tests and fix this method.
// Also virtual/override is going to be tricky -
// I think we'll need to consider the 'virtual' method first for
// reimplemenatation purposes, but then actually return the 'override'
// (as that's the method that ends up getting called)
interfaceMembers = interfaceMembers.ToList(); // avoid evaluating more than once
var result = new IMember[interfaceMembers.Count];
var signatureToIndexDict = new MultiDictionary<IMember, int>(SignatureComparer.Ordinal);
for (int i = 0; i < interfaceMembers.Count; i++) {
signatureToIndexDict.Add(interfaceMembers[i], i);
}
foreach (var member in GetMembers(m => !m.IsExplicitInterfaceImplementation)) {
foreach (int interfaceMemberIndex in signatureToIndexDict[member]) {
result[interfaceMemberIndex] = member;
}
}
foreach (var explicitImpl in GetMembers(m => m.IsExplicitInterfaceImplementation)) {
foreach (var interfaceMember in explicitImpl.ImplementedInterfaceMembers) {
foreach (int potentialMatchingIndex in signatureToIndexDict[interfaceMember]) {
if (interfaceMember.Equals(interfaceMembers[potentialMatchingIndex])) {
result[potentialMatchingIndex] = explicitImpl;
}
}
}
}
return result;
}
#endregion
}
}

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

@ -0,0 +1,124 @@ @@ -0,0 +1,124 @@
// 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 ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
sealed class MetadataTypeParameter : AbstractTypeParameter
{
readonly MetadataAssembly assembly;
readonly GenericParameterHandle handle;
readonly GenericParameterAttributes attr;
// lazy-loaded:
IReadOnlyList<IAttribute> customAttributes;
IReadOnlyList<IType> constraints;
public static IReadOnlyList<ITypeParameter> Create(MetadataAssembly assembly, IEntity owner, GenericParameterHandleCollection handles)
{
if (handles.Count == 0)
return EmptyList<ITypeParameter>.Instance;
var tps = new ITypeParameter[handles.Count];
int i = 0;
foreach (var handle in handles) {
tps[i] = Create(assembly, owner, handle);
}
return tps;
}
public static MetadataTypeParameter Create(MetadataAssembly assembly, IEntity owner, GenericParameterHandle handle)
{
var metadata = assembly.metadata;
var gp = metadata.GetGenericParameter(handle);
return new MetadataTypeParameter(assembly, owner, gp.Index, assembly.GetString(gp.Name), handle, gp.Attributes);
}
private MetadataTypeParameter(MetadataAssembly assembly, IEntity owner, int index, string name,
GenericParameterHandle handle, GenericParameterAttributes attr)
: base(owner, index, name, GetVariance(attr))
{
this.assembly = assembly;
this.handle = handle;
this.attr = attr;
}
private static VarianceModifier GetVariance(GenericParameterAttributes attr)
{
switch (attr & GenericParameterAttributes.VarianceMask) {
case GenericParameterAttributes.Contravariant:
return VarianceModifier.Contravariant;
case GenericParameterAttributes.Covariant:
return VarianceModifier.Covariant;
default:
return VarianceModifier.Invariant;
}
}
public GenericParameterHandle MetadataToken => handle;
public override 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 metadata = assembly.metadata;
var gp = metadata.GetGenericParameter(handle);
var attributes = gp.GetCustomAttributes();
var b = new AttributeListBuilder(assembly, attributes.Count);
b.Add(attributes);
return b.Build();
}
public override bool HasDefaultConstructorConstraint => (attr & GenericParameterAttributes.DefaultConstructorConstraint) != 0;
public override bool HasReferenceTypeConstraint => (attr & GenericParameterAttributes.ReferenceTypeConstraint) != 0;
public override bool HasValueTypeConstraint => (attr & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0;
public override IEnumerable<IType> DirectBaseTypes {
get {
var constraints = LazyInit.VolatileRead(ref this.constraints);
if (constraints != null)
return constraints;
return LazyInit.GetOrSet(ref this.constraints, DecodeConstraints());
}
}
private IReadOnlyList<IType> DecodeConstraints()
{
throw new NotImplementedException();
}
public override string ToString()
{
return $"{MetadataTokens.GetToken(handle):X8} Index={Index} Owner={Owner}";
}
}
}

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

@ -45,37 +45,39 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -45,37 +45,39 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IType Resolve(ITypeResolveContext context)
{
return Resolve(type, metadata, context,
return Resolve(type, metadata,
new TypeProvider(context.CurrentAssembly),
new GenericContext(context),
options, typeAttributes);
}
public static IType Resolve(SRM.EntityHandle type,
SRM.MetadataReader metadata,
ITypeResolveContext context,
TypeProvider typeProvider,
GenericContext genericContext,
TypeSystemOptions options,
SRM.CustomAttributeHandleCollection? typeAttributes = null)
{
if (type.IsNil)
return SpecialType.UnknownType;
var tp = new TypeProvider(context.CurrentAssembly);
IType ty;
switch (type.Kind) {
case SRM.HandleKind.TypeDefinition:
ty = tp.GetTypeFromDefinition(metadata, (SRM.TypeDefinitionHandle)type, 0);
ty = typeProvider.GetTypeFromDefinition(metadata, (SRM.TypeDefinitionHandle)type, 0);
break;
case SRM.HandleKind.TypeReference:
ty = tp.GetTypeFromReference(metadata, (SRM.TypeReferenceHandle)type, 0);
ty = typeProvider.GetTypeFromReference(metadata, (SRM.TypeReferenceHandle)type, 0);
break;
case SRM.HandleKind.TypeSpecification:
var typeSpec = metadata.GetTypeSpecification((SRM.TypeSpecificationHandle)type);
ty = typeSpec.DecodeSignature(tp, context);
ty = typeSpec.DecodeSignature(typeProvider, genericContext);
break;
default:
Debug.Fail("Not a type handle");
ty = SpecialType.UnknownType;
break;
}
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation,
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, typeProvider.Compilation,
typeAttributes, metadata, options);
return ty;
}
@ -111,7 +113,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -111,7 +113,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return Resolve((SRM.FieldDefinitionHandle)fieldHandle, metadata, context, options);
} else {
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)fieldHandle);
IType ty = memberRef.DecodeFieldSignature(new TypeProvider(context.CurrentAssembly), context);
IType ty = memberRef.DecodeFieldSignature(new TypeProvider(context.CurrentAssembly), new GenericContext(context));
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation,
memberRef.GetCustomAttributes(), metadata, options);
return ty;
@ -124,7 +126,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -124,7 +126,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
TypeSystemOptions options)
{
var fieldDef = metadata.GetFieldDefinition(fieldHandle);
IType ty = fieldDef.DecodeSignature(new TypeProvider(context.CurrentAssembly), context);
IType ty = fieldDef.DecodeSignature(new TypeProvider(context.CurrentAssembly), new GenericContext(context));
ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, context.Compilation,
fieldDef.GetCustomAttributes(), metadata, options);
return ty;
@ -184,7 +186,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -184,7 +186,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
TypeSystemOptions options)
{
var typeProvider = new TypeProvider(context.CurrentAssembly);
var signature = methodDef.DecodeSignature(typeProvider, context);
var signature = methodDef.DecodeSignature(typeProvider, new GenericContext(context));
return ApplyAttributes(signature, methodDef.GetParameters(), context.Compilation, metadata, options);
}
@ -193,7 +195,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -193,7 +195,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
TypeSystemOptions options)
{
var typeProvider = new TypeProvider(context.CurrentAssembly);
var signature = propertyDef.DecodeSignature(typeProvider, context);
var signature = propertyDef.DecodeSignature(typeProvider, new GenericContext(context));
var accessors = propertyDef.GetAccessors();
SRM.ParameterHandleCollection? parameterHandles = null;
if (!accessors.Getter.IsNil) {

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

@ -35,12 +35,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -35,12 +35,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly IList<IAssembly> referencedAssemblies;
INamespace rootNamespace;
public SimpleCompilation(IUnresolvedAssembly mainAssembly, params IAssemblyReference[] assemblyReferences)
public SimpleCompilation(IAssemblyReference mainAssembly, params IAssemblyReference[] assemblyReferences)
: this(mainAssembly, (IEnumerable<IAssemblyReference>)assemblyReferences)
{
}
public SimpleCompilation(IUnresolvedAssembly mainAssembly, IEnumerable<IAssemblyReference> assemblyReferences)
public SimpleCompilation(IAssemblyReference mainAssembly, IEnumerable<IAssemblyReference> assemblyReferences)
{
if (mainAssembly == null)
throw new ArgumentNullException("mainAssembly");

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

@ -223,13 +223,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -223,13 +223,15 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
internal TypeVisitor substitution;
public SpecializedTypeParameter(ITypeParameter baseTp, IMethod specializedOwner)
: base(specializedOwner, baseTp.Index, baseTp.Name, baseTp.Variance, baseTp.Attributes)
: base(specializedOwner, baseTp.Index, baseTp.Name, baseTp.Variance)
{
// We don't have to consider already-specialized baseTps because
// we read the baseTp directly from the unpacked memberDefinition.
this.baseTp = baseTp;
}
public override IReadOnlyList<IAttribute> Attributes => baseTp.Attributes;
public override int GetHashCode()
{
return baseTp.GetHashCode() ^ this.Owner.GetHashCode();

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

@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -94,7 +94,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IType Resolve(ITypeResolveContext context)
{
ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token);
ITypeDefinition td = ((MetadataAssembly)context.CurrentAssembly).GetDefinition(token);
if (td != null)
return td;
return SpecialType.UnknownType;
@ -112,7 +112,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -112,7 +112,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public IType Resolve(ITypeResolveContext context)
{
return typeSpec.DecodeSignature(new TypeProvider(context.CurrentAssembly), context);
return typeSpec.DecodeSignature(new TypeProvider(context.CurrentAssembly), new GenericContext(context));
}
}

2
ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs

@ -452,6 +452,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -452,6 +452,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return typeParameterCount; }
}
public TopLevelTypeName TypeName => new TopLevelTypeName(namespaceName, name, typeParameterCount);
public IType Resolve(ITypeResolveContext context)
{
return context.Compilation.FindType(knownTypeCode);

290
ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs

@ -0,0 +1,290 @@ @@ -0,0 +1,290 @@
// 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.InteropServices;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem
{
/// <summary>
/// Used as context object for metadata TS entities;
/// should be turned into IAssembly implementation when the TS refactoring is complete.
/// </summary>
[DebuggerDisplay("<MetadataAssembly: {AssemblyName}>")]
public class MetadataAssembly : IAssembly
{
public ICompilation Compilation { get; }
internal readonly Metadata.PEFile PEFile;
internal readonly MetadataReader metadata;
readonly TypeSystemOptions options;
internal readonly TypeProvider TypeProvider;
readonly MetadataNamespace rootNamespace;
readonly MetadataTypeDefinition[] typeDefs;
readonly MetadataField[] fieldDefs;
internal MetadataAssembly(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options)
{
this.Compilation = compilation;
this.PEFile = peFile;
this.metadata = peFile.Metadata;
this.options = options;
this.TypeProvider = new TypeProvider(this);
// assembly metadata
if (metadata.IsAssembly) {
var asmdef = metadata.GetAssemblyDefinition();
this.AssemblyName = metadata.GetString(asmdef.Name);
this.FullAssemblyName = metadata.GetFullAssemblyName();
} else {
var moddef = metadata.GetModuleDefinition();
this.AssemblyName = metadata.GetString(moddef.Name);
this.FullAssemblyName = this.AssemblyName;
}
// create arrays for resolved entities, indexed by row index
this.typeDefs = new MetadataTypeDefinition[metadata.TypeDefinitions.Count + 1];
this.fieldDefs = new MetadataField[metadata.FieldDefinitions.Count + 1];
}
internal string GetString(StringHandle name)
{
return metadata.GetString(name);
}
public TypeSystemOptions TypeSystemOptions => options;
#region IAssembly interface
public bool IsMainAssembly => this == Compilation.MainAssembly;
public string AssemblyName { get; }
public string FullAssemblyName { get; }
public INamespace RootNamespace => rootNamespace;
public IEnumerable<ITypeDefinition> TopLevelTypeDefinitions => TypeDefinitions.Where(td => td.DeclaringTypeDefinition == null);
public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
{
var typeDefHandle = PEFile.GetTypeDefinition(topLevelTypeName);
return GetDefinition(typeDefHandle);
}
#endregion
#region InternalsVisibleTo
public bool InternalsVisibleTo(IAssembly assembly)
{
if (this == assembly)
return true;
foreach (string shortName in GetInternalsVisibleTo()) {
if (assembly.AssemblyName == shortName)
return true;
}
return false;
}
string[] internalsVisibleTo;
string[] GetInternalsVisibleTo()
{
var result = LazyInit.VolatileRead(ref this.internalsVisibleTo);
if (result != null) {
return result;
}
if (metadata.IsAssembly) {
var list = new List<string>();
foreach (var attrHandle in metadata.GetAssemblyDefinition().GetCustomAttributes()) {
var attr = metadata.GetCustomAttribute(attrHandle);
if (attr.IsKnownAttribute(metadata, KnownAttribute.InternalsVisibleTo)) {
var attrValue = attr.DecodeValue(this.TypeProvider);
if (attrValue.FixedArguments.Length == 1) {
if (attrValue.FixedArguments[0].Value is string s) {
list.Add(s);
}
}
}
}
result = list.ToArray();
} else {
result = Empty<string>.Array;
}
return LazyInit.GetOrSet(ref this.internalsVisibleTo, result);
}
#endregion
#region GetDefinition
/// <summary>
/// Gets all types in the assembly, including nested types.
/// </summary>
public IEnumerable<ITypeDefinition> TypeDefinitions {
get {
for (int row = 1; row < typeDefs.Length; row++) {
var typeDef = LazyInit.VolatileRead(ref typeDefs[row]);
if (typeDef != null) {
yield return typeDef;
} else {
typeDef = new MetadataTypeDefinition(this, MetadataTokens.TypeDefinitionHandle(row));
yield return LazyInit.GetOrSet(ref typeDefs[row], typeDef);
}
}
}
}
public ITypeDefinition GetDefinition(TypeDefinitionHandle handle)
{
int row = MetadataTokens.GetRowNumber(handle);
if (row >= typeDefs.Length)
return null;
var typeDef = LazyInit.VolatileRead(ref typeDefs[row]);
if (typeDef != null || handle.IsNil)
return typeDef;
typeDef = new MetadataTypeDefinition(this, handle);
return LazyInit.GetOrSet(ref typeDefs[row], typeDef);
}
public IField GetDefinition(FieldDefinitionHandle handle)
{
int row = MetadataTokens.GetRowNumber(handle);
if (row >= fieldDefs.Length)
return null;
var field = LazyInit.VolatileRead(ref fieldDefs[row]);
if (field != null || handle.IsNil)
return field;
field = new MetadataField(this, handle);
return LazyInit.GetOrSet(ref fieldDefs[row], field);
}
public IMethod GetDefinition(MethodDefinitionHandle handle)
{
throw new NotImplementedException();
}
public IProperty GetDefinition(PropertyDefinitionHandle handle)
{
throw new NotImplementedException();
}
public IEvent GetDefinition(EventDefinitionHandle handle)
{
throw new NotImplementedException();
}
#endregion
public IMethod ResolveMethod(EntityHandle methodRefDefSpec, GenericContext context = default)
{
throw new NotImplementedException();
}
public IType ResolveType(EntityHandle typeRefDefSpec, GenericContext context = default, CustomAttributeHandleCollection? typeAttributes = null)
{
return MetadataTypeReference.Resolve(typeRefDefSpec, metadata, TypeProvider, context, options, typeAttributes);
}
#region Module / Assembly attributes
IAttribute[] assemblyAttributes;
IAttribute[] moduleAttributes;
/// <summary>
/// Gets the list of all assembly attributes in the project.
/// </summary>
public IReadOnlyList<IAttribute> AssemblyAttributes {
get {
var attrs = LazyInit.VolatileRead(ref this.assemblyAttributes);
if (attrs != null)
return attrs;
var b = new AttributeListBuilder(this);
if (metadata.IsAssembly) {
var assembly = metadata.GetAssemblyDefinition();
b.Add(metadata.GetCustomAttributes(Handle.AssemblyDefinition));
b.AddSecurityAttributes(assembly.GetDeclarativeSecurityAttributes());
// AssemblyVersionAttribute
if (assembly.Version != null) {
b.Add(KnownAttribute.AssemblyVersion, KnownTypeCode.String, assembly.Version.ToString());
}
}
return LazyInit.GetOrSet(ref this.assemblyAttributes, b.Build());
}
}
/// <summary>
/// Gets the list of all module attributes in the project.
/// </summary>
public IReadOnlyList<IAttribute> ModuleAttributes {
get {
var attrs = LazyInit.VolatileRead(ref this.moduleAttributes);
if (attrs != null)
return attrs;
var b = new AttributeListBuilder(this);
b.Add(metadata.GetCustomAttributes(Handle.ModuleDefinition));
return LazyInit.GetOrSet(ref this.moduleAttributes, b.Build());
}
}
#endregion
#region Attribute Helpers
/// <summary>
/// Cache for parameterless known attribute types.
/// </summary>
readonly IType[] knownAttributeTypes = new IType[KnownAttributes.Count];
internal IType GetAttributeType(KnownAttribute attr)
{
var ty = LazyInit.VolatileRead(ref knownAttributeTypes[(int)attr]);
if (ty != null)
return ty;
ty = Compilation.FindType(attr.GetTypeName());
return LazyInit.GetOrSet(ref knownAttributeTypes[(int)attr], ty);
}
/// <summary>
/// Cache for parameterless known attributes.
/// </summary>
readonly IAttribute[] knownAttributes = new IAttribute[KnownAttributes.Count];
/// <summary>
/// Construct a builtin attribute.
/// </summary>
internal IAttribute MakeAttribute(KnownAttribute type)
{
var attr = LazyInit.VolatileRead(ref knownAttributes[(int)type]);
if (attr != null)
return attr;
attr = new DefaultAttribute(GetAttributeType(type));
return LazyInit.GetOrSet(ref knownAttributes[(int)type], attr);
}
#endregion
#region Visibility Filter
internal bool IsVisible(FieldAttributes attributes)
{
return true;
}
#endregion
}
}

48
ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs

@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary>
/// Gets/Sets type system options.
/// </summary>
public TypeSystemOptions Options { get; set; }
public TypeSystemOptions Options { get; set; } = TypeSystemOptions.Default;
/// <summary>
/// Gets/Sets the cancellation token used by the assembly loader.
@ -555,6 +555,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -555,6 +555,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
if ((fieldDefinition.Attributes & FieldAttributes.NotSerialized) != 0) {
targetEntity.Attributes.Add(nonSerializedAttribute);
}
AddMarshalInfo(fieldDefinition.GetMarshallingDescriptor(), targetEntity.Attributes);
AddCustomAttributes(fieldDefinition.GetCustomAttributes(), targetEntity.Attributes);
}
@ -852,10 +853,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -852,10 +853,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
return TypeKind.Enum;
} else if (typeDefinition.IsValueType(module)) {
return TypeKind.Struct;
} else if (IsDelegate(module, typeDefinition)) {
} else if (typeDefinition.IsDelegate(module)) {
return TypeKind.Delegate;
} else if (IsModule(module, typeDefinition)) {
return TypeKind.Module;
} else {
return TypeKind.Class;
}
@ -889,31 +888,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -889,31 +888,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
}
static bool IsDelegate(MetadataReader currentModule, TypeDefinition type)
{
if (!type.BaseType.IsNil) {
var baseTypeName = type.BaseType.GetFullTypeName(currentModule).ToString();
if (baseTypeName == "System.MulticastDelegate")
return true;
var thisTypeName = type.GetFullTypeName(currentModule).ToString();
if (baseTypeName == "Delegate" && thisTypeName != "System.MulticastDelegate")
return true;
}
return false;
}
static bool IsModule(MetadataReader reader, TypeDefinition type)
{
foreach (var h in type.GetCustomAttributes()) {
var attType = reader.GetCustomAttribute(h).GetAttributeType(reader).GetFullTypeName(reader);
if (attType.ToString() == "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute"
|| attType.ToString() == "System.Runtime.CompilerServices.CompilerGlobalScopeAttribute") {
return true;
}
}
return false;
}
void InitMembers(TypeDefinition typeDefinition, IUnresolvedTypeDefinition td, IList<IUnresolvedMember> members)
{
foreach (MethodDefinitionHandle h in typeDefinition.GetMethods()) {
@ -971,8 +945,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -971,8 +945,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
foreach (var h in typeDefinition.GetCustomAttributes()) {
var a = reader.GetCustomAttribute(h);
var type = a.GetAttributeType(reader);
if (!type.IsTopLevelType(reader, "System.Reflection", "DefaultMemberAttribute"))
if (!a.IsKnownAttribute(reader, KnownAttribute.DefaultMember))
continue;
var value = a.DecodeValue(Metadata.MetadataExtensions.minimalCorlibTypeProvider);
if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is string name)
@ -1333,12 +1306,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -1333,12 +1306,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
if ((Options & TypeSystemOptions.ExtensionMethods) == 0)
return false;
foreach (var h in attributes) {
var attr = metadata.GetCustomAttribute(h);
if (attr.IsAttributeType(metadata, "System.Runtime.CompilerServices", "ExtensionAttribute"))
return true;
}
return false;
return attributes.HasKnownAttribute(metadata, KnownAttribute.Extension);
}
bool IsVisible(MethodAttributes att)
@ -1350,7 +1318,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -1350,7 +1318,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
|| att == MethodAttributes.FamORAssem;
}
static Accessibility GetAccessibility(MethodAttributes attr)
internal static Accessibility GetAccessibility(MethodAttributes attr)
{
switch (attr & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
@ -1423,7 +1391,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -1423,7 +1391,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (type == SignatureTypeCode.SZArray) {
foreach (CustomAttributeHandle h in parameter.GetCustomAttributes()) {
var att = currentMetadata.GetCustomAttribute(h);
if (att.IsAttributeType(currentMetadata, "System", "ParamArrayAttribute")) {
if (att.IsKnownAttribute(currentMetadata, KnownAttribute.ParamArray)) {
p.IsParams = true;
break;
}
@ -1510,7 +1478,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -1510,7 +1478,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
return f;
}
static Accessibility GetAccessibility(FieldAttributes attr)
internal static Accessibility GetAccessibility(FieldAttributes attr)
{
switch (attr & FieldAttributes.FieldAccessMask) {
case FieldAttributes.Public:

130
ICSharpCode.Decompiler/TypeSystem/ModifiedType.cs

@ -0,0 +1,130 @@ @@ -0,0 +1,130 @@
// Copyright (c) 2018 AlphaSierraPapa for the SharpDevelop Team
//
// 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;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
/// <summary>
/// Represents a modopt or modreq type.
/// </summary>
public class ModifiedType : TypeWithElementType, IType
{
readonly TypeKind kind;
readonly IType modifier;
public ModifiedType(IType modifier, IType unmodifiedType, bool isRequired) : base(unmodifiedType)
{
this.kind = isRequired ? TypeKind.ModReq : TypeKind.ModOpt;
this.modifier = modifier ?? throw new ArgumentNullException(nameof(modifier));
}
public IType Modifier => modifier;
public override TypeKind Kind => kind;
public override string NameSuffix => (kind == TypeKind.ModReq ? "modreq" : "modopt") + $"({modifier.FullName})";
public override bool? IsReferenceType => elementType.IsReferenceType;
public override ITypeDefinition GetDefinition()
{
return elementType.GetDefinition();
}
public override IEnumerable<IMethod> GetAccessors(Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return elementType.GetAccessors(filter, options);
}
public override IEnumerable<IMethod> GetConstructors(Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers)
{
return elementType.GetConstructors(filter, options);
}
public override IEnumerable<IEvent> GetEvents(Predicate<IEvent> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return elementType.GetEvents(filter, options);
}
public override IEnumerable<IField> GetFields(Predicate<IField> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return elementType.GetFields(filter, options);
}
public override IEnumerable<IMember> GetMembers(Predicate<IMember> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return elementType.GetMembers(filter, options);
}
public override IEnumerable<IMethod> GetMethods(IReadOnlyList<IType> typeArguments, Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return elementType.GetMethods(typeArguments, filter, options);
}
public override IEnumerable<IMethod> GetMethods(Predicate<IMethod> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return elementType.GetMethods(filter, options);
}
public override IEnumerable<IType> GetNestedTypes(IReadOnlyList<IType> typeArguments, Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return elementType.GetNestedTypes(typeArguments, filter, options);
}
public override IEnumerable<IType> GetNestedTypes(Predicate<ITypeDefinition> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return elementType.GetNestedTypes(filter, options);
}
public override IEnumerable<IProperty> GetProperties(Predicate<IProperty> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
return elementType.GetProperties(filter, options);
}
public override IType VisitChildren(TypeVisitor visitor)
{
var newElementType = elementType.AcceptVisitor(visitor);
var newModifier = modifier.AcceptVisitor(visitor);
if (newModifier != modifier || newElementType != elementType) {
return new ModifiedType(newModifier, newElementType, kind == TypeKind.ModReq);
}
return this;
}
public override IType AcceptVisitor(TypeVisitor visitor)
{
if (kind == TypeKind.ModReq)
return visitor.VisitModReq(this);
else
return visitor.VisitModOpt(this);
}
public override bool Equals(IType other)
{
return other is ModifiedType o && kind == o.kind && modifier.Equals(o.modifier) && elementType.Equals(o.elementType);
}
public override int GetHashCode()
{
unchecked {
return (int)kind ^ (elementType.GetHashCode() * 1344795899) ^ (modifier.GetHashCode() * 901375117);
}
}
}
}

2
ICSharpCode.Decompiler/TypeSystem/TopLevelTypeName.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// This struct cannot refer to nested classes.
/// </summary>
[Serializable]
public struct TopLevelTypeName : IEquatable<TopLevelTypeName>
public readonly struct TopLevelTypeName : IEquatable<TopLevelTypeName>
{
readonly string namespaceName;
readonly string name;

10
ICSharpCode.Decompiler/TypeSystem/TypeKind.cs

@ -39,8 +39,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -39,8 +39,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary>A <see cref="ITypeDefinition"/> that is an enum.</summary>
/// <remarks><c>System.Enum</c> itself is TypeKind.Class</remarks>
Enum,
/// <summary>A <see cref="ITypeDefinition"/> that is a module (VB).</summary>
Module,
/// <summary>The <c>System.Void</c> type.</summary>
/// <see cref="KnownTypeReference.Void"/>
@ -91,5 +89,13 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -91,5 +89,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
/// <see cref="TupleType"/>
Tuple,
/// <summary>
/// Modified type, with optional modifier.
/// </summary>
ModOpt,
/// <summary>
/// Modified type, with required modifier.
/// </summary>
ModReq,
}
}

39
ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs

@ -28,23 +28,26 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -28,23 +28,26 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// <summary>
/// Allows decoding signatures using decompiler types.
/// </summary>
sealed class TypeProvider : SRM.ISignatureTypeProvider<IType, ITypeResolveContext>, SRM.ICustomAttributeTypeProvider<IType>
sealed class TypeProvider : ICompilationProvider,
SRM.ISignatureTypeProvider<IType, GenericContext>,
SRM.ICustomAttributeTypeProvider<IType>
{
readonly IAssembly assembly;
readonly MetadataAssembly assembly;
readonly ICompilation compilation;
public TypeProvider(IAssembly assembly)
{
this.assembly = assembly;
this.assembly = (MetadataAssembly)assembly; // TODO: change parameter type instead of casting
this.compilation = assembly.Compilation;
}
public TypeProvider(ICompilation compilation)
{
this.assembly = null;
this.compilation = compilation ?? throw new ArgumentNullException(nameof(compilation));
this.compilation = compilation;
}
public ICompilation Compilation => compilation;
public IType GetArrayType(IType elementType, SRM.ArrayShape shape)
{
return new ArrayType(compilation, elementType, shape.Rank);
@ -65,29 +68,19 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -65,29 +68,19 @@ namespace ICSharpCode.Decompiler.TypeSystem
return new ParameterizedType(genericType, typeArguments);
}
public IType GetGenericMethodParameter(ITypeResolveContext genericContext, int index)
public IType GetGenericMethodParameter(GenericContext genericContext, int index)
{
// Note: returning type parameter, never type argument.
// Otherwise we risk screwing up the counting for dynamicTypeIndex.
IMethod method = genericContext.CurrentMember as IMethod;
if (method != null && index < method.TypeParameters.Count) {
return method.TypeParameters[index];
}
return DummyTypeParameter.GetMethodTypeParameter(index);
return genericContext.GetMethodTypeParameter(index);
}
public IType GetGenericTypeParameter(ITypeResolveContext genericContext, int index)
public IType GetGenericTypeParameter(GenericContext genericContext, int index)
{
ITypeDefinition typeDef = genericContext.CurrentTypeDefinition;
if (typeDef != null && index < typeDef.TypeParameters.Count) {
return typeDef.TypeParameters[index];
}
return DummyTypeParameter.GetClassTypeParameter(index);
return genericContext.GetClassTypeParameter(index);
}
public IType GetModifiedType(IType modifier, IType unmodifiedType, bool isRequired)
{
return unmodifiedType;
return new ModifiedType(modifier, unmodifiedType, isRequired);
}
public IType GetPinnedType(IType elementType)
@ -129,7 +122,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -129,7 +122,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
public IType GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{
ITypeDefinition td = assembly?.ResolveTypeDefToken(handle);
ITypeDefinition td = assembly?.GetDefinition(handle);
if (td != null)
return td;
bool? isReferenceType = IsReferenceType(reader, handle, rawTypeKind);
@ -156,9 +149,9 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -156,9 +149,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
.Resolve(assembly != null ? new SimpleTypeResolveContext(assembly) : new SimpleTypeResolveContext(compilation));
}
public IType GetTypeFromSpecification(SRM.MetadataReader reader, ITypeResolveContext genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
public IType GetTypeFromSpecification(SRM.MetadataReader reader, GenericContext genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
{
return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext);
return reader.GetTypeSpecification(handle).DecodeSignature<IType, GenericContext>(this, genericContext);
}
public SRM.PrimitiveTypeCode GetUnderlyingEnumType(IType type)

37
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -205,6 +205,36 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -205,6 +205,36 @@ namespace ICSharpCode.Decompiler.TypeSystem
var def = type.GetDefinition();
return def != null && def.KnownTypeCode == knownType;
}
/// <summary>
/// Gets whether the type is the specified known type.
/// For generic known types, this returns true any parameterization of the type (and also for the definition itself).
/// </summary>
internal static bool IsKnownType(this IType type, KnownAttribute knownType)
{
var def = type.GetDefinition();
return def != null && def.FullTypeName.IsKnownType(knownType);
}
public static bool IsKnownType(this FullTypeName typeName, KnownTypeCode knownType)
{
return typeName == KnownTypeReference.Get(knownType).TypeName;
}
public static bool IsKnownType(this TopLevelTypeName typeName, KnownTypeCode knownType)
{
return typeName == KnownTypeReference.Get(knownType).TypeName;
}
internal static bool IsKnownType(this FullTypeName typeName, KnownAttribute knownType)
{
return typeName == knownType.GetTypeName();
}
internal static bool IsKnownType(this TopLevelTypeName typeName, KnownAttribute knownType)
{
return typeName == knownType.GetTypeName();
}
#endregion
#region GetDelegateInvokeMethod
@ -235,18 +265,13 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -235,18 +265,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
return TreeTraversal.PreOrder(assembly.TopLevelTypeDefinitions, t => t.NestedTypes);
}
public static IEnumerable<ITypeDefinition> GetAllTypeDefinitions (this IAssembly assembly)
{
return TreeTraversal.PreOrder(assembly.TopLevelTypeDefinitions, t => t.NestedTypes);
}
/// <summary>
/// Gets all type definitions in the compilation.
/// This may include types from referenced assemblies that are not accessible in the main assembly.
/// </summary>
public static IEnumerable<ITypeDefinition> GetAllTypeDefinitions (this ICompilation compilation)
{
return compilation.Assemblies.SelectMany(a => a.GetAllTypeDefinitions());
return compilation.Assemblies.SelectMany(a => a.TypeDefinitions);
}
/// <summary>

13
ICSharpCode.Decompiler/TypeSystem/TypeVisitor.cs

@ -16,6 +16,9 @@ @@ -16,6 +16,9 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler.TypeSystem
{
/// <summary>
@ -62,5 +65,15 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -62,5 +65,15 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
return type.VisitChildren(this);
}
public virtual IType VisitModReq(ModifiedType type)
{
return type.VisitChildren(this);
}
public virtual IType VisitModOpt(ModifiedType type)
{
return type.VisitChildren(this);
}
}
}

3
ILSpy/Languages/CSharpLanguage.cs

@ -41,6 +41,7 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation; @@ -41,6 +41,7 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using System.Reflection;
using ICSharpCode.Decompiler.Disassembler;
using GenericContext = ICSharpCode.Decompiler.Metadata.GenericContext;
namespace ICSharpCode.ILSpy
{
@ -404,7 +405,7 @@ namespace ICSharpCode.ILSpy @@ -404,7 +405,7 @@ namespace ICSharpCode.ILSpy
}
}
public override string TypeToString(Entity type, GenericContext genericContext = null, bool includeNamespace = true)
public override string TypeToString(Entity type, Decompiler.Metadata.GenericContext genericContext = null, bool includeNamespace = true)
{
if (type.Handle.IsNil)
throw new ArgumentNullException(nameof(type));

2
ILSpy/SearchPane.cs

@ -221,7 +221,7 @@ namespace ICSharpCode.ILSpy @@ -221,7 +221,7 @@ namespace ICSharpCode.ILSpy
continue;
CancellationToken cancellationToken = cts.Token;
foreach (var type in module.TypeDefinitions) {
foreach (var type in module.TopLevelTypeDefinitions) {
cancellationToken.ThrowIfCancellationRequested();
searcher.Search(type, language, AddResult);
}

Loading…
Cancel
Save