Esempio n. 1
0
        static void CreateSiblingReference <T>(T basePropDef, ref T discoveredBaseMemberDef, INameService service) where T : class, IMemberDef
        {
            if (discoveredBaseMemberDef is null)
            {
                discoveredBaseMemberDef = basePropDef;
            }
            else
            {
                var references = service.GetReferences(discoveredBaseMemberDef)
                                 .OfType <MemberSiblingReference>()
                                 .ToArray();
                if (references.Length > 0)
                {
                    discoveredBaseMemberDef = (T)references[0].OldestSiblingDef;
                    foreach (var siblingRef in references.Skip(1))
                    {
                        // Redirect all the siblings to the new oldest reference
                        RedirectSiblingReferences(siblingRef.OldestSiblingDef, discoveredBaseMemberDef, service);
                    }
                }

                // Check if the discovered base type is the current type. If so, nothing needs to be done.
                if (ReferenceEquals(basePropDef, discoveredBaseMemberDef))
                {
                    return;
                }

                service.AddReference(basePropDef, new MemberSiblingReference(basePropDef, discoveredBaseMemberDef));
                UpdateOldestSiblingReference(discoveredBaseMemberDef, basePropDef, service);
            }
        }
Esempio n. 2
0
        static void UpdateOldestSiblingReference(IMemberDef oldestSiblingMemberDef, IMemberDef basePropDef, INameService service)
        {
            var reverseReference = service.GetReferences(oldestSiblingMemberDef).OfType <MemberOldestSiblingReference>()
                                   .SingleOrDefault();

            if (reverseReference is null)
            {
                service.AddReference(oldestSiblingMemberDef, new MemberOldestSiblingReference(oldestSiblingMemberDef, basePropDef));
                PropagateRenamingRestrictions(service, oldestSiblingMemberDef, basePropDef);
            }
            else if (!reverseReference.OtherSiblings.Contains(basePropDef))
            {
                reverseReference.OtherSiblings.Add(basePropDef);
                PropagateRenamingRestrictions(service, reverseReference.OtherSiblings);
            }
        }
Esempio n. 3
0
        static void RedirectSiblingReferences(IMemberDef oldMemberDef, IMemberDef newMemberDef, INameService service)
        {
            if (ReferenceEquals(oldMemberDef, newMemberDef))
            {
                return;
            }

            var referencesToUpdate = service.GetReferences(oldMemberDef)
                                     .OfType <MemberOldestSiblingReference>()
                                     .SelectMany(r => r.OtherSiblings)
                                     .SelectMany(service.GetReferences)
                                     .OfType <MemberSiblingReference>()
                                     .Where(r => ReferenceEquals(r.OldestSiblingDef, oldMemberDef));

            foreach (var reference in referencesToUpdate)
            {
                reference.OldestSiblingDef = newMemberDef;
                UpdateOldestSiblingReference(newMemberDef, reference.ThisMemberDef, service);
            }
            UpdateOldestSiblingReference(newMemberDef, oldMemberDef, service);
        }
Esempio n. 4
0
        static IEnumerable <IDnlibDef> GetTargetsWithDelay(IList <IDnlibDef> definitions, ConfuserContext context, INameService service)
        {
            var delayedItems = new List <IDnlibDef>();
            var currentList  = definitions;
            var lastCount    = -1;

            while (currentList.Any())
            {
                foreach (var def in currentList)
                {
                    if (service.GetReferences(def).Any(r => r.DelayRenaming(service, def)))
                    {
                        delayedItems.Add(def);
                    }
                    else
                    {
                        yield return(def);
                    }
                }

                if (delayedItems.Count == lastCount)
                {
                    var errorBuilder = new StringBuilder();
                    errorBuilder.AppendLine("Failed to rename all targeted members, because the references are blocking each other.");
                    errorBuilder.AppendLine("Remaining definitions: ");
                    foreach (var def in delayedItems)
                    {
                        errorBuilder.Append("• ").AppendDescription(def, service).AppendLine();
                    }
                    context.Logger.Warn(errorBuilder.ToString().Trim());
                    yield break;
                }
                lastCount    = delayedItems.Count;
                currentList  = delayedItems;
                delayedItems = new List <IDnlibDef>();
            }
        }
        public void Analyze(INameService nameService, ITraceService traceService, IReadOnlyList <ModuleDef> moduleDefs, ILogger logger, MethodDef method)
        {
            if (!method.HasBody)
            {
                return;
            }

            MethodTrace methodTrace = null;

            MethodTrace GetMethodTrace()
            {
                if (methodTrace == null)
                {
                    methodTrace = traceService.Trace(method);
                }
                return(methodTrace);
            }

            foreach (var instr in method.Body.Instructions)
            {
                if (instr.OpCode.Code == Code.Call && instr.Operand is IMethodDefOrRef calledMethod)
                {
                    if (calledMethod.DeclaringType.FullName == "System.Type")
                    {
                        Func <TypeDef, IEnumerable <IMemberDef> > getMember = null;
                        if (calledMethod.Name == nameof(Type.GetMethod))
                        {
                            getMember = t => t.Methods;
                        }
                        else if (calledMethod.Name == nameof(Type.GetField))
                        {
                            getMember = t => t.Fields;
                        }
                        else if (calledMethod.Name == nameof(Type.GetProperty))
                        {
                            getMember = t => t.Properties;
                        }
                        else if (calledMethod.Name == nameof(Type.GetEvent))
                        {
                            getMember = t => t.Events;
                        }
                        else if (calledMethod.Name == nameof(Type.GetMember))
                        {
                            getMember = t => Enumerable.Empty <IMemberDef>().Concat(t.Methods).Concat(t.Fields).Concat(t.Properties).Concat(t.Events);
                        }

                        if (getMember != null)
                        {
                            var trace     = GetMethodTrace();
                            var arguments = trace.TraceArguments(instr);
                            if (arguments == null)
                            {
                                logger.WarnFormat(Resources.ReflectionAnalyzer_Analyze_TracingArgumentsFailed, calledMethod.FullName, method.FullName);
                            }
                            else if (arguments.Length >= 2)
                            {
                                var types = GetReferencedTypes(method.Body.Instructions[arguments[0]], method, trace);
                                var names = GetReferencedNames(method.Body.Instructions[arguments[1]]);

                                if (!types.Any())
                                {
                                    types = moduleDefs.SelectMany(m => m.GetTypes()).ToArray();
                                }

                                foreach (var possibleMember in types.SelectMany(GetTypeAndBaseTypes).SelectMany(getMember).Where(m => names.Contains(m.Name)))
                                {
                                    nameService.SetCanRename(possibleMember, false);
                                    if (!(possibleMember is IMethod) && !(possibleMember is PropertyDef) && !(possibleMember is EventDef))
                                    {
                                        continue;
                                    }

                                    foreach (var reference in nameService.GetReferences(possibleMember).OfType <MemberOverrideReference>())
                                    {
                                        nameService.SetCanRename(reference.BaseMemberDef, false);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }