From baad38a5904f5b5c55a6c1a12966cb5a56cbc508 Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 12:50:06 +0200 Subject: [PATCH 01/16] Tests demonstrating that the accessors for a property that implements an interface property do not have any ImplementedInterfaceMembers. --- .../TypeSystem/TypeSystemTests.TestCase.cs | 12 ++++++++++++ .../TypeSystem/TypeSystemTests.cs | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs index 580138eae6..4facdc1764 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs @@ -236,4 +236,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase public static int Prop3 { get; set; } public int Prop4 { get; set; } } + + public interface IInterfaceWithProperty { + int Prop { get; set; } + } + + public class ClassWithVirtualProperty { + public virtual int Prop { get; set; } + } + + public class ClassThatImplementsProperty : IInterfaceWithProperty { + public int Prop { get; set; } + } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index 6f76812ac4..e61dc7d44d 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -847,5 +847,14 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.AreEqual("add_Event3", normalEvent.AddAccessor.Name); Assert.AreEqual("remove_Event3", normalEvent.RemoveAccessor.Name); } + + [Test] + public void PropertyAccessorsShouldBeReportedAsImplementingInterfaceAccessors() { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsProperty)); + var prop = type.Properties.Single(p => p.Name == "Prop"); + Assert.That(prop.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.Prop" })); + Assert.That(prop.Getter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.get_Prop" })); + Assert.That(prop.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.set_Prop" })); + } } } From 7ce5de3873fe6a231294b1cb8b0c33b577650254 Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 12:51:02 +0200 Subject: [PATCH 02/16] (Rather ugly) fix ensure that accessor method are reported as implementing the corresponding accessor methods from interfaces. --- .../TypeSystem/InheritanceHelper.cs | 53 ++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs index 3866974fa1..ef1d8d5456 100644 --- a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs @@ -69,13 +69,52 @@ namespace ICSharpCode.NRefactory.TypeSystem foreach (IType baseType in allBaseTypes.Reverse()) { if (baseType == member.DeclaringTypeDefinition) continue; - - foreach (IMember baseMember in baseType.GetMembers(m => m.Name == member.Name, GetMemberOptions.IgnoreInheritedMembers)) { - if (SignatureComparer.Ordinal.Equals(member, baseMember)) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseMember, specializedMember.Substitution); - else - yield return baseMember; + + if (member is IMethod && ((IMethod)member).IsAccessor) { + var accessorOwner = ((IMethod)member).AccessorOwner; + foreach (IMember baseOwner in baseType.GetMembers(m => m.Name == accessorOwner.Name, GetMemberOptions.IgnoreInheritedMembers)) { + if (accessorOwner is IProperty && baseOwner is IProperty) { + var accessorProperty = (IProperty)accessorOwner; + var baseProperty = (IProperty)baseOwner; + if (member == accessorProperty.Getter && baseProperty.CanGet) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseProperty.Getter, specializedMember.Substitution); + else + yield return baseProperty.Getter; + } + if (member == accessorProperty.Setter && baseProperty.CanSet) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseProperty.Setter, specializedMember.Substitution); + else + yield return baseProperty.Setter; + } + } + else if (accessorOwner is IEvent && baseOwner is IEvent) { + var accessorEvent = (IEvent)accessorOwner; + var baseEvent = (IEvent)baseOwner; + if (member == accessorEvent.AddAccessor && baseEvent.CanAdd) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseEvent.AddAccessor, specializedMember.Substitution); + else + yield return baseEvent.AddAccessor; + } + if (member == accessorEvent.RemoveAccessor && baseEvent.CanRemove) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseEvent.RemoveAccessor, specializedMember.Substitution); + else + yield return baseEvent.RemoveAccessor; + } + } + } + } + else { + foreach (IMember baseMember in baseType.GetMembers(m => m.Name == member.Name, GetMemberOptions.IgnoreInheritedMembers)) { + if (SignatureComparer.Ordinal.Equals(member, baseMember)) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseMember, specializedMember.Substitution); + else + yield return baseMember; + } } } } From 7e2a5a32bb231a5e196ce33b27d5b26a116c6769 Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 15:02:01 +0200 Subject: [PATCH 03/16] Tests for ImplementedInterfaceMembers for indexer accessors. --- .../TypeSystem/TypeSystemTests.TestCase.cs | 16 ++++++++++ .../TypeSystem/TypeSystemTests.cs | 29 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs index 4facdc1764..7a6fde0683 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs @@ -248,4 +248,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase public class ClassThatImplementsProperty : IInterfaceWithProperty { public int Prop { get; set; } } + + public interface IInterfaceWithIndexers { + int this[int x] { get; set; } + int this[string x] { get; set; } + int this[int x, int y] { get; set; } + } + + public interface IGenericInterfaceWithIndexer { + int this[T x] { get; set; } + } + + public class ClassThatImplementsIndexers : IInterfaceWithIndexers, IGenericInterfaceWithIndexer { + public int this[int x] { get { return 0; } set {} } + public int this[string x] { get { return 0; } set {} } + public int this[int x, int y] { get { return 0; } set {} } + } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index e61dc7d44d..e3918511c8 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -856,5 +856,34 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.That(prop.Getter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.get_Prop" })); Assert.That(prop.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.set_Prop" })); } + + [Test] + public void IndexerAccessorsShouldBeReportedAsImplementingTheCorrectInterfaceAccessors() { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsIndexers)); + var ix1 = type.Properties.Single(p => p.Parameters.Count == 1 && p.Parameters[0].Type.GetDefinition().KnownTypeCode == KnownTypeCode.Int32); + var ix2 = type.Properties.Single(p => p.Parameters.Count == 1 && p.Parameters[0].Type.GetDefinition().KnownTypeCode == KnownTypeCode.String); + var ix3 = type.Properties.Single(p => p.Parameters.Count == 2); + + Assert.That(ix1.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EquivalentTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.Item", "ICSharpCode.NRefactory.TypeSystem.TestCase.IGenericInterfaceWithIndexer`1.Item" })); + Assert.That(ix1.ImplementedInterfaceMembers.All(p => ((IProperty)p).Parameters.Select(x => x.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.Int32 }))); + Assert.That(ix1.Getter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EquivalentTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.get_Item", "ICSharpCode.NRefactory.TypeSystem.TestCase.IGenericInterfaceWithIndexer`1.get_Item" })); + Assert.That(ix1.Getter.ImplementedInterfaceMembers.All(m => ((IMethod)m).Parameters.Select(p => p.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.Int32 }))); + Assert.That(ix1.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EquivalentTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.set_Item", "ICSharpCode.NRefactory.TypeSystem.TestCase.IGenericInterfaceWithIndexer`1.set_Item" })); + Assert.That(ix1.Setter.ImplementedInterfaceMembers.All(m => ((IMethod)m).Parameters.Select(p => p.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.Int32, KnownTypeCode.Int32 }))); + + Assert.That(ix2.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.Item" })); + Assert.That(ix2.ImplementedInterfaceMembers.All(p => ((IProperty)p).Parameters.Select(x => x.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.String }))); + Assert.That(ix2.Getter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.get_Item" })); + Assert.That(ix2.Getter.ImplementedInterfaceMembers.All(m => ((IMethod)m).Parameters.Select(p => p.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.String }))); + Assert.That(ix2.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.set_Item" })); + Assert.That(ix2.Setter.ImplementedInterfaceMembers.All(m => ((IMethod)m).Parameters.Select(p => p.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.String, KnownTypeCode.Int32 }))); + + Assert.That(ix3.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.Item" })); + Assert.That(ix3.ImplementedInterfaceMembers.All(p => ((IProperty)p).Parameters.Select(x => x.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.Int32, KnownTypeCode.Int32 }))); + Assert.That(ix3.Getter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.get_Item" })); + Assert.That(ix3.Getter.ImplementedInterfaceMembers.All(m => ((IMethod)m).Parameters.Select(p => p.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.Int32, KnownTypeCode.Int32 }))); + Assert.That(ix3.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.set_Item" })); + Assert.That(ix3.Setter.ImplementedInterfaceMembers.All(m => ((IMethod)m).Parameters.Select(p => p.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.Int32, KnownTypeCode.Int32, KnownTypeCode.Int32 }))); + } } } From fd39748fcfd1c455203b7db325c7728b440e4bb7 Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 15:02:26 +0200 Subject: [PATCH 04/16] (Rather ugly) fix for indexer accessor's ImplementedInterfaceMembers. --- .../TypeSystem/InheritanceHelper.cs | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs index ef1d8d5456..430569ae2d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs @@ -73,36 +73,38 @@ namespace ICSharpCode.NRefactory.TypeSystem if (member is IMethod && ((IMethod)member).IsAccessor) { var accessorOwner = ((IMethod)member).AccessorOwner; foreach (IMember baseOwner in baseType.GetMembers(m => m.Name == accessorOwner.Name, GetMemberOptions.IgnoreInheritedMembers)) { - if (accessorOwner is IProperty && baseOwner is IProperty) { - var accessorProperty = (IProperty)accessorOwner; - var baseProperty = (IProperty)baseOwner; - if (member == accessorProperty.Getter && baseProperty.CanGet) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseProperty.Getter, specializedMember.Substitution); - else - yield return baseProperty.Getter; + if (SignatureComparer.Ordinal.Equals(accessorOwner, baseOwner)) { + if (accessorOwner is IProperty && baseOwner is IProperty) { + var accessorProperty = (IProperty)accessorOwner; + var baseProperty = (IProperty)baseOwner; + if (member == accessorProperty.Getter && baseProperty.CanGet) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseProperty.Getter, specializedMember.Substitution); + else + yield return baseProperty.Getter; + } + if (member == accessorProperty.Setter && baseProperty.CanSet) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseProperty.Setter, specializedMember.Substitution); + else + yield return baseProperty.Setter; + } } - if (member == accessorProperty.Setter && baseProperty.CanSet) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseProperty.Setter, specializedMember.Substitution); - else - yield return baseProperty.Setter; - } - } - else if (accessorOwner is IEvent && baseOwner is IEvent) { - var accessorEvent = (IEvent)accessorOwner; - var baseEvent = (IEvent)baseOwner; - if (member == accessorEvent.AddAccessor && baseEvent.CanAdd) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseEvent.AddAccessor, specializedMember.Substitution); - else - yield return baseEvent.AddAccessor; - } - if (member == accessorEvent.RemoveAccessor && baseEvent.CanRemove) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseEvent.RemoveAccessor, specializedMember.Substitution); - else - yield return baseEvent.RemoveAccessor; + else if (accessorOwner is IEvent && baseOwner is IEvent) { + var accessorEvent = (IEvent)accessorOwner; + var baseEvent = (IEvent)baseOwner; + if (member == accessorEvent.AddAccessor && baseEvent.CanAdd) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseEvent.AddAccessor, specializedMember.Substitution); + else + yield return baseEvent.AddAccessor; + } + if (member == accessorEvent.RemoveAccessor && baseEvent.CanRemove) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseEvent.RemoveAccessor, specializedMember.Substitution); + else + yield return baseEvent.RemoveAccessor; + } } } } From 4d868ba2b32c318872a053b4885305844b4997db Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 16:09:41 +0200 Subject: [PATCH 05/16] Failing test with explicit indexer implementation --- .../TypeSystem/TypeSystemTests.TestCase.cs | 7 +++++++ .../TypeSystem/TypeSystemTests.cs | 9 +++++++++ 2 files changed, 16 insertions(+) diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs index 7a6fde0683..f15071a7f4 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs @@ -264,4 +264,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase public int this[string x] { get { return 0; } set {} } public int this[int x, int y] { get { return 0; } set {} } } + + public class ClassThatImplementsIndexersExplicitly : IInterfaceWithIndexers, IGenericInterfaceWithIndexer { + int IInterfaceWithIndexers.this[int x] { get { return 0; } set {} } + int IGenericInterfaceWithIndexer.this[int x] { get { return 0; } set {} } + int IInterfaceWithIndexers.this[string x] { get { return 0; } set {} } + int IInterfaceWithIndexers.this[int x, int y] { get { return 0; } set {} } + } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index e3918511c8..44b63ca41e 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -885,5 +885,14 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.That(ix3.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithIndexers.set_Item" })); Assert.That(ix3.Setter.ImplementedInterfaceMembers.All(m => ((IMethod)m).Parameters.Select(p => p.Type.GetDefinition().KnownTypeCode).SequenceEqual(new[] { KnownTypeCode.Int32, KnownTypeCode.Int32, KnownTypeCode.Int32 }))); } + + [Test] + public void ExplicitIndexerImplementationReturnsTheCorrectMembers() { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsIndexersExplicitly)); + + Assert.That(type.Properties.All(p => p.ImplementedInterfaceMembers.Count == 1)); + Assert.That(type.Properties.All(p => p.Getter.ImplementedInterfaceMembers.Count == 1)); + Assert.That(type.Properties.All(p => p.Setter.ImplementedInterfaceMembers.Count == 1)); + } } } From 18995bd372d1cc4f9d015c12282153ffc918ff7e Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 16:16:14 +0200 Subject: [PATCH 06/16] Fixed InheritanceHelper to support explicit interface implementation of base accessors. --- .../TypeSystem/InheritanceHelper.cs | 101 +++++++++--------- 1 file changed, 53 insertions(+), 48 deletions(-) diff --git a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs index 430569ae2d..7eac11a93f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs @@ -39,6 +39,46 @@ namespace ICSharpCode.NRefactory.TypeSystem { return GetBaseMembers(member, false).FirstOrDefault(); } + + private static IEnumerable GetBaseAccessors(IMethod accessor, bool includeImplementedInterfaces) { + IMember accessorOwner = accessor.AccessorOwner; + SpecializedMember specializedMember = accessor as SpecializedMember; + + foreach (IMember baseOwner in GetBaseMembers(accessorOwner, includeImplementedInterfaces)) { + if (accessorOwner is IProperty && baseOwner is IProperty) { + var accessorProperty = (IProperty)accessorOwner; + var baseProperty = (IProperty)baseOwner; + if (accessor == accessorProperty.Getter && baseProperty.CanGet) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseProperty.Getter, specializedMember.Substitution); + else + yield return baseProperty.Getter; + } + if (accessor == accessorProperty.Setter && baseProperty.CanSet) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseProperty.Setter, specializedMember.Substitution); + else + yield return baseProperty.Setter; + } + } + else if (accessorOwner is IEvent && baseOwner is IEvent) { + var accessorEvent = (IEvent)accessorOwner; + var baseEvent = (IEvent)baseOwner; + if (accessor == accessorEvent.AddAccessor && baseEvent.CanAdd) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseEvent.AddAccessor, specializedMember.Substitution); + else + yield return baseEvent.AddAccessor; + } + if (accessor == accessorEvent.RemoveAccessor && baseEvent.CanRemove) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseEvent.RemoveAccessor, specializedMember.Substitution); + else + yield return baseEvent.RemoveAccessor; + } + } + } + } /// /// Gets all base members that have the same signature. @@ -50,7 +90,7 @@ namespace ICSharpCode.NRefactory.TypeSystem { if (member == null) throw new ArgumentNullException("member"); - + if (member.IsExplicitInterfaceImplementation && member.ImplementedInterfaceMembers.Count == 1) { // C#-style explicit interface implementation member = member.ImplementedInterfaceMembers[0]; @@ -59,6 +99,12 @@ namespace ICSharpCode.NRefactory.TypeSystem SpecializedMember specializedMember = member as SpecializedMember; member = member.MemberDefinition; + + if (member is IMethod && ((IMethod)member).IsAccessor) { + foreach (IMember m in GetBaseAccessors((IMethod)member, includeImplementedInterfaces)) + yield return m; + yield break; + } IEnumerable allBaseTypes; if (includeImplementedInterfaces) { @@ -70,53 +116,12 @@ namespace ICSharpCode.NRefactory.TypeSystem if (baseType == member.DeclaringTypeDefinition) continue; - if (member is IMethod && ((IMethod)member).IsAccessor) { - var accessorOwner = ((IMethod)member).AccessorOwner; - foreach (IMember baseOwner in baseType.GetMembers(m => m.Name == accessorOwner.Name, GetMemberOptions.IgnoreInheritedMembers)) { - if (SignatureComparer.Ordinal.Equals(accessorOwner, baseOwner)) { - if (accessorOwner is IProperty && baseOwner is IProperty) { - var accessorProperty = (IProperty)accessorOwner; - var baseProperty = (IProperty)baseOwner; - if (member == accessorProperty.Getter && baseProperty.CanGet) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseProperty.Getter, specializedMember.Substitution); - else - yield return baseProperty.Getter; - } - if (member == accessorProperty.Setter && baseProperty.CanSet) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseProperty.Setter, specializedMember.Substitution); - else - yield return baseProperty.Setter; - } - } - else if (accessorOwner is IEvent && baseOwner is IEvent) { - var accessorEvent = (IEvent)accessorOwner; - var baseEvent = (IEvent)baseOwner; - if (member == accessorEvent.AddAccessor && baseEvent.CanAdd) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseEvent.AddAccessor, specializedMember.Substitution); - else - yield return baseEvent.AddAccessor; - } - if (member == accessorEvent.RemoveAccessor && baseEvent.CanRemove) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseEvent.RemoveAccessor, specializedMember.Substitution); - else - yield return baseEvent.RemoveAccessor; - } - } - } - } - } - else { - foreach (IMember baseMember in baseType.GetMembers(m => m.Name == member.Name, GetMemberOptions.IgnoreInheritedMembers)) { - if (SignatureComparer.Ordinal.Equals(member, baseMember)) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseMember, specializedMember.Substitution); - else - yield return baseMember; - } + foreach (IMember baseMember in baseType.GetMembers(m => m.Name == member.Name, GetMemberOptions.IgnoreInheritedMembers)) { + if (SignatureComparer.Ordinal.Equals(member, baseMember)) { + if (specializedMember != null) + yield return SpecializedMember.Create(baseMember, specializedMember.Substitution); + else + yield return baseMember; } } } From 7640141783afa19b83b0cfa0a5418b1c0848c7f2 Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 19:02:13 +0200 Subject: [PATCH 07/16] Added support for explicit method and property implementations to the cecil loader. --- .../Parser/TypeSystemConvertVisitorTests.cs | 57 ---------------- .../TypeSystem/TypeSystemTests.TestCase.cs | 4 ++ .../TypeSystem/TypeSystemTests.cs | 67 +++++++++++++++++++ .../TypeSystem/CecilLoader.cs | 42 +++++++++++- .../Implementation/DefaultMemberReference.cs | 8 ++- 5 files changed, 117 insertions(+), 61 deletions(-) diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs index 7f5922f1ae..a95b19bbcd 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs @@ -61,63 +61,6 @@ namespace ICSharpCode.NRefactory.CSharp.Parser Assert.AreEqual(compilation.FindType(KnownTypeCode.Array), typeRef.Resolve(compilation.TypeResolveContext)); } - [Test] - public void ExplicitDisposableImplementation() - { - ITypeDefinition disposable = GetTypeDefinition(typeof(NRefactory.TypeSystem.TestCase.ExplicitDisposableImplementation)); - IMethod method = disposable.Methods.Single(m => m.Name == "Dispose"); - Assert.IsTrue(method.IsExplicitInterfaceImplementation); - Assert.AreEqual("System.IDisposable.Dispose", method.ImplementedInterfaceMembers.Single().FullName); - } - - [Test] - public void ExplicitGenericInterfaceImplementation() - { - ITypeDefinition impl = GetTypeDefinition(typeof(NRefactory.TypeSystem.TestCase.ExplicitGenericInterfaceImplementation)); - IType genericInterfaceOfString = compilation.FindType(typeof(IGenericInterface)); - IMethod implMethod1 = impl.Methods.Single(m => m.Name == "Test" && !m.Parameters[1].IsRef); - IMethod implMethod2 = impl.Methods.Single(m => m.Name == "Test" && m.Parameters[1].IsRef); - Assert.IsTrue(implMethod1.IsExplicitInterfaceImplementation); - Assert.IsTrue(implMethod2.IsExplicitInterfaceImplementation); - - IMethod interfaceMethod1 = (IMethod)implMethod1.ImplementedInterfaceMembers.Single(); - Assert.AreEqual(genericInterfaceOfString, interfaceMethod1.DeclaringType); - Assert.IsTrue(!interfaceMethod1.Parameters[1].IsRef); - - IMethod interfaceMethod2 = (IMethod)implMethod2.ImplementedInterfaceMembers.Single(); - Assert.AreEqual(genericInterfaceOfString, interfaceMethod2.DeclaringType); - Assert.IsTrue(interfaceMethod2.Parameters[1].IsRef); - } - - [Test] - public void ExplicitImplementationOfUnifiedMethods() - { - IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods)); - Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count()); - foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) { - Assert.AreEqual(1, method.ImplementedInterfaceMembers.Count, method.ToString()); - Assert.AreEqual("System.Int32", method.Parameters.Single().Type.ReflectionName); - IMethod interfaceMethod = (IMethod)method.ImplementedInterfaceMembers.Single(); - Assert.AreEqual("System.Int32", interfaceMethod.Parameters.Single().Type.ReflectionName); - var genericParamType = ((IMethod)method.MemberDefinition).Parameters.Single().Type; - var interfaceGenericParamType = ((IMethod)interfaceMethod.MemberDefinition).Parameters.Single().Type; - Assert.AreEqual(TypeKind.TypeParameter, genericParamType.Kind); - Assert.AreEqual(TypeKind.TypeParameter, interfaceGenericParamType.Kind); - Assert.AreEqual(genericParamType.ReflectionName, interfaceGenericParamType.ReflectionName); - } - } - - [Test] - public void ExplicitImplementationOfUnifiedMethods_ToMemberReference() - { - IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods)); - Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count()); - foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) { - IMethod resolvedMethod = (IMethod)method.ToMemberReference().Resolve(compilation.TypeResolveContext); - Assert.AreEqual(method, resolvedMethod); - } - } - [Test] public void PartialMethodWithImplementation() { diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs index f15071a7f4..e5c9b3f502 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs @@ -249,6 +249,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase public int Prop { get; set; } } + public class ClassThatImplementsPropertyExplicitly : IInterfaceWithProperty { + int IInterfaceWithProperty.Prop { get; set; } + } + public interface IInterfaceWithIndexers { int this[int x] { get; set; } int this[string x] { get; set; } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index 44b63ca41e..b8589447b4 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -894,5 +894,72 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.That(type.Properties.All(p => p.Getter.ImplementedInterfaceMembers.Count == 1)); Assert.That(type.Properties.All(p => p.Setter.ImplementedInterfaceMembers.Count == 1)); } + + [Test] + public void ExplicitDisposableImplementation() + { + ITypeDefinition disposable = GetTypeDefinition(typeof(NRefactory.TypeSystem.TestCase.ExplicitDisposableImplementation)); + IMethod method = disposable.Methods.Single(m => !m.IsConstructor); + Assert.IsTrue(method.IsExplicitInterfaceImplementation); + Assert.AreEqual("System.IDisposable.Dispose", method.ImplementedInterfaceMembers.Single().FullName); + } + + [Test] + public void ExplicitImplementationOfUnifiedMethods() + { + IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods)); + Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count()); + foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) { + Assert.AreEqual(1, method.ImplementedInterfaceMembers.Count, method.ToString()); + Assert.AreEqual("System.Int32", method.Parameters.Single().Type.ReflectionName); + IMethod interfaceMethod = (IMethod)method.ImplementedInterfaceMembers.Single(); + Assert.AreEqual("System.Int32", interfaceMethod.Parameters.Single().Type.ReflectionName); + var genericParamType = ((IMethod)method.MemberDefinition).Parameters.Single().Type; + var interfaceGenericParamType = ((IMethod)interfaceMethod.MemberDefinition).Parameters.Single().Type; + Assert.AreEqual(TypeKind.TypeParameter, genericParamType.Kind); + Assert.AreEqual(TypeKind.TypeParameter, interfaceGenericParamType.Kind); + Assert.AreEqual(genericParamType.ReflectionName, interfaceGenericParamType.ReflectionName); + } + } + + [Test] + public void ExplicitImplementationOfUnifiedMethods_ToMemberReference() + { + IType type = compilation.FindType(typeof(ExplicitGenericInterfaceImplementationWithUnifiableMethods)); + Assert.AreEqual(2, type.GetMethods(m => m.IsExplicitInterfaceImplementation).Count()); + foreach (IMethod method in type.GetMethods(m => m.IsExplicitInterfaceImplementation)) { + IMethod resolvedMethod = (IMethod)method.ToMemberReference().Resolve(compilation.TypeResolveContext); + Assert.AreEqual(method, resolvedMethod); + } + } + + [Test] + public void ExplicitGenericInterfaceImplementation() + { + ITypeDefinition impl = GetTypeDefinition(typeof(ExplicitGenericInterfaceImplementation)); + IType genericInterfaceOfString = compilation.FindType(typeof(IGenericInterface)); + IMethod implMethod1 = impl.Methods.Single(m => !m.IsConstructor && !m.Parameters[1].IsRef); + IMethod implMethod2 = impl.Methods.Single(m => !m.IsConstructor && m.Parameters[1].IsRef); + Assert.IsTrue(implMethod1.IsExplicitInterfaceImplementation); + Assert.IsTrue(implMethod2.IsExplicitInterfaceImplementation); + + IMethod interfaceMethod1 = (IMethod)implMethod1.ImplementedInterfaceMembers.Single(); + Assert.AreEqual(genericInterfaceOfString, interfaceMethod1.DeclaringType); + Assert.IsTrue(!interfaceMethod1.Parameters[1].IsRef); + + IMethod interfaceMethod2 = (IMethod)implMethod2.ImplementedInterfaceMembers.Single(); + Assert.AreEqual(genericInterfaceOfString, interfaceMethod2.DeclaringType); + Assert.IsTrue(interfaceMethod2.Parameters[1].IsRef); + } + + [Test] + public void ExplicitlyImplementedPropertiesShouldBeReportedAsBeingImplemented() { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsPropertyExplicitly)); + var prop = type.Properties.Single(); + Assert.That(prop.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.Prop" })); + Assert.That(prop.Getter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.get_Prop" })); + Assert.That(prop.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.set_Prop" })); + } + } } diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index 15530707a5..7251ebce7f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -88,6 +88,15 @@ namespace ICSharpCode.NRefactory.TypeSystem // Enable interning by default. this.InterningProvider = new SimpleInterningProvider(); } + + void ReadExplicitInterfaceImplementation(DefaultUnresolvedMethod m, MethodDefinition method) { + if (method.Name.Contains(".") && method.HasOverrides) { + m.IsExplicitInterfaceImplementation = true; + foreach (var or in method.Overrides) { + m.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(EntityType.Method, ReadTypeReference(or.DeclaringType), or.Name, or.GenericParameters.Count, m.Parameters.Select(p => p.Type).ToList(), false)); + } + } + } #region Load From AssemblyDefinition /// @@ -1650,7 +1659,7 @@ namespace ICSharpCode.NRefactory.TypeSystem return ReadMethod(method, parentType, null, methodType); } - IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, IUnresolvedMember accessorOwner, EntityType methodType = EntityType.Method) + IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, IUnresolvedMember accessorOwner, EntityType methodType = EntityType.Method, bool readExplicitInterfaceImplementation = true) { if (method == null) return null; @@ -1685,6 +1694,9 @@ namespace ICSharpCode.NRefactory.TypeSystem if (method.IsStatic && HasExtensionAttribute(method)) { m.IsExtensionMethod = true; } + + if (readExplicitInterfaceImplementation) + ReadExplicitInterfaceImplementation(m, method); FinishReadMember(m, method); return m; @@ -1870,6 +1882,7 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region Read Property + [CLSCompliant(false)] public IUnresolvedProperty ReadProperty(PropertyDefinition property, IUnresolvedTypeDefinition parentType, EntityType propertyType = EntityType.Property) { @@ -1891,6 +1904,33 @@ namespace ICSharpCode.NRefactory.TypeSystem } } AddAttributes(property, p); + + int lastDot = property.Name.LastIndexOf('.'); + if (lastDot >= 0) { + string name = property.Name.Substring(lastDot + 1); + if (p.Getter != null && p.Getter.IsExplicitInterfaceImplementation) { + p.IsExplicitInterfaceImplementation = true; + foreach (var x in p.Getter.ExplicitInterfaceImplementations) { + var r = new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList()); + p.ExplicitInterfaceImplementations.Add(r); + } + } + else if (p.Setter != null && p.Setter.IsExplicitInterfaceImplementation) { + p.IsExplicitInterfaceImplementation = true; + foreach (var x in p.Setter.ExplicitInterfaceImplementations) { + var r = new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList()); + p.ExplicitInterfaceImplementations.Add(r); + } + } + } + + // This is very hacky. Due to which code parts are taken later in the execution, we need to pretend that the accessors are not explicit interface implementations at this stage. + if (p.Getter != null && p.Getter.IsExplicitInterfaceImplementation) { + p.Getter = ReadMethod(property.GetMethod, parentType, p, readExplicitInterfaceImplementation: false); + } + if (p.Setter != null && p.Setter.IsExplicitInterfaceImplementation) { + p.Setter = ReadMethod(property.GetMethod, parentType, p, readExplicitInterfaceImplementation: false); + } FinishReadMember(p, property); return p; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs index 632207e621..ed67e6eba4 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs @@ -38,8 +38,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation string name; int typeParameterCount; IList parameterTypes; + bool isExplicitInterfaceImplementation; - public DefaultMemberReference(EntityType entityType, ITypeReference typeReference, string name, int typeParameterCount = 0, IList parameterTypes = null) + public DefaultMemberReference(EntityType entityType, ITypeReference typeReference, string name, int typeParameterCount = 0, IList parameterTypes = null, bool isExplicitInterfaceImplementation = false) { if (typeReference == null) throw new ArgumentNullException("typeReference"); @@ -52,6 +53,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.name = name; this.typeParameterCount = typeParameterCount; this.parameterTypes = parameterTypes ?? EmptyList.Instance; + this.isExplicitInterfaceImplementation = isExplicitInterfaceImplementation; } public ITypeReference DeclaringTypeReference { @@ -65,11 +67,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation if (entityType == EntityType.Method) { members = type.GetMethods( m => m.Name == name && m.EntityType == EntityType.Method - && m.TypeParameters.Count == typeParameterCount && !m.IsExplicitInterfaceImplementation, + && m.TypeParameters.Count == typeParameterCount && m.IsExplicitInterfaceImplementation == isExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers); } else { members = type.GetMembers( - m => m.Name == name && m.EntityType == entityType && !m.IsExplicitInterfaceImplementation, + m => m.Name == name && m.EntityType == entityType && m.IsExplicitInterfaceImplementation == isExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers); } var resolvedParameterTypes = parameterTypes.Resolve(context); From 8431aa00391891754fc3595888cede4b7daab23b Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 19:24:43 +0200 Subject: [PATCH 08/16] Fixed bugs with events: 1) Assignment of IsOverride to IsOverridable, and 2) AccessorOwner not being set for auto-events. --- .../TypeSystem/TypeSystemConvertVisitor.cs | 3 ++- .../TypeSystem/TypeSystemTests.TestCase.cs | 16 ++++++++++++ .../TypeSystem/TypeSystemTests.cs | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs index d2a273dcc0..cefb703c7f 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs @@ -756,11 +756,12 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem DefaultUnresolvedMethod CreateDefaultEventAccessor(IUnresolvedEvent ev, string name, IUnresolvedParameter valueParameter) { var a = new DefaultUnresolvedMethod(currentTypeDefinition, name); + a.AccessorOwner = ev; a.Region = ev.BodyRegion; a.BodyRegion = ev.BodyRegion; a.Accessibility = ev.Accessibility; a.IsAbstract = ev.IsAbstract; - a.IsOverride = ev.IsOverridable; + a.IsOverride = ev.IsOverride; a.IsSealed = ev.IsSealed; a.IsStatic = ev.IsStatic; a.IsSynthetic = ev.IsSynthetic; diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs index e5c9b3f502..2efddd385a 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs @@ -275,4 +275,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase int IInterfaceWithIndexers.this[string x] { get { return 0; } set {} } int IInterfaceWithIndexers.this[int x, int y] { get { return 0; } set {} } } + + public interface IHasEvent { + event EventHandler Event; + } + + public class ClassThatImplementsEvent : IHasEvent { + public event EventHandler Event; + } + + public class ClassThatImplementsEventWithCustomAccessors : IHasEvent { + public event EventHandler Event { add {} remove {} } + } + + public class ClassThatImplementsEventExplicitly : IHasEvent { + event EventHandler IHasEvent.Event { add {} remove {} } + } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index b8589447b4..4ee5534237 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -961,5 +961,31 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.That(prop.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.set_Prop" })); } + [Test] + public void EventAccessorsShouldBeReportedAsImplementingInterfaceAccessors() { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsEvent)); + var evt = type.Events.Single(p => p.Name == "Event"); + Assert.That(evt.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.Event" })); + Assert.That(evt.AddAccessor.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.add_Event" })); + Assert.That(evt.RemoveAccessor.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.remove_Event" })); + } + + [Test] + public void EventAccessorsShouldBeReportedAsImplementingInterfaceAccessorsWhenCustomAccessorMethodsAreUsed() { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsEventWithCustomAccessors)); + var evt = type.Events.Single(p => p.Name == "Event"); + Assert.That(evt.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.Event" })); + Assert.That(evt.AddAccessor.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.add_Event" })); + Assert.That(evt.RemoveAccessor.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.remove_Event" })); + } + + [Test] + public void ExplicitlyImplementedEventsShouldBeReportedAsBeingImplemented() { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsEventExplicitly)); + var evt = type.Events.Single(); + Assert.That(evt.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.Event" })); + Assert.That(evt.AddAccessor.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.add_Event" })); + Assert.That(evt.RemoveAccessor.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.remove_Event" })); + } } } From 481397973a94c14ad890b2974304d80d290da09e Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 19:29:20 +0200 Subject: [PATCH 09/16] Support explicitly implemented events in the CecilLoader. --- .../TypeSystem/CecilLoader.cs | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index 7251ebce7f..e0e6eb4737 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -1911,15 +1911,13 @@ namespace ICSharpCode.NRefactory.TypeSystem if (p.Getter != null && p.Getter.IsExplicitInterfaceImplementation) { p.IsExplicitInterfaceImplementation = true; foreach (var x in p.Getter.ExplicitInterfaceImplementations) { - var r = new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList()); - p.ExplicitInterfaceImplementations.Add(r); + p.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList())); } } else if (p.Setter != null && p.Setter.IsExplicitInterfaceImplementation) { p.IsExplicitInterfaceImplementation = true; foreach (var x in p.Setter.ExplicitInterfaceImplementations) { - var r = new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList()); - p.ExplicitInterfaceImplementations.Add(r); + p.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList())); } } } @@ -1956,6 +1954,34 @@ namespace ICSharpCode.NRefactory.TypeSystem AddAttributes(ev, e); + int lastDot = ev.Name.LastIndexOf('.'); + if (lastDot >= 0) { + string name = ev.Name.Substring(lastDot + 1); + if (e.AddAccessor != null && e.AddAccessor.IsExplicitInterfaceImplementation) { + e.IsExplicitInterfaceImplementation = true; + foreach (var x in e.AddAccessor.ExplicitInterfaceImplementations) { + e.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(EntityType.Event, x.DeclaringTypeReference, name)); + } + } + else if (e.RemoveAccessor != null && e.RemoveAccessor.IsExplicitInterfaceImplementation) { + e.IsExplicitInterfaceImplementation = true; + foreach (var x in e.RemoveAccessor.ExplicitInterfaceImplementations) { + e.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(EntityType.Event, x.DeclaringTypeReference, name)); + } + } + } + + // This is very hacky. Due to which code parts are taken later in the execution, we need to pretend that the accessors are not explicit interface implementations at this stage. + if (e.AddAccessor != null && e.AddAccessor.IsExplicitInterfaceImplementation) { + e.AddAccessor = ReadMethod(ev.AddMethod, parentType, e, readExplicitInterfaceImplementation: false); + } + if (e.RemoveAccessor != null && e.RemoveAccessor.IsExplicitInterfaceImplementation) { + e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType, e, readExplicitInterfaceImplementation: false); + } + if (e.InvokeAccessor != null && e.InvokeAccessor.IsExplicitInterfaceImplementation) { + e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType, e, readExplicitInterfaceImplementation: false); + } + FinishReadMember(e, ev); return e; From da0feac28634b0ec46af46e829e378edec7f555a Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 19:42:36 +0200 Subject: [PATCH 10/16] Another one of those x.IsOverride = y.IsOverridable issues. --- .../TypeSystem/TypeSystemConvertVisitor.cs | 2 +- .../TypeSystem/TypeSystemTests.cs | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs index cefb703c7f..793f99faf9 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs @@ -680,7 +680,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem a.AccessorOwner = p; a.Accessibility = GetAccessibility(accessor.Modifiers) ?? p.Accessibility; a.IsAbstract = p.IsAbstract; - a.IsOverride = p.IsOverridable; + a.IsOverride = p.IsOverride; a.IsSealed = p.IsSealed; a.IsStatic = p.IsStatic; a.IsSynthetic = p.IsSynthetic; diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index 4ee5534237..69c05190ef 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -678,6 +678,63 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.AreEqual("ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[`0]]", field2.Type.ReflectionName); Assert.AreEqual("ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[ICSharpCode.NRefactory.TypeSystem.TestCase.OuterGeneric`1+Inner[[`0]]]]", field3.Type.ReflectionName); } + + [Test] + public void FlagsOnInterfaceMembersAreCorrect() { + ITypeDefinition type = GetTypeDefinition(typeof(IInterfaceWithProperty)); + var p = type.Properties.Single(); + Assert.AreEqual(false, p.IsIndexer); + Assert.AreEqual(true, p.IsAbstract); + Assert.AreEqual(true, p.IsOverridable); + Assert.AreEqual(false, p.IsOverride); + Assert.AreEqual(true, p.IsPublic); + Assert.AreEqual(true, p.Getter.IsAbstract); + Assert.AreEqual(true, p.Getter.IsOverridable); + Assert.AreEqual(false, p.Getter.IsOverride); + Assert.AreEqual(true, p.Getter.IsPublic); + Assert.AreEqual(true, p.Setter.IsAbstract); + Assert.AreEqual(true, p.Setter.IsOverridable); + Assert.AreEqual(false, p.Setter.IsOverride); + Assert.AreEqual(true, p.Setter.IsPublic); + + type = GetTypeDefinition(typeof(IInterfaceWithIndexers)); + p = type.Properties.Single(x => x.Parameters.Count == 2); + Assert.AreEqual(true, p.IsIndexer); + Assert.AreEqual(true, p.IsAbstract); + Assert.AreEqual(true, p.IsOverridable); + Assert.AreEqual(false, p.IsOverride); + Assert.AreEqual(true, p.IsPublic); + Assert.AreEqual(true, p.Getter.IsAbstract); + Assert.AreEqual(true, p.Getter.IsOverridable); + Assert.AreEqual(false, p.Getter.IsOverride); + Assert.AreEqual(true, p.Getter.IsPublic); + Assert.AreEqual(true, p.Setter.IsAbstract); + Assert.AreEqual(true, p.Setter.IsOverridable); + Assert.AreEqual(false, p.Setter.IsOverride); + Assert.AreEqual(true, p.Setter.IsPublic); + + type = GetTypeDefinition(typeof(IHasEvent)); + var e = type.Events.Single(); + Assert.AreEqual(true, e.IsAbstract); + Assert.AreEqual(true, e.IsOverridable); + Assert.AreEqual(false, e.IsOverride); + Assert.AreEqual(true, e.IsPublic); + Assert.AreEqual(true, e.AddAccessor.IsAbstract); + Assert.AreEqual(true, e.AddAccessor.IsOverridable); + Assert.AreEqual(false, e.AddAccessor.IsOverride); + Assert.AreEqual(true, e.AddAccessor.IsPublic); + Assert.AreEqual(true, e.RemoveAccessor.IsAbstract); + Assert.AreEqual(true, e.RemoveAccessor.IsOverridable); + Assert.AreEqual(false, e.RemoveAccessor.IsOverride); + Assert.AreEqual(true, e.RemoveAccessor.IsPublic); + + type = GetTypeDefinition(typeof(IDisposable)); + var m = type.Methods.Single(); + Assert.AreEqual(true, m.IsAbstract); + Assert.AreEqual(true, m.IsOverridable); + Assert.AreEqual(false, m.IsOverride); + Assert.AreEqual(true, m.IsPublic); + } [Test] public void InnerClassInGenericClass_TypeParameterOwner() From d46cbdbb064e9b024289847ef06dc9f318a94be5 Mon Sep 17 00:00:00 2001 From: erikkallen Date: Thu, 14 Jun 2012 20:53:38 +0200 Subject: [PATCH 11/16] Don't report a member as implementing an interface member if there is another explicit implementation of that interface member. --- .../TypeSystem/Implementation/AbstractResolvedMember.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs index bae1d5b9db..d027f0b21d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedMember.cs @@ -80,9 +80,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return EmptyList.Instance; } else { // TODO: implement interface member mappings correctly - return InheritanceHelper.GetBaseMembers(this, true) + var result = InheritanceHelper.GetBaseMembers(this, true) .Where(m => m.DeclaringTypeDefinition != null && m.DeclaringTypeDefinition.Kind == TypeKind.Interface) .ToArray(); + + result = result.Where(item => !DeclaringTypeDefinition.Members.Any(m => m.IsExplicitInterfaceImplementation && m.ImplementedInterfaceMembers.Contains(item))).ToArray(); + + return result; } } From 806869e5632b0891c92d0fa93717c689ec5887bb Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 15 Jun 2012 23:41:14 +0200 Subject: [PATCH 12/16] Add IType.GetAccessors(). Accessors now use EntityType.Accessor instead of EntityType.Method. Added accessors support to DefaultMemberReference and ExplicitInterfaceImplementationMemberReference. Removed hacky code from CecilLoader - we now allow IsExplicitInterfaceImplementation=true on accessors. --- .../TypeSystem/TypeSystemConvertVisitor.cs | 15 ++- .../TypeSystemTests.cs | 23 ++++- .../TypeSystem/TypeSystemTests.cs | 34 ++++++- .../ICSharpCode.NRefactory.csproj | 1 + .../TypeSystem/AnonymousType.cs | 14 +++ .../TypeSystem/ArrayType.cs | 48 +++++---- .../TypeSystem/CecilLoader.cs | 98 ++++++------------- .../TypeSystem/EntityType.cs | 3 +- ICSharpCode.NRefactory/TypeSystem/IType.cs | 15 ++- .../AbstractResolvedTypeParameter.cs | 8 ++ .../TypeSystem/Implementation/AbstractType.cs | 5 + .../AccessorOwnerMemberReference.cs | 51 ++++++++++ .../Implementation/DefaultMemberReference.cs | 12 +-- .../DefaultResolvedTypeDefinition.cs | 32 ++++++ ...tInterfaceImplementationMemberReference.cs | 14 ++- .../Implementation/GetMembersHelper.cs | 28 +++++- .../TypeSystem/InheritanceHelper.cs | 54 ++-------- .../TypeSystem/IntersectionType.cs | 5 + .../TypeSystem/ParameterizedType.cs | 8 ++ 19 files changed, 308 insertions(+), 160 deletions(-) create mode 100644 ICSharpCode.NRefactory/TypeSystem/Implementation/AccessorOwnerMemberReference.cs diff --git a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs index 793f99faf9..bd47e64d1b 100644 --- a/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/TypeSystem/TypeSystemConvertVisitor.cs @@ -655,8 +655,6 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem AddXmlDocumentation(p, indexerDeclaration); ConvertParameters(p.Parameters, indexerDeclaration.Parameters); - p.Getter = ConvertAccessor(indexerDeclaration.Getter, p, "get_"); - p.Setter = ConvertAccessor(indexerDeclaration.Setter, p, "set_"); if (!indexerDeclaration.PrivateImplementationType.IsNull) { p.Accessibility = Accessibility.None; @@ -664,6 +662,8 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem p.ExplicitInterfaceImplementations.Add(new DefaultMemberReference( p.EntityType, indexerDeclaration.PrivateImplementationType.ToTypeReference(), p.Name, 0, GetParameterTypes(p.Parameters))); } + p.Getter = ConvertAccessor(indexerDeclaration.Getter, p, "get_"); + p.Setter = ConvertAccessor(indexerDeclaration.Setter, p, "set_"); currentTypeDefinition.Members.Add(p); if (interningProvider != null) { @@ -677,6 +677,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem if (accessor.IsNull) return null; var a = new DefaultUnresolvedMethod(currentTypeDefinition, prefix + p.Name); + a.EntityType = EntityType.Accessor; a.AccessorOwner = p; a.Accessibility = GetAccessibility(accessor.Modifiers) ?? p.Accessibility; a.IsAbstract = p.IsAbstract; @@ -708,6 +709,15 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem ConvertAttributes(a.Attributes, section); } } + if (p.IsExplicitInterfaceImplementation) { + a.IsExplicitInterfaceImplementation = true; + Debug.Assert(p.ExplicitInterfaceImplementations.Count == 1); + a.ExplicitInterfaceImplementations.Add(new DefaultMemberReference( + EntityType.Accessor, + p.ExplicitInterfaceImplementations[0].DeclaringTypeReference, + a.Name, 0, GetParameterTypes(a.Parameters) + )); + } return a; } #endregion @@ -756,6 +766,7 @@ namespace ICSharpCode.NRefactory.CSharp.TypeSystem DefaultUnresolvedMethod CreateDefaultEventAccessor(IUnresolvedEvent ev, string name, IUnresolvedParameter valueParameter) { var a = new DefaultUnresolvedMethod(currentTypeDefinition, name); + a.EntityType = EntityType.Accessor; a.AccessorOwner = ev; a.Region = ev.BodyRegion; a.BodyRegion = ev.BodyRegion; diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/TypeSystemTests.cs b/ICSharpCode.NRefactory.ConsistencyCheck/TypeSystemTests.cs index 381a4c7a51..e75d9d50ba 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.ConsistencyCheck/TypeSystemTests.cs @@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck if (!typeDef.Equals(part.Resolve(assemblyContext))) throw new InvalidOperationException(); } - foreach (var member in typeDef.Members) { + foreach (var member in IncludeAccessors(typeDef.Members)) { var resolvedMember = member.UnresolvedMember.Resolve(assemblyContext); if (!member.Equals(resolvedMember)) throw new InvalidOperationException(); @@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck else context = compilation.TypeResolveContext; // Include (potentially specialized) inherited members when testing ToMemberReference() - foreach (var member in typeDef.GetMembers()) { + foreach (var member in IncludeAccessors(typeDef.GetMembers())) { var resolvedMember = member.ToMemberReference().Resolve(context); if (!member.Equals(resolvedMember)) throw new InvalidOperationException(); @@ -83,5 +83,24 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck } } } + + static IEnumerable IncludeAccessors(IEnumerable members) + { + foreach (var member in members) { + yield return member; + IProperty p = member as IProperty; + if (p != null && p.CanGet) + yield return p.Getter; + if (p != null && p.CanSet) + yield return p.Setter; + IEvent e = member as IEvent; + if (e != null && e.CanAdd) + yield return e.AddAccessor; + if (e != null && e.CanRemove) + yield return e.RemoveAccessor; + if (e != null && e.CanInvoke) + yield return e.InvokeAccessor; + } + } } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index 59a3bc6b93..08ce99a935 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -241,7 +241,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } [Test] - public void Specialized_GetIndex_ToTypeReference() + public void Specialized_GetIndex_ToMemberReference() { var method = compilation.FindType(typeof(GenericClass)).GetMethods(m => m.Name == "GetIndex").Single(); Assert.AreSame(method.TypeParameters[0], method.Parameters[0].Type); @@ -347,6 +347,7 @@ namespace ICSharpCode.NRefactory.TypeSystem var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.IsIndexer); Assert.IsTrue(p.CanGet); + Assert.AreEqual(EntityType.Accessor, p.Getter.EntityType); Assert.AreEqual("get_Item", p.Getter.Name); Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); Assert.AreEqual(new[] { "index" }, p.Getter.Parameters.Select(x => x.Name).ToArray()); @@ -360,6 +361,7 @@ namespace ICSharpCode.NRefactory.TypeSystem var testClass = GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.IsIndexer); Assert.IsTrue(p.CanSet); + Assert.AreEqual(EntityType.Accessor, p.Setter.EntityType); Assert.AreEqual("set_Item", p.Setter.Name); Assert.AreEqual(Accessibility.Public, p.Setter.Accessibility); Assert.AreEqual(new[] { "index", "value" }, p.Setter.Parameters.Select(x => x.Name).ToArray()); @@ -934,6 +936,15 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.That(prop.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.set_Prop" })); } + [Test] + public void PropertyAccessorsShouldSupportToMemberReference() + { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsProperty)); + var prop = type.Properties.Single(p => p.Name == "Prop"); + var mr = prop.Getter.ToMemberReference(); + Assert.AreEqual(prop.Getter, mr.Resolve(compilation.TypeResolveContext)); + } + [Test] public void IndexerAccessorsShouldBeReportedAsImplementingTheCorrectInterfaceAccessors() { ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsIndexers)); @@ -972,6 +983,15 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.That(type.Properties.All(p => p.Setter.ImplementedInterfaceMembers.Count == 1)); } + [Test] + public void ExplicitlyImplementedPropertyAccessorsShouldSupportToMemberReference() + { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsPropertyExplicitly)); + var prop = type.Properties.Single(); + var mr = prop.Getter.ToMemberReference(); + Assert.AreEqual(prop.Getter, mr.Resolve(compilation.TypeResolveContext)); + } + [Test] public void ExplicitDisposableImplementation() { @@ -1037,6 +1057,15 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.That(prop.Getter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.get_Prop" })); Assert.That(prop.Setter.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IInterfaceWithProperty.set_Prop" })); } + + [Test] + public void ExplicitlyImplementedPropertiesShouldHaveExplicitlyImplementedAccessors() { + ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsPropertyExplicitly)); + var prop = type.Properties.Single(); + Assert.IsTrue(prop.IsExplicitInterfaceImplementation); + Assert.IsTrue(prop.Getter.IsExplicitInterfaceImplementation); + Assert.IsTrue(prop.Setter.IsExplicitInterfaceImplementation); + } [Test] public void EventAccessorsShouldBeReportedAsImplementingInterfaceAccessors() { @@ -1057,7 +1086,8 @@ namespace ICSharpCode.NRefactory.TypeSystem } [Test] - public void ExplicitlyImplementedEventsShouldBeReportedAsBeingImplemented() { + public void ExplicitlyImplementedEventsShouldBeReportedAsBeingImplemented() + { ITypeDefinition type = GetTypeDefinition(typeof(ClassThatImplementsEventExplicitly)); var evt = type.Events.Single(); Assert.That(evt.ImplementedInterfaceMembers.Select(p => p.ReflectionName).ToList(), Is.EqualTo(new[] { "ICSharpCode.NRefactory.TypeSystem.TestCase.IHasEvent.Event" })); diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 9c0a97ad81..7189df55a6 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -136,6 +136,7 @@ + diff --git a/ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs b/ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs index 26bd7a85e8..5060e1a72d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/AnonymousType.cs @@ -116,6 +116,20 @@ namespace ICSharpCode.NRefactory.TypeSystem } } + public override IEnumerable GetAccessors(Predicate filter, GetMemberOptions options) + { + for (int i = 0; i < unresolvedProperties.Length; i++) { + if (unresolvedProperties[i].CanGet) { + if (filter == null || filter(unresolvedProperties[i].Getter)) + yield return resolvedProperties[i].Getter; + } + if (unresolvedProperties[i].CanSet) { + if (filter == null || filter(unresolvedProperties[i].Setter)) + yield return resolvedProperties[i].Setter; + } + } + } + public override int GetHashCode() { unchecked { diff --git a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs index 5585be9f96..18ade936cf 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs @@ -96,36 +96,34 @@ namespace ICSharpCode.NRefactory.TypeSystem public override IEnumerable GetMethods(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - return compilation.FindType(KnownTypeCode.Array).GetMethods(filter, options); + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return compilation.FindType(KnownTypeCode.Array).GetMethods(filter, options); + } + + public override IEnumerable GetMethods(IList typeArguments, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return compilation.FindType(KnownTypeCode.Array).GetMethods(typeArguments, filter, options); } - //static readonly DefaultUnresolvedParameter indexerParam = new DefaultUnresolvedParameter(KnownTypeReference.Int32, string.Empty); + public override IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return compilation.FindType(KnownTypeCode.Array).GetAccessors(filter, options); + } public override IEnumerable GetProperties(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - ITypeDefinition arrayDef = compilation.FindType(KnownTypeCode.Array) as ITypeDefinition; - if (arrayDef != null) { - if ((options & GetMemberOptions.IgnoreInheritedMembers) == 0) { - foreach (IProperty p in arrayDef.GetProperties(filter, options)) { - yield return p; - } - } - /*DefaultUnresolvedProperty indexer = new DefaultUnresolvedProperty(arrayDef, "Items") { - EntityType = EntityType.Indexer, - ReturnType = elementType, - Accessibility = Accessibility.Public, - Getter = DefaultAccessor.GetFromAccessibility(Accessibility.Public), - Setter = DefaultAccessor.GetFromAccessibility(Accessibility.Public), - IsSynthetic = true - }; - for (int i = 0; i < dimensions; i++) { - indexer.Parameters.Add(indexerParam); - } - indexer.Freeze(); - if (filter == null || filter(indexer)) { - yield return indexer.CreateResolved(context); - }*/ - } + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return compilation.FindType(KnownTypeCode.Array).GetProperties(filter, options); } // NestedTypes, Events, Fields: System.Array doesn't have any; so we can use the AbstractType default implementation diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index e0e6eb4737..681812177e 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -89,15 +89,6 @@ namespace ICSharpCode.NRefactory.TypeSystem this.InterningProvider = new SimpleInterningProvider(); } - void ReadExplicitInterfaceImplementation(DefaultUnresolvedMethod m, MethodDefinition method) { - if (method.Name.Contains(".") && method.HasOverrides) { - m.IsExplicitInterfaceImplementation = true; - foreach (var or in method.Overrides) { - m.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(EntityType.Method, ReadTypeReference(or.DeclaringType), or.Name, or.GenericParameters.Count, m.Parameters.Select(p => p.Type).ToList(), false)); - } - } - } - #region Load From AssemblyDefinition /// /// Loads the assembly definition into a project content. @@ -1656,10 +1647,10 @@ namespace ICSharpCode.NRefactory.TypeSystem [CLSCompliant(false)] public IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, EntityType methodType = EntityType.Method) { - return ReadMethod(method, parentType, null, methodType); + return ReadMethod(method, parentType, methodType, null); } - IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, IUnresolvedMember accessorOwner, EntityType methodType = EntityType.Method, bool readExplicitInterfaceImplementation = true) + IUnresolvedMethod ReadMethod(MethodDefinition method, IUnresolvedTypeDefinition parentType, EntityType methodType, IUnresolvedMember accessorOwner) { if (method == null) return null; @@ -1695,9 +1686,19 @@ namespace ICSharpCode.NRefactory.TypeSystem m.IsExtensionMethod = true; } - if (readExplicitInterfaceImplementation) - ReadExplicitInterfaceImplementation(m, method); - + int lastDot = method.Name.LastIndexOf('.'); + if (lastDot >= 0 && method.HasOverrides) { + // To be consistent with the parser-initialized type system, shorten the method name: + m.Name = method.Name.Substring(lastDot + 1); + m.IsExplicitInterfaceImplementation = true; + foreach (var or in method.Overrides) { + m.ExplicitInterfaceImplementations.Add(new DefaultMemberReference( + accessorOwner != null ? EntityType.Accessor : EntityType.Method, + ReadTypeReference(or.DeclaringType), + or.Name, or.GenericParameters.Count, m.Parameters.Select(p => p.Type).ToList())); + } + } + FinishReadMember(m, method); return m; } @@ -1895,8 +1896,8 @@ namespace ICSharpCode.NRefactory.TypeSystem TranslateModifiers(property.GetMethod ?? property.SetMethod, p); p.ReturnType = ReadTypeReference(property.PropertyType, typeAttributes: property); - p.Getter = ReadMethod(property.GetMethod, parentType, p); - p.Setter = ReadMethod(property.SetMethod, parentType, p); + p.Getter = ReadMethod(property.GetMethod, parentType, EntityType.Accessor, p); + p.Setter = ReadMethod(property.SetMethod, parentType, EntityType.Accessor, p); if (property.HasParameters) { foreach (ParameterDefinition par in property.Parameters) { @@ -1905,31 +1906,15 @@ namespace ICSharpCode.NRefactory.TypeSystem } AddAttributes(property, p); - int lastDot = property.Name.LastIndexOf('.'); - if (lastDot >= 0) { - string name = property.Name.Substring(lastDot + 1); - if (p.Getter != null && p.Getter.IsExplicitInterfaceImplementation) { - p.IsExplicitInterfaceImplementation = true; - foreach (var x in p.Getter.ExplicitInterfaceImplementations) { - p.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList())); - } - } - else if (p.Setter != null && p.Setter.IsExplicitInterfaceImplementation) { - p.IsExplicitInterfaceImplementation = true; - foreach (var x in p.Setter.ExplicitInterfaceImplementations) { - p.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(p.Parameters.Count == 0 ? EntityType.Property : EntityType.Indexer, x.DeclaringTypeReference, name, 0, p.Parameters.Select(y => y.Type).ToList())); - } + var accessor = p.Getter ?? p.Setter; + if (accessor != null && accessor.IsExplicitInterfaceImplementation) { + p.Name = property.Name.Substring(property.Name.LastIndexOf('.') + 1); + p.IsExplicitInterfaceImplementation = true; + foreach (var mr in accessor.ExplicitInterfaceImplementations) { + p.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr)); } } - // This is very hacky. Due to which code parts are taken later in the execution, we need to pretend that the accessors are not explicit interface implementations at this stage. - if (p.Getter != null && p.Getter.IsExplicitInterfaceImplementation) { - p.Getter = ReadMethod(property.GetMethod, parentType, p, readExplicitInterfaceImplementation: false); - } - if (p.Setter != null && p.Setter.IsExplicitInterfaceImplementation) { - p.Setter = ReadMethod(property.GetMethod, parentType, p, readExplicitInterfaceImplementation: false); - } - FinishReadMember(p, property); return p; } @@ -1948,38 +1933,19 @@ namespace ICSharpCode.NRefactory.TypeSystem TranslateModifiers(ev.AddMethod, e); e.ReturnType = ReadTypeReference(ev.EventType, typeAttributes: ev); - e.AddAccessor = ReadMethod(ev.AddMethod, parentType, e); - e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType, e); - e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType, e); + e.AddAccessor = ReadMethod(ev.AddMethod, parentType, EntityType.Accessor, e); + e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType, EntityType.Accessor, e); + e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType, EntityType.Accessor, e); AddAttributes(ev, e); - int lastDot = ev.Name.LastIndexOf('.'); - if (lastDot >= 0) { - string name = ev.Name.Substring(lastDot + 1); - if (e.AddAccessor != null && e.AddAccessor.IsExplicitInterfaceImplementation) { - e.IsExplicitInterfaceImplementation = true; - foreach (var x in e.AddAccessor.ExplicitInterfaceImplementations) { - e.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(EntityType.Event, x.DeclaringTypeReference, name)); - } + var accessor = e.AddAccessor ?? e.RemoveAccessor ?? e.InvokeAccessor; + if (accessor != null && accessor.IsExplicitInterfaceImplementation) { + e.Name = ev.Name.Substring(ev.Name.LastIndexOf('.') + 1); + e.IsExplicitInterfaceImplementation = true; + foreach (var mr in accessor.ExplicitInterfaceImplementations) { + e.ExplicitInterfaceImplementations.Add(new AccessorOwnerMemberReference(mr)); } - else if (e.RemoveAccessor != null && e.RemoveAccessor.IsExplicitInterfaceImplementation) { - e.IsExplicitInterfaceImplementation = true; - foreach (var x in e.RemoveAccessor.ExplicitInterfaceImplementations) { - e.ExplicitInterfaceImplementations.Add(new DefaultMemberReference(EntityType.Event, x.DeclaringTypeReference, name)); - } - } - } - - // This is very hacky. Due to which code parts are taken later in the execution, we need to pretend that the accessors are not explicit interface implementations at this stage. - if (e.AddAccessor != null && e.AddAccessor.IsExplicitInterfaceImplementation) { - e.AddAccessor = ReadMethod(ev.AddMethod, parentType, e, readExplicitInterfaceImplementation: false); - } - if (e.RemoveAccessor != null && e.RemoveAccessor.IsExplicitInterfaceImplementation) { - e.RemoveAccessor = ReadMethod(ev.RemoveMethod, parentType, e, readExplicitInterfaceImplementation: false); - } - if (e.InvokeAccessor != null && e.InvokeAccessor.IsExplicitInterfaceImplementation) { - e.InvokeAccessor = ReadMethod(ev.InvokeMethod, parentType, e, readExplicitInterfaceImplementation: false); } FinishReadMember(e, ev); diff --git a/ICSharpCode.NRefactory/TypeSystem/EntityType.cs b/ICSharpCode.NRefactory/TypeSystem/EntityType.cs index efc74910e3..8c88411633 100644 --- a/ICSharpCode.NRefactory/TypeSystem/EntityType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/EntityType.cs @@ -31,6 +31,7 @@ namespace ICSharpCode.NRefactory.TypeSystem Method, Operator, Constructor, - Destructor + Destructor, + Accessor } } diff --git a/ICSharpCode.NRefactory/TypeSystem/IType.cs b/ICSharpCode.NRefactory/TypeSystem/IType.cs index 2dd1981a11..a6a4892f4c 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IType.cs @@ -194,7 +194,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Specified additional options for the GetMembers() operation. /// /// - /// The result does not include constructors. + /// The result does not include constructors or accessors. /// /// /// For methods on parameterized types, type substitution will be performed on the method signature, @@ -221,7 +221,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// The filter is tested on the original method definitions (before specialization). /// Specified additional options for the GetMembers() operation. /// - /// The result does not include constructors. + /// The result does not include constructors or accessors. /// /// Type substitution will be performed on the method signature, creating a /// with the specified type arguments. @@ -288,6 +288,17 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + + /// + /// Gets all accessors belonging to properties or events on this type. + /// + /// The filter used to select which members to return. + /// The filter is tested on the original member definitions (before specialization). + /// Specified additional options for the GetMembers() operation. + /// + /// Accessors are not returned by GetMembers() or GetMethods(). + /// + IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); } [Flags] diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs index 7dd6af61de..448a0bfd85 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractResolvedTypeParameter.cs @@ -294,6 +294,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return GetMembersHelper.GetMembers(this, FilterNonStatic(filter), options); } + public IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetAccessors(this, FilterNonStatic(filter), options); + } + static Predicate FilterNonStatic(Predicate filter) where T : class, IUnresolvedMember { if (filter == null) diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs index 226dadc9c5..48aac56559 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs @@ -123,6 +123,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation .Concat(GetEvents(filter, options)); } + public virtual IEnumerable GetAccessors(Predicate filter, GetMemberOptions options = GetMemberOptions.None) + { + return EmptyList.Instance; + } + public override sealed bool Equals(object obj) { return Equals(obj as IType); diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AccessorOwnerMemberReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AccessorOwnerMemberReference.cs new file mode 100644 index 0000000000..4d322a61e5 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AccessorOwnerMemberReference.cs @@ -0,0 +1,51 @@ +// 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 +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Given a reference to an accessor, returns the accessor's owner. + /// + [Serializable] + sealed class AccessorOwnerMemberReference : IMemberReference + { + readonly IMemberReference accessorReference; + + public AccessorOwnerMemberReference(IMemberReference accessorReference) + { + if (accessorReference == null) + throw new ArgumentNullException("accessorReference"); + this.accessorReference = accessorReference; + } + + public ITypeReference DeclaringTypeReference { + get { return accessorReference.DeclaringTypeReference; } + } + + public IMember Resolve(ITypeResolveContext context) + { + IMethod method = accessorReference.Resolve(context) as IMethod; + if (method != null) + return method.AccessorOwner; + else + return null; + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs index ed67e6eba4..5c630f9c09 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMemberReference.cs @@ -38,9 +38,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation string name; int typeParameterCount; IList parameterTypes; - bool isExplicitInterfaceImplementation; - public DefaultMemberReference(EntityType entityType, ITypeReference typeReference, string name, int typeParameterCount = 0, IList parameterTypes = null, bool isExplicitInterfaceImplementation = false) + public DefaultMemberReference(EntityType entityType, ITypeReference typeReference, string name, int typeParameterCount = 0, IList parameterTypes = null) { if (typeReference == null) throw new ArgumentNullException("typeReference"); @@ -53,7 +52,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.name = name; this.typeParameterCount = typeParameterCount; this.parameterTypes = parameterTypes ?? EmptyList.Instance; - this.isExplicitInterfaceImplementation = isExplicitInterfaceImplementation; } public ITypeReference DeclaringTypeReference { @@ -64,14 +62,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { IType type = typeReference.Resolve(context); IEnumerable members; - if (entityType == EntityType.Method) { + if (entityType == EntityType.Accessor) { + members = type.GetAccessors(m => m.Name == name && !m.IsExplicitInterfaceImplementation); + } else if (entityType == EntityType.Method) { members = type.GetMethods( m => m.Name == name && m.EntityType == EntityType.Method - && m.TypeParameters.Count == typeParameterCount && m.IsExplicitInterfaceImplementation == isExplicitInterfaceImplementation, + && m.TypeParameters.Count == typeParameterCount && !m.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers); } else { members = type.GetMembers( - m => m.Name == name && m.EntityType == entityType && m.IsExplicitInterfaceImplementation == isExplicitInterfaceImplementation, + m => m.Name == name && m.EntityType == entityType && !m.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers); } var resolvedParameterTypes = parameterTypes.Resolve(context); diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs index 068a5f7822..c0b1867726 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs @@ -830,6 +830,38 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return GetMembersHelper.GetMembers(this, filter, options); } } + + public virtual IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + return GetFilteredAccessors(filter); + } else { + return GetMembersHelper.GetAccessors(this, filter, options); + } + } + + IEnumerable GetFilteredAccessors(Predicate filter) + { + var members = GetMemberList(); + for (int i = 0; i < members.unresolvedMembers.Length; i++) { + IUnresolvedMember unresolved = members.unresolvedMembers[i]; + var unresolvedProperty = unresolved as IUnresolvedProperty; + var unresolvedEvent = unresolved as IUnresolvedEvent; + if (unresolvedProperty != null) { + if (unresolvedProperty.CanGet && (filter == null || filter(unresolvedProperty.Getter))) + yield return ((IProperty)members[i]).Getter; + if (unresolvedProperty.CanSet && (filter == null || filter(unresolvedProperty.Setter))) + yield return ((IProperty)members[i]).Setter; + } else if (unresolvedEvent != null) { + if (unresolvedEvent.CanAdd && (filter == null || filter(unresolvedEvent.AddAccessor))) + yield return ((IEvent)members[i]).AddAccessor; + if (unresolvedEvent.CanRemove && (filter == null || filter(unresolvedEvent.RemoveAccessor))) + yield return ((IEvent)members[i]).RemoveAccessor; + if (unresolvedEvent.CanInvoke && (filter == null || filter(unresolvedEvent.InvokeAccessor))) + yield return ((IEvent)members[i]).InvokeAccessor; + } + } + } #endregion public bool Equals(IType other) diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/ExplicitInterfaceImplementationMemberReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/ExplicitInterfaceImplementationMemberReference.cs index 89377284b5..a52cfbe788 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/ExplicitInterfaceImplementationMemberReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/ExplicitInterfaceImplementationMemberReference.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections.Generic; using System.Linq; namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -58,9 +59,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation IMember interfaceMember = interfaceMemberReference.Resolve(context.WithCurrentTypeDefinition(declaringType.GetDefinition())); if (interfaceMember == null) return null; - var members = declaringType.GetMembers( - m => m.EntityType == interfaceMember.EntityType && m.IsExplicitInterfaceImplementation, - GetMemberOptions.IgnoreInheritedMembers); + IEnumerable members; + if (interfaceMember.EntityType == EntityType.Accessor) { + members = declaringType.GetAccessors( + m => m.IsExplicitInterfaceImplementation, + GetMemberOptions.IgnoreInheritedMembers); + } else { + members = declaringType.GetMembers( + m => m.EntityType == interfaceMember.EntityType && m.IsExplicitInterfaceImplementation, + GetMemberOptions.IgnoreInheritedMembers); + } return members.FirstOrDefault(m => m.ImplementedInterfaceMembers.Count == 1 && interfaceMember.Equals(m.ImplementedInterfaceMembers[0])); } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs index 18d072b53b..dd75217c05 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs @@ -142,6 +142,22 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } #endregion + #region GetAccessors + public static IEnumerable GetAccessors(IType type, Predicate filter, GetMemberOptions options) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + return GetAccessorsImpl(type, filter, options); + } else { + return type.GetNonInterfaceBaseTypes().SelectMany(t => GetAccessorsImpl(t, filter, options)); + } + } + + static IEnumerable GetAccessorsImpl(IType baseType, Predicate filter, GetMemberOptions options) + { + return GetConstructorsOrAccessorsImpl(baseType, baseType.GetAccessors(filter, options | declaredMembers), filter, options); + } + #endregion + #region GetConstructors public static IEnumerable GetConstructors(IType type, Predicate filter, GetMemberOptions options) { @@ -154,17 +170,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation static IEnumerable GetConstructorsImpl(IType baseType, Predicate filter, GetMemberOptions options) { - IEnumerable declaredCtors = baseType.GetConstructors(filter, options | declaredMembers); + return GetConstructorsOrAccessorsImpl(baseType, baseType.GetConstructors(filter, options | declaredMembers), filter, options); + } + + static IEnumerable GetConstructorsOrAccessorsImpl(IType baseType, IEnumerable declaredMembers, Predicate filter, GetMemberOptions options) + { if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { - return declaredCtors; + return declaredMembers; } ParameterizedType pt = baseType as ParameterizedType; if (pt != null) { var substitution = pt.GetSubstitution(); - return declaredCtors.Select(m => new SpecializedMethod(m, substitution) { DeclaringType = pt }); + return declaredMembers.Select(m => new SpecializedMethod(m, substitution) { DeclaringType = pt }); } else { - return declaredCtors; + return declaredMembers; } } #endregion diff --git a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs index 7eac11a93f..1c9a05ca27 100644 --- a/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/InheritanceHelper.cs @@ -40,46 +40,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return GetBaseMembers(member, false).FirstOrDefault(); } - private static IEnumerable GetBaseAccessors(IMethod accessor, bool includeImplementedInterfaces) { - IMember accessorOwner = accessor.AccessorOwner; - SpecializedMember specializedMember = accessor as SpecializedMember; - - foreach (IMember baseOwner in GetBaseMembers(accessorOwner, includeImplementedInterfaces)) { - if (accessorOwner is IProperty && baseOwner is IProperty) { - var accessorProperty = (IProperty)accessorOwner; - var baseProperty = (IProperty)baseOwner; - if (accessor == accessorProperty.Getter && baseProperty.CanGet) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseProperty.Getter, specializedMember.Substitution); - else - yield return baseProperty.Getter; - } - if (accessor == accessorProperty.Setter && baseProperty.CanSet) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseProperty.Setter, specializedMember.Substitution); - else - yield return baseProperty.Setter; - } - } - else if (accessorOwner is IEvent && baseOwner is IEvent) { - var accessorEvent = (IEvent)accessorOwner; - var baseEvent = (IEvent)baseOwner; - if (accessor == accessorEvent.AddAccessor && baseEvent.CanAdd) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseEvent.AddAccessor, specializedMember.Substitution); - else - yield return baseEvent.AddAccessor; - } - if (accessor == accessorEvent.RemoveAccessor && baseEvent.CanRemove) { - if (specializedMember != null) - yield return SpecializedMember.Create(baseEvent.RemoveAccessor, specializedMember.Substitution); - else - yield return baseEvent.RemoveAccessor; - } - } - } - } - /// /// Gets all base members that have the same signature. /// @@ -99,12 +59,6 @@ namespace ICSharpCode.NRefactory.TypeSystem SpecializedMember specializedMember = member as SpecializedMember; member = member.MemberDefinition; - - if (member is IMethod && ((IMethod)member).IsAccessor) { - foreach (IMember m in GetBaseAccessors((IMethod)member, includeImplementedInterfaces)) - yield return m; - yield break; - } IEnumerable allBaseTypes; if (includeImplementedInterfaces) { @@ -116,7 +70,13 @@ namespace ICSharpCode.NRefactory.TypeSystem if (baseType == member.DeclaringTypeDefinition) continue; - foreach (IMember baseMember in baseType.GetMembers(m => m.Name == member.Name, GetMemberOptions.IgnoreInheritedMembers)) { + IEnumerable baseMembers; + if (member.EntityType == EntityType.Accessor) { + baseMembers = baseType.GetAccessors(m => m.Name == member.Name && !m.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers); + } else { + baseMembers = baseType.GetMembers(m => m.Name == member.Name && !m.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers); + } + foreach (IMember baseMember in baseMembers) { if (SignatureComparer.Ordinal.Equals(member, baseMember)) { if (specializedMember != null) yield return SpecializedMember.Create(baseMember, specializedMember.Substitution); diff --git a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs index c5c8205a1c..19c7f665b7 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs @@ -162,6 +162,11 @@ namespace ICSharpCode.NRefactory.TypeSystem return GetMembersHelper.GetMembers(this, FilterNonStatic(filter), options); } + public override IEnumerable GetAccessors(Predicate filter, GetMemberOptions options) + { + return GetMembersHelper.GetAccessors(this, FilterNonStatic(filter), options); + } + static Predicate FilterNonStatic(Predicate filter) where T : class, IUnresolvedMember { if (filter == null) diff --git a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs index c5b55d4dff..ad84d1218a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs @@ -259,6 +259,14 @@ namespace ICSharpCode.NRefactory.TypeSystem return GetMembersHelper.GetMembers(this, filter, options); } + public IEnumerable GetAccessors(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetAccessors(filter, options); + else + return GetMembersHelper.GetAccessors(this, filter, options); + } + public override bool Equals(object obj) { return Equals(obj as IType); From 4c875208f4911bc50fcfc64cd088ac399d7ab39b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 18 Jun 2012 06:39:08 +0200 Subject: [PATCH 13/16] [CodeAction] Create field now works on member reference expressions with 'this.' target. --- .../CodeActions/CreateFieldAction.cs | 24 +++++++++++------ .../CodeActions/CreatePropertyAction.cs | 4 +-- .../CSharp/CodeActions/CreateFieldTests.cs | 27 +++++++++++++++++++ 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateFieldAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateFieldAction.cs index 6af959b4cf..e93a827d91 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateFieldAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreateFieldAction.cs @@ -46,20 +46,28 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring public IEnumerable GetActions(RefactoringContext context) { - var identifier = context.GetNode(); - if (identifier == null) + var expr = context.GetNode(n => n is IdentifierExpression || n is MemberReferenceExpression) as Expression; + if (expr == null) yield break; - if (IsInvocationTarget(identifier)) + + if (expr is MemberReferenceExpression && !(((MemberReferenceExpression)expr).Target is ThisReferenceExpression)) + yield break; + + var propertyName = CreatePropertyAction.GetPropertyName(expr); + if (propertyName == null) + yield break; + + if (IsInvocationTarget(expr)) yield break; - var statement = identifier.GetParent(); + var statement = expr.GetParent(); if (statement == null) yield break; - if (!(context.Resolve(identifier).IsError)) + if (!(context.Resolve(expr).IsError)) yield break; - var guessedType = CreateFieldAction.GuessAstType(context, identifier); + var guessedType = CreateFieldAction.GuessAstType(context, expr); if (guessedType == null) yield break; - var state = context.GetResolverStateBefore(identifier); + var state = context.GetResolverStateBefore(expr); if (state.CurrentMember == null || state.CurrentTypeDefinition == null) yield break; @@ -73,7 +81,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring yield return new CodeAction(context.TranslateString("Create field"), script => { var decl = new FieldDeclaration() { ReturnType = guessedType, - Variables = { new VariableInitializer(identifier.Identifier) } + Variables = { new VariableInitializer(propertyName) } }; if (isStatic) decl.Modifiers |= Modifiers.Static; diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreatePropertyAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreatePropertyAction.cs index f86a6cee10..c9c750cad0 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreatePropertyAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeActions/CreatePropertyAction.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring isStatic |= state.CurrentMember.IsStatic || state.CurrentTypeDefinition.IsStatic; } -// var service = (NamingConventionService)context.GetService(typeof(NamingConventionService)); + // var service = (NamingConventionService)context.GetService(typeof(NamingConventionService)); // if (service != null && !service.IsValidName(propertyName, AffectedEntity.Property, Modifiers.Private, isStatic)) { // yield break; // } @@ -112,7 +112,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring }); } - static string GetPropertyName(Expression expr) + internal static string GetPropertyName(Expression expr) { if (expr is IdentifierExpression) return ((IdentifierExpression)expr).Identifier; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateFieldTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateFieldTests.cs index 7c48571ca0..f785374796 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateFieldTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeActions/CreateFieldTests.cs @@ -182,5 +182,32 @@ class Foo "); } + [Test()] + public void TestThisMemberReferenceCreation () + { + string result = RunContextAction ( + new CreateFieldAction (), + "using System;" + Environment.NewLine + + "class TestClass" + Environment.NewLine + + "{" + Environment.NewLine + + " void Test ()" + Environment.NewLine + + " {" + Environment.NewLine + + " this.$foo = 0x10;" + Environment.NewLine + + " }" + Environment.NewLine + + "}" + ); + + Assert.AreEqual ( + "using System;" + Environment.NewLine + + "class TestClass" + Environment.NewLine + + "{" + Environment.NewLine + + " int foo;" + Environment.NewLine + + " void Test ()" + Environment.NewLine + + " {" + Environment.NewLine + + " this.foo = 0x10;" + Environment.NewLine + + " }" + Environment.NewLine + + "}", result); + } + } } \ No newline at end of file From da2eea8353b31f4506f5cb5c8bbfebeae82687fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 18 Jun 2012 07:17:39 +0200 Subject: [PATCH 14/16] [CodeIssues] Improved naming check (skipp overriden members). --- .../Refactoring/CodeIssue.cs | 6 ++--- .../InconsistentNamingIssue.cs | 21 ++++++++++++++++ .../CodeIssues/InconsistentNamingTests.cs | 25 +++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssue.cs index df75077a6e..9394887a25 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssue.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssue.cs @@ -35,9 +35,9 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring public class CodeIssue { /// - /// Gets the desription of the issue. + /// Gets the description of the issue. /// - public string Desription { + public string Description { get; private set; } @@ -83,7 +83,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring /// public CodeIssue(string description, TextLocation start, TextLocation end, IEnumerable actions = null) { - Desription = description; + Description = description; Start = start; End = end; if (actions != null) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs index dc9d0d41b9..26d3e5a795 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs @@ -215,12 +215,31 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) { + if (propertyDeclaration.Modifiers.HasFlag (Modifiers.Override)) + return; base.VisitPropertyDeclaration(propertyDeclaration); CheckName(propertyDeclaration, AffectedEntity.Property, propertyDeclaration.NameToken, GetAccessibiltiy(propertyDeclaration, Modifiers.Private)); } public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { + if (methodDeclaration.Modifiers.HasFlag(Modifiers.Override)) { + var rr = ctx.Resolve (methodDeclaration) as MemberResolveResult; + if (rr == null) + return; + var baseType = rr.Member.DeclaringType.DirectBaseTypes.FirstOrDefault (t => t.Kind != TypeKind.Interface); + var method = baseType != null ? baseType.GetMethods (m => m.Name == rr.Member.Name && m.IsOverridable && m.Parameters.Count == methodDeclaration.Parameters.Count).FirstOrDefault () : null; + if (method == null) + return; + int i = 0; + foreach (var par in methodDeclaration.Parameters) { + if (method.Parameters[i++].Name != par.Name) { + par.AcceptVisitor (this); + } + } + + return; + } base.VisitMethodDeclaration(methodDeclaration); CheckName(methodDeclaration, methodDeclaration.Modifiers.HasFlag(Modifiers.Async) ? AffectedEntity.AsyncMethod : AffectedEntity.Method, methodDeclaration.NameToken, GetAccessibiltiy(methodDeclaration, Modifiers.Private)); @@ -262,6 +281,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring public override void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration) { + if (eventDeclaration.Modifiers.HasFlag (Modifiers.Override)) + return; base.VisitCustomEventDeclaration(eventDeclaration); CheckName(eventDeclaration, AffectedEntity.Event, eventDeclaration.NameToken, GetAccessibiltiy(eventDeclaration, Modifiers.Private)); } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/InconsistentNamingTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/InconsistentNamingTests.cs index f75e4bb35e..721b6e7adf 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/InconsistentNamingTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeIssues/InconsistentNamingTests.cs @@ -237,6 +237,31 @@ namespace ICSharpCode.NRefactory.CSharp.CodeIssues var output = @"struct Str { TK k;}"; CheckNaming (input, output); } + + + [Test] + public void TestOverrideMembers () + { + var input = @" +class Base { public virtual int method (int Param) {} } +class MyClass : Base { public override int method (int Param) {} }"; + TestRefactoringContext context; + var issues = GetIssues (new InconsistentNamingIssue (), input, out context); + Assert.AreEqual (2, issues.Count); + } + + [Test] + public void TestOverrideMembersParameterNameCaseMismatch () + { + var input = @" +class Base { public virtual int Method (int param) {} } +class MyClass : Base { public override int Method (int Param) {} }"; + TestRefactoringContext context; + var issues = GetIssues (new InconsistentNamingIssue (), input, out context); + foreach (var issue in issues) + Console.WriteLine(issue.Description); + Assert.AreEqual (1, issues.Count); + } } [TestFixture] From d355b0f84bafab94af7f3ec630d54dab1aedaebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 18 Jun 2012 07:19:02 +0200 Subject: [PATCH 15/16] [CodeIssues] Added indexer case. --- .../InconsistentNamingIssue.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs index 26d3e5a795..6e29445c04 100644 --- a/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/CodeIssues/InconsistentNamingIssue/InconsistentNamingIssue.cs @@ -221,6 +221,27 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring CheckName(propertyDeclaration, AffectedEntity.Property, propertyDeclaration.NameToken, GetAccessibiltiy(propertyDeclaration, Modifiers.Private)); } + public override void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration) + { + if (indexerDeclaration.Modifiers.HasFlag(Modifiers.Override)) { + var rr = ctx.Resolve (indexerDeclaration) as MemberResolveResult; + if (rr == null) + return; + var baseType = rr.Member.DeclaringType.DirectBaseTypes.FirstOrDefault (t => t.Kind != TypeKind.Interface); + var method = baseType != null ? baseType.GetProperties (m => m.IsIndexer && m.IsOverridable && m.Parameters.Count == indexerDeclaration.Parameters.Count).FirstOrDefault () : null; + if (method == null) + return; + int i = 0; + foreach (var par in indexerDeclaration.Parameters) { + if (method.Parameters[i++].Name != par.Name) { + par.AcceptVisitor (this); + } + } + return; + } + base.VisitIndexerDeclaration(indexerDeclaration); + } + public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { if (methodDeclaration.Modifiers.HasFlag(Modifiers.Override)) { From 3ded985188e4359b5a004f811c72454dfb4025e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 18 Jun 2012 09:32:12 +0200 Subject: [PATCH 16/16] [Formatting] Fixed overlapping changes issue. --- .../Formatter/AstFormattingVisitor.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs b/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs index ac58953794..f79e1f30b5 100644 --- a/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs @@ -173,10 +173,10 @@ namespace ICSharpCode.NRefactory.CSharp } if (change.Offset < previousChange.Offset + previousChange.RemovalLength) { #if DEBUG - Console.WriteLine ("change 1:" + change); + Console.WriteLine ("change 1:" + change + " at " + document.GetLocation (change.Offset)); Console.WriteLine (change.StackTrace); - Console.WriteLine ("change 2:" + change); + Console.WriteLine ("change 2:" + previousChange + " at " + document.GetLocation (previousChange.Offset)); Console.WriteLine (previousChange.StackTrace); #endif throw new InvalidOperationException ("Detected overlapping changes " + change + "/" + previousChange); @@ -1645,6 +1645,8 @@ namespace ICSharpCode.NRefactory.CSharp { if (!anonymousMethodExpression.Body.IsNull) { EnforceBraceStyle(policy.AnonymousMethodBraceStyle, anonymousMethodExpression.Body.LBraceToken, anonymousMethodExpression.Body.RBraceToken); + VisitBlockWithoutFixingBraces(anonymousMethodExpression.Body, policy.IndentBlocks); + return; } base.VisitAnonymousMethodExpression(anonymousMethodExpression); }