Beispiel #1
0
        public void RemoveSameClasses()
        {
            var handledNodes    = new HashSet <ICallGraphNode>(Nodes.Count);
            var processingNodes = new Queue <(ICallGraphNode, ICallGraphNode)>();

            EntryNodes.Clear();
            Nodes.Clear();
            var roots = Roots.Values;

            Roots = new Dictionary <MethodUniqueSignature, ICallGraphNode>();
            foreach (var rootNode in roots)
            {
                // we keep all parents of root(s)
                if (!handledNodes.Add(rootNode))
                {
                    continue;
                }

                var mappedRootNode = new CallInfoNode(rootNode.Info);
                Roots.Add(mappedRootNode.MethodSignature, mappedRootNode);
                Nodes.Add(mappedRootNode.MethodSignature, mappedRootNode);
                if (rootNode.InNodes.Count == 0 && !EntryNodes.ContainsKey(mappedRootNode.MethodSignature))
                {
                    EntryNodes.Add(mappedRootNode.MethodSignature, mappedRootNode);
                }

                foreach (var inNode in rootNode.InNodes)
                {
                    var mappedNode = new CallInfoNode(inNode.Info);
                    mappedRootNode.InNodes.Add(mappedNode);
                    mappedNode.OutNodes.Add(mappedRootNode);

                    if (!Nodes.ContainsKey(mappedNode.MethodSignature))
                    {
                        Nodes.Add(mappedNode.MethodSignature, mappedNode);
                        if (inNode.InNodes.Count == 0)
                        {
                            if (!EntryNodes.ContainsKey(mappedNode.MethodSignature))
                            {
                                EntryNodes.Add(mappedNode.MethodSignature, mappedNode);
                            }
                        }
                        else
                        {
                            processingNodes.Enqueue((inNode, mappedNode));
                        }
                    }
                }
            }

            // and keep only different classes for other parents
            while (processingNodes.Count > 0)
            {
                var(node, mappedNode) = processingNodes.Dequeue();
                if (!handledNodes.Add(node))
                {
                    continue;
                }

                var mappedInNodes = new HashSet <ICallGraphNode>(mappedNode.InNodes);
                foreach (var inNode in node.InNodes)
                {
                    var classSignature = new MethodUniqueSignature(inNode.MethodSignature.ToClassName());
                    if (Nodes.TryGetValue(classSignature, out var mappedInNode))
                    {
                        if (mappedInNode != mappedNode && mappedInNodes.Add(mappedInNode))
                        {
                            mappedInNode.OutNodes.Add(mappedNode);
                        }
                    }
                    else
                    {
                        mappedInNode = new CallInfoNode(new CallInfo(
                                                            0,
                                                            null,
                                                            inNode.AssemblyInfo,
                                                            classSignature,
                                                            inNode.IsPublic,
                                                            null));

                        mappedInNodes.Add(mappedInNode);
                        mappedInNode.OutNodes.Add(mappedNode);
                        Nodes.Add(mappedInNode.MethodSignature, mappedInNode);
                    }

                    if (inNode.InNodes.Count == 0)
                    {
                        if (!EntryNodes.ContainsKey(mappedInNode.MethodSignature))
                        {
                            EntryNodes.Add(mappedInNode.MethodSignature, mappedInNode);
                        }
                    }
                    else
                    {
                        processingNodes.Enqueue((inNode, mappedInNode));
                    }
                }

                if (mappedNode.InNodes.Count != mappedInNodes.Count)
                {
                    mappedNode.InNodes.Clear();
                    mappedNode.InNodes.AddRange(mappedInNodes);
                }
            }
        }
Beispiel #2
0
        public void RemoveNonPublicMiddleNodes()
        {
            var cache           = new Dictionary <ICallGraphNode, List <ICallGraphNode> >();
            var processingNodes = new HashSet <ICallGraphNode>(EntryNodes.Values);

            while (processingNodes.Count > 0)
            {
                var node = processingNodes.First();
                processingNodes.Remove(node);
                for (var i = node.OutNodes.Count - 1; i >= 0; i--)
                {
                    var outNode = node.OutNodes[i];
                    if (outNode.OutNodes.Count == 0)
                    {
                        continue;
                    }

                    if (outNode.IsPublic)
                    {
                        processingNodes.Add(outNode);
                        continue;
                    }

                    node.OutNodes.RemoveAt(i);
                    var publicNodes = FindPublicOutNodes(outNode);
                    node.OutNodes.AddRange(publicNodes);
                    foreach (var graphNode in publicNodes)
                    {
                        processingNodes.Add(graphNode);
                    }
                }

                for (var i = node.InNodes.Count - 1; i >= 0; i--)
                {
                    var inNode = node.InNodes[i];
                    if (!inNode.IsPublic && !EntryNodes.ContainsKey(inNode.MethodSignature))
                    {
                        node.InNodes.RemoveAt(i);
                    }
                }
            }

            List <ICallGraphNode> FindPublicOutNodes(ICallGraphNode node)
            {
                if (cache.TryGetValue(node, out var result))
                {
                    return(result);
                }

                result = new List <ICallGraphNode>();
                foreach (var outNode in node.OutNodes)
                {
                    if (outNode.IsPublic || outNode.OutNodes.Count == 0)
                    {
                        result.Add(outNode);
                    }
                    else
                    {
                        result.AddRange(FindPublicOutNodes(outNode));
                    }
                }

                if (node.InNodes.Count > 1)
                {
                    cache.Add(node, result);
                }

                Nodes.Remove(node.MethodSignature);
                return(result);
            }
        }