mirror of
https://github.com/icsharpcode/ILSpy.git
synced 2026-10-12 02:15:58 +00:00
Add tests for ExtensionEncodingV1 and ExtensionEncodingV2.
This commit is contained in:
@@ -133,7 +133,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers
|
||||
|
||||
await vswhereToolset.Fetch().ConfigureAwait(false);
|
||||
await RefAssembliesToolset.Fetch("5.0.0", sourcePath: "ref/net5.0").ConfigureAwait(false);
|
||||
await RefAssembliesToolset.Fetch("10.0.0-preview.4.25258.110", sourcePath: "ref/net10.0").ConfigureAwait(false);
|
||||
await RefAssembliesToolset.Fetch("10.0.0-rc.2.25502.107", sourcePath: "ref/net10.0").ConfigureAwait(false);
|
||||
|
||||
|
||||
#if DEBUG
|
||||
|
||||
@@ -96,6 +96,8 @@
|
||||
<None Include="TestCases\Disassembler\Pretty\InterfaceImplAttributes.il" />
|
||||
<None Include="TestCases\Disassembler\Pretty\SortMembers.expected.il" />
|
||||
<None Include="TestCases\Disassembler\Pretty\SortMembers.il" />
|
||||
<None Include="TestCases\ILPretty\ExtensionEncodingV2.il" />
|
||||
<None Include="testcases\ilpretty\ExtensionEncodingV1.il" />
|
||||
<None Include="TestCases\ILPretty\GuessAccessors.cs" />
|
||||
<None Include="TestCases\ILPretty\GuessAccessors.il" />
|
||||
<None Include="TestCases\ILPretty\Issue2260SwitchString.il" />
|
||||
@@ -145,6 +147,8 @@
|
||||
<Compile Include="ProjectDecompiler\TargetFrameworkTests.cs" />
|
||||
<Compile Include="ProjectDecompiler\WholeProjectDecompilerTests.cs" />
|
||||
<Compile Include="TestAssemblyResolver.cs" />
|
||||
<Compile Include="TestCases\ILPretty\ExtensionEncodingV2.cs" />
|
||||
<Compile Include="TestCases\ILPretty\ExtensionEncodingV1.cs" />
|
||||
<Compile Include="TestCases\ILPretty\Issue3344CkFinite.cs" />
|
||||
<Compile Include="TestCases\ILPretty\Issue3421.cs" />
|
||||
<Compile Include="TestCases\ILPretty\Issue3465.cs" />
|
||||
|
||||
@@ -323,6 +323,22 @@ namespace ICSharpCode.Decompiler.Tests
|
||||
await Run();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExtensionEncodingV1()
|
||||
{
|
||||
// uses Microsoft.Net.Compilers.Toolset 5.0.0-2.25380.108
|
||||
// see ExtensionEncodingV1.il for details
|
||||
await Run();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task ExtensionEncodingV2()
|
||||
{
|
||||
// uses Microsoft.Net.Compilers.Toolset 5.0.0-2.25451.107
|
||||
// see ExtensionEncodingV2.il for details
|
||||
await Run();
|
||||
}
|
||||
|
||||
async Task Run([CallerMemberName] string testName = null, DecompilerSettings settings = null,
|
||||
AssemblerOptions assemblerOptions = AssemblerOptions.Library)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
|
||||
{
|
||||
internal static class ExtensionPropertiesV1
|
||||
{
|
||||
extension<T>(ICollection<T> collection) where T : notnull
|
||||
{
|
||||
public bool IsEmpty => collection.Count == 0;
|
||||
|
||||
public int Test {
|
||||
get {
|
||||
return 42;
|
||||
}
|
||||
set {
|
||||
}
|
||||
}
|
||||
|
||||
public void AddIfNotNull(T item)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
collection.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public T2 Cast<T2>(int index) where T2 : T
|
||||
{
|
||||
return (T2)(object)collection.ElementAt(index);
|
||||
}
|
||||
|
||||
public static void StaticExtension()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
// To extend use:
|
||||
// see https://lab.razor.fyi/#fVHNbhMxEFYRqrBP0CcYbpsDVlioVDU_UrSNUBCqImVPnHC8k8TgtRd7tiSqcuMh-gbceQBeihdA66bJNlK5WDPzfTPffGP-65TzqXdLL0uhwtndaR20XcJsEwjLHm9nInPGoCLtbBAf0KLX6j-MSVnWJOcGjzhXWi6tC6RVeBoRmStwZKXZBH1M-6Tt96NSvvIoC22XT9VFLsO30OPcyhJDJRXCJJutpK8aIXGFypWVNuhFjoFCfDMZMIipR6INv-VMW0JvpYFAkrQCZWQIMF4T2qCdnXpXoSeNgbNbzhg-AP18mEwOl-nnQ1D7rAM_VugRcrgE68jWxnAW-1lVz41WMHfOwCSMy4o2MGj3iszVlmAwgG6Ptzq0JWgMQBzDlvgQMY9Uewvv017Mt_ENezzm2_aoG6cLGBXFZHHt6Lo2JslBE5adhnPfpBeQNCV4PYBm_QjtMNZadlQUkddpaT_SylPIZKB-ng6TxoK2Ba7390nhEvKD6s5JkqedxM2_oqJOS2tssERLI0ruh0TJR2K7P4z-ZjHef2RyMNcsueVsy7f87NW56Irum1Sk5-8uuuJt9-LjM20-sxd3P__-_rN4-fzLyfrkHw
|
||||
// created using https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-tools/NuGet/Microsoft.Net.Compilers.Toolset/overview/5.0.0-2.25380.108
|
||||
|
||||
.class private auto ansi abstract sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV1
|
||||
extends [System.Runtime]System.Object
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = (
|
||||
01 00 01 00 00
|
||||
)
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = (
|
||||
01 00 00 00 00
|
||||
)
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = (
|
||||
01 00 00 00
|
||||
)
|
||||
// Nested Types
|
||||
.class nested public auto ansi sealed specialname beforefieldinit '<>E__0`1'<T>
|
||||
extends [System.Runtime]System.Object
|
||||
{
|
||||
// Methods
|
||||
.method private hidebysig specialname static
|
||||
void '<Extension>$' (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!T> collection
|
||||
) cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
|
||||
01 00 00 00
|
||||
)
|
||||
// Method begins at RVA 0x209d
|
||||
// Header size: 1
|
||||
// Code size: 1 (0x1)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ret
|
||||
} // end of method '<>E__0`1'::'<Extension>$'
|
||||
|
||||
.method public hidebysig specialname
|
||||
instance bool get_IsEmpty () cil managed
|
||||
{
|
||||
// Method begins at RVA 0x209f
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<>E__0`1'::get_IsEmpty
|
||||
|
||||
.method public hidebysig specialname
|
||||
instance int32 get_Test () cil managed
|
||||
{
|
||||
// Method begins at RVA 0x209f
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<>E__0`1'::get_Test
|
||||
|
||||
.method public hidebysig specialname
|
||||
instance void set_Test (
|
||||
int32 'value'
|
||||
) cil managed
|
||||
{
|
||||
// Method begins at RVA 0x209f
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<>E__0`1'::set_Test
|
||||
|
||||
.method public hidebysig
|
||||
instance void AddIfNotNull (
|
||||
!T item
|
||||
) cil managed
|
||||
{
|
||||
// Method begins at RVA 0x209f
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<>E__0`1'::AddIfNotNull
|
||||
|
||||
.method public hidebysig
|
||||
instance !!T2 Cast<(!T) T2> (
|
||||
int32 index
|
||||
) cil managed
|
||||
{
|
||||
.param type T2
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = (
|
||||
01 00 00 00 00
|
||||
)
|
||||
// Method begins at RVA 0x209f
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<>E__0`1'::Cast
|
||||
|
||||
.method public hidebysig static
|
||||
void StaticExtension () cil managed
|
||||
{
|
||||
// Method begins at RVA 0x209f
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<>E__0`1'::StaticExtension
|
||||
|
||||
// Properties
|
||||
.property instance bool IsEmpty()
|
||||
{
|
||||
.get instance bool ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV1/'<>E__0`1'::get_IsEmpty()
|
||||
}
|
||||
.property instance int32 Test()
|
||||
{
|
||||
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV1/'<>E__0`1'::get_Test()
|
||||
.set instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV1/'<>E__0`1'::set_Test(int32)
|
||||
}
|
||||
|
||||
} // end of class <>E__0`1
|
||||
|
||||
|
||||
// Methods
|
||||
.method public hidebysig static
|
||||
bool get_IsEmpty<T> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection
|
||||
) cil managed
|
||||
{
|
||||
// Method begins at RVA 0x2050
|
||||
// Header size: 1
|
||||
// Code size: 10 (0xa)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldarg.0
|
||||
IL_0001: callvirt instance int32 class [System.Runtime]System.Collections.Generic.ICollection`1<!!T>::get_Count()
|
||||
IL_0006: ldc.i4.0
|
||||
IL_0007: ceq
|
||||
IL_0009: ret
|
||||
} // end of method ExtensionProperties::get_IsEmpty
|
||||
|
||||
.method public hidebysig static
|
||||
int32 get_Test<T> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection
|
||||
) cil managed
|
||||
{
|
||||
// Method begins at RVA 0x205b
|
||||
// Header size: 1
|
||||
// Code size: 4 (0x4)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ldc.i4.s 42
|
||||
IL_0003: ret
|
||||
} // end of method ExtensionProperties::get_Test
|
||||
|
||||
.method public hidebysig static
|
||||
void set_Test<T> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection,
|
||||
int32 'value'
|
||||
) cil managed
|
||||
{
|
||||
// Method begins at RVA 0x2060
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ret
|
||||
} // end of method ExtensionProperties::set_Test
|
||||
|
||||
.method public hidebysig static
|
||||
void AddIfNotNull<T> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection,
|
||||
!!T item
|
||||
) cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = (
|
||||
01 00 00 00
|
||||
)
|
||||
// Method begins at RVA 0x2064
|
||||
// Header size: 12
|
||||
// Code size: 25 (0x19)
|
||||
.maxstack 2
|
||||
.locals init (
|
||||
[0] bool
|
||||
)
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ldarg.1
|
||||
IL_0002: box !!T
|
||||
IL_0007: ldnull
|
||||
IL_0008: cgt.un
|
||||
IL_000a: stloc.0
|
||||
IL_000b: ldloc.0
|
||||
IL_000c: brfalse.s IL_0018
|
||||
|
||||
IL_000e: nop
|
||||
IL_000f: ldarg.0
|
||||
IL_0010: ldarg.1
|
||||
IL_0011: callvirt instance void class [System.Runtime]System.Collections.Generic.ICollection`1<!!T>::Add(!0)
|
||||
IL_0016: nop
|
||||
IL_0017: nop
|
||||
|
||||
IL_0018: ret
|
||||
} // end of method ExtensionProperties::AddIfNotNull
|
||||
|
||||
.method public hidebysig static
|
||||
!!T2 Cast<T, (!!T) T2> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection,
|
||||
int32 index
|
||||
) cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = (
|
||||
01 00 00 00
|
||||
)
|
||||
// Method begins at RVA 0x2089
|
||||
// Header size: 1
|
||||
// Code size: 19 (0x13)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ldarg.0
|
||||
IL_0002: ldarg.1
|
||||
IL_0003: call !!0 [System.Linq]System.Linq.Enumerable::ElementAt<!!T>(class [System.Runtime]System.Collections.Generic.IEnumerable`1<!!0>, int32)
|
||||
IL_0008: box !!T
|
||||
IL_000d: unbox.any !!T2
|
||||
IL_0012: ret
|
||||
} // end of method ExtensionProperties::Cast
|
||||
|
||||
.method public hidebysig static
|
||||
void StaticExtension<T> () cil managed
|
||||
{
|
||||
// Method begins at RVA 0x2060
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ret
|
||||
} // end of method ExtensionProperties::StaticExtension
|
||||
|
||||
} // end of class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV1
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
|
||||
{
|
||||
internal static class ExtensionPropertiesV2
|
||||
{
|
||||
extension<T>(ICollection<T> collection) where T : notnull
|
||||
{
|
||||
public bool IsEmpty => collection.Count == 0;
|
||||
public int Test {
|
||||
get {
|
||||
return 42;
|
||||
}
|
||||
set {
|
||||
}
|
||||
}
|
||||
public void AddIfNotNull(T item)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
collection.Add(item);
|
||||
}
|
||||
}
|
||||
public T2 Cast<T2>(int index) where T2 : T
|
||||
{
|
||||
return (T2)(object)collection.ElementAt(index);
|
||||
}
|
||||
public static void StaticExtension()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
// To extend use:
|
||||
// see https://lab.razor.fyi/#fVHBbtNAEFUQArwn6BcMPdkSrFyrFVKbVIrcgIKqKKKrHkBIbOyps3S9a3bHtFEViQvfwy9w4Qf4D66ckd00dSOVy2pn3nvz5u2y748ZmzpbOFnyzG_9fVR7ZQo4WXjC8oB1K55arTEjZY3nb9CgU9l_GOOyrEnONG5wjpQsjPWkMn8_wlOb49BIvfBqk3aszJeNlpg7lLkyxX19LqQ_3xz0rjakSuSn6LyyppWzD9J7LGd6sQ9CugLptZMlXlh3Hm7zyUik1uGwql6sRIOdmMfb0UfGjCzRVzJDGKcnc-mqJgI_wsyWldLouEBPvj1T6dHz8fHUIdGCXbFAGUJnpAZPklQGmZbew-iS0DQuU2crdKTQnyYsuGJBgDdQXxyG49t374tDyNZVBBdzdAgC9sFYMrXWLGj1QVXPtMpgZq2GsR-VFS1g0NXy1NaGYDCA-IB1FMoQNCGgHRMUeHMLHFLtDOwmB229bE-_xtt62R311aochnk-PptYmtRahwIUYRk1nGuROoOwacHzATTrt9AKCzrLDvO85UUd7zteIoFUeuqL5DBsIiiT4-X6fRLYB3HrukoSiiQK7ewzZhR1vEYaSzQ0pPB6SGt5x2z1i22-k_a-_srwNlyz5JIFS7ZkW8_2eMzjlwlP9nb3dvhO_OrtA6XfB09-__n14-fZ04efevPeZe9br_cP
|
||||
// created using https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-tools/NuGet/Microsoft.Net.Compilers.Toolset/overview/5.0.0-2.25451.107
|
||||
|
||||
.assembly TestProject
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = {
|
||||
}
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = {
|
||||
int32(8)
|
||||
}
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = {
|
||||
property bool WrapNonExceptionThrows = bool(true)
|
||||
}
|
||||
.custom instance void [System.Runtime]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [System.Runtime]System.Diagnostics.DebuggableAttribute/DebuggingModes) = {
|
||||
int32(263)
|
||||
}
|
||||
.custom instance void [System.Runtime]System.Runtime.Versioning.TargetFrameworkAttribute::.ctor(string) = {
|
||||
string('.NETCoreApp,Version=10.0')
|
||||
}
|
||||
.permissionset reqmin = {
|
||||
[System.Runtime]System.Security.Permissions.SecurityPermissionAttribute = {
|
||||
property bool SkipVerification = bool(true)
|
||||
}
|
||||
}
|
||||
.hash algorithm 0x00008004 // SHA1
|
||||
.ver 0:0:0:0
|
||||
}
|
||||
|
||||
.class private auto ansi '<Module>'
|
||||
{
|
||||
} // end of class <Module>
|
||||
|
||||
.class private auto ansi abstract sealed beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV2
|
||||
extends [System.Runtime]System.Object
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableContextAttribute::.ctor(uint8) = {
|
||||
uint8(1)
|
||||
}
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = {
|
||||
uint8(0)
|
||||
}
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = {
|
||||
}
|
||||
// Nested Types
|
||||
.class nested public auto ansi sealed specialname '<G>$847CB318C385471B1F4E7BD0A197DBCA'<$T0>
|
||||
extends [System.Runtime]System.Object
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = {
|
||||
}
|
||||
// Nested Types
|
||||
.class nested public auto ansi abstract sealed specialname '<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B'<T>
|
||||
extends [System.Runtime]System.Object
|
||||
{
|
||||
// Methods
|
||||
.method public hidebysig specialname static
|
||||
void '<Extension>$' (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!T> collection
|
||||
) cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = {
|
||||
}
|
||||
// Method begins at RVA 0x20a0
|
||||
// Header size: 1
|
||||
// Code size: 1 (0x1)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ret
|
||||
} // end of method '<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B'::'<Extension>$'
|
||||
|
||||
} // end of class <M>$6A79ECC07A7731C57E8EB4E3D9C8B38B
|
||||
|
||||
|
||||
// Methods
|
||||
.method public hidebysig specialname
|
||||
instance bool get_IsEmpty () cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionMarkerAttribute::.ctor(string) = {
|
||||
string('<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B')
|
||||
}
|
||||
// Method begins at RVA 0x209d
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<G>$847CB318C385471B1F4E7BD0A197DBCA'::get_IsEmpty
|
||||
|
||||
.method public hidebysig specialname
|
||||
instance int32 get_Test () cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionMarkerAttribute::.ctor(string) = {
|
||||
string('<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B')
|
||||
}
|
||||
// Method begins at RVA 0x209d
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<G>$847CB318C385471B1F4E7BD0A197DBCA'::get_Test
|
||||
|
||||
.method public hidebysig specialname
|
||||
instance void set_Test (
|
||||
int32 'value'
|
||||
) cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionMarkerAttribute::.ctor(string) = {
|
||||
string('<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B')
|
||||
}
|
||||
// Method begins at RVA 0x209d
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<G>$847CB318C385471B1F4E7BD0A197DBCA'::set_Test
|
||||
|
||||
.method public hidebysig
|
||||
instance void AddIfNotNull (
|
||||
!$T0 item
|
||||
) cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionMarkerAttribute::.ctor(string) = {
|
||||
string('<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B')
|
||||
}
|
||||
// Method begins at RVA 0x209d
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<G>$847CB318C385471B1F4E7BD0A197DBCA'::AddIfNotNull
|
||||
|
||||
.method public hidebysig
|
||||
instance !!T2 Cast<(!$T0) T2> (
|
||||
int32 index
|
||||
) cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionMarkerAttribute::.ctor(string) = {
|
||||
string('<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B')
|
||||
}
|
||||
.param type T2
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.NullableAttribute::.ctor(uint8) = {
|
||||
uint8(0)
|
||||
}
|
||||
// Method begins at RVA 0x209d
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<G>$847CB318C385471B1F4E7BD0A197DBCA'::Cast
|
||||
|
||||
.method public hidebysig static
|
||||
void StaticExtension () cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionMarkerAttribute::.ctor(string) = {
|
||||
string('<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B')
|
||||
}
|
||||
// Method begins at RVA 0x209d
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldnull
|
||||
IL_0001: throw
|
||||
} // end of method '<G>$847CB318C385471B1F4E7BD0A197DBCA'::StaticExtension
|
||||
|
||||
// Properties
|
||||
.property instance bool IsEmpty()
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionMarkerAttribute::.ctor(string) = {
|
||||
string('<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B')
|
||||
}
|
||||
.get instance bool ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV2/'<G>$847CB318C385471B1F4E7BD0A197DBCA'::get_IsEmpty()
|
||||
}
|
||||
.property instance int32 Test()
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionMarkerAttribute::.ctor(string) = {
|
||||
string('<M>$6A79ECC07A7731C57E8EB4E3D9C8B38B')
|
||||
}
|
||||
.get instance int32 ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV2/'<G>$847CB318C385471B1F4E7BD0A197DBCA'::get_Test()
|
||||
.set instance void ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV2/'<G>$847CB318C385471B1F4E7BD0A197DBCA'::set_Test(int32)
|
||||
}
|
||||
|
||||
} // end of class <G>$847CB318C385471B1F4E7BD0A197DBCA
|
||||
|
||||
|
||||
// Methods
|
||||
.method public hidebysig static
|
||||
bool get_IsEmpty<T> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection
|
||||
) cil managed
|
||||
{
|
||||
// Method begins at RVA 0x2050
|
||||
// Header size: 1
|
||||
// Code size: 10 (0xa)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: ldarg.0
|
||||
IL_0001: callvirt instance int32 class [System.Runtime]System.Collections.Generic.ICollection`1<!!T>::get_Count()
|
||||
IL_0006: ldc.i4.0
|
||||
IL_0007: ceq
|
||||
IL_0009: ret
|
||||
} // end of method ExtensionPropertiesV2::get_IsEmpty
|
||||
|
||||
.method public hidebysig static
|
||||
int32 get_Test<T> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection
|
||||
) cil managed
|
||||
{
|
||||
// Method begins at RVA 0x205b
|
||||
// Header size: 1
|
||||
// Code size: 4 (0x4)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ldc.i4.s 42
|
||||
IL_0003: ret
|
||||
} // end of method ExtensionPropertiesV2::get_Test
|
||||
|
||||
.method public hidebysig static
|
||||
void set_Test<T> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection,
|
||||
int32 'value'
|
||||
) cil managed
|
||||
{
|
||||
// Method begins at RVA 0x2060
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ret
|
||||
} // end of method ExtensionPropertiesV2::set_Test
|
||||
|
||||
.method public hidebysig static
|
||||
void AddIfNotNull<T> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection,
|
||||
!!T item
|
||||
) cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = {
|
||||
}
|
||||
// Method begins at RVA 0x2064
|
||||
// Header size: 12
|
||||
// Code size: 25 (0x19)
|
||||
.maxstack 2
|
||||
.locals init (
|
||||
[0] bool
|
||||
)
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ldarg.1
|
||||
IL_0002: box !!T
|
||||
IL_0007: ldnull
|
||||
IL_0008: cgt.un
|
||||
IL_000a: stloc.0
|
||||
IL_000b: ldloc.0
|
||||
IL_000c: brfalse.s IL_0018
|
||||
|
||||
IL_000e: nop
|
||||
IL_000f: ldarg.0
|
||||
IL_0010: ldarg.1
|
||||
IL_0011: callvirt instance void class [System.Runtime]System.Collections.Generic.ICollection`1<!!T>::Add(!0)
|
||||
IL_0016: nop
|
||||
IL_0017: nop
|
||||
|
||||
IL_0018: ret
|
||||
} // end of method ExtensionPropertiesV2::AddIfNotNull
|
||||
|
||||
.method public hidebysig static
|
||||
!!T2 Cast<T, (!!T) T2> (
|
||||
class [System.Runtime]System.Collections.Generic.ICollection`1<!!T> collection,
|
||||
int32 index
|
||||
) cil managed
|
||||
{
|
||||
.custom instance void [System.Runtime]System.Runtime.CompilerServices.ExtensionAttribute::.ctor() = {
|
||||
}
|
||||
// Method begins at RVA 0x2089
|
||||
// Header size: 1
|
||||
// Code size: 19 (0x13)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ldarg.0
|
||||
IL_0002: ldarg.1
|
||||
IL_0003: call !!0 [System.Linq]System.Linq.Enumerable::ElementAt<!!T>(class [System.Runtime]System.Collections.Generic.IEnumerable`1<!!0>, int32)
|
||||
IL_0008: box !!T
|
||||
IL_000d: unbox.any !!T2
|
||||
IL_0012: ret
|
||||
} // end of method ExtensionPropertiesV2::Cast
|
||||
|
||||
.method public hidebysig static
|
||||
void StaticExtension<T> () cil managed
|
||||
{
|
||||
// Method begins at RVA 0x2060
|
||||
// Header size: 1
|
||||
// Code size: 2 (0x2)
|
||||
.maxstack 8
|
||||
|
||||
IL_0000: nop
|
||||
IL_0001: ret
|
||||
} // end of method ExtensionPropertiesV2::StaticExtension
|
||||
|
||||
} // end of class ICSharpCode.Decompiler.Tests.TestCases.ILPretty.ExtensionPropertiesV2
|
||||
|
||||
// references
|
||||
.assembly extern System.Runtime
|
||||
{
|
||||
.publickeytoken = (
|
||||
b0 3f 5f 7f 11 d5 0a 3a
|
||||
)
|
||||
.ver 10:0:0:0
|
||||
}
|
||||
.assembly extern System.Linq
|
||||
{
|
||||
.publickeytoken = (
|
||||
b0 3f 5f 7f 11 d5 0a 3a
|
||||
)
|
||||
.ver 10:0:0:0
|
||||
}
|
||||
@@ -1367,13 +1367,16 @@ namespace ICSharpCode.Decompiler.CSharp
|
||||
foreach (var group in typeDef.ExtensionInfo?.GetGroups() ?? [])
|
||||
{
|
||||
var ext = new ExtensionDeclaration();
|
||||
ext.TypeParameters.AddRange(group.Key.DeclaringTypeDefinition.TypeParameters.Select(tp => typeSystemAstBuilder.ConvertTypeParameter(tp)));
|
||||
ext.ReceiverParameters.Add(typeSystemAstBuilder.ConvertParameter(group.Key.Parameters.Single()));
|
||||
ext.Constraints.AddRange(group.Key.DeclaringTypeDefinition.TypeParameters.Select(c => typeSystemAstBuilder.ConvertTypeParameterConstraint(c)));
|
||||
ITypeParameter[] typeParameters = group.Key.TypeParameters;
|
||||
var subst = new TypeParameterSubstitution(typeParameters, null);
|
||||
ext.TypeParameters.AddRange(typeParameters.Select(tp => typeSystemAstBuilder.ConvertTypeParameter(tp)));
|
||||
var marker = group.Key.Marker.Specialize(subst);
|
||||
ext.ReceiverParameters.Add(typeSystemAstBuilder.ConvertParameter(marker.Parameters.Single()));
|
||||
ext.Constraints.AddRange(typeParameters.Select(c => typeSystemAstBuilder.ConvertTypeParameterConstraint(c)));
|
||||
|
||||
foreach (var member in group)
|
||||
{
|
||||
IMember extMember = member.ExtensionMember;
|
||||
IMember extMember = member.ExtensionMember.Specialize(subst);
|
||||
if (member.ExtensionMember.IsAccessor)
|
||||
{
|
||||
extMember = member.ExtensionMember.AccessorOwner;
|
||||
@@ -1508,9 +1511,15 @@ namespace ICSharpCode.Decompiler.CSharp
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.ExtensionMembers && extensionInfo != null && entity is IMethod m && extensionInfo.InfoOfImplementationMember(m).HasValue)
|
||||
if (settings.ExtensionMembers && extensionInfo != null)
|
||||
{
|
||||
return;
|
||||
switch (entity)
|
||||
{
|
||||
case ITypeDefinition td when extensionInfo.IsExtensionGroupingType(td):
|
||||
return;
|
||||
case IMethod m when extensionInfo.InfoOfImplementationMember(m).HasValue:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EntityDeclaration entityDecl;
|
||||
@@ -1584,9 +1593,21 @@ namespace ICSharpCode.Decompiler.CSharp
|
||||
switch (extMember)
|
||||
{
|
||||
case IProperty p:
|
||||
return DoDecompile(p, decompileRun, decompilationContext.WithCurrentMember(p), info);
|
||||
var prop = DoDecompile(p, decompileRun, decompilationContext.WithCurrentMember(p), info);
|
||||
RemoveAttribute(prop, KnownAttribute.ExtensionMarker);
|
||||
if (p.Getter != null)
|
||||
{
|
||||
RemoveAttribute(prop.GetChildByRole(PropertyDeclaration.GetterRole), KnownAttribute.ExtensionMarker);
|
||||
}
|
||||
if (p.Setter != null)
|
||||
{
|
||||
RemoveAttribute(prop.GetChildByRole(PropertyDeclaration.SetterRole), KnownAttribute.ExtensionMarker);
|
||||
}
|
||||
return prop;
|
||||
case IMethod m:
|
||||
return DoDecompile(m, decompileRun, decompilationContext.WithCurrentMember(m), info);
|
||||
var meth = DoDecompile(m, decompileRun, decompilationContext.WithCurrentMember(m), info);
|
||||
RemoveAttribute(meth, KnownAttribute.ExtensionMarker);
|
||||
return meth;
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Extension member {extMember} is not supported for decompilation.");
|
||||
@@ -1762,7 +1783,7 @@ namespace ICSharpCode.Decompiler.CSharp
|
||||
{
|
||||
if (!method.IsStatic)
|
||||
parameterOffset = 1; // implementation method has an additional receiver parameter
|
||||
method = extensionInfo.InfoOfExtensionMember(method).Value.ImplementationMethod;
|
||||
method = extensionInfo.InfoOfExtensionMember((IMethod)method.MemberDefinition).Value.ImplementationMethod;
|
||||
}
|
||||
|
||||
var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
|
||||
|
||||
@@ -20,9 +20,12 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
using ICSharpCode.Decompiler.TypeSystem.Implementation;
|
||||
|
||||
namespace ICSharpCode.Decompiler.TypeSystem
|
||||
{
|
||||
public class ExtensionInfo
|
||||
@@ -59,6 +62,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
|
||||
IMethod? marker = null;
|
||||
bool hasMultipleMarkers = false;
|
||||
List<IMethod> extensionMethods = [];
|
||||
ITypeParameter[] extensionGroupTypeParameters = extGroup.TypeParameters.ToArray();
|
||||
|
||||
// For easier access to accessors we use SRM
|
||||
foreach (var h in td.GetMethods())
|
||||
@@ -82,7 +86,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
|
||||
if (marker == null || hasMultipleMarkers)
|
||||
return false;
|
||||
|
||||
CollectImplementationMethods(extGroup, marker, extensionMethods);
|
||||
CollectImplementationMethods(extGroup, marker, extensionMethods, extensionGroupTypeParameters);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -102,6 +106,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
|
||||
|
||||
TypeDefinition td = metadata.GetTypeDefinition((TypeDefinitionHandle)extGroup.MetadataToken);
|
||||
List<IMethod> extensionMethods = [];
|
||||
ITypeParameter[] extensionGroupTypeParameters = new ITypeParameter[extGroup.TypeParameterCount];
|
||||
|
||||
// For easier access to accessors we use SRM
|
||||
foreach (var h in td.GetMethods())
|
||||
@@ -121,12 +126,16 @@ namespace ICSharpCode.Decompiler.TypeSystem
|
||||
extensionMethods.Add(method);
|
||||
}
|
||||
|
||||
CollectImplementationMethods(extGroup, marker, extensionMethods);
|
||||
CollectImplementationMethods(extGroup, marker, extensionMethods, extensionGroupTypeParameters);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CollectImplementationMethods(ITypeDefinition extGroup, IMethod marker, List<IMethod> extensionMethods)
|
||||
void CollectImplementationMethods(ITypeDefinition extGroup, IMethod marker, List<IMethod> extensionMethods, ITypeParameter[] extensionGroupTypeParameters)
|
||||
{
|
||||
List<(IMethod extension, IMethod implementation)> implementations = [];
|
||||
|
||||
string[] typeParameterNames = new string[extGroup.TypeParameterCount];
|
||||
|
||||
foreach (var extension in extensionMethods)
|
||||
{
|
||||
int expectedTypeParameterCount = extension.TypeParameters.Count + extGroup.TypeParameterCount;
|
||||
@@ -165,15 +174,62 @@ namespace ICSharpCode.Decompiler.TypeSystem
|
||||
);
|
||||
}
|
||||
|
||||
IMethod? foundImpl = null;
|
||||
|
||||
foreach (var impl in extensionContainer.Methods)
|
||||
{
|
||||
if (!IsMatchingImplementation(impl))
|
||||
continue;
|
||||
var emi = new ExtensionMemberInfo(marker, extension, impl);
|
||||
extensionMemberMap[extension] = emi;
|
||||
implementationMemberMap[impl] = emi;
|
||||
Debug.Assert(foundImpl == null, "Multiple matching implementations found");
|
||||
foundImpl = impl;
|
||||
}
|
||||
|
||||
Debug.Assert(foundImpl != null, "No matching implementation found");
|
||||
|
||||
implementations.Add((extension, foundImpl));
|
||||
}
|
||||
|
||||
foreach (var (extension, implementation) in implementations)
|
||||
{
|
||||
for (int i = 0; i < extensionGroupTypeParameters.Length; i++)
|
||||
{
|
||||
if (typeParameterNames[i] == null)
|
||||
{
|
||||
typeParameterNames[i] = implementation.TypeParameters[i].Name;
|
||||
}
|
||||
else if (typeParameterNames[i] != implementation.TypeParameters[i].Name)
|
||||
{
|
||||
// TODO: Handle name conflicts properly
|
||||
typeParameterNames[i] = $"T{i + 1}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < extensionGroupTypeParameters.Length; i++)
|
||||
{
|
||||
var originalTypeParameter = extGroup.TypeParameters[i];
|
||||
if (extensionGroupTypeParameters[i] == null)
|
||||
{
|
||||
extensionGroupTypeParameters[i] = new DefaultTypeParameter(
|
||||
extGroup, i, typeParameterNames[i],
|
||||
VarianceModifier.Invariant,
|
||||
attributes: originalTypeParameter.GetAttributes().ToArray(),
|
||||
originalTypeParameter.HasValueTypeConstraint,
|
||||
originalTypeParameter.HasReferenceTypeConstraint,
|
||||
originalTypeParameter.HasDefaultConstructorConstraint,
|
||||
originalTypeParameter.TypeConstraints.Select(c => c.Type).ToArray(),
|
||||
originalTypeParameter.NullabilityConstraint
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var (extension, implementation) in implementations)
|
||||
{
|
||||
var info = new ExtensionMemberInfo(marker, extension, implementation, extensionGroupTypeParameters);
|
||||
this.extensionMemberMap[extension] = info;
|
||||
this.implementationMemberMap[implementation] = info;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,13 +243,18 @@ namespace ICSharpCode.Decompiler.TypeSystem
|
||||
return this.implementationMemberMap.TryGetValue(method, out var value) ? value : null;
|
||||
}
|
||||
|
||||
public IEnumerable<IGrouping<IMethod, ExtensionMemberInfo>> GetGroups()
|
||||
public IEnumerable<IGrouping<(IMethod Marker, ITypeParameter[] TypeParameters), ExtensionMemberInfo>> GetGroups()
|
||||
{
|
||||
return this.extensionMemberMap.Values.GroupBy(x => x.ExtensionMarkerMethod);
|
||||
return this.extensionMemberMap.Values.GroupBy(x => (x.ExtensionMarkerMethod, x.ExtensionGroupingTypeParameters));
|
||||
}
|
||||
|
||||
public bool IsExtensionGroupingType(ITypeDefinition type)
|
||||
{
|
||||
return this.extensionMemberMap.Values.Any(x => x.ExtensionGroupingType.Equals(type));
|
||||
}
|
||||
}
|
||||
|
||||
public readonly struct ExtensionMemberInfo(IMethod marker, IMethod extension, IMethod implementation)
|
||||
public readonly struct ExtensionMemberInfo(IMethod marker, IMethod extension, IMethod implementation, ITypeParameter[] extensionGroupingTypeParameters)
|
||||
{
|
||||
/// <summary>
|
||||
/// Metadata-only method called '<Extension>$'. Has the C# signature for the extension declaration.
|
||||
@@ -223,6 +284,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
|
||||
/// </summary>
|
||||
public ITypeDefinition ExtensionGroupingType => ExtensionMember.DeclaringTypeDefinition!;
|
||||
|
||||
/// <summary>
|
||||
/// This is the array of type parameters for the extension declaration.
|
||||
/// </summary>
|
||||
public ITypeParameter[] ExtensionGroupingTypeParameters => extensionGroupingTypeParameters;
|
||||
|
||||
/// <summary>
|
||||
/// This class holds the type parameters for the extension declaration with full fidelity of C# constraints.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user