code2llm 0.5.102__tar.gz → 0.5.103__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {code2llm-0.5.102 → code2llm-0.5.103}/PKG-INFO +18 -8
- {code2llm-0.5.102 → code2llm-0.5.103}/README.md +7 -7
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/__init__.py +1 -1
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/base.py +24 -5
- code2llm-0.5.103/code2llm/core/lang/cpp.py +35 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/csharp.py +1 -1
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/go_lang.py +27 -12
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/java.py +1 -1
- code2llm-0.5.103/code2llm/core/lang/ts_extractors.py +180 -0
- code2llm-0.5.103/code2llm/core/lang/ts_parser.py +158 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/nlp/__init__.py +1 -1
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm.egg-info/PKG-INFO +18 -8
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm.egg-info/SOURCES.txt +2 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm.egg-info/requires.txt +10 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/pyproject.toml +11 -1
- {code2llm-0.5.102 → code2llm-0.5.103}/setup.py +1 -1
- code2llm-0.5.102/code2llm/core/lang/cpp.py +0 -42
- {code2llm-0.5.102 → code2llm-0.5.103}/LICENSE +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/__main__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/call_graph.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/cfg.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/coupling.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/data_analysis.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/dfg.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/pipeline_detector.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/side_effects.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/smells.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/type_inference.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/utils/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/analysis/utils/ast_helpers.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/api.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/cli.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/cli_analysis.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/cli_commands.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/cli_exports/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/cli_exports/code2logic.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/cli_exports/formats.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/cli_exports/orchestrator.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/cli_exports/prompt.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/cli_parser.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/analyzer.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/ast_registry.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/config.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/export_pipeline.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/file_analyzer.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/file_cache.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/file_filter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/gitignore.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/incremental.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/generic.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/php.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/ruby.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/rust.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/lang/typescript.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/large_repo.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/models.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/refactoring.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/repo_files.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/streaming/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/streaming/cache.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/streaming/incremental.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/streaming/prioritizer.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/streaming/scanner.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/streaming/strategies.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/streaming_analyzer.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/core/toon_size_manager.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/article_view.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/base.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/context_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/context_view.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/evolution_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/flow_constants.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/flow_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/flow_renderer.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/html_dashboard.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/index_generator.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/json_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/llm_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/map_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/mermaid_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/mermaid_flow_helpers.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/project_yaml_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/readme_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/report_generators.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/toon/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/toon/helpers.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/toon/metrics.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/toon/module_detail.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/toon/renderer.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/toon.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/toon_view.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/validate_project.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/exporters/yaml_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/generators/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/generators/llm_flow.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/generators/llm_task.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/generators/mermaid.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/nlp/config.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/nlp/entity_resolution.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/nlp/intent_matching.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/nlp/normalization.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/nlp/pipeline.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/patterns/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/patterns/detector.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/refactor/__init__.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm/refactor/prompt_engine.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm.egg-info/dependency_links.txt +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm.egg-info/entry_points.txt +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/code2llm.egg-info/top_level.txt +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/setup.cfg +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_advanced_analysis.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_analyzer.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_deep_analysis.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_edge_cases.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_flow_exporter.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_format_quality.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_multilanguage_e2e.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_nlp_pipeline.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_nonpython_cc_calls.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_pipeline_detector.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_project_toon_export.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_prompt_engine.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_prompt_txt.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_refactoring_engine.py +0 -0
- {code2llm-0.5.102 → code2llm-0.5.103}/tests/test_toon_v2.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.103
|
|
4
4
|
Summary: High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries
|
|
5
5
|
Home-page: https://github.com/wronai/stts
|
|
6
6
|
Author: STTS Project
|
|
@@ -37,6 +37,16 @@ Requires-Dist: vulture>=2.10
|
|
|
37
37
|
Requires-Dist: tiktoken>=0.5
|
|
38
38
|
Requires-Dist: tree-sitter>=0.21
|
|
39
39
|
Requires-Dist: tree-sitter-python>=0.21
|
|
40
|
+
Requires-Dist: tree-sitter-javascript>=0.21
|
|
41
|
+
Requires-Dist: tree-sitter-typescript>=0.21
|
|
42
|
+
Requires-Dist: tree-sitter-go>=0.21
|
|
43
|
+
Requires-Dist: tree-sitter-rust>=0.21
|
|
44
|
+
Requires-Dist: tree-sitter-java>=0.21
|
|
45
|
+
Requires-Dist: tree-sitter-c>=0.21
|
|
46
|
+
Requires-Dist: tree-sitter-cpp>=0.22
|
|
47
|
+
Requires-Dist: tree-sitter-c-sharp>=0.21
|
|
48
|
+
Requires-Dist: tree-sitter-php>=0.22
|
|
49
|
+
Requires-Dist: tree-sitter-ruby>=0.21
|
|
40
50
|
Provides-Extra: dev
|
|
41
51
|
Requires-Dist: pytest>=6.2; extra == "dev"
|
|
42
52
|
Requires-Dist: pytest-cov>=2.12; extra == "dev"
|
|
@@ -56,11 +66,11 @@ Dynamic: requires-python
|
|
|
56
66
|
|
|
57
67
|
## AI Cost Tracking
|
|
58
68
|
|
|
59
|
-
     
|
|
70
|
+
  
|
|
61
71
|
|
|
62
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
63
|
-
- 👤 **Human dev:** ~$
|
|
72
|
+
- 🤖 **LLM usage:** $7.5000 (151 commits)
|
|
73
|
+
- 👤 **Human dev:** ~$5223 (52.2h @ $100/h, 30min dedup)
|
|
64
74
|
|
|
65
75
|
Generated on 2026-03-31 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
66
76
|
|
|
@@ -391,9 +401,9 @@ code2llm ./ -f yaml --separate-orphans
|
|
|
391
401
|
|
|
392
402
|
**Generated by**: `code2llm ./ -f all --readme`
|
|
393
403
|
**Analysis Date**: 2026-03-31
|
|
394
|
-
**Total Functions**:
|
|
395
|
-
**Total Classes**:
|
|
396
|
-
**Modules**:
|
|
404
|
+
**Total Functions**: 1006
|
|
405
|
+
**Total Classes**: 111
|
|
406
|
+
**Modules**: 131
|
|
397
407
|
|
|
398
408
|
For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
|
|
399
409
|
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
|
|
4
4
|
## AI Cost Tracking
|
|
5
5
|
|
|
6
|
-
     
|
|
7
|
+
  
|
|
8
8
|
|
|
9
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
10
|
-
- 👤 **Human dev:** ~$
|
|
9
|
+
- 🤖 **LLM usage:** $7.5000 (151 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$5223 (52.2h @ $100/h, 30min dedup)
|
|
11
11
|
|
|
12
12
|
Generated on 2026-03-31 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
13
13
|
|
|
@@ -338,9 +338,9 @@ code2llm ./ -f yaml --separate-orphans
|
|
|
338
338
|
|
|
339
339
|
**Generated by**: `code2llm ./ -f all --readme`
|
|
340
340
|
**Analysis Date**: 2026-03-31
|
|
341
|
-
**Total Functions**:
|
|
342
|
-
**Total Classes**:
|
|
343
|
-
**Modules**:
|
|
341
|
+
**Total Functions**: 1006
|
|
342
|
+
**Total Classes**: 111
|
|
343
|
+
**Modules**: 131
|
|
344
344
|
|
|
345
345
|
For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
|
|
346
346
|
|
|
@@ -8,7 +8,7 @@ Includes NLP Processing Pipeline for query normalization, intent matching,
|
|
|
8
8
|
and entity resolution with multilingual support.
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
|
-
__version__ = "0.5.
|
|
11
|
+
__version__ = "0.5.103"
|
|
12
12
|
__author__ = "STTS Project"
|
|
13
13
|
|
|
14
14
|
# Core analysis components (lightweight, always needed)
|
|
@@ -420,15 +420,34 @@ def analyze_c_family(
|
|
|
420
420
|
patterns: Dict,
|
|
421
421
|
lang_config: Dict,
|
|
422
422
|
cc_lang: str = 'c_family',
|
|
423
|
+
ext: str = '',
|
|
423
424
|
) -> Dict:
|
|
424
425
|
"""Shared analyzer for C-family languages (Java, C#, C++, etc.).
|
|
425
426
|
|
|
426
|
-
|
|
427
|
+
Uses tree-sitter when available (10× faster), falls back to regex.
|
|
427
428
|
"""
|
|
428
|
-
result =
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
429
|
+
result = None
|
|
430
|
+
|
|
431
|
+
# Try tree-sitter first (much faster)
|
|
432
|
+
if ext:
|
|
433
|
+
try:
|
|
434
|
+
from .ts_parser import parse_source
|
|
435
|
+
from .ts_extractors import extract_declarations_ts
|
|
436
|
+
tree = parse_source(content, ext)
|
|
437
|
+
if tree:
|
|
438
|
+
result = extract_declarations_ts(
|
|
439
|
+
tree, content.encode('utf-8'), ext, file_path, module_name
|
|
440
|
+
)
|
|
441
|
+
except ImportError:
|
|
442
|
+
pass # tree-sitter not installed
|
|
443
|
+
|
|
444
|
+
# Fallback to regex
|
|
445
|
+
if result is None:
|
|
446
|
+
result = _extract_declarations(
|
|
447
|
+
content, file_path, module_name,
|
|
448
|
+
patterns, stats, lang_config,
|
|
449
|
+
)
|
|
450
|
+
|
|
432
451
|
calculate_complexity_regex(content, result, lang=cc_lang)
|
|
433
452
|
extract_calls_regex(content, module_name, result)
|
|
434
453
|
stats['files_processed'] += 1
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""C++ analyzer (regex-based, with tree-sitter support)."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import Dict
|
|
5
|
+
|
|
6
|
+
from code2llm.core.lang.base import analyze_c_family
|
|
7
|
+
|
|
8
|
+
# C++-specific patterns
|
|
9
|
+
_CPP_PATTERNS = {
|
|
10
|
+
'import': re.compile(r'^\s*#include\s*["<]([^">]+)[">]'),
|
|
11
|
+
'class': re.compile(
|
|
12
|
+
r'^\s*(?:class|struct)\s+(\w+)'
|
|
13
|
+
r'(?:\s*:\s*(?:public|private|protected)\s+(\w+))?'
|
|
14
|
+
),
|
|
15
|
+
'function': re.compile(
|
|
16
|
+
r'^\s*(?:virtual\s+|static\s+|inline\s+)?'
|
|
17
|
+
r'(?:[\w:*&<>\s]+\s+)?'
|
|
18
|
+
r'(\w+)\s*\([^)]*\)'
|
|
19
|
+
),
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
_CPP_CONFIG = {
|
|
23
|
+
'index_files': (),
|
|
24
|
+
'brace_track': True,
|
|
25
|
+
'reserved': {'if', 'for', 'while', 'switch', 'return', 'catch', 'class'},
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def analyze_cpp(content: str, file_path: str, module_name: str,
|
|
30
|
+
ext: str, stats: Dict) -> Dict:
|
|
31
|
+
"""Analyze C++ files using shared C-family extraction."""
|
|
32
|
+
return analyze_c_family(
|
|
33
|
+
content, file_path, module_name, stats,
|
|
34
|
+
_CPP_PATTERNS, _CPP_CONFIG, ext=ext,
|
|
35
|
+
)
|
|
@@ -38,5 +38,5 @@ def analyze_csharp(content: str, file_path: str, module_name: str,
|
|
|
38
38
|
"""Analyze C# files using shared C-family extraction."""
|
|
39
39
|
return analyze_c_family(
|
|
40
40
|
content, file_path, module_name, stats,
|
|
41
|
-
_CSHARP_PATTERNS, _CSHARP_CONFIG,
|
|
41
|
+
_CSHARP_PATTERNS, _CSHARP_CONFIG, ext=ext,
|
|
42
42
|
)
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
"""Go analyzer (regex-based)."""
|
|
1
|
+
"""Go analyzer (regex-based, with tree-sitter support)."""
|
|
2
2
|
|
|
3
3
|
import re
|
|
4
|
-
from pathlib import Path
|
|
5
4
|
from typing import Dict
|
|
6
5
|
|
|
7
6
|
from code2llm.core.models import ClassInfo, FunctionInfo, ModuleInfo
|
|
8
7
|
from code2llm.core.lang.base import calculate_complexity_regex, extract_calls_regex
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
def
|
|
12
|
-
|
|
13
|
-
"""Analyze Go files using regex-based parsing."""
|
|
10
|
+
def _analyze_go_regex(content: str, file_path: str, module_name: str, stats: Dict) -> Dict:
|
|
11
|
+
"""Regex fallback for Go analysis."""
|
|
14
12
|
result = {
|
|
15
13
|
'module': ModuleInfo(name=module_name, file=file_path, is_package=False),
|
|
16
14
|
'functions': {},
|
|
@@ -20,7 +18,6 @@ def analyze_go(content: str, file_path: str, module_name: str,
|
|
|
20
18
|
}
|
|
21
19
|
|
|
22
20
|
lines = content.split('\n')
|
|
23
|
-
|
|
24
21
|
import_pattern = re.compile(r'^\s*import\s+(?:\(\s*["\']([^"\']+)["\']|["\']([^"\']+)["\'])')
|
|
25
22
|
func_pattern = re.compile(r'^\s*func\s+(?:\([^)]+\)\s+)?(\w+)\s*\(')
|
|
26
23
|
struct_pattern = re.compile(r'^\s*type\s+(\w+)\s+struct')
|
|
@@ -31,14 +28,12 @@ def analyze_go(content: str, file_path: str, module_name: str,
|
|
|
31
28
|
if not line or line.startswith('//'):
|
|
32
29
|
continue
|
|
33
30
|
|
|
34
|
-
# Imports
|
|
35
31
|
import_match = import_pattern.match(line)
|
|
36
32
|
if import_match:
|
|
37
33
|
imp = import_match.group(1) or import_match.group(2)
|
|
38
34
|
if imp:
|
|
39
35
|
result['module'].imports.append(imp)
|
|
40
36
|
|
|
41
|
-
# Functions
|
|
42
37
|
func_match = func_pattern.match(line)
|
|
43
38
|
if func_match:
|
|
44
39
|
func_name = func_match.group(1)
|
|
@@ -53,7 +48,6 @@ def analyze_go(content: str, file_path: str, module_name: str,
|
|
|
53
48
|
result['module'].functions.append(qualified_name)
|
|
54
49
|
stats['functions_found'] += 1
|
|
55
50
|
|
|
56
|
-
# Structs (treated as classes)
|
|
57
51
|
struct_match = struct_pattern.match(line)
|
|
58
52
|
if struct_match:
|
|
59
53
|
class_name = struct_match.group(1)
|
|
@@ -66,7 +60,6 @@ def analyze_go(content: str, file_path: str, module_name: str,
|
|
|
66
60
|
result['module'].classes.append(qualified_name)
|
|
67
61
|
stats['classes_found'] += 1
|
|
68
62
|
|
|
69
|
-
# Interfaces
|
|
70
63
|
interface_match = interface_pattern.match(line)
|
|
71
64
|
if interface_match:
|
|
72
65
|
class_name = interface_match.group(1)
|
|
@@ -79,9 +72,31 @@ def analyze_go(content: str, file_path: str, module_name: str,
|
|
|
79
72
|
result['module'].classes.append(qualified_name)
|
|
80
73
|
stats['classes_found'] += 1
|
|
81
74
|
|
|
82
|
-
|
|
75
|
+
return result
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def analyze_go(content: str, file_path: str, module_name: str,
|
|
79
|
+
ext: str, stats: Dict) -> Dict:
|
|
80
|
+
"""Analyze Go files. Uses tree-sitter when available, regex fallback."""
|
|
81
|
+
result = None
|
|
82
|
+
|
|
83
|
+
# Try tree-sitter first
|
|
84
|
+
try:
|
|
85
|
+
from .ts_parser import parse_source
|
|
86
|
+
from .ts_extractors import extract_declarations_ts
|
|
87
|
+
tree = parse_source(content, ext)
|
|
88
|
+
if tree:
|
|
89
|
+
result = extract_declarations_ts(
|
|
90
|
+
tree, content.encode('utf-8'), ext, file_path, module_name
|
|
91
|
+
)
|
|
92
|
+
except ImportError:
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
# Fallback to regex
|
|
96
|
+
if result is None:
|
|
97
|
+
result = _analyze_go_regex(content, file_path, module_name, stats)
|
|
98
|
+
|
|
83
99
|
calculate_complexity_regex(content, result, lang='go')
|
|
84
100
|
extract_calls_regex(content, module_name, result)
|
|
85
|
-
|
|
86
101
|
stats['files_processed'] += 1
|
|
87
102
|
return result
|
|
@@ -39,5 +39,5 @@ def analyze_java(content: str, file_path: str, module_name: str,
|
|
|
39
39
|
"""Analyze Java files using shared C-family extraction."""
|
|
40
40
|
return analyze_c_family(
|
|
41
41
|
content, file_path, module_name, stats,
|
|
42
|
-
_JAVA_PATTERNS, _JAVA_CONFIG,
|
|
42
|
+
_JAVA_PATTERNS, _JAVA_CONFIG, ext=ext,
|
|
43
43
|
)
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""Tree-sitter based declaration extractors — fast CST traversal.
|
|
2
|
+
|
|
3
|
+
Each language has specific node types for functions, classes, methods.
|
|
4
|
+
This module provides unified extraction using tree-sitter queries.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Dict, List, Optional, Any
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from code2llm.core.models import ClassInfo, FunctionInfo, ModuleInfo
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Node type mappings per language
|
|
14
|
+
FUNCTION_TYPES = {
|
|
15
|
+
'python': ('function_definition', 'async_function_definition'),
|
|
16
|
+
'javascript': ('function_declaration', 'function_expression', 'arrow_function', 'method_definition'),
|
|
17
|
+
'typescript': ('function_declaration', 'function_expression', 'arrow_function', 'method_definition'),
|
|
18
|
+
'go': ('function_declaration', 'method_declaration'),
|
|
19
|
+
'rust': ('function_item', 'impl_item'),
|
|
20
|
+
'java': ('method_declaration', 'constructor_declaration'),
|
|
21
|
+
'c': ('function_definition',),
|
|
22
|
+
'cpp': ('function_definition', 'template_function'),
|
|
23
|
+
'csharp': ('method_declaration', 'constructor_declaration'),
|
|
24
|
+
'php': ('function_definition', 'method_declaration'),
|
|
25
|
+
'ruby': ('method', 'singleton_method'),
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
CLASS_TYPES = {
|
|
29
|
+
'python': ('class_definition',),
|
|
30
|
+
'javascript': ('class_declaration', 'class_expression'),
|
|
31
|
+
'typescript': ('class_declaration', 'class_expression', 'interface_declaration'),
|
|
32
|
+
'go': ('type_declaration',),
|
|
33
|
+
'rust': ('struct_item', 'enum_item', 'impl_item', 'trait_item'),
|
|
34
|
+
'java': ('class_declaration', 'interface_declaration', 'enum_declaration'),
|
|
35
|
+
'c': ('struct_specifier',),
|
|
36
|
+
'cpp': ('class_specifier', 'struct_specifier'),
|
|
37
|
+
'csharp': ('class_declaration', 'interface_declaration', 'struct_declaration'),
|
|
38
|
+
'php': ('class_declaration', 'interface_declaration', 'trait_declaration'),
|
|
39
|
+
'ruby': ('class', 'module'),
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
EXT_TO_LANG = {
|
|
43
|
+
'.py': 'python',
|
|
44
|
+
'.js': 'javascript', '.jsx': 'javascript', '.mjs': 'javascript', '.cjs': 'javascript',
|
|
45
|
+
'.ts': 'typescript', '.tsx': 'typescript',
|
|
46
|
+
'.go': 'go',
|
|
47
|
+
'.rs': 'rust',
|
|
48
|
+
'.java': 'java',
|
|
49
|
+
'.c': 'c', '.h': 'c',
|
|
50
|
+
'.cpp': 'cpp', '.cc': 'cpp', '.cxx': 'cpp', '.hpp': 'cpp', '.hxx': 'cpp',
|
|
51
|
+
'.cs': 'csharp',
|
|
52
|
+
'.php': 'php',
|
|
53
|
+
'.rb': 'ruby',
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _get_node_text(node, source_bytes: bytes) -> str:
|
|
58
|
+
"""Extract text content of a node."""
|
|
59
|
+
return source_bytes[node.start_byte:node.end_byte].decode('utf-8', errors='replace')
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _find_name_node(node) -> Optional[Any]:
|
|
63
|
+
"""Find the name/identifier child of a node."""
|
|
64
|
+
for child in node.children:
|
|
65
|
+
if child.type in ('identifier', 'name', 'property_identifier', 'type_identifier'):
|
|
66
|
+
return child
|
|
67
|
+
# For method definitions, look for property_identifier
|
|
68
|
+
if child.type == 'property_identifier':
|
|
69
|
+
return child
|
|
70
|
+
# Fallback: look in named children
|
|
71
|
+
for child in node.children:
|
|
72
|
+
if 'name' in child.type or 'identifier' in child.type:
|
|
73
|
+
return child
|
|
74
|
+
return None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _extract_functions_ts(tree, source_bytes: bytes, lang: str,
|
|
78
|
+
module_name: str, file_path: str) -> Dict[str, FunctionInfo]:
|
|
79
|
+
"""Extract functions using tree-sitter traversal."""
|
|
80
|
+
functions = {}
|
|
81
|
+
func_types = FUNCTION_TYPES.get(lang, ())
|
|
82
|
+
|
|
83
|
+
def visit(node, class_context: Optional[str] = None):
|
|
84
|
+
if node.type in func_types:
|
|
85
|
+
name_node = _find_name_node(node)
|
|
86
|
+
if name_node:
|
|
87
|
+
name = _get_node_text(name_node, source_bytes)
|
|
88
|
+
if class_context:
|
|
89
|
+
qname = f"{module_name}.{class_context}.{name}"
|
|
90
|
+
else:
|
|
91
|
+
qname = f"{module_name}.{name}"
|
|
92
|
+
|
|
93
|
+
# Count lines
|
|
94
|
+
start_line = node.start_point[0] + 1
|
|
95
|
+
end_line = node.end_point[0] + 1
|
|
96
|
+
line_count = end_line - start_line + 1
|
|
97
|
+
|
|
98
|
+
functions[qname] = FunctionInfo(
|
|
99
|
+
name=name,
|
|
100
|
+
qualified_name=qname,
|
|
101
|
+
file=file_path,
|
|
102
|
+
line=start_line,
|
|
103
|
+
end_line=end_line,
|
|
104
|
+
line_count=line_count,
|
|
105
|
+
is_method=class_context is not None,
|
|
106
|
+
class_name=class_context,
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# Recurse, tracking class context
|
|
110
|
+
new_class = None
|
|
111
|
+
class_types = CLASS_TYPES.get(lang, ())
|
|
112
|
+
if node.type in class_types:
|
|
113
|
+
name_node = _find_name_node(node)
|
|
114
|
+
if name_node:
|
|
115
|
+
new_class = _get_node_text(name_node, source_bytes)
|
|
116
|
+
|
|
117
|
+
for child in node.children:
|
|
118
|
+
visit(child, new_class or class_context)
|
|
119
|
+
|
|
120
|
+
visit(tree.root_node)
|
|
121
|
+
return functions
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def _extract_classes_ts(tree, source_bytes: bytes, lang: str,
|
|
125
|
+
module_name: str, file_path: str) -> Dict[str, ClassInfo]:
|
|
126
|
+
"""Extract classes using tree-sitter traversal."""
|
|
127
|
+
classes = {}
|
|
128
|
+
class_types = CLASS_TYPES.get(lang, ())
|
|
129
|
+
|
|
130
|
+
def visit(node):
|
|
131
|
+
if node.type in class_types:
|
|
132
|
+
name_node = _find_name_node(node)
|
|
133
|
+
if name_node:
|
|
134
|
+
name = _get_node_text(name_node, source_bytes)
|
|
135
|
+
qname = f"{module_name}.{name}"
|
|
136
|
+
start_line = node.start_point[0] + 1
|
|
137
|
+
end_line = node.end_point[0] + 1
|
|
138
|
+
|
|
139
|
+
classes[qname] = ClassInfo(
|
|
140
|
+
name=name,
|
|
141
|
+
qualified_name=qname,
|
|
142
|
+
file=file_path,
|
|
143
|
+
line=start_line,
|
|
144
|
+
end_line=end_line,
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
for child in node.children:
|
|
148
|
+
visit(child)
|
|
149
|
+
|
|
150
|
+
visit(tree.root_node)
|
|
151
|
+
return classes
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def extract_declarations_ts(
|
|
155
|
+
tree,
|
|
156
|
+
source_bytes: bytes,
|
|
157
|
+
ext: str,
|
|
158
|
+
file_path: str,
|
|
159
|
+
module_name: str,
|
|
160
|
+
) -> Dict:
|
|
161
|
+
"""Extract all declarations from a tree-sitter tree.
|
|
162
|
+
|
|
163
|
+
Returns dict compatible with regex-based _extract_declarations.
|
|
164
|
+
"""
|
|
165
|
+
lang = EXT_TO_LANG.get(ext, 'generic')
|
|
166
|
+
|
|
167
|
+
functions = _extract_functions_ts(tree, source_bytes, lang, module_name, file_path)
|
|
168
|
+
classes = _extract_classes_ts(tree, source_bytes, lang, module_name, file_path)
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
'module': ModuleInfo(
|
|
172
|
+
name=module_name,
|
|
173
|
+
file=file_path,
|
|
174
|
+
is_package=Path(file_path).name in ('__init__.py', 'index.js', 'index.ts', 'mod.rs', 'lib.rs'),
|
|
175
|
+
),
|
|
176
|
+
'functions': functions,
|
|
177
|
+
'classes': classes,
|
|
178
|
+
'nodes': {},
|
|
179
|
+
'edges': [],
|
|
180
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""Tree-sitter parser wrapper — fast CST parsing for all supported languages.
|
|
2
|
+
|
|
3
|
+
Replaces regex-based parsing with tree-sitter for 10× speedup and better accuracy.
|
|
4
|
+
Falls back to regex parsing if tree-sitter grammar is unavailable.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Any, Dict, Optional
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__name__)
|
|
11
|
+
|
|
12
|
+
# Lazy-loaded language modules
|
|
13
|
+
_LANGUAGE_MODULES: Dict[str, Any] = {}
|
|
14
|
+
_PARSERS: Dict[str, Any] = {}
|
|
15
|
+
_TS_AVAILABLE = False
|
|
16
|
+
|
|
17
|
+
# Extension -> (grammar module name, language getter)
|
|
18
|
+
EXTENSION_MAP = {
|
|
19
|
+
'.py': ('tree_sitter_python', 'language'),
|
|
20
|
+
'.js': ('tree_sitter_javascript', 'language'),
|
|
21
|
+
'.jsx': ('tree_sitter_javascript', 'language'),
|
|
22
|
+
'.mjs': ('tree_sitter_javascript', 'language'),
|
|
23
|
+
'.cjs': ('tree_sitter_javascript', 'language'),
|
|
24
|
+
'.ts': ('tree_sitter_typescript', 'language_typescript'),
|
|
25
|
+
'.tsx': ('tree_sitter_typescript', 'language_tsx'),
|
|
26
|
+
'.go': ('tree_sitter_go', 'language'),
|
|
27
|
+
'.rs': ('tree_sitter_rust', 'language'),
|
|
28
|
+
'.java': ('tree_sitter_java', 'language'),
|
|
29
|
+
'.c': ('tree_sitter_c', 'language'),
|
|
30
|
+
'.h': ('tree_sitter_c', 'language'),
|
|
31
|
+
'.cpp': ('tree_sitter_cpp', 'language'),
|
|
32
|
+
'.cc': ('tree_sitter_cpp', 'language'),
|
|
33
|
+
'.cxx': ('tree_sitter_cpp', 'language'),
|
|
34
|
+
'.hpp': ('tree_sitter_cpp', 'language'),
|
|
35
|
+
'.hxx': ('tree_sitter_cpp', 'language'),
|
|
36
|
+
'.cs': ('tree_sitter_c_sharp', 'language'),
|
|
37
|
+
'.php': ('tree_sitter_php', 'language_php'),
|
|
38
|
+
'.rb': ('tree_sitter_ruby', 'language'),
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _init_tree_sitter() -> bool:
|
|
43
|
+
"""Initialize tree-sitter. Returns True if available."""
|
|
44
|
+
global _TS_AVAILABLE
|
|
45
|
+
try:
|
|
46
|
+
import tree_sitter
|
|
47
|
+
_TS_AVAILABLE = True
|
|
48
|
+
return True
|
|
49
|
+
except ImportError:
|
|
50
|
+
logger.debug("tree-sitter not installed, using regex fallback")
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _get_language(ext: str) -> Optional[Any]:
|
|
55
|
+
"""Get tree-sitter Language for file extension."""
|
|
56
|
+
if not _TS_AVAILABLE and not _init_tree_sitter():
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
if ext not in EXTENSION_MAP:
|
|
60
|
+
return None
|
|
61
|
+
|
|
62
|
+
module_name, lang_attr = EXTENSION_MAP[ext]
|
|
63
|
+
|
|
64
|
+
if module_name in _LANGUAGE_MODULES:
|
|
65
|
+
return _LANGUAGE_MODULES[module_name]
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
import importlib
|
|
69
|
+
mod = importlib.import_module(module_name)
|
|
70
|
+
lang_fn = getattr(mod, lang_attr, None)
|
|
71
|
+
if callable(lang_fn):
|
|
72
|
+
lang = lang_fn()
|
|
73
|
+
_LANGUAGE_MODULES[module_name] = lang
|
|
74
|
+
return lang
|
|
75
|
+
except (ImportError, AttributeError) as e:
|
|
76
|
+
logger.debug("Cannot load %s: %s", module_name, e)
|
|
77
|
+
_LANGUAGE_MODULES[module_name] = None
|
|
78
|
+
|
|
79
|
+
return None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _get_parser(ext: str) -> Optional[Any]:
|
|
83
|
+
"""Get or create tree-sitter Parser for file extension."""
|
|
84
|
+
if ext in _PARSERS:
|
|
85
|
+
return _PARSERS[ext]
|
|
86
|
+
|
|
87
|
+
lang = _get_language(ext)
|
|
88
|
+
if not lang:
|
|
89
|
+
_PARSERS[ext] = None
|
|
90
|
+
return None
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
from tree_sitter import Parser
|
|
94
|
+
parser = Parser(lang)
|
|
95
|
+
_PARSERS[ext] = parser
|
|
96
|
+
return parser
|
|
97
|
+
except Exception as e:
|
|
98
|
+
logger.debug("Cannot create parser for %s: %s", ext, e)
|
|
99
|
+
_PARSERS[ext] = None
|
|
100
|
+
return None
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
class TreeSitterParser:
|
|
104
|
+
"""Unified tree-sitter parser for all supported languages.
|
|
105
|
+
|
|
106
|
+
Usage::
|
|
107
|
+
|
|
108
|
+
parser = TreeSitterParser()
|
|
109
|
+
tree = parser.parse(source_bytes, ".ts")
|
|
110
|
+
if tree:
|
|
111
|
+
# Use tree.root_node for traversal
|
|
112
|
+
for node in tree.root_node.children:
|
|
113
|
+
...
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
def __init__(self):
|
|
117
|
+
self._initialized = _init_tree_sitter()
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def available(self) -> bool:
|
|
121
|
+
return self._initialized
|
|
122
|
+
|
|
123
|
+
def parse(self, source: bytes, ext: str) -> Optional[Any]:
|
|
124
|
+
"""Parse source code and return tree, or None if unavailable."""
|
|
125
|
+
parser = _get_parser(ext)
|
|
126
|
+
if not parser:
|
|
127
|
+
return None
|
|
128
|
+
try:
|
|
129
|
+
return parser.parse(source)
|
|
130
|
+
except Exception as e:
|
|
131
|
+
logger.debug("Parse error for %s: %s", ext, e)
|
|
132
|
+
return None
|
|
133
|
+
|
|
134
|
+
def supports(self, ext: str) -> bool:
|
|
135
|
+
"""Check if extension is supported by tree-sitter."""
|
|
136
|
+
return ext in EXTENSION_MAP and _get_language(ext) is not None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# Singleton instance
|
|
140
|
+
_parser_instance: Optional[TreeSitterParser] = None
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def get_parser() -> TreeSitterParser:
|
|
144
|
+
"""Get global TreeSitterParser instance."""
|
|
145
|
+
global _parser_instance
|
|
146
|
+
if _parser_instance is None:
|
|
147
|
+
_parser_instance = TreeSitterParser()
|
|
148
|
+
return _parser_instance
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def parse_source(content: str, ext: str) -> Optional[Any]:
|
|
152
|
+
"""Convenience function: parse string content for given extension."""
|
|
153
|
+
return get_parser().parse(content.encode('utf-8'), ext)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def is_available() -> bool:
|
|
157
|
+
"""Check if tree-sitter is available."""
|
|
158
|
+
return get_parser().available
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.103
|
|
4
4
|
Summary: High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries
|
|
5
5
|
Home-page: https://github.com/wronai/stts
|
|
6
6
|
Author: STTS Project
|
|
@@ -37,6 +37,16 @@ Requires-Dist: vulture>=2.10
|
|
|
37
37
|
Requires-Dist: tiktoken>=0.5
|
|
38
38
|
Requires-Dist: tree-sitter>=0.21
|
|
39
39
|
Requires-Dist: tree-sitter-python>=0.21
|
|
40
|
+
Requires-Dist: tree-sitter-javascript>=0.21
|
|
41
|
+
Requires-Dist: tree-sitter-typescript>=0.21
|
|
42
|
+
Requires-Dist: tree-sitter-go>=0.21
|
|
43
|
+
Requires-Dist: tree-sitter-rust>=0.21
|
|
44
|
+
Requires-Dist: tree-sitter-java>=0.21
|
|
45
|
+
Requires-Dist: tree-sitter-c>=0.21
|
|
46
|
+
Requires-Dist: tree-sitter-cpp>=0.22
|
|
47
|
+
Requires-Dist: tree-sitter-c-sharp>=0.21
|
|
48
|
+
Requires-Dist: tree-sitter-php>=0.22
|
|
49
|
+
Requires-Dist: tree-sitter-ruby>=0.21
|
|
40
50
|
Provides-Extra: dev
|
|
41
51
|
Requires-Dist: pytest>=6.2; extra == "dev"
|
|
42
52
|
Requires-Dist: pytest-cov>=2.12; extra == "dev"
|
|
@@ -56,11 +66,11 @@ Dynamic: requires-python
|
|
|
56
66
|
|
|
57
67
|
## AI Cost Tracking
|
|
58
68
|
|
|
59
|
-
     
|
|
70
|
+
  
|
|
61
71
|
|
|
62
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
63
|
-
- 👤 **Human dev:** ~$
|
|
72
|
+
- 🤖 **LLM usage:** $7.5000 (151 commits)
|
|
73
|
+
- 👤 **Human dev:** ~$5223 (52.2h @ $100/h, 30min dedup)
|
|
64
74
|
|
|
65
75
|
Generated on 2026-03-31 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
66
76
|
|
|
@@ -391,9 +401,9 @@ code2llm ./ -f yaml --separate-orphans
|
|
|
391
401
|
|
|
392
402
|
**Generated by**: `code2llm ./ -f all --readme`
|
|
393
403
|
**Analysis Date**: 2026-03-31
|
|
394
|
-
**Total Functions**:
|
|
395
|
-
**Total Classes**:
|
|
396
|
-
**Modules**:
|
|
404
|
+
**Total Functions**: 1006
|
|
405
|
+
**Total Classes**: 111
|
|
406
|
+
**Modules**: 131
|
|
397
407
|
|
|
398
408
|
For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
|
|
399
409
|
|
|
@@ -58,6 +58,8 @@ code2llm/core/lang/java.py
|
|
|
58
58
|
code2llm/core/lang/php.py
|
|
59
59
|
code2llm/core/lang/ruby.py
|
|
60
60
|
code2llm/core/lang/rust.py
|
|
61
|
+
code2llm/core/lang/ts_extractors.py
|
|
62
|
+
code2llm/core/lang/ts_parser.py
|
|
61
63
|
code2llm/core/lang/typescript.py
|
|
62
64
|
code2llm/core/streaming/__init__.py
|
|
63
65
|
code2llm/core/streaming/cache.py
|
|
@@ -10,6 +10,16 @@ vulture>=2.10
|
|
|
10
10
|
tiktoken>=0.5
|
|
11
11
|
tree-sitter>=0.21
|
|
12
12
|
tree-sitter-python>=0.21
|
|
13
|
+
tree-sitter-javascript>=0.21
|
|
14
|
+
tree-sitter-typescript>=0.21
|
|
15
|
+
tree-sitter-go>=0.21
|
|
16
|
+
tree-sitter-rust>=0.21
|
|
17
|
+
tree-sitter-java>=0.21
|
|
18
|
+
tree-sitter-c>=0.21
|
|
19
|
+
tree-sitter-cpp>=0.22
|
|
20
|
+
tree-sitter-c-sharp>=0.21
|
|
21
|
+
tree-sitter-php>=0.22
|
|
22
|
+
tree-sitter-ruby>=0.21
|
|
13
23
|
|
|
14
24
|
[dev]
|
|
15
25
|
pytest>=6.2
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "code2llm"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.103"
|
|
8
8
|
description = "High-performance Python code flow analysis with optimized TOON format - CFG, DFG, call graphs, and intelligent code queries"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -51,6 +51,16 @@ dependencies = [
|
|
|
51
51
|
"tiktoken>=0.5",
|
|
52
52
|
"tree-sitter>=0.21",
|
|
53
53
|
"tree-sitter-python>=0.21",
|
|
54
|
+
"tree-sitter-javascript>=0.21",
|
|
55
|
+
"tree-sitter-typescript>=0.21",
|
|
56
|
+
"tree-sitter-go>=0.21",
|
|
57
|
+
"tree-sitter-rust>=0.21",
|
|
58
|
+
"tree-sitter-java>=0.21",
|
|
59
|
+
"tree-sitter-c>=0.21",
|
|
60
|
+
"tree-sitter-cpp>=0.22",
|
|
61
|
+
"tree-sitter-c-sharp>=0.21",
|
|
62
|
+
"tree-sitter-php>=0.22",
|
|
63
|
+
"tree-sitter-ruby>=0.21",
|
|
54
64
|
]
|
|
55
65
|
|
|
56
66
|
[project.optional-dependencies]
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"""C++ analyzer (regex-based)."""
|
|
2
|
-
|
|
3
|
-
import re
|
|
4
|
-
from typing import Dict
|
|
5
|
-
|
|
6
|
-
from code2llm.core.models import ClassInfo, FunctionInfo, ModuleInfo
|
|
7
|
-
from code2llm.core.lang.base import calculate_complexity_regex, extract_calls_regex, _extract_declarations
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def analyze_cpp(content: str, file_path: str, module_name: str,
|
|
11
|
-
ext: str, stats: Dict) -> Dict:
|
|
12
|
-
"""Analyze C++ files using shared extraction."""
|
|
13
|
-
|
|
14
|
-
patterns = {
|
|
15
|
-
'import': re.compile(r'^\s*#include\s*["<]([^">]+)[">]'),
|
|
16
|
-
'class': re.compile(
|
|
17
|
-
r'^\s*(?:class|struct)\s+(\w+)'
|
|
18
|
-
r'(?:\s*:\s*(?:public|private|protected)\s+(\w+))?'
|
|
19
|
-
),
|
|
20
|
-
'function': re.compile(
|
|
21
|
-
r'^\s*(?:virtual\s+|static\s+|inline\s+)?'
|
|
22
|
-
r'(?:[\w:*&<>\s]+\s+)?' # return type
|
|
23
|
-
r'(\w+)\s*\([^)]*\)' # name and params
|
|
24
|
-
),
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
lang_config = {
|
|
28
|
-
'index_files': (),
|
|
29
|
-
'brace_track': True,
|
|
30
|
-
'reserved': {'if', 'for', 'while', 'switch', 'return', 'catch', 'class'},
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
result = _extract_declarations(
|
|
34
|
-
content, file_path, module_name,
|
|
35
|
-
patterns, stats, lang_config
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
calculate_complexity_regex(content, result, lang='c_family')
|
|
39
|
-
extract_calls_regex(content, module_name, result)
|
|
40
|
-
|
|
41
|
-
stats['files_processed'] += 1
|
|
42
|
-
return result
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|