.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

151 lines
5.7 KiB

// Copyright (c) 2010-2013 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;
using System.Collections.Generic;
using System.Linq;
namespace ICSharpCode.Decompiler.TypeSystem
{
/// <summary>
/// Provides helper methods for inheritance.
/// </summary>
public static class InheritanceHelper
{
// TODO: maybe these should be extension methods?
// or even part of the interface itself? (would allow for easy caching)
#region GetBaseMember
/// <summary>
/// Gets the base member that has the same signature.
/// </summary>
public static IMember GetBaseMember(IMember member)
{
return GetBaseMembers(member, false).FirstOrDefault();
}
/// <summary>
/// Gets all base members that have the same signature.
/// </summary>
/// <returns>
/// List of base members with the same signature. The member from the derived-most base class is returned first.
/// </returns>
public static IEnumerable<IMember> GetBaseMembers(IMember member, bool includeImplementedInterfaces)
{
if (member == null)
throw new ArgumentNullException("member");
if (member.IsExplicitInterfaceImplementation && member.ImplementedInterfaceMembers.Count == 1) {
// C#-style explicit interface implementation
member = member.ImplementedInterfaceMembers[0];
yield return member;
}
// Remove generic specialization
var substitution = member.Substitution;
member = member.MemberDefinition;
if (member.DeclaringTypeDefinition == null) {
// For global methods, return empty list. (prevent SharpDevelop UDC crash 4524)
yield break;
}
IEnumerable<IType> allBaseTypes;
if (includeImplementedInterfaces) {
allBaseTypes = member.DeclaringTypeDefinition.GetAllBaseTypes();
} else {
allBaseTypes = member.DeclaringTypeDefinition.GetNonInterfaceBaseTypes();
}
foreach (IType baseType in allBaseTypes.Reverse()) {
if (baseType == member.DeclaringTypeDefinition)
continue;
IEnumerable<IMember> baseMembers;
if (member.SymbolKind == SymbolKind.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 (baseMember.Accessibility == Accessibility.Private) {
// skip private base members;
continue;
}
if (SignatureComparer.Ordinal.Equals(member, baseMember)) {
yield return baseMember.Specialize(substitution);
}
}
}
}
#endregion
#region GetDerivedMember
/// <summary>
/// Finds the member declared in 'derivedType' that has the same signature (could override) 'baseMember'.
/// </summary>
public static IMember GetDerivedMember(IMember baseMember, ITypeDefinition derivedType)
{
if (baseMember == null)
throw new ArgumentNullException("baseMember");
if (derivedType == null)
throw new ArgumentNullException("derivedType");
if (baseMember.Compilation != derivedType.Compilation)
throw new ArgumentException("baseMember and derivedType must be from the same compilation");
baseMember = baseMember.MemberDefinition;
bool includeInterfaces = baseMember.DeclaringTypeDefinition.Kind == TypeKind.Interface;
IMethod method = baseMember as IMethod;
if (method != null) {
foreach (IMethod derivedMethod in derivedType.Methods) {
if (derivedMethod.Name == method.Name && derivedMethod.Parameters.Count == method.Parameters.Count) {
if (derivedMethod.TypeParameters.Count == method.TypeParameters.Count) {
// The method could override the base method:
if (GetBaseMembers(derivedMethod, includeInterfaces).Any(m => m.MemberDefinition == baseMember))
return derivedMethod;
}
}
}
}
IProperty property = baseMember as IProperty;
if (property != null) {
foreach (IProperty derivedProperty in derivedType.Properties) {
if (derivedProperty.Name == property.Name && derivedProperty.Parameters.Count == property.Parameters.Count) {
// The property could override the base property:
if (GetBaseMembers(derivedProperty, includeInterfaces).Any(m => m.MemberDefinition == baseMember))
return derivedProperty;
}
}
}
if (baseMember is IEvent) {
foreach (IEvent derivedEvent in derivedType.Events) {
if (derivedEvent.Name == baseMember.Name)
return derivedEvent;
}
}
if (baseMember is IField) {
foreach (IField derivedField in derivedType.Fields) {
if (derivedField.Name == baseMember.Name)
return derivedField;
}
}
return null;
}
#endregion
}
}