Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,14 @@
<Compile Remove="TestCases\ILPretty\Issue3729.cs" />
<None Include="TestCases\ILPretty\Issue3729.cs" />
<None Include="TestCases\ILPretty\Issue3729.il" />
<Compile Remove="TestCases\ILPretty\ParameterizedPropertyInitializer.cs" />
<None Include="TestCases\ILPretty\ParameterizedPropertyInitializer.cs" />
<None Include="TestCases\ILPretty\ParameterizedPropertyInitializer.il" />
<None Include="TestCases\ILPretty\ParamsPropertySetter.il" />
<None Include="TestCases\ILPretty\IndexerAccessorParameterNames.il" />
<Compile Remove="TestCases\ILPretty\ParameterizedPropertySetterCall.cs" />
<None Include="TestCases\ILPretty\ParameterizedPropertySetterCall.cs" />
<None Include="TestCases\ILPretty\ParameterizedPropertySetterCall.il" />
<Compile Remove="TestCases\ILPretty\SpanConversionOperatorMismatch.cs" />
<None Include="TestCases\ILPretty\SpanConversionOperatorMismatch.cs" />
<Compile Remove="TestCases\ILPretty\FSharpLoops_Debug.cs" />
Expand Down
24 changes: 24 additions & 0 deletions ICSharpCode.Decompiler.Tests/ILPrettyTestRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,30 @@ public async Task Issue3729()
await Run();
}

[Test]
public async Task ParamsPropertySetter()
{
await Run();
}

[Test]
public async Task ParameterizedPropertyInitializer()
{
await Run();
}

[Test]
public async Task IndexerAccessorParameterNames()
{
await Run();
}

[Test]
public async Task ParameterizedPropertySetterCall()
{
await Run();
}

async Task Run([CallerMemberName] string testName = null, DecompilerSettings settings = null,
AssemblerOptions assemblerOptions = AssemblerOptions.Library)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ static void Main()
Generics();
ConstructorTest();
TestIndexer();
TestIndexerWithNamedArguments();
TestRedeclaredDefaultValues();
#if !MCS2
TestNamedWithOmittedOptional();
#endif
Issue1281();
Issue1747();
CallAmbiguousOutParam();
Expand Down Expand Up @@ -330,6 +335,87 @@ static void TestIndexer()
}
#endregion

#region Named arguments with omitted optional arguments
// mcs 2.6.4 crashes while emitting a call that names its arguments and leaves an optional
// one out.
#if !MCS2
static void TestNamedWithOmittedOptional()
{
var obj = new NamedOptionalTests();
obj.M(b: Trace(2), a: Trace(1));
obj.N(y: Trace(1), x: Trace(2));
obj.N(z: Trace(1), x: Trace(2));
}

class NamedOptionalTests
{
public void M(int a, int b, int c = 3)
{
Console.WriteLine("M(" + a + ", " + b + ", " + c + ")");
}

public void N(int x, int y = 10, int z = 20)
{
Console.WriteLine("N(" + x + ", " + y + ", " + z + ")");
}
}
#endif
#endregion

#region Redeclared default values
static void TestRedeclaredDefaultValues()
{
var derived = new DerivedDefaultValue();
Console.WriteLine(derived[1, 10]);
Console.WriteLine(derived.Method(1, 10));
}

class BaseDefaultValue
{
public virtual int this[int x, int y = 10] {
get {
return x + y;
}
}

public virtual int Method(int x, int y = 10)
{
return x + y;
}
}

class DerivedDefaultValue : BaseDefaultValue
{
public override int this[int x, int y = 20] {
get {
return x + y + 1;
}
}

public override int Method(int x, int y = 20)
{
return x + y + 1;
}
}
#endregion

#region Indexer with named arguments
static void TestIndexerWithNamedArguments()
{
var obj = new NamedArgumentIndexerTests();
Console.WriteLine(obj[y: Trace(1), x: Trace(2)]);
obj[y: Trace(3), x: Trace(4)] = Trace(5);
Console.WriteLine(obj[y: Trace(6), x: Trace(7)] = Trace(8));
obj[y: Trace(9), x: Trace(10)] += 5;
}

static int Trace(int i)
{
Console.WriteLine("Trace(" + i + ")");
return i;
}
#endregion

#region Out Parameter
static void AmbiguousOutParam(out string a)
{
Expand Down Expand Up @@ -602,6 +688,19 @@ public void Test()
#endregion
}

class NamedArgumentIndexerTests
{
public int this[int x, int y] {
get {
Console.WriteLine("get_Item(" + x + ", " + y + ")");
return x;
}
set {
Console.WriteLine("set_Item(" + x + ", " + y + ", " + value + ")");
}
}
}

class IndexerTests
{
public object this[object key] {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
public class IndexerAccessorParameterNames
{
public int this[int x, int y] {
get {
return x;
}
set {
}
}

private int Get(int i)
{
return i;
}

public void Use()
{
this[y: Get(1), x: Get(2)] = 3;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#define CORE_ASSEMBLY "System.Runtime"

.assembly extern CORE_ASSEMBLY
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 4:0:0:0
}

.assembly IndexerAccessorParameterNames { }

.class public auto ansi beforefieldinit IndexerAccessorParameterNames
extends [CORE_ASSEMBLY]System.Object
{
.custom instance void [CORE_ASSEMBLY]System.Reflection.DefaultMemberAttribute::.ctor(string) = ( 01 00 04 49 74 65 6D 00 00 )

// The indexer's parameter names are the getter's: x and y.
.method public hidebysig specialname instance int32 get_Item (int32 x, int32 y) cil managed
{
.maxstack 8
ldarg.1
ret
}

// The setter is free to name the same parameters differently, which C# cannot express.
.method public hidebysig specialname instance void set_Item (int32 a, int32 b, int32 'value') cil managed
{
.maxstack 8
ret
}

.property instance int32 Item(int32, int32)
{
.get instance int32 IndexerAccessorParameterNames::get_Item(int32, int32)
.set instance void IndexerAccessorParameterNames::set_Item(int32, int32, int32)
}

.method private hidebysig instance int32 Get (int32 i) cil managed
{
.maxstack 8
ldarg.1
ret
}

// this[y: Get(1), x: Get(2)] = 3;
.method public hidebysig instance void Use () cil managed
{
.maxstack 4
.locals init (int32 V_0)
ldarg.0
ldarg.0
ldc.i4.1
call instance int32 IndexerAccessorParameterNames::Get(int32)
stloc.0
ldarg.0
ldc.i4.2
call instance int32 IndexerAccessorParameterNames::Get(int32)
ldloc.0
ldc.i4.3
call instance void IndexerAccessorParameterNames::set_Item(int32, int32, int32)
ret
}

.method public hidebysig specialname rtspecialname instance void .ctor () cil managed
{
.maxstack 8
ldarg.0
call instance void [CORE_ASSEMBLY]System.Object::.ctor()
ret
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
public class ParameterizedPropertyInitializer
{
// C# has no syntax for parameterized property 'Foo'.
public int get_Foo(int x)
{
return x;
}

public void set_Foo(int x, int value)
{
}

public static void Consume(ParameterizedPropertyInitializer p)
{
}

public static void Use()
{
Consume(new ParameterizedPropertyInitializer { [7] = 5 });
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#define CORE_ASSEMBLY "System.Runtime"

.assembly extern CORE_ASSEMBLY
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 4:0:0:0
}

.assembly ParameterizedPropertyInitializer { }

// A parameterized property that is not an indexer: the type carries no DefaultMemberAttribute,
// which C# cannot express, but VB, C++/CLI and COM interop all produce it.
.class public auto ansi beforefieldinit ParameterizedPropertyInitializer
extends [CORE_ASSEMBLY]System.Object
{
.method public hidebysig specialname instance int32 get_Foo (int32 x) cil managed
{
.maxstack 8
ldarg.1
ret
}

.method public hidebysig specialname instance void set_Foo (int32 x, int32 'value') cil managed
{
.maxstack 8
ret
}

.property instance int32 Foo(int32)
{
.get instance int32 ParameterizedPropertyInitializer::get_Foo(int32)
.set instance void ParameterizedPropertyInitializer::set_Foo(int32, int32)
}

.method public hidebysig static void Consume (class ParameterizedPropertyInitializer p) cil managed
{
.maxstack 8
ret
}

.method public hidebysig static void Use () cil managed
{
.maxstack 8
newobj instance void ParameterizedPropertyInitializer::.ctor()
dup
ldc.i4.7
ldc.i4.5
call instance void ParameterizedPropertyInitializer::set_Foo(int32, int32)
call void ParameterizedPropertyInitializer::Consume(class ParameterizedPropertyInitializer)
ret
}

.method public hidebysig specialname rtspecialname instance void .ctor () cil managed
{
.maxstack 8
ldarg.0
call instance void [CORE_ASSEMBLY]System.Object::.ctor()
ret
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.Runtime.InteropServices;

public class ParameterizedPropertySetterCall
{
// C# has no syntax for parameterized property 'P'.
public int get_P(int i)
{
return i;
}

public void set_P([Optional][DefaultParameterValue(0)] int i, int value)
{
}

public void Use()
{
this.set_P(0, 5);
}
}
Loading
Loading