/**
   * Connects cfgNode to the proper CATCH block if target subtree might throw an exception. If there
   * are FINALLY blocks reached before a CATCH, it will make the corresponding entry in finallyMap.
   */
  private void connectToPossibleExceptionHandler(Node cfgNode, Node target) {
    if (mayThrowException(target) && !exceptionHandler.isEmpty()) {
      Node lastJump = cfgNode;
      for (Node handler : exceptionHandler) {
        if (NodeUtil.isFunction(handler)) {
          return;
        }
        Preconditions.checkState(handler.getType() == Token.TRY);
        Node catchBlock = NodeUtil.getCatchBlock(handler);

        if (!NodeUtil.hasCatchHandler(catchBlock)) { // No catch but a FINALLY.
          if (lastJump == cfgNode) {
            createEdge(cfgNode, Branch.ON_EX, handler.getLastChild());
          } else {
            finallyMap.put(lastJump, handler.getLastChild());
          }
        } else { // Has a catch.
          if (lastJump == cfgNode) {
            createEdge(cfgNode, Branch.ON_EX, catchBlock);
            return;
          } else {
            finallyMap.put(lastJump, catchBlock);
          }
        }
        lastJump = handler;
      }
    }
  }
  private void handleReturn(Node node) {
    Node lastJump = null;
    for (Iterator<Node> iter = exceptionHandler.iterator(); iter.hasNext(); ) {
      Node curHandler = iter.next();
      if (NodeUtil.isFunction(curHandler)) {
        break;
      }
      if (NodeUtil.hasFinally(curHandler)) {
        if (lastJump == null) {
          createEdge(node, Branch.UNCOND, curHandler.getLastChild());
        } else {
          finallyMap.put(lastJump, computeFallThrough(curHandler.getLastChild()));
        }
        lastJump = curHandler;
      }
    }

    if (node.hasChildren()) {
      connectToPossibleExceptionHandler(node, node.getFirstChild());
    }

    if (lastJump == null) {
      createEdge(node, Branch.UNCOND, null);
    } else {
      finallyMap.put(lastJump, null);
    }
  }