Browse Source

Merge pull request #132 from erik-kallen/decimal-constant-bug

Decimal constant bug
newNRvisualizers
Daniel Grunwald 13 years ago
parent
commit
256bcf3440
  1. 16
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  2. 24
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  3. 46
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

16
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs

@ -342,4 +342,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -342,4 +342,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
private void Private() {}
void None() {}
}
public class ConstantFieldTest
{
public const byte Cb = 42;
public const sbyte Csb = 42;
public const char Cc = '\x42';
public const short Cs = 42;
public const ushort Cus = 42;
public const int Ci = 42;
public const uint Cui = 42;
public const long Cl = 42;
public const ulong Cul = 42;
public const double Cd = 42;
public const float Cf = 42;
public const decimal Cm = 42;
}
}

24
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -1228,5 +1228,29 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1228,5 +1228,29 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(Accessibility.Private, type.Methods.Single(m => m.Name == "Private").Accessibility);
Assert.AreEqual(Accessibility.Private, type.Methods.Single(m => m.Name == "None").Accessibility);
}
private void AssertConstantField<T>(ITypeDefinition type, string name, T expected) {
var f = type.GetFields().Single(x => x.Name == name);
Assert.IsTrue(f.IsConst);
Assert.AreEqual(expected, f.ConstantValue);
}
[Test]
public void ConstantFields()
{
ITypeDefinition type = GetTypeDefinition(typeof(ConstantFieldTest));
AssertConstantField<byte>(type, "Cb", 42);
AssertConstantField<sbyte>(type, "Csb", 42);
AssertConstantField<char>(type, "Cc", '\x42');
AssertConstantField<short>(type, "Cs", 42);
AssertConstantField<ushort>(type, "Cus", 42);
AssertConstantField<int>(type, "Ci", 42);
AssertConstantField<uint>(type, "Cui", 42);
AssertConstantField<long>(type, "Cl", 42);
AssertConstantField<ulong>(type, "Cul", 42);
AssertConstantField<double>(type, "Cd", 42);
AssertConstantField<float>(type, "Cf", 42);
AssertConstantField<decimal>(type, "Cm", 42);
}
}
}

46
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -788,7 +788,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -788,7 +788,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
foreach (var cecilAttribute in attributes) {
TypeReference type = cecilAttribute.AttributeType;
if (type.Namespace == "System.Runtime.CompilerServices") {
if (type.Name == "DynamicAttribute" || type.Name == "ExtensionAttribute")
if (type.Name == "DynamicAttribute" || type.Name == "ExtensionAttribute" || type.Name == "DecimalConstantAttribute")
continue;
} else if (type.Name == "ParamArrayAttribute" && type.Namespace == "System") {
continue;
@ -2074,6 +2074,42 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -2074,6 +2074,42 @@ namespace ICSharpCode.NRefactory.TypeSystem
|| att == FieldAttributes.Family
|| att == FieldAttributes.FamORAssem;
}
decimal? TryDecodeDecimalConstantAttribute(CustomAttribute attribute)
{
if (attribute.ConstructorArguments.Count != 5)
return null;
BlobReader reader = new BlobReader(attribute.GetBlob(), null);
if (reader.ReadUInt16() != 0x0001) {
Debug.WriteLine("Unknown blob prolog");
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.
var ctorArgs = new object[attribute.ConstructorArguments.Count];
for (int i = 0; i < ctorArgs.Length; i++) {
switch (attribute.ConstructorArguments[i].Type.FullName) {
case "System.Byte":
ctorArgs[i] = reader.ReadByte();
break;
case "System.Int32":
ctorArgs[i] = reader.ReadInt32();
break;
case "System.UInt32":
ctorArgs[i] = unchecked((int)reader.ReadUInt32());
break;
default:
return null;
}
}
if (!ctorArgs.Select(a => a.GetType()).SequenceEqual(new[] { typeof(byte), typeof(byte), typeof(int), typeof(int), typeof(int) }))
return null;
return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]);
}
[CLSCompliant(false)]
public IUnresolvedField ReadField(FieldDefinition field, IUnresolvedTypeDefinition parentType)
@ -2091,6 +2127,14 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -2091,6 +2127,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
if (field.HasConstant) {
f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, field.Constant);
}
else {
var decConstant = field.CustomAttributes.FirstOrDefault(a => a.AttributeType.FullName == "System.Runtime.CompilerServices.DecimalConstantAttribute");
if (decConstant != null) {
var constValue = TryDecodeDecimalConstantAttribute(decConstant);
if (constValue != null)
f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, constValue);
}
}
AddAttributes(field, f);
RequiredModifierType modreq = field.FieldType as RequiredModifierType;

Loading…
Cancel
Save