1
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections.Generic;
22
using ICSharpCode.NRefactory.TypeSystem.Implementation;
24
namespace ICSharpCode.NRefactory.TypeSystem
27
/// Provides helper methods for inheritance.
29
public static class InheritanceHelper
31
// TODO: maybe these should be extension methods?
32
// or even part of the interface itself? (would allow for easy caching)
36
/// Gets the base member that has the same signature.
38
public static IMember GetBaseMember(IMember member)
40
return GetBaseMembers(member, false).FirstOrDefault();
44
/// Gets all base members that have the same signature.
47
/// List of base members with the same signature. The member from the derived-most base class is returned first.
49
public static IEnumerable<IMember> GetBaseMembers(IMember member, bool includeImplementedInterfaces)
52
throw new ArgumentNullException("member");
54
if (member.IsExplicitInterfaceImplementation && member.ImplementedInterfaceMembers.Count == 1) {
55
// C#-style explicit interface implementation
56
member = member.ImplementedInterfaceMembers[0];
60
// TODO: can we get rid of this upcast?
61
SpecializedMember specializedMember = member as SpecializedMember;
62
member = member.MemberDefinition;
64
IEnumerable<IType> allBaseTypes;
65
if (includeImplementedInterfaces) {
66
allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes();
68
allBaseTypes = member.DeclaringTypeDefinition.GetNonInterfaceBaseTypes();
70
foreach (IType baseType in allBaseTypes.Reverse()) {
71
if (baseType == member.DeclaringTypeDefinition)
74
IEnumerable<IMember> baseMembers;
75
if (member.EntityType == EntityType.Accessor) {
76
baseMembers = baseType.GetAccessors(m => m.Name == member.Name && !m.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers);
78
baseMembers = baseType.GetMembers(m => m.Name == member.Name && !m.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers);
80
foreach (IMember baseMember in baseMembers) {
81
if (SignatureComparer.Ordinal.Equals(member, baseMember)) {
82
if (specializedMember != null)
83
yield return baseMember.Specialize(specializedMember.Substitution);
85
yield return baseMember;
92
#region GetDerivedMember
94
/// Finds the member declared in 'derivedType' that has the same signature (could override) 'baseMember'.
96
public static IMember GetDerivedMember(IMember baseMember, ITypeDefinition derivedType)
98
if (baseMember == null)
99
throw new ArgumentNullException("baseMember");
100
if (derivedType == null)
101
throw new ArgumentNullException("derivedType");
103
if (baseMember.Compilation != derivedType.Compilation)
104
throw new ArgumentException("baseMember and derivedType must be from the same compilation");
106
baseMember = baseMember.MemberDefinition;
107
bool includeInterfaces = baseMember.DeclaringTypeDefinition.Kind == TypeKind.Interface;
108
IMethod method = baseMember as IMethod;
109
if (method != null) {
110
foreach (IMethod derivedMethod in derivedType.Methods) {
111
if (derivedMethod.Name == method.Name && derivedMethod.Parameters.Count == method.Parameters.Count) {
112
if (derivedMethod.TypeParameters.Count == method.TypeParameters.Count) {
113
// The method could override the base method:
114
if (GetBaseMembers(derivedMethod, includeInterfaces).Any(m => m.MemberDefinition == baseMember))
115
return derivedMethod;
120
IProperty property = baseMember as IProperty;
121
if (property != null) {
122
foreach (IProperty derivedProperty in derivedType.Properties) {
123
if (derivedProperty.Name == property.Name && derivedProperty.Parameters.Count == property.Parameters.Count) {
124
// The property could override the base property:
125
if (GetBaseMembers(derivedProperty, includeInterfaces).Any(m => m.MemberDefinition == baseMember))
126
return derivedProperty;
130
if (baseMember is IEvent) {
131
foreach (IEvent derivedEvent in derivedType.Events) {
132
if (derivedEvent.Name == baseMember.Name)
136
if (baseMember is IField) {
137
foreach (IField derivedField in derivedType.Fields) {
138
if (derivedField.Name == baseMember.Name)