예제 #1
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);
        }
예제 #2
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)));
        }
예제 #3
0
        /// <summary>
        /// Gets the first 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);
        }
예제 #4
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)));
        }
예제 #5
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)));
        }
예제 #6
0
        public override bool detectType(Expression expr)
        {
            if (expr is InstanceFieldReference instFieldRef2)
            {
                var actualType = GenericsResolver.fromObject(instFieldRef2.object_).resolveType(instFieldRef2.field.type, true);
                instFieldRef2.setActualType(actualType, false, TypeHelper.isGeneric(instFieldRef2.object_.actualType));
                return(true);
            }
            else if (expr is InstancePropertyReference instPropRef)
            {
                var actualType = GenericsResolver.fromObject(instPropRef.object_).resolveType(instPropRef.property.type, true);
                instPropRef.setActualType(actualType);
                return(true);
            }
            else if (expr is StaticPropertyReference statPropRef)
            {
                statPropRef.setActualType(statPropRef.decl.type, false, false);
                return(true);
            }
            else if (expr is StaticFieldReference statFieldRef)
            {
                statFieldRef.setActualType(statFieldRef.decl.type, false, false);
                return(true);
            }

            return(false);
        }
예제 #7
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);
        }
예제 #8
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)));
        }
예제 #9
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);
        }
예제 #10
0
        /// <summary>
        /// Does the given method have a call to a base class ctor?
        /// </summary>
        private static bool HasBaseOrThisClassCtorCall(Mono.Cecil.MethodDefinition method)
        {
            var resolver = new GenericsResolver(method.DeclaringType);

            foreach (var ins in method.Body.Instructions.Where(x => x.OpCode.Code == Code.Call))
            {
                var target = ins.Operand as Mono.Cecil.MethodReference;
                if ((target != null) && (target.Name == ".ctor") &&
                    ((target.DeclaringType.AreSame(method.DeclaringType, resolver.Resolve)) ||
                     (target.DeclaringType.AreSame(method.DeclaringType.BaseType, resolver.Resolve))))
                {
                    return(true);
                }
            }
            return(false);
        }
            /// <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);
            }
예제 #12
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;
 }
예제 #13
0
            /// <summary>
            /// Rename the given method and all references to it from code.
            /// </summary>
            private void Rename(MethodDefinition method, string newName)
            {
                methodReferences = methodReferences ?? CollectMethodReferences();
                var resolver = new GenericsResolver(method.DeclaringType);

                foreach (var methodRef in methodReferences)
                {
                    if (ReferenceEquals(method, methodRef))
                    {
                        continue;
                    }
                    if (methodRef.AreSameIncludingDeclaringType(method, resolver.Resolve))
                    {
                        methodRef.Name = newName;
                    }
                }
                method.Name = newName;
            }
            /// <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));
            }
예제 #15
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);
        }
        protected void resolveReturnType(IMethodCallExpression expr, GenericsResolver genericsResolver)
        {
            genericsResolver.collectFromMethodCall(expr);

            for (int i = 0; i < expr.args.length(); i++)
            {
                // actually doesn't have to resolve, but must check if generic type confirm the previous argument with the same generic type
                var paramType = genericsResolver.resolveType(expr.method.parameters.get(i).type, false);
                if (paramType != null)
                {
                    expr.args.get(i).setExpectedType(paramType);
                }
                expr.args.set(i, this.main.runPluginsOn(expr.args.get(i)));
                genericsResolver.collectResolutionsFromActualType(paramType, expr.args.get(i).actualType);
            }

            if (expr.method.returns == null)
            {
                this.errorMan.throw_($"Method ({expr.method.parentInterface.name}::{expr.method.name}) return type was not specified or infered before the call.");
                return;
            }

            expr.setActualType(genericsResolver.resolveType(expr.method.returns, true), true, expr is InstanceMethodCallExpression instMethCallExpr && TypeHelper.isGeneric(instMethCallExpr.object_.getType()));
        }
예제 #17
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);
 }
예제 #18
0
            /// <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.SelectMany(x => x.Methods).Where(m => m.IsReachable).OrderBy(x => x.FullName).ToList();
                methodNames      = new NameSet(reachableMethods.Select(m => m.Name));
                interfaces       = reachableContext.ReachableTypes.Where(x => x.IsInterface).ToList();

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

                // 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;
                        }
                    }
                }
            }