oct
Loading...
Searching...
No Matches
oct.docs.callgraph Namespace Reference

Classes

class  Function
class  CallGraph

Functions

Path run_doxygen_xml (Path project_root)
str _dotted (str name)
CallGraph parse_doxygen_xml (Path xml_dir)
dict[str, int] reachable (CallGraph graph, str root_id, int|None max_depth=None)
str to_dot (CallGraph graph, dict[str, int] nodes, str root_id, str title)

Variables

Path CALLGRAPH_REL = Path("docs") / "_build" / "callgraph"
tuple _XML_OVERRIDES
tuple MODULE_COLOURS
tuple UNFLATTEN_ARGS = ("-l", "5", "-f", "-c", "6")

Detailed Description

Purpose
-------
Chart C of the overview-charts plan (docs/DOCS_OVERVIEW_CHARTS_PLAN_2026-09-27.md
in the workspace): the full transitive call graph of one entry point,
assembled from Doxygen's own call analysis.

Doxygen already resolves calls for every function; the HTML tier shows
that as one graph per function, capped at ``DOT_GRAPH_MAX_NODES`` (50)
and rooted at that function only. This module asks Doxygen for the same
analysis as XML, where each function carries a ``<references>`` element
for every call it resolved, and assembles the whole reachable graph from
a chosen root with no cap - for ``oct git commit`` that is expected to be
hundreds of nodes, and the operator asked to see it whole.

It is the static half of chart C. The dynamic half, a trace of a real
run through the ``_dbg`` stream, comes later and will be compared with
this one: the differences are exactly what a textual resolver misses
(dynamic dispatch, Click's command objects) or invents (a call matched
to the wrong function of the same name).

Responsibilities
----------------
- :func:`run_doxygen_xml` - one XML-only Doxygen run over a project,
  using the project's own Doxyfile with overrides appended, into a
  gitignored directory. No HTML, no dot, so it is quick.
- :func:`parse_doxygen_xml` - every function and its resolved calls.
- :func:`reachable` - the transitive closure from a root, with depths.
- :func:`to_dot` - render the closure, clustered and coloured by module,
  root marked; :data:`UNFLATTEN_ARGS` is how the static chart is laid out.

Diagnostics
-----------
Domain: OCT-DOCS
Levels:
    L2 - run entry / exit, graph sizes
    L3 - root resolution, per-step decisions
    L4 - per-file parse detail

Contracts
---------
- The project's Doxyfile is never modified. The run uses a temporary copy
  with overrides appended after the project's settings, which Doxygen
  honours because a later assignment wins.
- Output goes under ``docs/_build/callgraph/`` of the project, which the
  workspace ``.gitignore`` already covers.
- Only calls Doxygen resolved to a documented function become edges.
  Nothing here guesses a target; unresolved calls are simply absent, and
  :class:`CallGraph` says how many functions were parsed so the reader
  can judge coverage.

Dependencies
------------
- oct.core.diagnostics (_dbg structured logger)
- oct.docs.doxyfile_init (DOXYFILE_REL - where a project declares Doxygen)

Function Documentation

◆ _dotted()

str oct.docs.callgraph._dotted ( str name)
protected

Definition at line 172 of file callgraph.py.

Here is the caller graph for this function:

◆ parse_doxygen_xml()

CallGraph oct.docs.callgraph.parse_doxygen_xml ( Path xml_dir)
Read every compound file in *xml_dir* into a :class:`CallGraph`.

A function's qualified name is its compound's name (a Python module is
a Doxygen namespace, a class a class) plus the member name, with
Doxygen's ``::`` turned into dots. Only ``<references>`` whose target
is itself a parsed function become calls.

Definition at line 176 of file callgraph.py.

Here is the call graph for this function:

◆ reachable()

dict[str, int] oct.docs.callgraph.reachable ( CallGraph graph,
str root_id,
int | None max_depth = None )
Breadth-first closure from *root_id*: ``function id -> depth``.

Definition at line 227 of file callgraph.py.

◆ run_doxygen_xml()

Path oct.docs.callgraph.run_doxygen_xml ( Path project_root)
Run Doxygen over *project_root* for XML only; return the XML directory.

Raises
------
FileNotFoundError
    When the project declares no Doxyfile or ``doxygen`` is not on PATH.
subprocess.CalledProcessError
    When Doxygen itself fails.

Definition at line 126 of file callgraph.py.

◆ to_dot()

str oct.docs.callgraph.to_dot ( CallGraph graph,
dict[str, int] nodes,
str root_id,
str title )
Render the closure *nodes* as DOT, clustered and coloured by module, root highlighted.

Definition at line 263 of file callgraph.py.

Variable Documentation

◆ _XML_OVERRIDES

tuple oct.docs.callgraph._XML_OVERRIDES
protected
Initial value:
1= (
2 "GENERATE_HTML = NO",
3 "GENERATE_LATEX = NO",
4 "GENERATE_XML = YES",
5 "XML_OUTPUT = xml",
6 "XML_PROGRAMLISTING = NO",
7 "HAVE_DOT = NO",
8 "CALL_GRAPH = NO",
9 "CALLER_GRAPH = NO",
10 "REFERENCES_RELATION = YES",
11 "REFERENCED_BY_RELATION = YES",
12 "QUIET = YES",
13 "WARNINGS = NO",
14)

Definition at line 82 of file callgraph.py.

◆ CALLGRAPH_REL

Path oct.docs.callgraph.CALLGRAPH_REL = Path("docs") / "_build" / "callgraph"

Definition at line 78 of file callgraph.py.

◆ MODULE_COLOURS

tuple oct.docs.callgraph.MODULE_COLOURS
Initial value:
1= (
2 ("#e6f0ff", "#3366cc"), ("#e8f7e4", "#3a9d23"), ("#fff1d6", "#cc8400"),
3 ("#fde2e4", "#c0392b"), ("#ece4f7", "#7d3cc0"), ("#e0f4f4", "#138d8d"),
4 ("#f7f0e0", "#9a7d0a"), ("#e4e9f2", "#5d6d7e"), ("#f3e6ef", "#a93a7e"),
5 ("#e9f5d9", "#6a9a1f"), ("#fbe8d3", "#c86b00"), ("#dff0fb", "#2e86c1"),
6 ("#f0e6ff", "#8e44ad"), ("#e6fff2", "#1e8449"), ("#fff9d9", "#b7950b"),
7 ("#f2f2f2", "#707b7c"), ("#ffe6e6", "#cb4335"), ("#e6ecff", "#2851a3"),
8 ("#eaf7ea", "#239b56"), ("#fdf0e6", "#ca6f1e"), ("#e6f7ff", "#2874a6"),
9)

Definition at line 245 of file callgraph.py.

◆ UNFLATTEN_ARGS

tuple oct.docs.callgraph.UNFLATTEN_ARGS = ("-l", "5", "-f", "-c", "6")

Definition at line 260 of file callgraph.py.