예제 #1
0
        /// <summary>
        /// Gets the method the given method overrides.
        /// </summary>
        public static MethodDefinition GetBaseMethod(this MethodDefinition method)
        {
            var declaringType = method.DeclaringType;
            var baseTypeRef = declaringType.BaseType;
            var resolver = new GenericsResolver(method.DeclaringType);

            while (baseTypeRef != null)
            {
                var baseType = baseTypeRef.Resolve();
                if (baseType == null)
                    return null;

                var result = baseType.Methods.FirstOrDefault(x => x.AreSame(method, resolver.Resolve));
                if (result != null)
                    return result;

                baseTypeRef = baseType.BaseType;
            }

            return null;
        }
예제 #2
0
        /// <summary>
        /// Gets the first method the given method overrides from an implemented interface.
        /// </summary>
        public static MethodDefinition GetBaseInterfaceMethod(this MethodDefinition method)
        {
            var declaringType = method.DeclaringType;
            var resolver = new GenericsResolver(method.DeclaringType);

            while (declaringType != null)
            {
                foreach (var ifaceRef in declaringType.Interfaces.Select(x => x.Interface))
                {
                    var iface = ifaceRef.Resolve();
                    if (iface == null)
                        continue;

                    var result = iface.Methods.FirstOrDefault(x => x.AreSame(method, resolver.Resolve));
                    if (result != null)
                        return result;
                }
                declaringType = (declaringType.BaseType != null) ? declaringType.BaseType.Resolve() : null;
            }

            return null;
        }
예제 #3
0
        /// <summary>
        /// Is the given method an implementation (implicit or explicit) of the given interface method.
        /// </summary>
        /// <param name="method">The method to investigate</param>
        /// <param name="iMethod">The interface method.</param>
        public static bool IsImplementationOf(this MethodDefinition method, MethodDefinition iMethod)
        {
            // Try explicit first
            var resolver = new GenericsResolver(method.DeclaringType);
            if (method.IsExplicitImplementation())
            {
                return method.Overrides.Any(x => x.GetElementMethod().AreSameIncludingDeclaringType(iMethod, resolver.Resolve));
            }
            // Private methods cannot be an implicit implementation
            if (method.IsPrivate)
                return false;

            // Try implicit
            if (method.AreSame(iMethod, resolver.Resolve))
            {
                // If the declaring class also has an explicit implementation of the method we have no match.
                // Otherwise we have a match.
                return !method.DeclaringType.HasExplicitImplementationOf(iMethod);
            }
            return false;
        }
예제 #4
0
 /// <summary>
 /// Is the given method an explicit implementation of the given interface method.
 /// </summary>
 /// <param name="method">The method to investigate</param>
 /// <param name="iMethod">The interface method.</param>
 public static bool IsExplicitImplementationOf(this MethodDefinition method, MethodDefinition iMethod, GenericsResolver resolver = null)
 {
     resolver = resolver ?? new GenericsResolver(method.DeclaringType);
     if (method.IsExplicitImplementation())
     {
         return method.Overrides.Any(x => x.GetElementMethod().AreSameIncludingDeclaringType(iMethod, resolver.Resolve));
     }
     return false;
 }
예제 #5
0
 /// <summary>
 /// Is the given method an implicit interface implementation?
 /// </summary>
 internal static bool IsImplicitImplementation(this MethodDefinition method)
 {
     if (method.IsPrivate)
         return false;
     var declaringType = method.DeclaringType;
     var resolver = new GenericsResolver(method.DeclaringType);
     return declaringType.GetImplementedInterfaces().OfType<TypeDefinition>().SelectMany(x => x.Methods).Any(x => x.AreSame(method, resolver.Resolve));
 }
예제 #6
0
 /// <summary>
 /// Try to resolve definition from reference.
 /// </summary>
 internal static MethodDefinition Resolve(this MethodReference method, ReachableContext context)
 {
     var declType = method.DeclaringType.Resolve(context);
     var resolver = new GenericsResolver(declType);
     return (declType == null) ? null : declType.Methods.FirstOrDefault(x => x.AreSame(method, resolver.Resolve));
 }
예제 #7
0
        /// <summary>
        /// Gets the first implementation of the given interface method in the given type.
        /// </summary>
        public static MethodDefinition GetImplementation(this MethodDefinition interfaceMethod, TypeDefinition type)
        {
            if (!interfaceMethod.DeclaringType.IsInterface)
                throw new ArgumentException("interfaceMethod");
            var resolver = new GenericsResolver(type);

            while (type != null)
            {
                // Look for explicit implementation
                var result = type.Methods.FirstOrDefault(x => x.IsExplicitImplementationOf(interfaceMethod, resolver));
                if (result != null)
                    return result;

                // Look for implicit implementation
                result = type.Methods.FirstOrDefault(x => x.AreSame(interfaceMethod, resolver.Resolve));
                if (result != null)
                    return result;

                type = (type.BaseType != null) ? type.BaseType.Resolve() : null;
            }

            return null;
        }
예제 #8
0
 /// <summary>
 /// Try to resolve definition from reference.
 /// </summary>
 internal static EventDefinition Resolve(this EventReference evt, ReachableContext context)
 {
     var declType = evt.DeclaringType.Resolve(context);
     var resolver = new GenericsResolver(declType);
     return (declType == null) ? null : declType.Events.FirstOrDefault(x => x.AreSame(evt, resolver.Resolve));
 }
예제 #9
0
 /// <summary>
 /// Try to resolve definition from reference.
 /// </summary>
 internal static PropertyDefinition Resolve(this PropertyReference prop, ReachableContext context)
 {
     var declType = prop.DeclaringType.Resolve(context);
     var resolver = new GenericsResolver(declType);
     return (declType == null) ? null : declType.Properties.FirstOrDefault(x => x.AreSame(prop, resolver.Resolve));
 }
 /// <summary>
 /// Is the given instruction a call to a ctor of the same class as the given ctor?
 /// </summary>
 private static bool IsCallToThisCtor(Instruction ins, MethodDefinition ctor)
 {
     if (ins.OpCode.Code != Mono.Cecil.Cil.Code.Call)
         return false;
     var ctorRef = ins.Operand as MethodReference;
     if (ctorRef == null)
         return false;
     if (ctorRef.Name != ".ctor")
         return false;
     var resolver = new GenericsResolver(ctor.DeclaringType);
     return ctorRef.DeclaringType.AreSame(ctor.DeclaringType, resolver.Resolve);
 }
예제 #11
0
 /// <summary>
 /// Rename the given method and all references to it from code.
 /// </summary>
 private void Rename(MethodDefinition method, string newName)
 {
     // Rename reference to method
     foreach (var body in reachableMethods.Select(x => x.Body).Where(x => x != null))
     {
         var resolver = new GenericsResolver(method.DeclaringType);
         foreach (var ins in body.Instructions.Where(x => x.Operand is MethodReference))
         {
             var methodRef = ((MethodReference) ins.Operand).GetElementMethod();
             if (!ReferenceEquals(methodRef, method) && methodRef.AreSameIncludingDeclaringType(method, resolver.Resolve))
             {
                 methodRef.Name = newName;
             }
         }
     }
     // Rename method itself
     method.Name = newName;
 }
            /// <summary>
            /// Convert interface methods that have an explicit implementation.
            /// </summary>
            public void Convert(ReachableContext reachableContext)
            {
                this.reachableContext = reachableContext;

                // Do we need to convert anything?
                if (!reachableContext.ReachableTypes.SelectMany(x => x.Methods).Any(NeedsConversion))
                    return;

                // Initialize some sets                                                 
                reachableMethods = reachableContext.ReachableTypes.OrderBy(r=>r.FullName)
                                                                   // order,so we get a stable output. useful for debugging.
                                                                  .SelectMany(x => x.Methods)
                                                                  .Where(m => m.IsReachable)
                                                                  .ToList();
                methodNames = new NameSet(reachableMethods.Select(m => m.Name));
                interfaces = reachableContext.ReachableTypes.Where(x => x.IsInterface).ToList();

                var interfaceToImplementingTypes = interfaces.ToDictionary(i=>i,  i=>reachableContext.ReachableTypes
                                                                                                     .Where(x=>x.Implements(i))
                                                                                                     .ToList());

                // Go over all interfaces
                foreach (var iType in interfaces)
                {
                    foreach (var iMethod in iType.Methods)
                    {
                        ConvertInterfaceMethod(iType, iMethod, interfaceToImplementingTypes);
                    }
                }

                // Remove added stubs that are an override of another added stub.
                foreach (var stubPair in addedStubs)
                {
                    var stub = stubPair.Item1;
                    var oldName = stubPair.Item2;
                    if (stub.GetBaseMethod() != null)
                    {
                        stub.DeclaringType.Methods.Remove(stub);
                    }
                    else
                    {
                        // Check for duplicate methods
                        var resolver = new GenericsResolver(stub.DeclaringType);
                        //var methodsWithSameName = stub.DeclaringType.Methods.Where(x => (x != stub) && (x.Name == stub.Name)).ToList();
                        //var duplicate = methodsWithSameName.FirstOrDefault(x => (x != stub) && x.AreSame(stub, resolver.Resolve));
                        var duplicate = stub.DeclaringType.Methods.FirstOrDefault(x => (x != stub) && x.AreSame(stub, resolver.Resolve));
                        if (duplicate != null)
                        {
                            stub.DeclaringType.Methods.Remove(stub);
                            continue;
                        }

                        if (oldName != stub.Name)
                        {
                            var newName = stub.Name;
                            stub.Name = oldName;
                            duplicate = stub.DeclaringType.Methods.FirstOrDefault(x => (x != stub) && x.AreSame(stub, resolver.Resolve));
                            if (duplicate != null)
                            {
                                stub.DeclaringType.Methods.Remove(stub);
                                continue;
                            }
                            stub.Name = newName;
                        }
                    }
                }
            }
 /// <summary>
 /// Rename the given method and all references to it from code.
 /// </summary>
 private void Rename(MethodDefinition method, string newName)
 {
     methodReferences = methodReferences ?? InterfaceHelper.GetReachableMethodReferencesByName(reachableMethods);
     var resolver = new GenericsResolver(method.DeclaringType);
     foreach (var methodRef in methodReferences[method.Name])
     {
         if (ReferenceEquals(method, methodRef))
             continue;
         if (methodRef.AreSameIncludingDeclaringType(method, resolver.Resolve))
         {
             methodRef.Name = newName;
         }
     }
     method.SetName(newName);
 }
예제 #14
0
        /// <summary>
        /// Rename the given method and all references to it from code.
        /// 
        /// Note that the passed lookup will not be accurate after completion of this method.
        /// If you rename methods multiple times, but know that you will rename each single method
        /// only once, this should not be a problem.
        /// </summary>
        public static void Rename(MethodDefinition method, string newName, ILookup<string, MethodReference> reachableMethodReferencesByMethodName)
        {
            var resolver = new GenericsResolver(method.DeclaringType);

            // Rename reference to method
            foreach (var methodRef in reachableMethodReferencesByMethodName[method.Name])
            {
                if (!ReferenceEquals(methodRef, method) && methodRef.AreSameIncludingDeclaringType(method, resolver.Resolve))
                {
                    methodRef.Name = newName;
                }
            }
            // Rename method itself
            method.SetName(newName);
        }