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);