code2llm 0.5.60__tar.gz → 0.5.62__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.60 → code2llm-0.5.62}/PKG-INFO +1 -1
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/__init__.py +1 -1
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/__init__.py +13 -4
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/analyzer.py +7 -2
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/file_analyzer.py +4 -4
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/file_filter.py +2 -2
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/cpp.py +1 -1
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/csharp.py +1 -1
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/generic.py +1 -1
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/go_lang.py +1 -1
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/java.py +1 -1
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/php.py +1 -1
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/ruby.py +1 -1
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/rust.py +1 -1
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/typescript.py +1 -1
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/refactoring.py +3 -3
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/index_generator.py +38 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/toon/__init__.py +6 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/toon/renderer.py +86 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/nlp/__init__.py +1 -1
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm.egg-info/PKG-INFO +1 -1
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm.egg-info/SOURCES.txt +15 -16
- {code2llm-0.5.60 → code2llm-0.5.62}/pyproject.toml +1 -1
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_advanced_analysis.py +1 -1
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_format_quality.py +4 -2
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_toon_v2.py +2 -2
- code2llm-0.5.60/code2llm/core/core/__init__.py +0 -6
- {code2llm-0.5.60 → code2llm-0.5.62}/LICENSE +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/README.md +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/__main__.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/__init__.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/call_graph.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/cfg.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/coupling.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/data_analysis.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/dfg.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/pipeline_detector.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/side_effects.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/smells.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/analysis/type_inference.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/api.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/cli.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/cli_analysis.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/cli_commands.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/cli_exports/__init__.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/cli_exports/code2logic.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/cli_exports/formats.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/cli_exports/orchestrator.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/cli_exports/prompt.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/cli_parser.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/config.py +0 -0
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/file_cache.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/gitignore.py +0 -0
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/__init__.py +0 -0
- {code2llm-0.5.60/code2llm/core → code2llm-0.5.62/code2llm}/core/lang/base.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/large_repo.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/models.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/repo_files.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/streaming/__init__.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/streaming/cache.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/streaming/incremental.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/streaming/prioritizer.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/streaming/scanner.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/streaming/strategies.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/streaming_analyzer.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/core/toon_size_manager.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/__init__.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/article_view.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/base.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/context_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/context_view.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/evolution_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/flow_constants.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/flow_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/flow_renderer.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/html_dashboard.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/json_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/llm_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/map_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/mermaid_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/project_yaml_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/readme_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/report_generators.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/toon/helpers.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/toon/metrics.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/toon/module_detail.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/toon.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/toon_view.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/validate_project.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/exporters/yaml_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/generators/__init__.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/generators/llm_flow.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/generators/llm_task.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/generators/mermaid.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/nlp/config.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/nlp/entity_resolution.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/nlp/intent_matching.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/nlp/normalization.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/nlp/pipeline.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/patterns/__init__.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/patterns/detector.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/refactor/__init__.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm/refactor/prompt_engine.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm.egg-info/dependency_links.txt +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm.egg-info/entry_points.txt +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm.egg-info/requires.txt +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/code2llm.egg-info/top_level.txt +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/setup.cfg +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/setup.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_analyzer.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_deep_analysis.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_edge_cases.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_flow_exporter.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_multilanguage_e2e.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_nlp_pipeline.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_nonpython_cc_calls.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_pipeline_detector.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_prompt_engine.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_prompt_txt.py +0 -0
- {code2llm-0.5.60 → code2llm-0.5.62}/tests/test_refactoring_engine.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.62
|
|
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
|
|
@@ -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.62"
|
|
12
12
|
__author__ = "STTS Project"
|
|
13
13
|
|
|
14
14
|
# Core analysis components (lightweight, always needed)
|
|
@@ -28,10 +28,19 @@ __all__ = [
|
|
|
28
28
|
|
|
29
29
|
def __getattr__(name):
|
|
30
30
|
"""Lazy import heavy modules on first access."""
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
if name == 'ProjectAnalyzer':
|
|
32
|
+
from .analyzer import ProjectAnalyzer
|
|
33
|
+
return ProjectAnalyzer
|
|
34
|
+
if name == 'FileAnalyzer':
|
|
35
|
+
from .file_analyzer import FileAnalyzer
|
|
36
|
+
return FileAnalyzer
|
|
37
|
+
if name == 'RefactoringAnalyzer':
|
|
38
|
+
from .refactoring import RefactoringAnalyzer
|
|
39
|
+
return RefactoringAnalyzer
|
|
40
|
+
if name in {'FileCache', 'FastFileFilter'}:
|
|
41
|
+
from .file_cache import FileCache
|
|
42
|
+
from .file_filter import FastFileFilter
|
|
43
|
+
return locals()[name]
|
|
35
44
|
|
|
36
45
|
_streaming_names = {
|
|
37
46
|
'StreamingAnalyzer', 'IncrementalAnalyzer', 'ScanStrategy',
|
|
@@ -9,7 +9,10 @@ from .config import Config, FAST_CONFIG, ALL_EXTENSIONS, LANGUAGE_EXTENSIONS
|
|
|
9
9
|
from .models import AnalysisResult, FlowEdge, FlowNode, Pattern
|
|
10
10
|
from ..analysis.call_graph import CallGraphExtractor
|
|
11
11
|
|
|
12
|
-
from .
|
|
12
|
+
from .file_cache import FileCache
|
|
13
|
+
from .file_filter import FastFileFilter
|
|
14
|
+
from .file_analyzer import FileAnalyzer, _analyze_single_file
|
|
15
|
+
from .refactoring import RefactoringAnalyzer
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
class ProjectAnalyzer:
|
|
@@ -325,4 +328,6 @@ class ProjectAnalyzer:
|
|
|
325
328
|
|
|
326
329
|
|
|
327
330
|
# Re-export for backward compatibility
|
|
328
|
-
from .
|
|
331
|
+
from .file_cache import FileCache
|
|
332
|
+
from .file_filter import FastFileFilter
|
|
333
|
+
from .file_analyzer import FileAnalyzer
|
|
@@ -7,13 +7,13 @@ from typing import Dict, List, Optional
|
|
|
7
7
|
|
|
8
8
|
from radon.complexity import cc_visit, cc_rank
|
|
9
9
|
|
|
10
|
-
from
|
|
11
|
-
from
|
|
10
|
+
from .config import Config, LANGUAGE_EXTENSIONS
|
|
11
|
+
from .models import (
|
|
12
12
|
AnalysisResult, ClassInfo, FlowEdge, FlowNode,
|
|
13
13
|
FunctionInfo, ModuleInfo
|
|
14
14
|
)
|
|
15
|
-
from
|
|
16
|
-
from
|
|
15
|
+
from ..analysis.dfg import DFGExtractor
|
|
16
|
+
from ..analysis.call_graph import CallGraphExtractor
|
|
17
17
|
from .file_filter import FastFileFilter
|
|
18
18
|
from .lang import (
|
|
19
19
|
analyze_typescript_js, analyze_go, analyze_rust, analyze_java,
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
from typing import Optional
|
|
5
5
|
|
|
6
|
-
from
|
|
7
|
-
from
|
|
6
|
+
from .config import Config
|
|
7
|
+
from .models import AnalysisResult
|
|
8
8
|
from .file_filter import FastFileFilter
|
|
9
9
|
|
|
10
10
|
|
|
@@ -21,7 +21,7 @@ class RefactoringAnalyzer:
|
|
|
21
21
|
print("Performing refactoring analysis...")
|
|
22
22
|
|
|
23
23
|
# 1. Calculate metrics (fan-in/fan-out)
|
|
24
|
-
from
|
|
24
|
+
from ..analysis.call_graph import CallGraphExtractor
|
|
25
25
|
cg_ext = CallGraphExtractor(self.config)
|
|
26
26
|
cg_ext.result = result
|
|
27
27
|
cg_ext._calculate_metrics()
|
|
@@ -28,6 +28,12 @@ class IndexHTMLGenerator:
|
|
|
28
28
|
'.go': {'icon': '🐹', 'type': 'code', 'name': 'Go'},
|
|
29
29
|
'.rs': {'icon': '🦀', 'type': 'code', 'name': 'Rust'},
|
|
30
30
|
'.java': {'icon': '☕', 'type': 'code', 'name': 'Java'},
|
|
31
|
+
'.png': {'icon': '🖼️', 'type': 'image', 'name': 'Image'},
|
|
32
|
+
'.jpg': {'icon': '🖼️', 'type': 'image', 'name': 'Image'},
|
|
33
|
+
'.jpeg': {'icon': '🖼️', 'type': 'image', 'name': 'Image'},
|
|
34
|
+
'.gif': {'icon': '🖼️', 'type': 'image', 'name': 'Image'},
|
|
35
|
+
'.svg': {'icon': '🖼️', 'type': 'image', 'name': 'Image'},
|
|
36
|
+
'.webp': {'icon': '🖼️', 'type': 'image', 'name': 'Image'},
|
|
31
37
|
}
|
|
32
38
|
|
|
33
39
|
def __init__(self, output_dir: Path):
|
|
@@ -124,6 +130,7 @@ class IndexHTMLGenerator:
|
|
|
124
130
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
|
|
125
131
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
|
126
132
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/json.min.js"></script>
|
|
133
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/yaml.min.js"></script>
|
|
127
134
|
<style>
|
|
128
135
|
:root {{
|
|
129
136
|
--bg: #0f172a;
|
|
@@ -535,6 +542,22 @@ class IndexHTMLGenerator:
|
|
|
535
542
|
background: transparent;
|
|
536
543
|
}}
|
|
537
544
|
|
|
545
|
+
/* Image preview styles */
|
|
546
|
+
.image-preview {{
|
|
547
|
+
display: flex;
|
|
548
|
+
justify-content: center;
|
|
549
|
+
align-items: center;
|
|
550
|
+
height: 100%;
|
|
551
|
+
padding: 1rem;
|
|
552
|
+
background: var(--surface);
|
|
553
|
+
border-radius: 0.5rem;
|
|
554
|
+
border: 1px solid var(--border);
|
|
555
|
+
}}
|
|
556
|
+
|
|
557
|
+
.image-preview img {{
|
|
558
|
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
559
|
+
}}
|
|
560
|
+
|
|
538
561
|
/* Mobile responsive */
|
|
539
562
|
@media (max-width: 768px) {{
|
|
540
563
|
.container {{
|
|
@@ -694,6 +717,9 @@ class IndexHTMLGenerator:
|
|
|
694
717
|
}} else if (file.type === 'html') {{
|
|
695
718
|
// For HTML files, show in iframe for safety
|
|
696
719
|
body.innerHTML = `<iframe src="${{file.rel_path}}" style="width:100%;height:100%;border:none;border-radius:0.5rem;"></iframe>`;
|
|
720
|
+
}} else if (file.type === 'image') {{
|
|
721
|
+
// For images, display the actual image
|
|
722
|
+
body.innerHTML = `<div class="image-preview"><img src="${{file.rel_path}}" alt="${{file.name}}" style="max-width:100%;max-height:100%;object-fit:contain;border-radius:0.5rem;"></div>`;
|
|
697
723
|
}} else if (file.type === 'mermaid') {{
|
|
698
724
|
// Render mermaid diagram
|
|
699
725
|
const diagramId = 'mermaid-diagram-' + Date.now();
|
|
@@ -711,6 +737,18 @@ class IndexHTMLGenerator:
|
|
|
711
737
|
}} catch {{
|
|
712
738
|
body.innerHTML = `<pre>${{file.content}}</pre>`;
|
|
713
739
|
}}
|
|
740
|
+
}} else if (file.type === 'yaml') {{
|
|
741
|
+
// YAML with syntax highlighting
|
|
742
|
+
body.innerHTML = `<pre><code class="language-yaml">${{file.content.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')}}</code></pre>`;
|
|
743
|
+
hljs.highlightElement(body.querySelector('code'));
|
|
744
|
+
}} else if (file.type === 'toon') {{
|
|
745
|
+
// TOON with simple highlighting (use ini as closest match for key: value format)
|
|
746
|
+
body.innerHTML = `<pre><code class="language-ini">${{file.content.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')}}</code></pre>`;
|
|
747
|
+
hljs.highlightElement(body.querySelector('code'));
|
|
748
|
+
}} else if (file.type === 'code') {{
|
|
749
|
+
// Code files with auto-highlighting
|
|
750
|
+
body.innerHTML = `<pre><code>${{file.content.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')}}</code></pre>`;
|
|
751
|
+
hljs.highlightElement(body.querySelector('code'));
|
|
714
752
|
}} else {{
|
|
715
753
|
body.innerHTML = `<pre>${{file.content}}</pre>`;
|
|
716
754
|
}}
|
|
@@ -38,9 +38,15 @@ class ToonExporter:
|
|
|
38
38
|
sections.append("")
|
|
39
39
|
sections.extend(self.renderer.render_health(ctx))
|
|
40
40
|
sections.append("")
|
|
41
|
+
sections.extend(self.renderer.render_refactor(ctx))
|
|
42
|
+
sections.append("")
|
|
43
|
+
sections.extend(self.renderer.render_pipelines(ctx))
|
|
44
|
+
sections.append("")
|
|
41
45
|
sections.extend(self.renderer.render_layers(ctx))
|
|
42
46
|
sections.append("")
|
|
43
47
|
sections.extend(self.renderer.render_coupling(ctx))
|
|
48
|
+
sections.append("")
|
|
49
|
+
sections.extend(self.renderer.render_external(ctx))
|
|
44
50
|
|
|
45
51
|
Path(output_path).parent.mkdir(parents=True, exist_ok=True)
|
|
46
52
|
with open(output_path, "w", encoding="utf-8") as f:
|
|
@@ -383,3 +383,89 @@ class ToonRenderer:
|
|
|
383
383
|
)
|
|
384
384
|
|
|
385
385
|
return lines
|
|
386
|
+
|
|
387
|
+
def render_pipelines(self, ctx: Dict[str, Any]) -> List[str]:
|
|
388
|
+
"""Render PIPELINES section - data flow pipelines from entry points."""
|
|
389
|
+
result: AnalysisResult = ctx["result"]
|
|
390
|
+
|
|
391
|
+
# Find entry points and their downstream pipelines
|
|
392
|
+
pipelines = []
|
|
393
|
+
for func_name, func_info in result.functions.items():
|
|
394
|
+
# Entry points: functions with no callers but have calls
|
|
395
|
+
if not func_info.called_by and func_info.calls:
|
|
396
|
+
chain = self._trace_pipeline(func_name, result, depth=0)
|
|
397
|
+
if chain:
|
|
398
|
+
pipelines.append({
|
|
399
|
+
"entry": func_name.split(".")[-1],
|
|
400
|
+
"chain": chain,
|
|
401
|
+
"purity": self._calculate_purity(chain, result),
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
if not pipelines:
|
|
405
|
+
return ["PIPELINES[0]: none detected"]
|
|
406
|
+
|
|
407
|
+
lines = [f"PIPELINES[{len(pipelines)}]:"]
|
|
408
|
+
for i, pipe in enumerate(pipelines[:5], 1): # Max 5 pipelines
|
|
409
|
+
purity_pct = int(pipe["purity"] * 100)
|
|
410
|
+
chain_str = " → ".join(pipe["chain"][:4]) # Show first 4 steps
|
|
411
|
+
if len(pipe["chain"]) > 4:
|
|
412
|
+
chain_str += f" → ...({len(pipe['chain']) - 4} more)"
|
|
413
|
+
lines.append(f" [{i}] Src [{pipe['entry']}]: {chain_str}")
|
|
414
|
+
lines.append(f" PURITY: {purity_pct}% pure")
|
|
415
|
+
|
|
416
|
+
return lines
|
|
417
|
+
|
|
418
|
+
def _trace_pipeline(self, start_func: str, result: AnalysisResult, depth: int) -> List[str]:
|
|
419
|
+
"""Trace a pipeline starting from an entry point."""
|
|
420
|
+
if depth > 10: # Prevent infinite recursion
|
|
421
|
+
return []
|
|
422
|
+
|
|
423
|
+
chain = []
|
|
424
|
+
current = start_func
|
|
425
|
+
visited = set()
|
|
426
|
+
|
|
427
|
+
while current and current not in visited and len(chain) < 20:
|
|
428
|
+
visited.add(current)
|
|
429
|
+
func_info = result.functions.get(current)
|
|
430
|
+
if not func_info:
|
|
431
|
+
break
|
|
432
|
+
|
|
433
|
+
chain.append(current.split(".")[-1])
|
|
434
|
+
|
|
435
|
+
# Follow the first call that's not a builtin
|
|
436
|
+
next_func = None
|
|
437
|
+
for callee in func_info.calls:
|
|
438
|
+
if callee in result.functions:
|
|
439
|
+
next_func = callee
|
|
440
|
+
break
|
|
441
|
+
|
|
442
|
+
current = next_func
|
|
443
|
+
|
|
444
|
+
return chain
|
|
445
|
+
|
|
446
|
+
def _calculate_purity(self, chain: List[str], result: AnalysisResult) -> float:
|
|
447
|
+
"""Calculate purity ratio (functions without side effects)."""
|
|
448
|
+
if not chain:
|
|
449
|
+
return 0.0
|
|
450
|
+
|
|
451
|
+
pure_count = 0
|
|
452
|
+
for func_name in chain:
|
|
453
|
+
full_name = None
|
|
454
|
+
for qname, fi in result.functions.items():
|
|
455
|
+
if fi.name == func_name:
|
|
456
|
+
full_name = qname
|
|
457
|
+
break
|
|
458
|
+
|
|
459
|
+
if full_name:
|
|
460
|
+
func_info = result.functions.get(full_name)
|
|
461
|
+
if func_info and not getattr(func_info, 'has_side_effects', False):
|
|
462
|
+
pure_count += 1
|
|
463
|
+
|
|
464
|
+
return pure_count / len(chain)
|
|
465
|
+
|
|
466
|
+
def render_external(self, ctx: Dict[str, Any]) -> List[str]:
|
|
467
|
+
"""Render EXTERNAL section - cross-references to other tools."""
|
|
468
|
+
lines = ["EXTERNAL:"]
|
|
469
|
+
lines.append(" validation: run `vallm batch .` → validation.toon")
|
|
470
|
+
lines.append(" duplication: run `redup scan .` → duplication.toon")
|
|
471
|
+
return lines
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.62
|
|
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
|
|
@@ -33,28 +33,27 @@ code2llm/cli_exports/prompt.py
|
|
|
33
33
|
code2llm/core/__init__.py
|
|
34
34
|
code2llm/core/analyzer.py
|
|
35
35
|
code2llm/core/config.py
|
|
36
|
+
code2llm/core/file_analyzer.py
|
|
37
|
+
code2llm/core/file_cache.py
|
|
38
|
+
code2llm/core/file_filter.py
|
|
36
39
|
code2llm/core/gitignore.py
|
|
37
40
|
code2llm/core/large_repo.py
|
|
38
41
|
code2llm/core/models.py
|
|
42
|
+
code2llm/core/refactoring.py
|
|
39
43
|
code2llm/core/repo_files.py
|
|
40
44
|
code2llm/core/streaming_analyzer.py
|
|
41
45
|
code2llm/core/toon_size_manager.py
|
|
42
|
-
code2llm/core/
|
|
43
|
-
code2llm/core/
|
|
44
|
-
code2llm/core/
|
|
45
|
-
code2llm/core/
|
|
46
|
-
code2llm/core/
|
|
47
|
-
code2llm/core/
|
|
48
|
-
code2llm/core/
|
|
49
|
-
code2llm/core/
|
|
50
|
-
code2llm/core/
|
|
51
|
-
code2llm/core/
|
|
52
|
-
code2llm/core/
|
|
53
|
-
code2llm/core/core/lang/java.py
|
|
54
|
-
code2llm/core/core/lang/php.py
|
|
55
|
-
code2llm/core/core/lang/ruby.py
|
|
56
|
-
code2llm/core/core/lang/rust.py
|
|
57
|
-
code2llm/core/core/lang/typescript.py
|
|
46
|
+
code2llm/core/lang/__init__.py
|
|
47
|
+
code2llm/core/lang/base.py
|
|
48
|
+
code2llm/core/lang/cpp.py
|
|
49
|
+
code2llm/core/lang/csharp.py
|
|
50
|
+
code2llm/core/lang/generic.py
|
|
51
|
+
code2llm/core/lang/go_lang.py
|
|
52
|
+
code2llm/core/lang/java.py
|
|
53
|
+
code2llm/core/lang/php.py
|
|
54
|
+
code2llm/core/lang/ruby.py
|
|
55
|
+
code2llm/core/lang/rust.py
|
|
56
|
+
code2llm/core/lang/typescript.py
|
|
58
57
|
code2llm/core/streaming/__init__.py
|
|
59
58
|
code2llm/core/streaming/cache.py
|
|
60
59
|
code2llm/core/streaming/incremental.py
|
|
@@ -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.62"
|
|
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"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
import ast
|
|
3
3
|
from code2llm.core.analyzer import ProjectAnalyzer
|
|
4
|
-
from code2llm.core
|
|
4
|
+
from code2llm.core import FileAnalyzer, FastFileFilter, RefactoringAnalyzer
|
|
5
5
|
from code2llm.core.config import Config
|
|
6
6
|
from code2llm.core.models import AnalysisResult
|
|
7
7
|
|
|
@@ -188,7 +188,7 @@ class TestAnalysisToon:
|
|
|
188
188
|
assert "HEALTH[" in toon_content
|
|
189
189
|
|
|
190
190
|
def test_has_refactor_section(self, toon_content):
|
|
191
|
-
assert "REFACTOR["
|
|
191
|
+
assert "REFACTOR[" in toon_content
|
|
192
192
|
|
|
193
193
|
def test_has_coupling_section(self, toon_content):
|
|
194
194
|
assert "COUPLING" in toon_content
|
|
@@ -340,7 +340,9 @@ class TestCrossFormat:
|
|
|
340
340
|
assert "HEALTH[" in toon
|
|
341
341
|
assert "LAYERS" in toon
|
|
342
342
|
assert "COUPLING" in toon
|
|
343
|
-
assert "REFACTOR["
|
|
343
|
+
assert "REFACTOR[" in toon
|
|
344
|
+
assert "PIPELINES" in toon
|
|
345
|
+
assert "EXTERNAL" in toon
|
|
344
346
|
|
|
345
347
|
def test_project_map_has_unique_structure_info(self, all_formats):
|
|
346
348
|
"""map.toon should have the structural import/signature map."""
|
|
@@ -105,13 +105,13 @@ class TestToonExporterV2:
|
|
|
105
105
|
assert "HEALTH[" in content
|
|
106
106
|
|
|
107
107
|
def test_refactor_section(self, sample_result, tmp_path):
|
|
108
|
-
"""REFACTOR section should
|
|
108
|
+
"""REFACTOR section should be present in analysis.toon with actionable steps."""
|
|
109
109
|
exporter = ToonExporter()
|
|
110
110
|
output_file = tmp_path / "test.toon"
|
|
111
111
|
exporter.export(sample_result, str(output_file))
|
|
112
112
|
|
|
113
113
|
content = output_file.read_text()
|
|
114
|
-
assert "REFACTOR["
|
|
114
|
+
assert "REFACTOR[" in content
|
|
115
115
|
|
|
116
116
|
def test_layers_section(self, sample_result, tmp_path):
|
|
117
117
|
"""Test LAYERS section shows package structure."""
|
|
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
|