private static ControlFlowGraph ConnectNodes(IEnumerable <Instruction> instructions, IDictionary <string, CFGNode> leaders)
        {
            var     cfg = new ControlFlowGraph();
            var     connectWithPreviousNode = true;
            var     current = cfg.Entry;
            CFGNode previous;

            foreach (var instruction in instructions)
            {
                if (leaders.ContainsKey(instruction.Label))
                {
                    previous = current;
                    current  = leaders[instruction.Label];

                    // A node cannot fall-through itself,
                    // unless it contains another
                    // instruction with the same label
                    // of the node's leader instruction
                    if (connectWithPreviousNode && previous.Id != current.Id)
                    {
                        cfg.ConnectNodes(previous, current);
                    }
                }

                current.Instructions.Add(instruction);
                connectWithPreviousNode = instruction.CanFallThroughNextInstruction();

                IList <string> targets;
                var            isBranch        = instruction.IsBranch(out targets);
                var            isExitingMethod = instruction.IsExitingMethod();

                if (isBranch)
                {
                    foreach (var label in targets)
                    {
                        var target = leaders[label];

                        cfg.ConnectNodes(current, target);
                    }
                }
                else if (isExitingMethod)
                {
                    //TODO: not always connect to exit, could exists a catch or finally block
                    cfg.ConnectNodes(current, cfg.Exit);
                }
            }

            cfg.ConnectNodes(current, cfg.Exit);
            return(cfg);
        }
        private void ConnectNodesWithExceptionHandlers(ControlFlowGraph cfg, IDictionary <string, CFGNode> leaders)
        {
            var activeProtectedBlocks = new HashSet <ProtectedBlock>();
            var protectedBlocksStart  = methodBody.ExceptionInformation.ToLookup(pb => pb.Start);
            var protectedBlocksEnd    = methodBody.ExceptionInformation.ToLookup(pb => pb.End);

            var orderedLeaders = from entry in leaders
                                 where entry.Value.Instructions.Any()
                                 orderby entry.Value.StartOffset()
                                 select entry;

            foreach (var entry in orderedLeaders)
            {
                var label = entry.Key;
                var node  = entry.Value;

                if (protectedBlocksStart.Contains(label))
                {
                    var startingProtectedBlocks = protectedBlocksStart[label];
                    activeProtectedBlocks.UnionWith(startingProtectedBlocks);
                }

                if (protectedBlocksEnd.Contains(label))
                {
                    var endingProtectedBlocks = protectedBlocksEnd[label];
                    activeProtectedBlocks.ExceptWith(endingProtectedBlocks);
                }

                // Connect each node inside a try block to the first corresponding handler block
                foreach (var block in activeProtectedBlocks)
                {
                    var target = leaders[block.Handler.Start];
                    cfg.ConnectNodes(node, target);
                }
            }
        }