Skip to content

Commit f95bf7c

Browse files
feat(docs): code analysis engine
changes: - file: formats.py area: cli added: [_export_calls_toon] - file: yaml_exporter.py area: core added: [_render_edges, _render_hubs, export_calls_toon, _render_calls_header, _render_modules] modified: [YAMLExporter] stats: lines: "+4066/-66 (net +4000)" files: 8 complexity: "Large structural change (normalized)"
1 parent 09eb89b commit f95bf7c

14 files changed

Lines changed: 4084 additions & 71 deletions

File tree

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
## [Unreleased]
22

3+
## [0.5.111] - 2026-04-18
4+
5+
### Docs
6+
- Update project/README.md
7+
- Update project/context.md
8+
9+
### Other
10+
- Update code2llm/cli_exports/formats.py
11+
- Update code2llm/exporters/yaml_exporter.py
12+
- Update project/analysis.toon.yaml
13+
- Update project/calls.yaml
14+
- Update project/index.html
15+
316
## [0.5.110] - 2026-04-18
417

518
### Other

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
## AI Cost Tracking
55

6-
![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.110-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
6+
![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.111-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
77
![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-53.7h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
88

99
- 🤖 **LLM usage:** $7.5000 (154 commits)

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.5.110
1+
0.5.111

code2llm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
and entity resolution with multilingual support.
99
"""
1010

11-
__version__ = "0.5.110"
11+
__version__ = "0.5.111"
1212
__author__ = "STTS Project"
1313

1414
# Core analysis components (lightweight, always needed)

code2llm/cli_exports/formats.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,17 @@ def _export_calls(args, result, output_dir: Path):
225225
print(f" - CALLS (call graph YAML): {output_dir / 'calls.yaml'}")
226226

227227

228+
def _export_calls_toon(args, result, output_dir: Path):
229+
"""Export calls.toon.yaml (call graph in human-readable toon format).
230+
231+
Generates calls.toon.yaml with hubs, modules, and edges sections.
232+
"""
233+
yaml_exporter = YAMLExporter()
234+
yaml_exporter.export_calls_toon(result, str(output_dir / 'calls.toon.yaml'))
235+
if args.verbose:
236+
print(f" - CALLS (toon format): {output_dir / 'calls.toon.yaml'}")
237+
238+
228239
def _export_mermaid(args, result, output_dir: Path):
229240
"""Export Mermaid diagrams + optional PNG generation.
230241

code2llm/exporters/yaml_exporter.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,75 @@ def _get_cc(fi: FunctionInfo) -> int:
252252
if isinstance(fi.complexity, dict):
253253
return fi.complexity.get('cyclomatic_complexity', 0)
254254
return fi.complexity or 0
255+
256+
def export_calls_toon(self, result: AnalysisResult, output_path: str, max_calls_per_func: int = 10, max_edges: int = 500) -> None:
257+
"""Export call graph as toon.yaml format (human-readable).
258+
259+
Generates a human-readable toon format with:
260+
- Header with project stats
261+
- HUBS: high-degree functions (many calls in/out)
262+
- CHAINS: call chains/paths
263+
- MODULES: functions grouped by module with call relationships
264+
"""
265+
connected, edges = self._collect_edges(result, max_calls_per_func, max_edges)
266+
nodes = self._build_nodes(result, connected)
267+
modules = self._group_by_module(result, connected)
268+
269+
# Build toon format sections
270+
lines = []
271+
lines.extend(self._render_calls_header(result, nodes, edges, modules))
272+
lines.append("")
273+
lines.extend(self._render_hubs(nodes))
274+
lines.append("")
275+
lines.extend(self._render_modules(modules, nodes, edges))
276+
lines.append("")
277+
lines.extend(self._render_edges(edges))
278+
279+
Path(output_path).parent.mkdir(parents=True, exist_ok=True)
280+
with open(output_path, 'w', encoding='utf-8') as f:
281+
f.write('\n'.join(lines) + '\n')
282+
283+
def _render_calls_header(self, result: AnalysisResult, nodes: Dict, edges: List, modules: Dict) -> List[str]:
284+
"""Render header section for calls.toon.yaml."""
285+
nfuncs = len(result.functions)
286+
all_cc = [self._get_cc(fi) for fi in result.functions.values()]
287+
avg_cc = round(sum(all_cc) / len(all_cc), 1) if all_cc else 0.0
288+
289+
return [
290+
f"# code2llm call graph | {result.project_path}",
291+
f"# nodes: {len(nodes)} | edges: {len(edges)} | modules: {len(modules)}",
292+
f"# CC̄={avg_cc}",
293+
]
294+
295+
def _render_hubs(self, nodes: Dict) -> List[str]:
296+
"""Render high-degree hub functions (sorted by total calls)."""
297+
hubs = sorted(
298+
[(name, data) for name, data in nodes.items()],
299+
key=lambda x: x[1]['calls_in'] + x[1]['calls_out'],
300+
reverse=True
301+
)[:20]
302+
303+
lines = ['HUBS[20]:']
304+
for name, data in hubs:
305+
total_calls = data['calls_in'] + data['calls_out']
306+
lines.append(f" {name}")
307+
lines.append(f" CC={data['cyclomatic_complexity']} in:{data['calls_in']} out:{data['calls_out']} total:{total_calls}")
308+
return lines
309+
310+
def _render_modules(self, modules: Dict, nodes: Dict, edges: List) -> List[str]:
311+
"""Render modules section with functions and call relationships."""
312+
lines = ['MODULES:']
313+
for module, funcs in sorted(modules.items()):
314+
lines.append(f" {module} [{len(funcs)} funcs]")
315+
for func in funcs[:10]: # Show up to 10 funcs per module
316+
if func in nodes:
317+
data = nodes[func]
318+
lines.append(f" {data['name']} CC={data['cyclomatic_complexity']} out:{data['calls_out']}")
319+
return lines
320+
321+
def _render_edges(self, edges: List) -> List[str]:
322+
"""Render call edges section."""
323+
lines = ['EDGES:']
324+
for edge in edges[:50]: # Show up to 50 edges
325+
lines.append(f" {edge['caller']}{edge['callee']}")
326+
return lines

code2llm/nlp/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
with multilingual support and fuzzy matching.
55
"""
66

7-
__version__ = "0.5.110"
7+
__version__ = "0.5.111"
88

99
from .pipeline import NLPPipeline
1010
from .normalization import QueryNormalizer

project/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ code2llm ./ -f yaml --separate-orphans
332332

333333
**Generated by**: `code2llm ./ -f all --readme`
334334
**Analysis Date**: 2026-04-18
335-
**Total Functions**: 1014
335+
**Total Functions**: 1035
336336
**Total Classes**: 111
337337
**Modules**: 131
338338

project/analysis.toon.yaml

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1-
# code2llm | 122f 22773L | python:117,shell:4,java:1 | 2026-04-18
2-
# CC̄=4.4 | critical:3/1014 | dups:0 | cycles:0
1+
# code2llm | 122f 22887L | python:117,shell:4,java:1 | 2026-04-18
2+
# CC̄=4.3 | critical:0/1035 | dups:0 | cycles:0
33

4-
HEALTH[3]:
5-
🟡 CC export_calls CC=18 (limit:15)
6-
🟡 CC main CC=17 (limit:15)
7-
🟡 CC validate_chunked_output CC=15 (limit:15)
4+
HEALTH[0]: ok
85

9-
REFACTOR[1]:
10-
1. split 3 high-CC methods (CC>15)
6+
REFACTOR[0]: none needed
117

12-
PIPELINES[673]:
8+
PIPELINES[683]:
139
[1] Src [read_readme]: read_readme
1410
PURITY: 100% pure
1511
[2] Src [main]: main → run_analysis
@@ -44,22 +40,22 @@ LAYERS:
4440
│ analyzer 355L 1C 9m CC=14 ←0
4541
│ entity_resolution 326L 3C 16m CC=13 ←1
4642
│ cli_analysis 323L 0C 11m CC=14 ←1
43+
│ formats 301L 0C 14m CC=13 ←3
4744
│ intent_matching 297L 3C 15m CC=7 ←0
45+
│ cli_parser 295L 0C 2m CC=2 ←1
4846
│ side_effects 294L 2C 15m CC=14 ←0
4947
│ cfg 293L 1C 17m CC=5 ←0
5048
│ type_inference 290L 1C 17m CC=9 ←0
51-
│ formats 289L 0C 13m CC=13 ←3
5249
│ data_analysis 286L 1C 18m CC=14 ←0
5350
│ llm_task 284L 0C 15m CC=14 ←0
54-
│ cli_parser 277L 0C 1m CC=1 ←1
5551
│ toon_size_manager 265L 0C 8m CC=10 ←1
5652
│ mermaid_flow_helpers 262L 0C 12m CC=10 ←1
53+
│ yaml_exporter 254L 1C 19m CC=8 ←0
54+
│ cli_commands 250L 0C 12m CC=7 ←1
5755
│ context_exporter 248L 1C 15m CC=10 ←0
5856
│ dfg 224L 1C 12m CC=7 ←0
59-
│ !! cli_commands 220L 0C 6m CC=15 ←1
6057
│ call_graph 211L 1C 13m CC=9 ←0
6158
│ config 210L 6C 0m CC=0.0 ←0
62-
│ !! yaml_exporter 203L 1C 10m CC=18 ←0
6359
│ scanner 201L 1C 6m CC=14 ←0
6460
│ refactoring 196L 1C 11m CC=9 ←0
6561
│ __init__ 196L 1C 11m CC=9 ←0
@@ -75,10 +71,10 @@ LAYERS:
7571
│ module_detail 162L 1C 9m CC=7 ←0
7672
│ ts_parser 158L 1C 9m CC=7 ←2
7773
│ toon_view 157L 1C 9m CC=6 ←0
74+
│ orchestrator 156L 0C 5m CC=11 ←1
7875
│ export_pipeline 153L 2C 5m CC=4 ←0
7976
│ incremental 150L 1C 10m CC=4 ←0
8077
│ prompt_engine 150L 1C 7m CC=12 ←0
81-
│ orchestrator 149L 0C 5m CC=11 ←1
8278
│ toon_parser 147L 0C 10m CC=8 ←1
8379
│ ruby 143L 0C 3m CC=14 ←1
8480
│ context_view 140L 1C 8m CC=11 ←0
@@ -125,16 +121,16 @@ LAYERS:
125121
│ __init__ 0L 0C 0m CC=0.0 ←0
126122
│ __init__ 0L 0C 0m CC=0.0 ←0
127123
128-
./ CC̄=4.2 ←in:0 →out:0
129-
│ !! validate_toon 394L 0C 15m CC=17 ←0
130-
│ setup 67L 0C 1m CC=2 ←0
131-
│ orchestrator.sh 58L 0C 0m CC=0.0 ←0
132-
│ project.sh 49L 0C 0m CC=0.0 ←0
133-
134124
scripts/ CC̄=3.9 ←in:0 →out:0
135125
│ benchmark_badges 392L 0C 9m CC=13 ←0
136126
│ bump_version 96L 0C 7m CC=4 ←0
137127
128+
./ CC̄=3.6 ←in:0 →out:0
129+
│ validate_toon 390L 0C 19m CC=7 ←0
130+
│ setup 67L 0C 1m CC=2 ←0
131+
│ orchestrator.sh 58L 0C 0m CC=0.0 ←0
132+
│ project.sh 49L 0C 0m CC=0.0 ←0
133+
138134
benchmarks/ CC̄=3.0 ←in:0 →out:1
139135
│ benchmark_performance 306L 0C 7m CC=6 ←0
140136
│ project_generator 233L 0C 6m CC=1 ←1
@@ -149,11 +145,11 @@ LAYERS:
149145
│ server 110L 0C 3m CC=4 ←0
150146
151147
demo_langs/ CC̄=1.5 ←in:0 →out:0
152-
│ sample.rs 47L 1C 5m CC=20
153-
│ sample.java 47L 2C 7m CC=31
148+
│ sample.java 47L 2C 7m CC=32
149+
│ sample.rs 47L 1C 4m CC=20
154150
│ sample.go 46L 0C 4m CC=3 ←0
155151
│ sample.php 44L 1C 1m CC=1 ←0
156-
│ sample 40L 1C 4m CC=3 ←0
152+
│ sample 40L 1C 5m CC=3 ←0
157153
│ sample.ts 26L 1C 1m CC=1 ←0
158154
159155
── zero ──

0 commit comments

Comments
 (0)