public virtual void PrintEnumValue(ITypeDefinition enumType, object valObj) {
bool flags = (Utils.FindAttribute(enumType.Attributes, SpecialAttribute.Flags) != null);
// Loop through all the enum constants looking for a match
ulong value = UnboxToULong(valObj);
bool success = false;
List<IFieldDefinition> constants = new List<IFieldDefinition>();
foreach (var f in enumType.Fields) {
if (f.IsCompileTimeConstant && TypeHelper.TypesAreEquivalent(f.Type, enumType))
constants.Add(f);
}
// Sort by order in type - hopefully this gives the minimum set of flags
constants.Sort((f1, f2) => {
if (f1 is IMetadataObjectWithToken && f2 is IMetadataObjectWithToken)
return ((IMetadataObjectWithToken)f1).TokenValue.CompareTo(((IMetadataObjectWithToken)f2).TokenValue);
return UnboxToULong(f1.CompileTimeValue.Value).CompareTo(UnboxToULong(f2.CompileTimeValue.Value));
});
// If the value has the high bit set, and no constant does, then it's probably best represented as a negation
bool negate = false;
int nBits = Marshal.SizeOf(valObj)*8;
ulong highBit = 1ul << (nBits - 1);
if (flags && (value & highBit) == highBit && constants.Count > 0 && (UnboxToULong(constants[0].CompileTimeValue.Value) & highBit) == 0) {
value = (~value) & ((1UL << nBits) - 1);
negate = true;
sourceEmitterOutput.Write("~(");
}
ulong valLeft = value;
foreach (var c in constants) {
ulong fv = UnboxToULong(c.CompileTimeValue.Value);
if (valLeft == fv || (flags && (fv != 0) && ((valLeft & fv) == fv))) {
if (valLeft != value)
sourceEmitterOutput.Write(" | ");
TraverseChildren((IFieldReference)c);
valLeft -= fv;
if (valLeft == 0) {
success = true;
break;
}
}
}
// No match, output cast
if (!success) {
if (valLeft != value)
sourceEmitterOutput.Write(" | ");
sourceEmitterOutput.Write("unchecked((");
TraverseChildren((ITypeReference)enumType);
sourceEmitterOutput.Write(")0x" + valLeft.ToString("X") + ")");
}
if (negate)
sourceEmitterOutput.Write(")");
}