Browse Source

Fix #1111: Only hide "enum value initializers" when all of them can be hidden or only the first needs to be specified.

pull/1213/head
Siegfried Pammer 7 years ago
parent
commit
5856df001a
  1. 6
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs
  2. 70
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

6
ICSharpCode.Decompiler.Tests/TestCases/Pretty/CompoundAssignmentTest.cs

@ -34,9 +34,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -34,9 +34,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
public enum ShortEnum : short
{
None,
One,
Two,
None = 0,
One = 1,
Two = 2,
Four = 4
}

70
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1031,9 +1031,56 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1031,9 +1031,56 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
}
if (typeDecl.ClassType == ClassType.Enum) {
switch (DetectBestEnumValueDisplayMode(typeDef)) {
case EnumValueDisplayMode.FirstOnly:
foreach (var enumMember in typeDecl.Members.OfType<EnumMemberDeclaration>().Skip(1)) {
enumMember.Initializer = null;
}
break;
case EnumValueDisplayMode.None:
foreach (var enumMember in typeDecl.Members.OfType<EnumMemberDeclaration>()) {
enumMember.Initializer = null;
}
break;
case EnumValueDisplayMode.All:
// nothing needs to be changed.
break;
default:
throw new ArgumentOutOfRangeException();
}
}
return typeDecl;
}
enum EnumValueDisplayMode
{
None,
All,
FirstOnly
}
EnumValueDisplayMode DetectBestEnumValueDisplayMode(ITypeDefinition typeDef)
{
if (typeDef.GetAttribute(new TopLevelTypeName("System", "FlagsAttribute")) != null)
return EnumValueDisplayMode.All;
bool first = true;
long firstValue = 0, previousValue = 0;
foreach (var field in typeDef.Fields) {
var fieldDef = typeSystem.GetCecil(field) as FieldDefinition;
if (!(fieldDef != null && !MemberIsHidden(fieldDef, settings))) continue;
long currentValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false);
if (first) {
firstValue = currentValue;
first = false;
} else if (previousValue + 1 != currentValue) {
return EnumValueDisplayMode.All;
}
previousValue = currentValue;
}
return firstValue == 0 ? EnumValueDisplayMode.None : EnumValueDisplayMode.FirstOnly;
}
static readonly Syntax.Attribute obsoleteAttributePattern = new Syntax.Attribute() {
Type = new TypePattern(typeof(ObsoleteAttribute)),
Arguments = {
@ -1217,26 +1264,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1217,26 +1264,17 @@ namespace ICSharpCode.Decompiler.CSharp
Debug.Assert(decompilationContext.CurrentMember == field);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
if (decompilationContext.CurrentTypeDefinition.Kind == TypeKind.Enum && field.ConstantValue != null) {
var index = decompilationContext.CurrentTypeDefinition.Members.IndexOf(field);
long previousValue = -1;
if (index > 0) {
var previousMember = (IField)decompilationContext.CurrentTypeDefinition.Members[index - 1];
previousValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, previousMember.ConstantValue, false);
}
var enumDec = new EnumMemberDeclaration { Name = field.Name };
long initValue = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, field.ConstantValue, false);
if (decompilationContext.CurrentTypeDefinition.Attributes.Any(a => a.AttributeType.FullName == "System.FlagsAttribute")) {
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue);
if (enumDec.Initializer is PrimitiveExpression primitive)
primitive.SetValue(initValue, $"0x{initValue:X}");
} else if (previousValue + 1 != initValue) {
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue);
if (enumDec.Initializer is PrimitiveExpression primitive && initValue > 9 && ((initValue & (initValue - 1)) == 0 || (initValue & (initValue + 1)) == 0)) {
primitive.SetValue(initValue, $"0x{initValue:X}");
}
enumDec.Initializer = typeSystemAstBuilder.ConvertConstantValue(decompilationContext.CurrentTypeDefinition.EnumUnderlyingType, field.ConstantValue);
if (enumDec.Initializer is PrimitiveExpression primitive
&& (decompilationContext.CurrentTypeDefinition.Attributes.Any(a => a.AttributeType.FullName == "System.FlagsAttribute")
|| (initValue > 9 && ((initValue & (initValue - 1)) == 0 || (initValue & (initValue + 1)) == 0))))
{
primitive.SetValue(initValue, $"0x{initValue:X}");
}
enumDec.Attributes.AddRange(field.Attributes.Select(a => new AttributeSection(typeSystemAstBuilder.ConvertAttribute(a))));
enumDec.AddAnnotation(new Semantics.MemberResolveResult(null, field));
enumDec.AddAnnotation(new MemberResolveResult(null, field));
return enumDec;
}
typeSystemAstBuilder.UseSpecialConstants = !field.DeclaringType.Equals(field.ReturnType);

Loading…
Cancel
Save