mirror of https://github.com/icsharpcode/ILSpy.git
Browse Source
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
52 changed files with 2927 additions and 577 deletions
@ -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++; |
||||
} |
||||
} |
||||
} |
@ -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 *********************** |
@ -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 *********************** |
@ -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 *********************** |
@ -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 *********************** |
@ -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; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
||||
} |
@ -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)); |
||||
} |
||||
} |
||||
} |
@ -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()); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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
|
||||
} |
||||
} |
@ -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}"; |
||||
} |
||||
} |
||||
} |
@ -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
|
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue