/// <summary> /// A version of Implements that works over instantiated types and methods. /// /// t-devinc: Not entirely convinced this is correct. /// </summary> /// <param name="derived"></param> /// <param name="upto"></param> /// <param name="m"></param> /// <returns></returns> internal static IMethodDefinition ImplementsInstantiated(ITypeDefinition derived, IMethodDefinition m) { Contract.Requires(derived != null); Contract.Requires(!(derived is Dummy)); Contract.Requires(m != null); Contract.Requires(!(m is Dummy)); Contract.Requires(TypeHelper.Type1DerivesFromOrIsTheSameAsType2(derived, m.ContainingTypeDefinition)); Contract.Requires(!derived.IsInterface); Contract.Ensures(Contract.Result <IMethodDefinition>() != null); Contract.Ensures(!(Contract.Result <IMethodDefinition>() is Dummy)); var classHierarchyChain = new ITypeDefinition[] { derived }.Concat(GarbageCollectHelper.AllSuperClasses(derived)); foreach (var classInHierarchy in classHierarchyChain) { IMethodDefinition specializedImplementation = ImplementationForMethodInClass(m, classInHierarchy); if (specializedImplementation != null) { return(specializedImplementation); } } // We shouldn't get here return(null); }
/// <summary> /// Find possible implementations of m for derived, upto (and including) 'upto'). /// /// If m is an unspecialized generic interface, they may be multiple possible implementations; at this /// point we can't tell which one would be called since we've removed all specialization from m. /// /// We require 'derived' to be unspecialized, but note that its super types may be specialized. /// We require 'm' to be unspecialized. /// /// </summary> internal static ICollection <IMethodDefinition> Implements(ITypeDefinition derived, ITypeDefinition upto, IMethodDefinition m) { Contract.Requires(derived != null); Contract.Requires(!(derived is Dummy)); Contract.Requires(upto != null); Contract.Requires(!(upto is Dummy)); Contract.Requires(m != null); Contract.Requires(!(m is Dummy)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(derived)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(m)); Contract.Requires(!derived.IsInterface); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => GarbageCollectHelper.MethodDefinitionIsUnspecialized(resultM))); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => resultM != null && !(resultM is Dummy)) ); ISet <IMethodDefinition> foundImplementations = new HashSet <IMethodDefinition>(); // If derived implements an interface multiple times, there may be multiple specialized versions for derived IEnumerable <IMethodDefinition> versionsOfMSpecializedForDerived = SearchSpecializedHierarchyForVersionOfMethod(derived, m); var classHierarchyChain = new ITypeDefinition[] { derived }.Concat(GarbageCollectHelper.AllSuperClasses(derived)); foreach (IMethodDefinition mSpecializedForDerived in versionsOfMSpecializedForDerived) { // Check explicit implementation overrides before implicit methods IMethodDefinition foundImplementation = null; foreach (var classInHierarchy in classHierarchyChain) { IMethodDefinition specializedImplementation = ImplementationForMethodInClass(mSpecializedForDerived, classInHierarchy); if (specializedImplementation != null) { foundImplementation = specializedImplementation; break; } if (TypeHelper.TypesAreEquivalent(GarbageCollectHelper.UnspecializeAndResolveTypeReference(classInHierarchy), upto)) { break; } } // Do we really expect to find an implementation for EACH mSpecializedForDerived; or do we expect to find at least one overall all? Contract.Assert(foundImplementation != null); foundImplementations.Add(GarbageCollectHelper.UnspecializeAndResolveMethodReference(foundImplementation)); } return(foundImplementations); }
/// <summary> /// Find possible implementations of m for derived, upto (and including) 'upto'). /// /// If m is an unspecialized generic interface, they may be multiple possible implementations; at this /// point we can't tell which one would be called since we've removed all specialization from m. /// /// We require 'derived' to be unspecialized, but note that its super types may be specialized. /// We require 'm' to be unspecialized. /// /// </summary> internal static ICollection <IMethodDefinition> Implements(ITypeDefinition derived, ITypeDefinition upto, IMethodDefinition m) { Contract.Requires(derived != null); Contract.Requires(!(derived is Dummy)); Contract.Requires(upto != null); Contract.Requires(!(upto is Dummy)); Contract.Requires(m != null); Contract.Requires(!(m is Dummy)); Contract.Requires(GarbageCollectHelper.TypeDefinitionIsUnspecialized(derived)); Contract.Requires(GarbageCollectHelper.MethodDefinitionIsUnspecialized(m)); Contract.Requires(!derived.IsInterface); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => GarbageCollectHelper.MethodDefinitionIsUnspecialized(resultM))); Contract.Ensures(Contract.ForAll(Contract.Result <ICollection <IMethodDefinition> >(), resultM => resultM != null && !(resultM is Dummy)) ); ISet <IMethodDefinition> foundImplementations = new HashSet <IMethodDefinition>(); // If derived implements an interface multiple times, there may be multiple specialized versions for derived IEnumerable <IMethodDefinition> versionsOfMSpecializedForDerived = SearchSpecializedHierarchyForVersionOfMethod(derived, m); var classHierarchyChain = new ITypeDefinition[] { derived }.Concat(GarbageCollectHelper.AllSuperClasses(derived)); foreach (IMethodDefinition mSpecializedForDerived in versionsOfMSpecializedForDerived) { IMethodDefinition foundImplementation = null; // If this is a method defined on an inteface, we must first search the hierarchy for explicit implementations, // since an explicit implementation on a base type supercedes an implicit implementation on a derived type if (m.ContainingTypeDefinition.IsInterface) { foreach (var classInHierarchy in classHierarchyChain) { foreach (IMethodImplementation methodImplementation in classInHierarchy.ExplicitImplementationOverrides) { if (methodImplementation.ImplementedMethod.InternedKey == mSpecializedForDerived.InternedKey) { foundImplementation = methodImplementation.ImplementingMethod.ResolvedMethod; break; } } if (foundImplementation != null) { break; } if (TypeHelper.TypesAreEquivalent(GarbageCollectHelper.UnspecializeAndResolveTypeReference(classInHierarchy), upto)) { break; } } } // If we found an explicit implementation, don't seach for an implicit one if (foundImplementation == null) { foreach (var classInHierarchy in classHierarchyChain) { foundImplementation = ImplementationForMethodInClass(mSpecializedForDerived, classInHierarchy); if (foundImplementation != null) { break; } if (TypeHelper.TypesAreEquivalent(GarbageCollectHelper.UnspecializeAndResolveTypeReference(classInHierarchy), upto)) { break; } } } // Do we really expect to find an implementation for EACH mSpecializedForDerived; or do we expect to find at least one overall all? Contract.Assert(foundImplementation != null); foundImplementations.Add(GarbageCollectHelper.UnspecializeAndResolveMethodReference(foundImplementation)); } return(foundImplementations); }