private List <MethodCall> Analyze(IEnumerable <Node> relevantNodes, InterfaceImplementationsMap interfaceImplementationsMap, List <Type> analyzed, List <Type> callers)
        {
            var calls = callers.AsParallel()
                        .SelectMany(t =>
                                    GetCalledMethods(t)
                                    .Where(r => CoveredByAssemblyGraph(relevantNodes, r.To.DeclaringType))
                                    .SelectMany(x => interfaceImplementationsMap.ResolveInterface(x)))
                        .ToList();

            var unknownTypes = calls.AsParallel()
                               .Select(e => e.To.DeclaringType)
                               .Distinct()
                               .ToList()
                               .Except(analyzed)
                               .ToList();

            if (!unknownTypes.Any())
            {
                return(calls);
            }
            else
            {
                var children = Analyze(relevantNodes, interfaceImplementationsMap, callers.Concat(analyzed).Distinct().ToList(), unknownTypes);
                return(calls.Concat(children).ToList());
            }
        }
        // traces from the given source nodes all calls within the assembly graph
        private List <MethodCall> TraceCalles(IEnumerable <Node> relevantNodes, InterfaceImplementationsMap interfaceImplementationsMap, List <MethodDesc> targets, IEnumerable <Assembly> sources)
        {
            var targetTypes = targets
                              .Select(m => m.myDeclaringType)
                              .Distinct()
                              .ToList();

            return(Analyze(relevantNodes, interfaceImplementationsMap, targetTypes,
                           sources.SelectMany(x => x.GetTypes()).ToList())
                   .Distinct()
                   .ToList());
        }
        private GraphPresentation BuildCallTree(List <Assembly> sources, List <MethodDesc> targets, GraphPresentation assemblyGraphPresentation)
        {
            var relevantNodes = assemblyGraphPresentation.Graph.Nodes
                                .Where(n => assemblyGraphPresentation.Picking.Pick(n))
                                .ToList();

            var interfaceImplementationsMap = new InterfaceImplementationsMap();

            interfaceImplementationsMap.Build(relevantNodes, targets.Select(t => t.myDeclaringType));

            var calls = TraceCalles(relevantNodes, interfaceImplementationsMap, targets, sources);

            Console.WriteLine();
            Console.WriteLine("NOT analyzed assemblies:");

            foreach (var x in myMonoLoader.SkippedAssemblies)
            {
                Shell.Warn($"    {x}");
            }

            return(Shell.Profile("Generating call graph ...", () =>
            {
                var builder = new RelaxedGraphBuilder();
                var edges = calls
                            .Select(call => (CreateMethodNode(call.From), CreateMethodNode(call.To)))
                            // we assume that usages within same class are not relevant
                            .Where(x => x.Item1.myDeclaringType != x.Item2.myDeclaringType)
                            .ToList();

                foreach (var edge in edges)
                {
                    builder.TryAddEdge(edge.Item1.myId, edge.Item2.myId);
                }

                var nodes = edges
                            .SelectMany(e => new[] { e.Item1, e.Item2 })
                            .Distinct(new MethodNodeComparer())
                            .ToList();

                var clusters = nodes
                               .GroupBy(n => n.myDeclaringType)
                               .Select(x => (R.TypeFullName(x.Key), x.Key.Name, x.Select(n => n.myId).ToList()))
                               .ToList();

                foreach (var cluster in clusters)
                {
                    builder.TryAddCluster(cluster.Item1, cluster.Item3);
                }

                builder.Freeze();

                var presentation = new GraphPresentation();
                presentation.Graph = builder.Graph;

                // add captions for readability
                var captions = presentation.GetModule <ICaptionModule>();

                foreach (var n in nodes)
                {
                    captions.Add(new Caption(n.myId, n.myCaption));
                }

                foreach (var cluster in clusters)
                {
                    captions.Add(new Caption(cluster.Item1, cluster.Item2));
                }

                return presentation;
            }));