Browse Source

Fix #2124: Unwrap nullables when printing constant values.

pull/2126/head
Siegfried Pammer 5 years ago
parent
commit
3bac7e1d4e
  1. 2
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  2. 58
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/OptionalArguments.cs
  3. 19
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

2
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -425,7 +425,7 @@ namespace ICSharpCode.Decompiler.Tests
[Test] [Test]
public void OptionalArguments([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions) public void OptionalArguments([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
} }
[Test] [Test]

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

@ -23,6 +23,12 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
internal class OptionalArguments : List<int> internal class OptionalArguments : List<int>
{ {
public enum MyEnum
{
A,
B
}
public OptionalArguments(string name, int a = 5) public OptionalArguments(string name, int a = 5)
{ {
@ -170,5 +176,57 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
throw null; throw null;
} }
public static void Definition_Enum(MyEnum p = MyEnum.A)
{
}
public static void Definition_Enum_OutOfRangeDefault(MyEnum p = (MyEnum)(-1))
{
}
public static void Definition_NullableEnum(MyEnum? p = MyEnum.A)
{
}
public static void Definition_NullableEnum_OutOfRangeDefault(MyEnum? p = (MyEnum)(-1))
{
}
public static void Definition_Int(int p = 0)
{
}
public static void Definition_NullableInt(int? p = 0)
{
}
public static void Definition_Int100(int p = 100)
{
}
public static void Definition_NullableInt100(int? p = 100)
{
}
#if CS90
public static void Definition_NInt(nint p = 100)
{
}
public static void Definition_NullableNInt(nint? p = 100)
{
}
#endif
} }
} }

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

@ -792,20 +792,22 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
} }
expr.Initializer = new ArrayInitializerExpression(arr.Select(e => ConvertConstantValue(elementType, e.Type, e.Value))); expr.Initializer = new ArrayInitializerExpression(arr.Select(e => ConvertConstantValue(elementType, e.Type, e.Value)));
return expr; return expr;
} else if (type.Kind == TypeKind.Enum) {
return ConvertEnumValue(type, (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false));
} else { } else {
if (IsSpecialConstant(type, constantValue, out var expr)) IType underlyingType = NullableType.GetUnderlyingType(type);
if (underlyingType.Kind == TypeKind.Enum) {
return ConvertEnumValue(underlyingType, (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false));
} else {
if (IsSpecialConstant(underlyingType, constantValue, out var expr))
return expr; return expr;
if (type.IsKnownType(KnownTypeCode.Double) || type.IsKnownType(KnownTypeCode.Single)) if (underlyingType.IsKnownType(KnownTypeCode.Double) || underlyingType.IsKnownType(KnownTypeCode.Single))
return ConvertFloatingPointLiteral(type, constantValue); return ConvertFloatingPointLiteral(underlyingType, constantValue);
IType literalType = type; IType literalType = underlyingType;
bool integerTypeMismatch = type.IsCSharpSmallIntegerType() || type.IsCSharpNativeIntegerType(); bool integerTypeMismatch = underlyingType.IsCSharpSmallIntegerType() || underlyingType.IsCSharpNativeIntegerType();
if (integerTypeMismatch) { if (integerTypeMismatch) {
// C# does not have integer literals of small integer types, // C# does not have integer literals of small integer types,
// use `int` literal instead. // use `int` literal instead.
// It also doesn't have native integer literals, those also use `int` (or `uint` for `nuint`). // It also doesn't have native integer literals, those also use `int` (or `uint` for `nuint`).
bool unsigned = type.Kind == TypeKind.NUInt; bool unsigned = underlyingType.Kind == TypeKind.NUInt;
constantValue = CSharpPrimitiveCast.Cast(unsigned ? TypeCode.UInt32 : TypeCode.Int32, constantValue, false); constantValue = CSharpPrimitiveCast.Cast(unsigned ? TypeCode.UInt32 : TypeCode.Int32, constantValue, false);
var compilation = resolver?.Compilation ?? expectedType.GetDefinition()?.Compilation; var compilation = resolver?.Compilation ?? expectedType.GetDefinition()?.Compilation;
literalType = compilation?.FindType(unsigned ? KnownTypeCode.UInt32 : KnownTypeCode.Int32); literalType = compilation?.FindType(unsigned ? KnownTypeCode.UInt32 : KnownTypeCode.Int32);
@ -823,6 +825,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return expr; return expr;
} }
} }
}
bool IsSpecialConstant(IType expectedType, object constant, out Expression expression) bool IsSpecialConstant(IType expectedType, object constant, out Expression expression)
{ {

Loading…
Cancel
Save