Browse Source

Enum members are implicitly cast to the underlying type when used in an enum member initializer.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
f410a2b5d5
  1. 2
      ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs
  2. 6
      ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs
  3. 13
      ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs
  4. 26
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  5. 29
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs
  6. 9
      ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs

2
ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs

@ -625,7 +625,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -625,7 +625,7 @@ namespace ICSharpCode.NRefactory.CSharp
newField.AddChild (new CSharpTokenNode (Convert (em.Initializer.Location), 1), EnumMemberDeclaration.Roles.Assign);
newField.AddChild ((Expression)em.Initializer.Accept (this), EnumMemberDeclaration.InitializerRole);
}
Console.WriteLine (newField.StartLocation +"-" + newField.EndLocation);
//Console.WriteLine (newField.StartLocation +"-" + newField.EndLocation);
typeStack.Peek ().AddChild (newField, TypeDeclaration.MemberRole);
}

6
ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs

@ -1255,6 +1255,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1255,6 +1255,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolveResult LookInCurrentType(string identifier, IList<IType> typeArguments, SimpleNameLookupMode lookupMode, bool parameterizeResultType)
{
int k = typeArguments.Count;
MemberLookup lookup = CreateMemberLookup();
// look in current type definitions
for (ITypeDefinition t = this.CurrentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) {
if (k == 0) {
@ -1272,7 +1273,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1272,7 +1273,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
continue;
}
MemberLookup lookup = new MemberLookup(t, t.ParentAssembly);
ResolveResult r;
if (lookupMode == SimpleNameLookupMode.Expression || lookupMode == SimpleNameLookupMode.InvocationTarget) {
r = lookup.Lookup(new TypeResolveResult(t), identifier, typeArguments, lookupMode == SimpleNameLookupMode.InvocationTarget);
@ -1451,7 +1451,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1451,7 +1451,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
public MemberLookup CreateMemberLookup()
{
return new MemberLookup(this.CurrentTypeDefinition, this.Compilation.MainAssembly);
bool isInEnumMemberInitializer = this.CurrentMember != null && this.CurrentMember.EntityType == EntityType.Field
&& this.CurrentTypeDefinition != null && this.CurrentTypeDefinition.Kind == TypeKind.Enum;
return new MemberLookup(this.CurrentTypeDefinition, this.Compilation.MainAssembly, isInEnumMemberInitializer);
}
#endregion

13
ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs

@ -50,11 +50,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -50,11 +50,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ITypeDefinition currentTypeDefinition;
IAssembly currentAssembly;
bool isInEnumMemberInitializer;
public MemberLookup(ITypeDefinition currentTypeDefinition, IAssembly currentAssembly)
public MemberLookup(ITypeDefinition currentTypeDefinition, IAssembly currentAssembly, bool isInEnumMemberInitializer = false)
{
this.currentTypeDefinition = currentTypeDefinition;
this.currentAssembly = currentAssembly;
this.isInEnumMemberInitializer = isInEnumMemberInitializer;
}
#region IsAccessible
@ -566,6 +568,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -566,6 +568,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (lookupGroups.Count > 1) {
return new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod);
} else {
if (isInEnumMemberInitializer) {
IField field = resultGroup.NonMethod as IField;
if (field != null && field.DeclaringTypeDefinition != null && field.DeclaringTypeDefinition.Kind == TypeKind.Enum) {
return new MemberResolveResult(
targetResolveResult, field,
field.DeclaringTypeDefinition.EnumUnderlyingType,
field.IsConst, field.ConstantValue);
}
}
return new MemberResolveResult(targetResolveResult, resultGroup.NonMethod);
}
}

26
ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

@ -273,6 +273,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -273,6 +273,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
void ProcessConversion(Expression expr, ResolveResult rr, Conversion conversion, IType targetType)
{
if (expr == null || expr.IsNull)
return;
if (conversion.IsAnonymousFunctionConversion) {
Log.WriteLine("Processing conversion of anonymous function to " + targetType + "...");
AnonymousFunctionConversionData data = conversion.data as AnonymousFunctionConversionData;
@ -287,7 +289,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -287,7 +289,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Log.WriteLine(" Data not found.");
}
}
if (expr != null && !expr.IsNull && conversion != Conversion.IdentityConversion)
if (conversion != Conversion.IdentityConversion)
navigator.ProcessConversion(expr, rr, conversion, targetType);
}
@ -296,6 +298,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -296,6 +298,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
/// </summary>
void ProcessConversion(Expression expr, ResolveResult rr, IType targetType)
{
if (expr == null || expr.IsNull)
return;
ProcessConversion(expr, rr, resolver.conversions.ImplicitConversion(rr, targetType), targetType);
}
@ -791,14 +795,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -791,14 +795,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ResolveResult IAstVisitor<object, ResolveResult>.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data)
{
try {
resolver.CurrentMember = GetMemberFromLocation(enumMemberDeclaration.StartLocation);
// Scan enum member attributes before setting resolver.CurrentMember, so that
// enum values used as attribute arguments have the correct type.
// (which an enum member, all other enum members are treated as having their underlying type)
foreach (var attributeSection in enumMemberDeclaration.Attributes)
Scan(attributeSection);
ScanChildren(enumMemberDeclaration);
resolver.CurrentMember = GetMemberFromLocation(enumMemberDeclaration.StartLocation);
if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(null, resolver.CurrentMember);
else
if (resolverEnabled && resolver.CurrentTypeDefinition != null) {
ResolveAndProcessConversion(enumMemberDeclaration.Initializer, resolver.CurrentTypeDefinition.EnumUnderlyingType);
if (resolverEnabled && resolver.CurrentMember != null)
return new MemberResolveResult(null, resolver.CurrentMember);
else
return errorResult;
} else {
Scan(enumMemberDeclaration.Initializer);
return errorResult;
}
} finally {
resolver.CurrentMember = null;
}

29
ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs

@ -899,5 +899,34 @@ class B @@ -899,5 +899,34 @@ class B
var result = Resolve<TypeResolveResult>(program);
Assert.AreEqual("Test.Base", result.Type.FullName);
}
[Test]
public void EnumMembersHaveUnderlyingTypeWithinInitializers_MemberFromSameEnum()
{
string program = @"enum E { A = 0, B = $A$ + 1 }";
var result = Resolve<MemberResolveResult>(program);
Assert.AreEqual("E.A", result.Member.FullName);
Assert.AreEqual("System.Int32", result.Type.ReflectionName);
Assert.AreEqual("E", result.Member.ReturnType.ReflectionName);
}
[Test]
public void EnumMembersHaveUnderlyingTypeWithinInitializers_MemberFromOtherEnum()
{
string program = @"enum A : ushort { X = 1 } enum B { Y = $A.X$ }";
var result = Resolve<MemberResolveResult>(program);
Assert.AreEqual("A.X", result.Member.FullName);
Assert.AreEqual("System.UInt16", result.Type.ReflectionName);
Assert.AreEqual("A", result.Member.ReturnType.ReflectionName);
}
[Test]
public void EnumMembersHaveUnderlyingTypeWithinInitializers_RuleDoesNotApplyToAttributes()
{
string program = @"enum A { X = 1, [SomeAttribute($X$)] Y }";
var result = Resolve<MemberResolveResult>(program);
Assert.AreEqual("A.X", result.Member.FullName);
Assert.AreEqual("A", result.Type.ReflectionName);
}
}
}

9
ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs

@ -46,6 +46,15 @@ namespace ICSharpCode.NRefactory.Semantics @@ -46,6 +46,15 @@ namespace ICSharpCode.NRefactory.Semantics
}
}
public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, bool isConstant, object constantValue)
: base(returnType)
{
this.targetResult = targetResult;
this.member = member;
this.isConstant = isConstant;
this.constantValue = constantValue;
}
public ResolveResult TargetResult {
get { return targetResult; }
}

Loading…
Cancel
Save