Ejemplo n.º 1
0
        public Structure FindAllTargets(object obj)
        {
            Dictionary <Delegate, object> delegate_to_instance = new Dictionary <Delegate, object>();
            Delegate     lambda_delegate = (Delegate)obj;
            BindingFlags findFlags       = BindingFlags.NonPublic |
                                           BindingFlags.Public |
                                           BindingFlags.Static |
                                           BindingFlags.Instance |
                                           BindingFlags.InvokeMethod |
                                           BindingFlags.OptionalParamBinding |
                                           BindingFlags.DeclaredOnly;

            _control_flow_graph.Add(Campy.Types.Utils.ReflectionCecilInterop.ConvertToMonoCecilMethodDefinition(lambda_delegate.Method));
            _control_flow_graph.ExtractBasicBlocks();

            // Construct graph containing all objects used in lambda.
            StackQueue <object> stack = new StackQueue <object>();

            stack.Push(lambda_delegate);
            Campy.Graphs.GraphLinkedList <object> data_graph = new GraphLinkedList <object>();
            while (stack.Count > 0)
            {
                object node = stack.Pop();

                // Case 1: object is multicast delegate.
                // A multicast delegate is a list of delegates called in the order
                // they appear in the list.
                System.MulticastDelegate md = node as System.MulticastDelegate;
                if (md != null)
                {
                    foreach (System.Delegate node2 in md.GetInvocationList())
                    {
                        if ((object)node2 != (object)node)
                        {
                            if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
                            {
                                System.Console.WriteLine("Pushing2 " + MyToString(node2));
                            }
                            stack.Push(node2);
                        }
                    }
                    // Note, if multicast delegate, then it does not make sense to continue.
                    // Handle normal delegates.
                    //continue;
                }

                // Case 2: object is plain delegate.
                System.Delegate del = node as System.Delegate;
                if (del != null)
                {
                    object target = del.Target;
                    if (target == null)
                    {
                        // If target is null, then the delegate is a function that
                        // uses either static data, or does not require any additional
                        // data. If target isn't null, then it's probably a class.
                        target = Activator.CreateInstance(del.Method.DeclaringType);
                        if (data_graph.Vertices.Contains(target))
                        {
                            continue;
                        }
                        if (!delegate_to_instance.ContainsKey(del))
                        {
                            Debug.Assert(!TypesUtility.IsBaseType(target.GetType(), typeof(Delegate)));
                            data_graph.AddVertex(target);
                            delegate_to_instance.Add(del, target);
                            stack.Push(target);
                        }
                    }
                    else
                    {
                        // Target isn't null for delegate. Most likely, the method
                        // is part of the target, so let's assert that.
                        bool found = false;
                        foreach (System.Reflection.MethodInfo mi in target.GetType().GetMethods(findFlags))
                        {
                            if (mi == del.Method)
                            {
                                found = true;
                                break;
                            }
                        }
                        Debug.Assert(found);
                        if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
                        {
                            System.Console.WriteLine("Pushing " + MyToString(target));
                        }
                        if (delegate_to_instance.ContainsKey(del))
                        {
                            Debug.Assert(delegate_to_instance[del] == target);
                        }
                        else
                        {
                            delegate_to_instance.Add(del, target);
                        }
                        stack.Push(target);
                    }
                    continue;
                }

                if (data_graph.Vertices.Contains(node))
                {
                    continue;
                }

                Debug.Assert(!TypesUtility.IsBaseType(node.GetType(), typeof(Delegate)));
                data_graph.AddVertex(node);

                // Case 3: object is a class, and potentially could point to delegate.
                // Examine all fields, looking for list_of_targets.

                Type target_type = node.GetType();

                FieldInfo[] target_type_fieldinfo = target_type.GetFields();
                foreach (var field in target_type_fieldinfo)
                {
                    var value = field.GetValue(node);
                    if (value != null)
                    {
                        if (field.FieldType.IsValueType)
                        {
                            continue;
                        }
                        if (TypesUtility.IsCampyArrayType(field.FieldType))
                        {
                            continue;
                        }
                        if (TypesUtility.IsSimpleCampyType(field.FieldType))
                        {
                            continue;
                        }
                        // chase pointer type.
                        if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
                        {
                            System.Console.WriteLine("Pushingf " + MyToString(value));
                        }
                        stack.Push(value);
                    }
                }
            }

            if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
            {
                System.Console.WriteLine();
                System.Console.WriteLine("Dump of nodes.");
                foreach (object node in data_graph.Vertices)
                {
                    System.Console.WriteLine("Node "
                                             + MyToString(node));
                    System.Console.WriteLine("typeof node = "
                                             + node.GetType());
                    System.Console.WriteLine("Node "
                                             + (((node as Delegate) != null) ? "is " : "is not ")
                                             + "a delegate.");
                    System.Console.WriteLine();
                }
            }

            // Add edges.
            foreach (object node in data_graph.Vertices)
            {
                Type node_type = node.GetType();

                FieldInfo[] node_type_fieldinfo = node_type.GetFields();
                foreach (var field in node_type_fieldinfo)
                {
                    if (field.FieldType.IsValueType)
                    {
                        continue;
                    }
                    if (TypesUtility.IsCampyArrayType(field.FieldType))
                    {
                        continue;
                    }
                    if (TypesUtility.IsSimpleCampyType(field.FieldType))
                    {
                        continue;
                    }
                    var value = field.GetValue(node);
                    if (value == null)
                    {
                    }
                    else if (TypesUtility.IsBaseType(value.GetType(), typeof(Delegate)))
                    {
                        Delegate del          = value as Delegate;
                        object   value_target = del.Target;
                        if (value_target == node)
                        {
                            ;
                        }
                        else if (value_target != null)
                        {
                            Debug.Assert(data_graph.Vertices.Contains(node));
                            Debug.Assert(data_graph.Vertices.Contains(value_target));
                            data_graph.AddEdge(node, value_target);
                        }
                        else
                        {
                            value_target = delegate_to_instance[del];
                            if (value_target != node)
                            {
                                Debug.Assert(data_graph.Vertices.Contains(node));
                                Debug.Assert(data_graph.Vertices.Contains(value_target));
                                data_graph.AddEdge(node, value_target);
                            }
                        }
                    }
                    else
                    {
                        Debug.Assert(data_graph.Vertices.Contains(node));
                        Debug.Assert(data_graph.Vertices.Contains(value));
                        data_graph.AddEdge(node, value);
                    }
                }
            }

            if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
            {
                foreach (object node in data_graph.Vertices)
                {
                    System.Console.WriteLine("Node "
                                             + MyToString(node));
                    System.Console.WriteLine("typeof node = "
                                             + node.GetType());
                    System.Console.WriteLine("Node "
                                             + (((node as Delegate) != null) ? "is " : "is not ")
                                             + "a delegate.");
                    foreach (object succ in data_graph.Successors(node))
                    {
                        System.Console.WriteLine("-> "
                                                 + succ.GetHashCode() + " " + MyToString(succ));
                    }
                    System.Console.WriteLine();
                }
                System.Console.WriteLine();
            }

            Structure res = Structure.Initialize(delegate_to_instance, lambda_delegate.Method, data_graph, _control_flow_graph);

            if (Options.Singleton.Get(Options.OptionType.DisplayStructureComputation))
            {
                res.Dump();
            }

            return(res);
        }