Browse Source

Fix several bugs with anonymous types:

- DeclaringType, IsAccessor and AccessorOwner properties of anonymous type accessors (#148)
 - equality comparison of anonymous type accessors
 - roundtrip of anonymous type properties via IMemberReference
 - roundtrip of anonymous type accessors via IMemberReference
pull/32/merge
Daniel Grunwald 13 years ago
parent
commit
3797b12fa7
  1. 17
      ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs
  2. 63
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/AnonymousTypeTests.cs
  3. 39
      ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs
  4. 4
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedEntity.cs
  5. 7
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs
  6. 8
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedMethod.cs

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

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -1161,15 +1161,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1161,15 +1161,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (resolveExpr != null) {
var initRR = Resolve(resolveExpr);
var returnTypeRef = initRR.Type.ToTypeReference();
var property = new DefaultUnresolvedProperty {
Name = name,
var property = new DefaultUnresolvedProperty();
property.Name = name;
property.Accessibility = Accessibility.Public;
property.ReturnType = returnTypeRef;
property.Getter = new DefaultUnresolvedMethod {
Name = "get_" + name,
Accessibility = Accessibility.Public,
ReturnType = returnTypeRef,
Getter = new DefaultUnresolvedMethod {
Name = "get_" + name,
Accessibility = Accessibility.Public,
ReturnType = returnTypeRef
}
EntityType = EntityType.Accessor,
AccessorOwner = property
};
unresolvedProperties.Add(property);
members.Add(new AnonymousTypeMember(expr, initRR));

63
ICSharpCode.NRefactory.Tests/CSharp/Resolver/AnonymousTypeTests.cs

@ -96,5 +96,68 @@ class TestClass { @@ -96,5 +96,68 @@ class TestClass {
Assert.That(result.Type.GetProperties().Select(p => p.Name), Is.EquivalentTo(new[] { "a", "b", "c" }));
Assert.That(result.Type.GetProperties().Single(p => p.Name == "c").ReturnType.GetProperties().Select(p => p.Name), Is.EquivalentTo(new[] { "d", "e", "f" }));
}
[Test]
public void DeclaringTypeIsSetCorrectlyForMembersOfAnonymousType()
{
string program = @"using System;
class TestClass {
void F() {
var o = $new { Prop = 0 }$;
}
}";
var result = Resolve<InvocationResolveResult>(program);
var prop = result.Type.GetProperties().Single();
Assert.That(prop.DeclaringType, Is.EqualTo(result.Type));
Assert.That(prop.Getter.DeclaringType, Is.EqualTo(result.Type));
Assert.That(prop.Getter.IsAccessor, Is.True);
Assert.That(prop.Getter.AccessorOwner, Is.EqualTo(prop));
Assert.That(prop.Setter, Is.Null);
}
[Test]
public void CanRoundtripAnonymousTypeThroughTypeReference()
{
string program = @"using System;
class TestClass {
void F() {
var o = $new { Prop = 0 }$;
}
}";
var result = Resolve<InvocationResolveResult>(program);
Assert.AreEqual(TypeKind.Anonymous, result.Type.Kind);
IType typeAfterRoundtrip = result.Type.ToTypeReference().Resolve(result.Member.Compilation);
Assert.AreEqual(result.Type, typeAfterRoundtrip);
}
[Test]
public void CanRoundtripAnonymousTypePropertyThroughMemberReference()
{
string program = @"using System;
class TestClass {
void F() {
var o = $new { Prop = 0 }$;
}
}";
var result = Resolve<InvocationResolveResult>(program);
IProperty prop = result.Type.GetProperties().Single();
IProperty propAfterRoundtrip = (IProperty)prop.ToMemberReference().Resolve(result.Member.Compilation.TypeResolveContext);
Assert.AreEqual(prop, propAfterRoundtrip);
}
[Test]
public void CanRoundtripAnonymousTypeGetterThroughMemberReference()
{
string program = @"using System;
class TestClass {
void F() {
var o = $new { Prop = 0 }$;
}
}";
var result = Resolve<InvocationResolveResult>(program);
IMethod getter = result.Type.GetProperties().Single().Getter;
IMethod getterAfterRoundtrip = (IMethod)getter.ToMemberReference().Resolve(result.Member.Compilation.TypeResolveContext);
Assert.AreEqual(getter, getterAfterRoundtrip);
}
}
}

39
ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
this.resolvedProperties = new ProjectedList<ITypeResolveContext, IUnresolvedProperty, IProperty>(context, unresolvedProperties, (c, p) => new AnonymousTypeProperty(p, c, this));
}
sealed class AnonymousTypeProperty : DefaultResolvedProperty, IEntity
sealed class AnonymousTypeProperty : DefaultResolvedProperty
{
readonly AnonymousType declaringType;
@ -55,7 +55,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -55,7 +55,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
this.declaringType = declaringType;
}
IType IEntity.DeclaringType {
public override IType DeclaringType {
get { return declaringType; }
}
@ -69,6 +69,41 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -69,6 +69,41 @@ namespace ICSharpCode.NRefactory.TypeSystem
{
return declaringType.GetHashCode() ^ unchecked(27 * this.Name.GetHashCode());
}
protected override IMethod CreateResolvedAccessor(IUnresolvedMethod unresolvedAccessor)
{
return new AnonymousTypeAccessor(unresolvedAccessor, context, this);
}
}
sealed class AnonymousTypeAccessor : DefaultResolvedMethod
{
readonly AnonymousTypeProperty owner;
public AnonymousTypeAccessor(IUnresolvedMethod unresolved, ITypeResolveContext parentContext, AnonymousTypeProperty owner)
: base(unresolved, parentContext, isExtensionMethod: false)
{
this.owner = owner;
}
public override IMember AccessorOwner {
get { return owner; }
}
public override IType DeclaringType {
get { return owner.DeclaringType; }
}
public override bool Equals(object obj)
{
AnonymousTypeAccessor p = obj as AnonymousTypeAccessor;
return p != null && this.Name == p.Name && owner.DeclaringType.Equals(p.owner.DeclaringType);
}
public override int GetHashCode()
{
return owner.DeclaringType.GetHashCode() ^ unchecked(27 * this.Name.GetHashCode());
}
}
public override ITypeReference ToTypeReference()

4
ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedEntity.cs

@ -57,8 +57,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -57,8 +57,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return parentContext.CurrentTypeDefinition; }
}
public IType DeclaringType {
get { return parentContext.CurrentTypeDefinition; }
public virtual IType DeclaringType {
get { return parentContext.CurrentTypeDefinition ?? (IType)SpecialType.UnknownType; }
}
public IAssembly ParentAssembly {

7
ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs

@ -142,8 +142,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -142,8 +142,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (result != null) {
return result;
} else {
return LazyInit.GetOrSet(ref accessorField, (IMethod)unresolvedAccessor.CreateResolved(context));
return LazyInit.GetOrSet(ref accessorField, CreateResolvedAccessor(unresolvedAccessor));
}
}
protected virtual IMethod CreateResolvedAccessor(IUnresolvedMethod unresolvedAccessor)
{
return (IMethod)unresolvedAccessor.CreateResolved(context);
}
}
}

8
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedMethod.cs

@ -224,7 +224,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -224,7 +224,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return null; }
}
public IMember AccessorOwner {
public virtual IMember AccessorOwner {
get {
var reference = ((IUnresolvedMethod)unresolved).AccessorOwner;
if (reference != null)
@ -261,8 +261,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -261,8 +261,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
StringBuilder b = new StringBuilder("[");
b.Append(this.EntityType);
b.Append(' ');
b.Append(this.DeclaringType.ReflectionName);
b.Append('.');
if (this.DeclaringType.Kind != TypeKind.Unknown) {
b.Append(this.DeclaringType.ReflectionName);
b.Append('.');
}
b.Append(this.Name);
if (this.TypeParameters.Count > 0) {
b.Append("``");

Loading…
Cancel
Save