Skip to content

Latest commit

 

History

History
79 lines (68 loc) · 8.36 KB

File metadata and controls

79 lines (68 loc) · 8.36 KB

ARCHITECTURE.md

Внутреннее устройство репозитория — как файлы связаны и в каком порядке выполняется пайплайн. Про фичи и семантику диаграмм смотри README.md, здесь — только "как это работает изнутри".

Обновляй этот файл, если правка меняет что-то из описанного ниже: порядок стадий в index.mjs, состав промежуточных структур (funcs / varDefs / peripherals / fileRecords), формат graph-data.js, связь source ↔ generated файлов, или сам факт разбиения на файлы. Небольшие правки внутри одной стадии (новый паттерн парсинга, новый tier, изменение верстки страницы) документировать здесь не нужно — это и так видно из кода.

Пайплайн index.mjs (один проход, без модулей)

Файл — линейный скрипт ~1800 строк, не разбитый на модули; функции выше по файлу — примитивы (обход AST, работа со строками), ниже — стадии, которые используют накопленное состояние. Порядок выполнения:

  1. Parse (walkDir, extractIncludes, extractFunctions, extractFileScopeVars, buildCommentIndex/docCommentFor) — tree-sitter парсит каждый файл; комментарии индексируются отдельно и приклеиваются к соседней декларации.

  2. Analyze (analyzeFunction, buildCfg, classifyAccess, resolveVar, periph, isrBaseName) — по каждой функции строится CFG и множество read/write обращений к глобалам; имена резолвятся в ключи через funcKey/resolveVar; макро-периферия (X->field, не резолвящаяся в реальную переменную) распознаётся отдельно от обычных globals. Результат копится в module-level Mapах: funcs, varDefs, peripherals, fileRecords.

  3. Score/tier (varTier, sizeTier, fnClass, varClass) — на основе накопленных связей считается важность переменной (кол-во читателей/писателей) для визуальных tier'ов.

  4. Build diagrams (build*Diagram — overview/aggregate/include/file/level0/function/cfg, все async) — каждая функция берёт срез из funcs/varDefs/peripherals и генерирует DOT через общие эмиттеры (dotFnNode/dotVarNode/dotPeriphNode/dotFileNode/dotEdge/..., рядом с buildLevel0Diagram), затем renderDotAll считает раскладку на сборке через WASM (@hpcc-js/wasm-graphviz) сразу всеми движками из LEVEL0_ENGINES (neato/dot/fdp). Все семь типов диаграмм — на graphviz; выбор движка по умолчанию зависит от формы графа, не единый для всех: file/level0/overview — neato (хаб-структуры, циклы через периферию, ранговая раскладка сминает их в столбцы), include/function/cfg — dot (файлы/вызовы/control-flow — DAG с одной точкой входа или явной иерархией, ранговая раскладка тут как раз к месту). Переключение движка в браузере (setupEngineSwitchable в viewer.js) — подмена уже готового SVG, не пересчёт. Раньше большие file-диаграммы сворачивались в кликабельные grey-box группы (groupedDiagramBlock/setupGroupedDiagram) — эта механика убрана вместе с переходом file-диаграмм на graphviz: он не упирается в то же ограничение по размеру, что раньше было у ELK, так что сворачивать стало незачем.

  5. Render — htmlPage/diagramBlockSvg оборачивают diagram-код в HTML; в конце скрипта (после определения всех функций) идут три плоских блока без обёртки в function: запись graph-data.js (per-node metadata для тултипов), index.html, по одной странице на файл и на функцию в filesDir/funcsDir.

    mermaid+ELK полностью убраны (были рантаймом в viewer.js до перехода всех диаграмм на graphviz): нет ни зависимостей (mermaid/@mermaid-js/layout-elk/esbuild), ни viewer-entry.mjs/dist/, ни копирования mermaid-elk.min.js в сгенерированный сайт.

Всё состояние — module-level переменные, а не передаваемые аргументы; стадии друг за другом читают то, что накопили предыдущие. Добавлять новую стадию — значит вставлять код в нужную точку этой последовательности, а не создавать отдельный файл.

Source vs generated — не путать

  • viewer.js — исходник клиентского runtime (hover, pin, zoom, breadcrumbs). graph-html/app.js — это копия viewer.js, сделанная fs.copyFileSync в конце index.mjs при генерации примера в graph-html/. Править надо только viewer.js; graph-html/app.js перезатирается при следующей генерации и не должен расходиться с ним.
  • graph-html/ целиком — закоммиченный пример вывода инструмента (сгенерированный сайт), не исходный код. graph-html/index.html, graph-html/graph-data.js — артефакты, не редактируются руками.
  • codegraph.ps1/codegraph.cmd — самостоятельный drop-in лаунчер для чужих проектов: клонирует этот репозиторий в %LOCALAPPDATA%\code-graph, ставит зависимости и запускает node index.mjs. Он не импортирует ничего из этого репо напрямую — держи в уме, что правки в способе вызова index.mjs (аргументы, порядок) нужно синхронизировать вручную.

Данные, которых нет в коде одной строкой

  • graph-data.js — единственный мост между build-time (index.mjs) и runtime (viewer.js): плоский window.GRAPH.nodes, ключ — id ноды (fnId/varId/periphId/file_<name>), значение — всё нужное для тултипа. Если добавляешь новое поле для тултипа, оно должно появиться и здесь (в блоке "graph-data.js" в index.mjs), и в чтении на стороне viewer.js.
  • Каждая HTML-страница самодостаточна: уже готовый SVG инлайнится прямо в разметку (diagramBlockSvg), плюс скрытый <script type="application/json" class="engine-data"> с SVG остальных движков для мгновенного переключения в браузере. app.js/graph-data.js — общие ассеты между страницами; у graphviz-диаграмм собственного бандла в браузере нет — @hpcc-js/wasm-graphviz нужен только на сборке (в Node), не подключается ни на одной странице.