docs: def _update_function_transition_graph(self, src_node_key, dst_node_key, jumpkind='Ijk_Boring', ins_addr=None,
                                            stmt_idx=None, confirmed=None):
          """
          Update transition graphs of functions in function manager based on information passed in.
  
          :param str jumpkind: Jumpkind.
          :param CFGNode src_node: Source CFGNode
          :param CFGNode dst_node: Destionation CFGNode
          :param int ret_addr: The theoretical return address for calls
          :return: None
          """
  
          if dst_node_key is not None:
              dst_node = self._graph_get_node(dst_node_key, terminator_for_nonexistent_node=True)
              dst_node_addr = dst_node.addr
              dst_codenode = dst_node.to_codenode()
              dst_node_func_addr = dst_node.function_address
          else:
              dst_node = None
              dst_node_addr = None
              dst_codenode = None
              dst_node_func_addr = None
  
          if src_node_key is None:
              if dst_node is None:
                  raise ValueError("Either src_node_key or dst_node_key must be specified.")
              self.kb.functions.function(dst_node.function_address, create=True)._register_nodes(True,
                                                                                                 dst_codenode
                                                                                                 )
              return
  
          src_node = self._graph_get_node(src_node_key, terminator_for_nonexistent_node=True)
  
          # Update the transition graph of current function
          if jumpkind == "Ijk_Call":
              ret_addr = src_node.return_target
              ret_node = self.kb.functions.function(
                  src_node.function_address,
                  create=True
              )._get_block(ret_addr).codenode if ret_addr else None
  
              self.kb.functions._add_call_to(
                  function_addr=src_node.function_address,
                  from_node=src_node.to_codenode(),
                  to_addr=dst_node_addr,
                  retn_node=ret_node,
                  syscall=False,
                  ins_addr=ins_addr,
                  stmt_idx=stmt_idx,
              )
  
          if jumpkind.startswith('Ijk_Sys'):
  
              self.kb.functions._add_call_to(
                  function_addr=src_node.function_address,
                  from_node=src_node.to_codenode(),
                  to_addr=dst_node_addr,
                  retn_node=src_node.to_codenode(),  # For syscalls, they are returning to the address of themselves
                  syscall=True,
                  ins_addr=ins_addr,
                  stmt_idx=stmt_idx,
              )
  
          elif jumpkind == 'Ijk_Ret':
              # Create a return site for current function
              self.kb.functions._add_return_from(
                  function_addr=src_node.function_address,
                  from_node=src_node.to_codenode(),
                  to_node=dst_codenode,
              )
  
              if dst_node is not None:
                  # Create a returning edge in the caller function
                  self.kb.functions._add_return_from_call(
                      function_addr=dst_node_func_addr,
                      src_function_addr=src_node.function_address,
                      to_node=dst_codenode,
                  )
  
          elif jumpkind == 'Ijk_FakeRet':
              self.kb.functions._add_fakeret_to(
                  function_addr=src_node.function_address,
                  from_node=src_node.to_codenode(),
                  to_node=dst_codenode,
                  confirmed=confirmed,
              )
  
          elif jumpkind in ('Ijk_Boring', 'Ijk_InvalICache'):
  
              src_obj = self.project.loader.find_object_containing(src_node.addr)
              dest_obj = self.project.loader.find_object_containing(dst_node.addr) if dst_node is not None else None
  
              if src_obj is dest_obj:
                  # Jump/branch within the same object. Might be an outside jump.
                  to_outside = src_node.function_address != dst_node_func_addr
              else:
                  # Jump/branch between different objects. Must be an outside jump.
                  to_outside = True
  
              if not to_outside:
                  self.kb.functions._add_transition_to(
                      function_addr=src_node.function_address,
                      from_node=src_node.to_codenode(),
                      to_node=dst_codenode,
                      ins_addr=ins_addr,
                      stmt_idx=stmt_idx,
                  )
  
              else:
                  self.kb.functions._add_outside_transition_to(
                      function_addr=src_node.function_address,
                      from_node=src_node.to_codenode(),
                      to_node=dst_codenode,
                      to_function_addr=dst_node_func_addr,
                      ins_addr=ins_addr,
                      stmt_idx=stmt_idx,
                  )