diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs index 4e54821c74..52078704c8 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs @@ -44,4 +44,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase public string this[int index] { get { return "Test"; } } } + + public enum MyEnum : short + { + First, + Second, + Flag1 = 0x10, + Flag2 = 0x20, + CombinedFlags = Flag1 | Flag2 + } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index 5764434bfe..758af7e85e 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -181,5 +181,15 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.IsFalse(p.CanSet); Assert.AreEqual(Accessibility.None, p.SetterAccessibility); } + + [Test] + public void EnumTest() + { + var e = testCasePC.GetClass(typeof(MyEnum)); + Assert.AreEqual(ClassType.Enum, e.ClassType); + Assert.AreEqual(false, e.IsReferenceType); + Assert.AreEqual("System.Int16", e.BaseTypes[0].Resolve(ctx).DotNetName); + Assert.AreEqual(new[] { "System.Enum" }, e.GetBaseTypes(ctx).Select(t => t.DotNetName).ToArray()); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs index 54e1ce763e..98a228d963 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs @@ -378,7 +378,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver else return new ErrorResolveResult(targetType); } else if (targetType.IsEnum()) { - throw new NotImplementedException(); + code = ReflectionHelper.GetTypeCode(targetType.GetEnumUnderlyingType(context)); + if (code >= TypeCode.SByte && code <= TypeCode.UInt64) { + try { + return new ConstantResolveResult(targetType, Convert.ChangeType(expression.ConstantValue, code, CultureInfo.InvariantCulture)); + } catch (InvalidCastException) { + return new ErrorResolveResult(targetType); + } + } } } return new ResolveResult(targetType); diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index f4abb6c8ee..780c3f0b80 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -456,12 +456,21 @@ namespace ICSharpCode.NRefactory.TypeSystem } // set base classes - if (typeDefinition.BaseType != null) { - BaseTypes.Add(loader.ReadTypeReference(typeDefinition.BaseType, entity: this)); - } - if (typeDefinition.HasInterfaces) { - foreach (TypeReference iface in typeDefinition.Interfaces) { - BaseTypes.Add(loader.ReadTypeReference(iface, entity: this)); + if (typeDefinition.IsEnum) { + foreach (FieldDefinition enumField in typeDefinition.Fields) { + if (!enumField.IsStatic) { + BaseTypes.Add(loader.ReadTypeReference(enumField.FieldType, entity: this)); + break; + } + } + } else { + if (typeDefinition.BaseType != null) { + BaseTypes.Add(loader.ReadTypeReference(typeDefinition.BaseType, entity: this)); + } + if (typeDefinition.HasInterfaces) { + foreach (TypeReference iface in typeDefinition.Interfaces) { + BaseTypes.Add(loader.ReadTypeReference(iface, entity: this)); + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs index 3d65b15a19..a55a760f3e 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs @@ -88,7 +88,9 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new ArgumentNullException("type"); return type is ITypeDefinition && type.TypeParameterCount > 0; } + #endregion + #region IsEnum / GetEnumUnderlyingType /// /// Gets whether the type is an enumeration type. /// @@ -99,6 +101,26 @@ namespace ICSharpCode.NRefactory.TypeSystem ITypeDefinition def = type.GetDefinition(); return def != null && def.ClassType == ClassType.Enum; } + + /// + /// Gets the underlying type for this enum type. + /// + public static IType GetEnumUnderlyingType(this IType enumType, ITypeResolveContext context) + { + if (enumType == null) + throw new ArgumentNullException("enumType"); + if (context == null) + throw new ArgumentNullException("context"); + ITypeDefinition def = enumType.GetDefinition(); + if (def != null && def.ClassType == ClassType.Enum) { + if (def.BaseTypes.Count == 1) + return def.BaseTypes[0].Resolve(context); + else + return context.GetClass(typeof(int)) ?? SharedTypes.UnknownType; + } else { + throw new ArgumentException("enumType must be an enum"); + } + } #endregion } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs index 0456d008fa..dbacbdd78c 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs @@ -319,7 +319,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public IEnumerable GetBaseTypes(ITypeResolveContext context) { bool hasNonInterface = false; - if (baseTypes != null) { + if (baseTypes != null && this.ClassType != ClassType.Enum) { foreach (ITypeReference baseTypeRef in baseTypes) { IType baseType = baseTypeRef.Resolve(context); ITypeDefinition baseTypeDef = baseType.GetDefinition();