Browse Source

Fixed bug with decimal optional parameters not being resolved correctly.

Added option to uglify presentation of decimal constants (show `[DecimalConstant(...)]`).
pull/1236/head
Andrey Shchekin 7 years ago
parent
commit
d15fe0f254
  1. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 7
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs
  3. 32
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.il
  4. 29
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.il
  5. 37
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.roslyn.il
  6. 41
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.roslyn.il
  7. 14
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.Expected.cs
  8. 31
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.cs
  9. 95
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.opt.roslyn.il
  10. 97
      ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.roslyn.il
  11. 19
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs
  12. 1
      ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs
  13. 8
      ICSharpCode.Decompiler.Tests/UglyTestRunner.cs
  14. 2
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  15. 2
      ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs
  16. 15
      ICSharpCode.Decompiler/DecompilerSettings.cs
  17. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  18. 10
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  19. 17
      ICSharpCode.Decompiler/TypeSystem/IParameter.cs
  20. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/AttributeListBuilder.cs
  21. 72
      ICSharpCode.Decompiler/TypeSystem/Implementation/DecimalConstantHelper.cs
  22. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultParameter.cs
  23. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/KnownAttributes.cs
  24. 57
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataField.cs
  25. 39
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataParameter.cs
  26. 1
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs

2
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -71,6 +71,8 @@ @@ -71,6 +71,8 @@
<Compile Include="TestCases\Pretty\OptionalArguments.cs" />
<Compile Include="TestCases\Pretty\CustomShortCircuitOperators.cs" />
<Compile Include="TestCases\Pretty\TypeTests.cs" />
<None Include="TestCases\Ugly\NoDecimalConstants.Expected.cs" />
<Compile Include="TestCases\Ugly\NoDecimalConstants.cs" />
<None Include="TestCases\Disassembler\Pretty\SecurityDeclarations.il" />
<Compile Include="TestCases\Pretty\CustomAttributeConflicts.cs" />
<Compile Include="TestCases\Pretty\DynamicTests.cs" />

7
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs

@ -42,6 +42,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -42,6 +42,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Test();
Test(5);
Test(10, "Hello World!");
Decimal();
Decimal(5m);
}
private void Conflicts()
@ -124,6 +127,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -124,6 +127,10 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
}
private void Decimal(decimal d = 10m)
{
}
private void OnlyDifferenceIsLastArgument(int a, int b, string c = null)
{
}

32
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.il

@ -76,8 +76,8 @@ @@ -76,8 +76,8 @@
.method private hidebysig instance void
SimpleTests() cil managed
{
// Code size 43 (0x2b)
.maxstack 8
// Code size 70 (0x46)
.maxstack 3
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.s 10
@ -97,7 +97,17 @@ @@ -97,7 +97,17 @@
IL_0024: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Test(int32,
string)
IL_0029: nop
IL_002a: ret
IL_002a: ldarg.0
IL_002b: ldc.i4.s 10
IL_002d: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0032: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
IL_0037: nop
IL_0038: ldarg.0
IL_0039: ldc.i4.5
IL_003a: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_003f: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
IL_0044: nop
IL_0045: ret
} // end of method OptionalArguments::SimpleTests
.method private hidebysig instance void
@ -400,6 +410,22 @@ @@ -400,6 +410,22 @@
IL_0001: ret
} // end of method OptionalArguments::Test
.method private hidebysig instance void
Decimal([opt] valuetype [mscorlib]System.Decimal d) cil managed
{
.param [1]
.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 0A 00 00 00
00 00 )
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method OptionalArguments::Decimal
.method private hidebysig instance void
OnlyDifferenceIsLastArgument(int32 a,
int32 b,

29
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.il

@ -69,8 +69,8 @@ @@ -69,8 +69,8 @@
.method private hidebysig instance void
SimpleTests() cil managed
{
// Code size 39 (0x27)
.maxstack 8
// Code size 64 (0x40)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.s 10
IL_0003: ldstr "Test"
@ -86,7 +86,15 @@ @@ -86,7 +86,15 @@
IL_001c: ldstr "Hello World!"
IL_0021: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Test(int32,
string)
IL_0026: ret
IL_0026: ldarg.0
IL_0027: ldc.i4.s 10
IL_0029: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_002e: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
IL_0033: ldarg.0
IL_0034: ldc.i4.5
IL_0035: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_003a: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
IL_003f: ret
} // end of method OptionalArguments::SimpleTests
.method private hidebysig instance void
@ -358,6 +366,21 @@ @@ -358,6 +366,21 @@
IL_0000: ret
} // end of method OptionalArguments::Test
.method private hidebysig instance void
Decimal([opt] valuetype [mscorlib]System.Decimal d) cil managed
{
.param [1]
.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 0A 00 00 00
00 00 )
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method OptionalArguments::Decimal
.method private hidebysig instance void
OnlyDifferenceIsLastArgument(int32 a,
int32 b,

37
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.opt.roslyn.il

@ -73,8 +73,8 @@ @@ -73,8 +73,8 @@
.method private hidebysig instance void
SimpleTests() cil managed
{
// Code size 39 (0x27)
.maxstack 8
// Code size 64 (0x40)
.maxstack 3
IL_0000: ldarg.0
IL_0001: ldc.i4.s 10
IL_0003: ldstr "Test"
@ -90,7 +90,15 @@ @@ -90,7 +90,15 @@
IL_001c: ldstr "Hello World!"
IL_0021: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Test(int32,
string)
IL_0026: ret
IL_0026: ldarg.0
IL_0027: ldc.i4.s 10
IL_0029: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_002e: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
IL_0033: ldarg.0
IL_0034: ldc.i4.5
IL_0035: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_003a: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
IL_003f: ret
} // end of method OptionalArguments::SimpleTests
.method private hidebysig instance void
@ -334,6 +342,21 @@ @@ -334,6 +342,21 @@
IL_0000: ret
} // end of method OptionalArguments::Test
.method private hidebysig instance void
Decimal([opt] valuetype [mscorlib]System.Decimal d) cil managed
{
.param [1]
.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 0A 00 00 00
00 00 )
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method OptionalArguments::Decimal
.method private hidebysig instance void
OnlyDifferenceIsLastArgument(int32 a,
int32 b,
@ -400,15 +423,15 @@ @@ -400,15 +423,15 @@
.size 12
} // end of class '__StaticArrayInitTypeSize=12'
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '0F3DD643C5167ACFC541F72809FFF828A6E41494' at I_00002D2C
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_00002D3C
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '0F3DD643C5167ACFC541F72809FFF828A6E41494' at I_00002DC4
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_00002DD4
} // end of class '<PrivateImplementationDetails>'
// =============================================================
.data cil I_00002D2C = bytearray (
.data cil I_00002DC4 = bytearray (
0A 00 00 00 09 00 00 00 08 00 00 00)
.data cil I_00002D3C = bytearray (
.data cil I_00002DD4 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00)
// *********** DISASSEMBLY COMPLETE ***********************

41
ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.roslyn.il

@ -78,8 +78,8 @@ @@ -78,8 +78,8 @@
.method private hidebysig instance void
SimpleTests() cil managed
{
// Code size 43 (0x2b)
.maxstack 8
// Code size 70 (0x46)
.maxstack 3
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.s 10
@ -99,7 +99,17 @@ @@ -99,7 +99,17 @@
IL_0024: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Test(int32,
string)
IL_0029: nop
IL_002a: ret
IL_002a: ldarg.0
IL_002b: ldc.i4.s 10
IL_002d: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_0032: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
IL_0037: nop
IL_0038: ldarg.0
IL_0039: ldc.i4.5
IL_003a: newobj instance void [mscorlib]System.Decimal::.ctor(int32)
IL_003f: call instance void ICSharpCode.Decompiler.Tests.TestCases.Pretty.OptionalArguments::Decimal(valuetype [mscorlib]System.Decimal)
IL_0044: nop
IL_0045: ret
} // end of method OptionalArguments::SimpleTests
.method private hidebysig instance void
@ -375,6 +385,22 @@ @@ -375,6 +385,22 @@
IL_0001: ret
} // end of method OptionalArguments::Test
.method private hidebysig instance void
Decimal([opt] valuetype [mscorlib]System.Decimal d) cil managed
{
.param [1]
.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 0A 00 00 00
00 00 )
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method OptionalArguments::Decimal
.method private hidebysig instance void
OnlyDifferenceIsLastArgument(int32 a,
int32 b,
@ -446,16 +472,15 @@ @@ -446,16 +472,15 @@
.size 12
} // end of class '__StaticArrayInitTypeSize=12'
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '0F3DD643C5167ACFC541F72809FFF828A6E41494' at I_00002D58
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_00002D68
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' '0F3DD643C5167ACFC541F72809FFF828A6E41494' at I_00002DF4
.field static assembly initonly valuetype '<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=12' E429CCA3F703A39CC5954A6572FEC9086135B34E at I_00002E04
} // end of class '<PrivateImplementationDetails>'
// =============================================================
.data cil I_00002D58 = bytearray (
.data cil I_00002DF4 = bytearray (
0A 00 00 00 09 00 00 00 08 00 00 00)
.data cil I_00002D64 = int8[4]
.data cil I_00002D68 = bytearray (
.data cil I_00002E04 = bytearray (
01 00 00 00 02 00 00 00 03 00 00 00)
// *********** DISASSEMBLY COMPLETE ***********************

14
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.Expected.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly
{
public class NoDecimalConstants
{
[DecimalConstant(1, 0, 0u, 0u, 10u)]
private static readonly decimal constant = 1.0m;
private void MethodWithOptionalParameter([Optional] [DecimalConstant(1, 0, 0u, 0u, 10u)] decimal parameter)
{
}
}
}

31
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
// Copyright (c) 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;
namespace ICSharpCode.Decompiler.Tests.TestCases.Ugly
{
public class NoDecimalConstants
{
private const decimal constant = 1.0m;
private void MethodWithOptionalParameter(decimal parameter = 1.0m)
{
}
}
}

95
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.opt.roslyn.il

@ -0,0 +1,95 @@ @@ -0,0 +1,95 @@
// 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 NoDecimalConstants
{
.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 NoDecimalConstants.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 public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants
extends [mscorlib]System.Object
{
.field private static initonly valuetype [mscorlib]System.Decimal constant
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 0A 00 00 00
00 00 )
.method private hidebysig instance void
MethodWithOptionalParameter([opt] valuetype [mscorlib]System.Decimal parameter) cil managed
{
.param [1]
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 0A 00 00 00
00 00 )
// Code size 1 (0x1)
.maxstack 8
IL_0000: ret
} // end of method NoDecimalConstants::MethodWithOptionalParameter
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method NoDecimalConstants::.ctor
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldc.i4.s 10
IL_0002: ldc.i4.0
IL_0003: ldc.i4.0
IL_0004: ldc.i4.0
IL_0005: ldc.i4.1
IL_0006: newobj instance void [mscorlib]System.Decimal::.ctor(int32,
int32,
int32,
bool,
uint8)
IL_000b: stsfld valuetype [mscorlib]System.Decimal ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants::constant
IL_0010: ret
} // end of method NoDecimalConstants::.cctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

97
ICSharpCode.Decompiler.Tests/TestCases/Ugly/NoDecimalConstants.roslyn.il

@ -0,0 +1,97 @@ @@ -0,0 +1,97 @@
// 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 NoDecimalConstants
{
.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 NoDecimalConstants.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 public auto ansi beforefieldinit ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants
extends [mscorlib]System.Object
{
.field private static initonly valuetype [mscorlib]System.Decimal constant
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 0A 00 00 00
00 00 )
.method private hidebysig instance void
MethodWithOptionalParameter([opt] valuetype [mscorlib]System.Decimal parameter) cil managed
{
.param [1]
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(uint8,
uint8,
uint32,
uint32,
uint32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 0A 00 00 00
00 00 )
// Code size 2 (0x2)
.maxstack 8
IL_0000: nop
IL_0001: ret
} // end of method NoDecimalConstants::MethodWithOptionalParameter
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: ret
} // end of method NoDecimalConstants::.ctor
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldc.i4.s 10
IL_0002: ldc.i4.0
IL_0003: ldc.i4.0
IL_0004: ldc.i4.0
IL_0005: ldc.i4.1
IL_0006: newobj instance void [mscorlib]System.Decimal::.ctor(int32,
int32,
int32,
bool,
uint8)
IL_000b: stsfld valuetype [mscorlib]System.Decimal ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants::constant
IL_0010: ret
} // end of method NoDecimalConstants::.cctor
} // end of class ICSharpCode.Decompiler.Tests.TestCases.Ugly.NoDecimalConstants
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************

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

@ -658,6 +658,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -658,6 +658,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count());
Assert.AreEqual(4, p.ConstantValue);
}
@ -670,6 +671,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -670,6 +671,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
Assert.IsFalse(p.HasConstantValueInSignature);
// explicit optional parameter appears in type system if it's read from C#, but not when read from IL
//Assert.AreEqual(1, p.GetAttributes().Count());
}
@ -682,6 +684,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -682,6 +684,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count());
Assert.AreEqual((int)StringComparison.OrdinalIgnoreCase, p.ConstantValue);
}
@ -694,6 +697,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -694,6 +697,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(0, p.GetAttributes().Count());
Assert.IsNull(p.ConstantValue);
}
@ -706,6 +710,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -706,6 +710,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1L, p.ConstantValue);
Assert.AreEqual(typeof(long), p.ConstantValue.GetType());
}
@ -718,10 +723,24 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -718,10 +723,24 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1L, p.ConstantValue);
Assert.AreEqual(typeof(long), p.ConstantValue.GetType());
}
[Test]
public void MethodWithOptionalDecimalParameter()
{
IParameter p = GetTypeDefinition(typeof(ParameterTests)).Methods.Single(m => m.Name == "MethodWithOptionalDecimalParameter").Parameters.Single();
Assert.IsTrue(p.IsOptional);
Assert.IsFalse(p.IsRef);
Assert.IsFalse(p.IsOut);
Assert.IsFalse(p.IsParams);
Assert.IsTrue(p.HasConstantValueInSignature);
Assert.AreEqual(1M, p.ConstantValue);
Assert.AreEqual(typeof(decimal), p.ConstantValue.GetType());
}
[Test]
public void VarArgsMethod()
{

1
ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemTestCase.cs

@ -162,6 +162,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -162,6 +162,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void MethodWithOptionalNullableParameter(int? x = null) { }
public void MethodWithOptionalLongParameter(long x = 1) { }
public void MethodWithOptionalNullableLongParameter(long? x = 1) { }
public void MethodWithOptionalDecimalParameter(decimal x = 1) { }
public void VarArgsMethod(__arglist) { }
}

8
ICSharpCode.Decompiler.Tests/UglyTestRunner.cs

@ -75,6 +75,14 @@ namespace ICSharpCode.Decompiler.Tests @@ -75,6 +75,14 @@ namespace ICSharpCode.Decompiler.Tests
});
}
[Test]
public void NoDecimalConstants([ValueSource("roslynOnlyOptions")] CSharpCompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions, decompilerSettings: new DecompilerSettings {
DecimalConstants = false
});
}
void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CSharpCompilerOptions cscOptions = CSharpCompilerOptions.None, DecompilerSettings decompilerSettings = null)
{
Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CSharpCompilerOptions.Library, decompilerSettings);

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

@ -933,7 +933,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -933,7 +933,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
if (this.ShowParameterNames) {
decl.Name = parameter.Name;
}
if (parameter.IsOptional && this.ShowConstantValues) {
if (parameter.IsOptional && parameter.HasConstantValueInSignature && this.ShowConstantValues) {
decl.DefaultExpression = ConvertConstantValue(parameter.Type, parameter.ConstantValue);
}
return decl;

2
ICSharpCode.Decompiler/CSharp/Transforms/DecimalConstantTransform.cs

@ -50,6 +50,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -50,6 +50,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public void Run(AstNode rootNode, TransformContext context)
{
if (!context.Settings.DecimalConstants)
return;
rootNode.AcceptVisitor(this);
}
}

15
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -221,6 +221,21 @@ namespace ICSharpCode.Decompiler @@ -221,6 +221,21 @@ namespace ICSharpCode.Decompiler
}
}
bool decimalConstants = true;
/// <summary>
/// Decompile [DecimalConstant(...)] as simple literal values.
/// </summary>
public bool DecimalConstants {
get { return decimalConstants; }
set {
if (decimalConstants != value) {
decimalConstants = value;
OnPropertyChanged();
}
}
}
bool fixedBuffers = true;
/// <summary>

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -349,6 +349,7 @@ @@ -349,6 +349,7 @@
<Compile Include="TypeSystem\GenericContext.cs" />
<Compile Include="TypeSystem\Implementation\AttributeListBuilder.cs" />
<Compile Include="TypeSystem\Implementation\CustomAttribute.cs" />
<Compile Include="TypeSystem\Implementation\DecimalConstantHelper.cs" />
<Compile Include="TypeSystem\Implementation\DefaultTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\FakeMember.cs" />
<Compile Include="TypeSystem\Implementation\KnownAttributes.cs" />

10
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -71,11 +71,15 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -71,11 +71,15 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// Also, some code in the decompiler expects to be able to compare type/member definitions by reference equality,
/// and thus will fail with uncached type systems.
/// </summary>
Uncached = 0x10,
Uncached = 16,
/// <summary>
/// If this option is active, [DecimalConstantAttribute] is removed and constant values are transformed into simple decimal literals.
/// </summary>
DecimalConstants = 32,
/// <summary>
/// Default settings: all features enabled.
/// </summary>
Default = Dynamic | Tuple | ExtensionMethods
Default = Dynamic | Tuple | ExtensionMethods | DecimalConstants
}
/// <summary>
@ -95,6 +99,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -95,6 +99,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
typeSystemOptions |= TypeSystemOptions.Tuple;
if (settings.ExtensionMethods)
typeSystemOptions |= TypeSystemOptions.ExtensionMethods;
if (settings.DecimalConstants)
typeSystemOptions |= TypeSystemOptions.DecimalConstants;
return typeSystemOptions;
}

17
ICSharpCode.Decompiler/TypeSystem/IParameter.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Runtime.CompilerServices;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.TypeSystem
@ -48,6 +49,22 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -48,6 +49,22 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
bool IsOptional { get; }
/// <summary>
/// Gets whether this parameter has a constant value when presented in method signature.
/// </summary>
/// <remarks>
/// This can only be <c>true</c> if the parameter is optional, and it's true for most
/// optional parameters. However it is possible to compile a parameter without a default value,
/// and some parameters handle their default values in an special way.
///
/// For example, <see cref="DecimalConstantAttribute"/> does not use normal constants,
/// so when <see cref="DecompilerSettings.DecimalConstants" /> is <c>false</c>
/// we expose <c>DecimalConstantAttribute</c> directly instead of a constant value.
///
/// On the call sites, though, we can still use the value inferred from the attribute.
/// </remarks>
bool HasConstantValueInSignature { get; }
/// <summary>
/// Gets the owner of this parameter.
/// May return null; for example when parameters belong to lambdas or anonymous methods.

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

@ -199,7 +199,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -199,7 +199,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
case "ExtensionAttribute":
return (options & TypeSystemOptions.ExtensionMethods) != 0;
case "DecimalConstantAttribute":
return true;
return (options & TypeSystemOptions.DecimalConstants) != 0;
default:
return false;
}

72
ICSharpCode.Decompiler/TypeSystem/Implementation/DecimalConstantHelper.cs

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
// 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.Reflection.Metadata;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
static class DecimalConstantHelper
{
public static bool AllowsDecimalConstants(MetadataModule module)
{
return ((module.TypeSystemOptions & TypeSystemOptions.DecimalConstants) == TypeSystemOptions.DecimalConstants);
}
public static bool IsDecimalConstant(MetadataModule module, CustomAttributeHandleCollection attributeHandles)
{
return attributeHandles.HasKnownAttribute(module.metadata, KnownAttribute.DecimalConstant);
}
public static object GetDecimalConstantValue(MetadataModule module, CustomAttributeHandleCollection attributeHandles)
{
var metadata = module.metadata;
foreach (var attributeHandle in attributeHandles) {
var attribute = metadata.GetCustomAttribute(attributeHandle);
if (attribute.IsKnownAttribute(metadata, KnownAttribute.DecimalConstant))
return TryDecodeDecimalConstantAttribute(module, attribute);
}
return null;
}
static decimal? TryDecodeDecimalConstantAttribute(MetadataModule module, System.Reflection.Metadata.CustomAttribute attribute)
{
var attrValue = attribute.DecodeValue(module.TypeProvider);
if (attrValue.FixedArguments.Length != 5)
return null;
// DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low)
// Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required.
if (!(attrValue.FixedArguments[0].Value is byte scale && attrValue.FixedArguments[1].Value is byte sign))
return null;
unchecked {
if (attrValue.FixedArguments[2].Value is uint hi
&& attrValue.FixedArguments[3].Value is uint mid
&& attrValue.FixedArguments[4].Value is uint lo) {
return new decimal((int)lo, (int)mid, (int)hi, sign != 0, scale);
}
}
{
if (attrValue.FixedArguments[2].Value is int hi
&& attrValue.FixedArguments[3].Value is int mid
&& attrValue.FixedArguments[4].Value is int lo) {
return new decimal(lo, mid, hi, sign != 0, scale);
}
}
return null;
}
}
}

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

@ -102,6 +102,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -102,6 +102,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return false; }
}
public bool HasConstantValueInSignature {
get { return IsOptional; }
}
public object ConstantValue {
get { return defaultValue; }
}
@ -123,7 +127,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -123,7 +127,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
b.Append(parameter.Name);
b.Append(':');
b.Append(parameter.Type.ReflectionName);
if (parameter.IsOptional) {
if (parameter.IsOptional && parameter.HasConstantValueInSignature) {
b.Append(" = ");
if (parameter.ConstantValue != null)
b.Append(parameter.ConstantValue.ToString());

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

@ -78,6 +78,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -78,6 +78,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
ParamArray,
In,
Out,
Optional,
CallerMemberName,
CallerFilePath,
CallerLineNumber,
@ -133,6 +134,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -133,6 +134,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
new TopLevelTypeName("System", nameof(ParamArrayAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(InAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(OutAttribute)),
new TopLevelTypeName("System.Runtime.InteropServices", nameof(OptionalAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CallerMemberNameAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CallerFilePathAttribute)),
new TopLevelTypeName("System.Runtime.CompilerServices", nameof(CallerLineNumberAttribute)),

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

@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
object constantValue;
IType type;
bool isVolatile; // initialized together with this.type
byte decimalConstant; // 0=no, 1=yes, 2=unknown
bool? isDecimalConstant;
internal MetadataField(MetadataModule module, FieldDefinitionHandle handle)
{
@ -52,8 +52,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -52,8 +52,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.handle = handle;
var def = module.metadata.GetFieldDefinition(handle);
this.attributes = def.Attributes;
if ((attributes & (FieldAttributes.Static | FieldAttributes.InitOnly)) == (FieldAttributes.Static | FieldAttributes.InitOnly)) {
decimalConstant = 2; // may be decimal constant
if ((attributes & (FieldAttributes.Static | FieldAttributes.InitOnly)) != (FieldAttributes.Static | FieldAttributes.InitOnly)) {
isDecimalConstant = false;
}
}
@ -187,19 +188,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -187,19 +188,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return LazyInit.GetOrSet(ref this.type, ty);
}
public bool IsConst => (attributes & FieldAttributes.Literal) != 0 || IsDecimalConstant;
public bool IsConst => (attributes & FieldAttributes.Literal) != 0
|| (IsDecimalConstant && DecimalConstantHelper.AllowsDecimalConstants(module));
bool IsDecimalConstant {
get {
if (decimalConstant == 2) {
var metadata = module.metadata;
var fieldDef = metadata.GetFieldDefinition(handle);
if (fieldDef.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.DecimalConstant))
decimalConstant = 1;
else
decimalConstant = 0;
if (isDecimalConstant == null) {
var fieldDef = module.metadata.GetFieldDefinition(handle);
isDecimalConstant = DecimalConstantHelper.IsDecimalConstant(module, fieldDef.GetCustomAttributes());
}
return decimalConstant == 1;
return (bool)isDecimalConstant;
}
}
@ -210,13 +208,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -210,13 +208,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return val;
var metadata = module.metadata;
var fieldDef = metadata.GetFieldDefinition(handle);
if (IsDecimalConstant) {
foreach (var attrHandle in fieldDef.GetCustomAttributes()) {
var attribute = metadata.GetCustomAttribute(attrHandle);
if (attribute.IsKnownAttribute(metadata, KnownAttribute.DecimalConstant)) {
val = TryDecodeDecimalConstantAttribute(attribute);
}
}
if (IsDecimalConstant && DecimalConstantHelper.AllowsDecimalConstants(module)) {
val = DecimalConstantHelper.GetDecimalConstantValue(module, fieldDef.GetCustomAttributes());
} else {
var constantHandle = fieldDef.GetDefaultValue();
if (constantHandle.IsNil)
@ -229,32 +222,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -229,32 +222,6 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
decimal? TryDecodeDecimalConstantAttribute(System.Reflection.Metadata.CustomAttribute attribute)
{
var attrValue = attribute.DecodeValue(module.TypeProvider);
if (attrValue.FixedArguments.Length != 5)
return null;
// DecimalConstantAttribute has the arguments (byte scale, byte sign, uint hi, uint mid, uint low) or (byte scale, byte sign, int hi, int mid, int low)
// Both of these invoke the Decimal constructor (int lo, int mid, int hi, bool isNegative, byte scale) with explicit argument conversions if required.
if (!(attrValue.FixedArguments[0].Value is byte scale && attrValue.FixedArguments[1].Value is byte sign))
return null;
unchecked {
if (attrValue.FixedArguments[2].Value is uint hi
&& attrValue.FixedArguments[3].Value is uint mid
&& attrValue.FixedArguments[4].Value is uint lo) {
return new decimal((int)lo, (int)mid, (int)hi, sign != 0, scale);
}
}
{
if (attrValue.FixedArguments[2].Value is int hi
&& attrValue.FixedArguments[3].Value is int mid
&& attrValue.FixedArguments[4].Value is int lo) {
return new decimal(lo, mid, hi, sign != 0, scale);
}
}
return null;
}
public override bool Equals(object obj)
{
if (obj is MetadataField f) {

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

@ -37,6 +37,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -37,6 +37,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
// lazy-loaded:
string name;
bool? hasConstantValueInSignature;
bool? isDecimalConstant;
internal MetadataParameter(MetadataModule module, IParameterizedMember owner, IType type, ParameterHandle handle)
{
@ -47,6 +49,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -47,6 +49,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var param = module.metadata.GetParameter(handle);
this.attributes = param.Attributes;
if (!IsOptional)
isDecimalConstant = false; // only optional parameters can be constants
}
public EntityHandle MetadataToken => handle;
@ -58,6 +62,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -58,6 +62,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var metadata = module.metadata;
var parameter = metadata.GetParameter(handle);
if (IsOptional && !HasConstantValueInSignature)
b.Add(KnownAttribute.Optional);
if (!IsOut) {
if ((attributes & ParameterAttributes.In) == ParameterAttributes.In)
b.Add(KnownAttribute.In);
@ -102,16 +109,44 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -102,16 +109,44 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public object ConstantValue {
get {
var metadata = module.metadata;
var propertyDef = metadata.GetParameter(handle);
var constantHandle = propertyDef.GetDefaultValue();
var parameterDef = metadata.GetParameter(handle);
if (IsDecimalConstant)
return DecimalConstantHelper.GetDecimalConstantValue(module, parameterDef.GetCustomAttributes());
var constantHandle = parameterDef.GetDefaultValue();
if (constantHandle.IsNil)
return null;
var constant = metadata.GetConstant(constantHandle);
var blobReader = metadata.GetBlobReader(constant.Value);
return blobReader.ReadConstant(constant.TypeCode);
}
}
public bool HasConstantValueInSignature {
get {
if (hasConstantValueInSignature == null) {
if (IsDecimalConstant) {
hasConstantValueInSignature = DecimalConstantHelper.AllowsDecimalConstants(module);
}
else {
hasConstantValueInSignature = !module.metadata.GetParameter(handle).GetDefaultValue().IsNil;
}
}
return (bool)hasConstantValueInSignature;
}
}
bool IsDecimalConstant {
get {
if (isDecimalConstant == null) {
var parameterDef = module.metadata.GetParameter(handle);
isDecimalConstant = DecimalConstantHelper.IsDecimalConstant(module, parameterDef.GetCustomAttributes());
}
return (bool)isDecimalConstant;
}
}
SymbolKind ISymbol.SymbolKind => SymbolKind.Parameter;
public override string ToString()

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

@ -40,6 +40,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -40,6 +40,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool IParameter.IsOut => baseParameter.IsOut;
bool IParameter.IsParams => baseParameter.IsParams;
bool IParameter.IsOptional => baseParameter.IsOptional;
bool IParameter.HasConstantValueInSignature => baseParameter.HasConstantValueInSignature;
IParameterizedMember IParameter.Owner => newOwner;
string IVariable.Name => baseParameter.Name;
string ISymbol.Name => baseParameter.Name;

Loading…
Cancel
Save