code2llm 0.5.144__tar.gz → 0.5.145__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.144/code2llm.egg-info → code2llm-0.5.145}/PKG-INFO +12 -12
- {code2llm-0.5.144 → code2llm-0.5.145}/README.md +9 -9
- code2llm-0.5.145/VERSION +1 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/__init__.py +1 -1
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_analysis.py +14 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_parser.py +6 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/__init__.py +2 -2
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/analyzer.py +47 -28
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/config.py +14 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/file_analyzer.py +11 -4
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/persistent_cache.py +50 -32
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/refactoring.py +21 -7
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/__init__.py +1 -1
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/incremental.py +11 -11
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming_analyzer.py +2 -2
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_task.py +44 -34
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/__init__.py +1 -1
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/pipeline.py +8 -8
- {code2llm-0.5.144 → code2llm-0.5.145/code2llm.egg-info}/PKG-INFO +12 -12
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/requires.txt +1 -1
- {code2llm-0.5.144 → code2llm-0.5.145}/pyproject.toml +5 -3
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_deep_analysis.py +1 -0
- code2llm-0.5.144/VERSION +0 -1
- {code2llm-0.5.144 → code2llm-0.5.145}/LICENSE +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/MANIFEST.in +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/__main__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/call_graph.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/cfg.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/coupling.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/data_analysis.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/dfg.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/pipeline_classifier.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/pipeline_detector.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/pipeline_resolver.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/side_effects.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/smells.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/type_inference.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/utils/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/analysis/utils/ast_helpers.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/api.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_commands.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/code2logic.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/formats.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/orchestrator.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/orchestrator_chunked.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/orchestrator_constants.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/orchestrator_handlers.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/cli_exports/prompt.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/ast_registry.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/export_pipeline.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/file_cache.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/file_filter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/gitignore.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/incremental.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/base.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/cpp.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/csharp.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/generic.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/go_lang.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/java.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/php.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/ruby.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/rust.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/ts_extractors.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/ts_parser.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/lang/typescript.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/large_repo.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/models.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/repo_files.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/cache.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/prioritizer.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/scanner.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/streaming/strategies.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/core/toon_size_manager.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/article_view.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/base.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/context_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/context_view.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/dashboard_data.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/dashboard_renderer.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/computation.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/constants.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/exclusion.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/render.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution/yaml_export.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/evolution_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/flow_constants.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/flow_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/flow_renderer.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/html_dashboard.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/index_generator/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/index_generator/renderer.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/index_generator/scanner.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/index_generator.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/json_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/llm_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/alerts.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/details.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/header.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/module_list.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/utils.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map/yaml_export.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/map_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/calls.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/classic.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/compact.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/flow_compact.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/flow_detailed.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/flow_full.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid/utils.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/mermaid_flow_helpers.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/constants.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/core.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/evolution.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/health.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/hotspots.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml/modules.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/project_yaml_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/content.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/files.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/insights.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme/sections.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/readme_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/report_generators.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/helpers.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/metrics.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/metrics_core.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/metrics_duplicates.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/metrics_health.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/module_detail.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon/renderer.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/toon_view.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/validate_project.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/exporters/yaml_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/_utils.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/analysis.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/cli.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/generator.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/nodes.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/parsing.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow/utils.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/llm_flow.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid/fix.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid/png.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid/validation.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/generators/mermaid.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/config.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/entity_resolution.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/intent_matching.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/nlp/normalization.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/parsers/toon_parser.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/patterns/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/patterns/detector.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/refactor/__init__.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm/refactor/prompt_engine.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/SOURCES.txt +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/dependency_links.txt +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/entry_points.txt +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/code2llm.egg-info/top_level.txt +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/setup.cfg +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/setup.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_advanced_analysis.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_analyzer.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_cache_invalidation_e2e.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_calls_toon_export.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_declarative_collection.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_edge_cases.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_file_analyzer_tagging.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_flow_exporter.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_format_quality.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_multilanguage_e2e.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_nlp_pipeline.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_nonpython_cc_calls.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_orchestrator_cache_mtime.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_persistent_cache.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_pipeline_detector.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_project_toon_export.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_prompt_engine.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_prompt_txt.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_refactoring_engine.py +0 -0
- {code2llm-0.5.144 → code2llm-0.5.145}/tests/test_toon_v2.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: code2llm
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.145
|
|
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
|
|
7
7
|
Author-email: Tom Sapletta <tom@sapletta.com>
|
|
8
|
-
License
|
|
8
|
+
License: Apache-2.0
|
|
9
9
|
Project-URL: Homepage, https://github.com/wronai/stts
|
|
10
10
|
Project-URL: Repository, https://github.com/wronai/stts
|
|
11
11
|
Project-URL: Issues, https://github.com/wronai/stts/issues
|
|
@@ -54,7 +54,7 @@ Requires-Dist: pytest-xdist>=3.0; extra == "dev"
|
|
|
54
54
|
Requires-Dist: black>=21.0; extra == "dev"
|
|
55
55
|
Requires-Dist: flake8>=3.9; extra == "dev"
|
|
56
56
|
Requires-Dist: mypy>=0.910; extra == "dev"
|
|
57
|
-
Requires-Dist: goal>=2.1.
|
|
57
|
+
Requires-Dist: goal>=2.1.218; extra == "dev"
|
|
58
58
|
Requires-Dist: costs>=0.1.20; extra == "dev"
|
|
59
59
|
Requires-Dist: pfix>=0.1.60; extra == "dev"
|
|
60
60
|
Dynamic: author
|
|
@@ -67,13 +67,13 @@ Dynamic: requires-python
|
|
|
67
67
|
|
|
68
68
|
## AI Cost Tracking
|
|
69
69
|
|
|
70
|
-
     
|
|
71
|
+
  
|
|
72
72
|
|
|
73
|
-
- 🤖 **LLM usage:** $7.5000 (
|
|
74
|
-
- 👤 **Human dev:** ~$
|
|
73
|
+
- 🤖 **LLM usage:** $7.5000 (197 commits)
|
|
74
|
+
- 👤 **Human dev:** ~$7124 (71.2h @ $100/h, 30min dedup)
|
|
75
75
|
|
|
76
|
-
Generated on 2026-
|
|
76
|
+
Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
@@ -407,10 +407,10 @@ code2llm ./ -f yaml --separate-orphans
|
|
|
407
407
|
---
|
|
408
408
|
|
|
409
409
|
**Generated by**: `code2llm ./ -f all --readme`
|
|
410
|
-
**Analysis Date**: 2026-
|
|
411
|
-
**Total Functions**:
|
|
412
|
-
**Total Classes**:
|
|
413
|
-
**Modules**:
|
|
410
|
+
**Analysis Date**: 2026-05-06
|
|
411
|
+
**Total Functions**: 3625
|
|
412
|
+
**Total Classes**: 250
|
|
413
|
+
**Modules**: 492
|
|
414
414
|
|
|
415
415
|
For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
|
|
416
416
|
|
|
@@ -3,13 +3,13 @@
|
|
|
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 (197 commits)
|
|
10
|
+
- 👤 **Human dev:** ~$7124 (71.2h @ $100/h, 30min dedup)
|
|
11
11
|
|
|
12
|
-
Generated on 2026-
|
|
12
|
+
Generated on 2026-05-06 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
@@ -343,10 +343,10 @@ code2llm ./ -f yaml --separate-orphans
|
|
|
343
343
|
---
|
|
344
344
|
|
|
345
345
|
**Generated by**: `code2llm ./ -f all --readme`
|
|
346
|
-
**Analysis Date**: 2026-
|
|
347
|
-
**Total Functions**:
|
|
348
|
-
**Total Classes**:
|
|
349
|
-
**Modules**:
|
|
346
|
+
**Analysis Date**: 2026-05-06
|
|
347
|
+
**Total Functions**: 3625
|
|
348
|
+
**Total Classes**: 250
|
|
349
|
+
**Modules**: 492
|
|
350
350
|
|
|
351
351
|
For more information about code2llm, visit: https://github.com/tom-sapletta/code2llm
|
|
352
352
|
|
code2llm-0.5.145/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.5.145
|
|
@@ -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.145"
|
|
12
12
|
__author__ = "STTS Project"
|
|
13
13
|
|
|
14
14
|
# Core analysis components (lightweight, always needed)
|
|
@@ -88,6 +88,20 @@ def _build_config(args, output_dir: Path):
|
|
|
88
88
|
config.watch = getattr(args, 'watch', False)
|
|
89
89
|
# Dry-run mode (handled in orchestrator, but stored for reference)
|
|
90
90
|
config.dry_run = getattr(args, 'dry_run', False)
|
|
91
|
+
|
|
92
|
+
# --fast: skip expensive analyses (vulture, centrality, DFG, communities)
|
|
93
|
+
if getattr(args, 'fast', False):
|
|
94
|
+
config.performance.fast_mode = True
|
|
95
|
+
config.performance.apply_fast_mode()
|
|
96
|
+
|
|
97
|
+
# Strategy-based performance tuning
|
|
98
|
+
strategy = getattr(args, 'strategy', 'standard')
|
|
99
|
+
if strategy == 'quick':
|
|
100
|
+
config.performance.skip_data_flow = True
|
|
101
|
+
config.performance.skip_dead_code_detection = True
|
|
102
|
+
config.performance.skip_centrality = True
|
|
103
|
+
config.performance.skip_community_detection = True
|
|
104
|
+
|
|
91
105
|
return config
|
|
92
106
|
|
|
93
107
|
|
|
@@ -159,6 +159,12 @@ Strategy Options (--strategy):
|
|
|
159
159
|
help='Auto-detect changed files and only re-analyze those (faster subsequent runs)'
|
|
160
160
|
)
|
|
161
161
|
|
|
162
|
+
parser.add_argument(
|
|
163
|
+
'--fast',
|
|
164
|
+
action='store_true',
|
|
165
|
+
help='Skip expensive analyses (vulture, centrality, DFG, communities) for faster runs'
|
|
166
|
+
)
|
|
167
|
+
|
|
162
168
|
parser.add_argument(
|
|
163
169
|
'--strategy',
|
|
164
170
|
choices=['quick', 'standard', 'deep'],
|
|
@@ -9,7 +9,7 @@ from .models import (
|
|
|
9
9
|
__all__ = [
|
|
10
10
|
'ProjectAnalyzer',
|
|
11
11
|
'StreamingAnalyzer',
|
|
12
|
-
'
|
|
12
|
+
'StreamingIncrementalAnalyzer',
|
|
13
13
|
'ScanStrategy',
|
|
14
14
|
'SmartPrioritizer',
|
|
15
15
|
'STRATEGY_QUICK',
|
|
@@ -43,7 +43,7 @@ def __getattr__(name):
|
|
|
43
43
|
return locals()[name]
|
|
44
44
|
|
|
45
45
|
_streaming_names = {
|
|
46
|
-
'StreamingAnalyzer', '
|
|
46
|
+
'StreamingAnalyzer', 'StreamingIncrementalAnalyzer', 'ScanStrategy',
|
|
47
47
|
'SmartPrioritizer', 'STRATEGY_QUICK', 'STRATEGY_STANDARD', 'STRATEGY_DEEP',
|
|
48
48
|
}
|
|
49
49
|
if name in _streaming_names:
|
|
@@ -121,10 +121,16 @@ class ProjectAnalyzer:
|
|
|
121
121
|
return None, [], files
|
|
122
122
|
|
|
123
123
|
def _run_analysis(self, files_to_analyze: List[Tuple[str, str]]) -> List[Dict]:
|
|
124
|
-
"""Analyze files in parallel or sequentially depending on config.
|
|
124
|
+
"""Analyze files in parallel or sequentially depending on config.
|
|
125
|
+
|
|
126
|
+
Parallel mode has significant startup/pickle overhead. It is only
|
|
127
|
+
beneficial for larger file sets (threshold: 30 files).
|
|
128
|
+
"""
|
|
125
129
|
if not files_to_analyze:
|
|
126
130
|
return []
|
|
127
|
-
|
|
131
|
+
_PARALLEL_THRESHOLD = 30
|
|
132
|
+
if (self.config.performance.parallel_enabled
|
|
133
|
+
and len(files_to_analyze) > _PARALLEL_THRESHOLD):
|
|
128
134
|
return self._analyze_parallel(files_to_analyze)
|
|
129
135
|
return self._analyze_sequential(files_to_analyze)
|
|
130
136
|
|
|
@@ -197,39 +203,61 @@ class ProjectAnalyzer:
|
|
|
197
203
|
if self.config.verbose:
|
|
198
204
|
self._print_summary(merged)
|
|
199
205
|
|
|
206
|
+
@staticmethod
|
|
207
|
+
def _should_collect_file(
|
|
208
|
+
filename: str,
|
|
209
|
+
ext_set: set,
|
|
210
|
+
filename_set_lower: frozenset,
|
|
211
|
+
filename_prefixes_lower: tuple,
|
|
212
|
+
) -> bool:
|
|
213
|
+
"""Return True if *filename* matches a known language extension,
|
|
214
|
+
well-known filename (Dockerfile, Makefile, ...), or filename prefix
|
|
215
|
+
(Dockerfile.dev, Makefile.am).
|
|
216
|
+
"""
|
|
217
|
+
filename_lower = filename.lower()
|
|
218
|
+
suffix = os.path.splitext(filename)[1].lower()
|
|
219
|
+
return (
|
|
220
|
+
suffix in ext_set
|
|
221
|
+
or filename_lower in filename_set_lower
|
|
222
|
+
or filename_lower.startswith(filename_prefixes_lower)
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
@staticmethod
|
|
226
|
+
def _compute_module_name(
|
|
227
|
+
rel: str, filename: str, project_name: str
|
|
228
|
+
) -> str:
|
|
229
|
+
"""Derive a Pythonic module name from a relative file path."""
|
|
230
|
+
parts = rel.replace('\\', '/').split('/')
|
|
231
|
+
dir_parts = parts[:-1]
|
|
232
|
+
init_names = frozenset({'__init__.py', 'index.js', 'index.ts', 'mod.rs', 'lib.rs'})
|
|
233
|
+
if filename in init_names:
|
|
234
|
+
return '.'.join(dir_parts) if dir_parts else project_name
|
|
235
|
+
stem = os.path.splitext(filename)[0]
|
|
236
|
+
return '.'.join(dir_parts + [stem]) if dir_parts else stem
|
|
237
|
+
|
|
200
238
|
def _collect_files(self, project_path: Path) -> List[Tuple[str, str]]:
|
|
201
239
|
"""Collect all source files with their module names for all supported languages.
|
|
202
|
-
|
|
240
|
+
|
|
203
241
|
Uses a single os.walk traversal with early directory pruning instead of
|
|
204
242
|
separate rglob calls per extension (~40x speedup on large repos).
|
|
205
243
|
"""
|
|
206
244
|
files = []
|
|
207
|
-
ext_set = set(ALL_EXTENSIONS)
|
|
208
|
-
# Filename lookup uses a case-insensitive set. We lowercase once
|
|
209
|
-
# here so the hot loop only does a single lower() per file.
|
|
245
|
+
ext_set = set(ALL_EXTENSIONS)
|
|
210
246
|
filename_set_lower = frozenset(n.lower() for n in ALL_FILENAMES)
|
|
211
247
|
filename_prefixes_lower = tuple(p.lower() for p in LANGUAGE_FILENAME_PREFIXES)
|
|
212
|
-
|
|
213
|
-
seen = set() # guard against duplicate paths (e.g. .h in both c and cpp lists)
|
|
248
|
+
seen = set()
|
|
214
249
|
project_str = str(project_path)
|
|
250
|
+
project_name = project_path.name
|
|
215
251
|
|
|
216
252
|
for dirpath, dirnames, filenames in os.walk(project_str, topdown=True):
|
|
217
|
-
# Prune skipped directories in-place so os.walk won't descend into them
|
|
218
253
|
dirnames[:] = [
|
|
219
254
|
d for d in dirnames
|
|
220
255
|
if not self.file_filter.should_skip_dir(d)
|
|
221
256
|
]
|
|
222
257
|
|
|
223
258
|
for filename in filenames:
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
# Accept by extension, well-known filename
|
|
227
|
-
# (Dockerfile, Makefile, Jenkinsfile, ...), or known
|
|
228
|
-
# prefix (Dockerfile.dev, Dockerfile.prod, Makefile.am).
|
|
229
|
-
if (
|
|
230
|
-
suffix not in ext_set
|
|
231
|
-
and filename_lower not in filename_set_lower
|
|
232
|
-
and not filename_lower.startswith(filename_prefixes_lower)
|
|
259
|
+
if not self._should_collect_file(
|
|
260
|
+
filename, ext_set, filename_set_lower, filename_prefixes_lower
|
|
233
261
|
):
|
|
234
262
|
continue
|
|
235
263
|
|
|
@@ -241,17 +269,8 @@ class ProjectAnalyzer:
|
|
|
241
269
|
if not self.file_filter.should_process(file_str):
|
|
242
270
|
continue
|
|
243
271
|
|
|
244
|
-
# Calculate module name from relative path
|
|
245
272
|
rel = os.path.relpath(file_str, project_str)
|
|
246
|
-
|
|
247
|
-
dir_parts = parts[:-1] # everything before filename
|
|
248
|
-
|
|
249
|
-
if filename in init_names:
|
|
250
|
-
module_name = '.'.join(dir_parts) if dir_parts else project_path.name
|
|
251
|
-
else:
|
|
252
|
-
stem = os.path.splitext(filename)[0]
|
|
253
|
-
module_name = '.'.join(dir_parts + [stem]) if dir_parts else stem
|
|
254
|
-
|
|
273
|
+
module_name = self._compute_module_name(rel, filename, project_name)
|
|
255
274
|
files.append((file_str, module_name))
|
|
256
275
|
|
|
257
276
|
return files
|
|
@@ -81,6 +81,10 @@ class PerformanceConfig:
|
|
|
81
81
|
fast_mode: bool = False
|
|
82
82
|
skip_data_flow: bool = False
|
|
83
83
|
skip_pattern_detection: bool = False
|
|
84
|
+
skip_refactoring_analysis: bool = False
|
|
85
|
+
skip_dead_code_detection: bool = True
|
|
86
|
+
skip_centrality: bool = False
|
|
87
|
+
skip_community_detection: bool = False
|
|
84
88
|
|
|
85
89
|
def get_workers(self) -> int:
|
|
86
90
|
"""Get effective worker count (auto-detect if set to 0)."""
|
|
@@ -88,6 +92,16 @@ class PerformanceConfig:
|
|
|
88
92
|
return _get_optimal_workers(default=4)
|
|
89
93
|
return self.parallel_workers
|
|
90
94
|
|
|
95
|
+
def apply_fast_mode(self) -> None:
|
|
96
|
+
"""Apply fast_mode overrides — skip expensive analyses."""
|
|
97
|
+
if not self.fast_mode:
|
|
98
|
+
return
|
|
99
|
+
self.skip_data_flow = True
|
|
100
|
+
self.skip_pattern_detection = True
|
|
101
|
+
self.skip_dead_code_detection = True
|
|
102
|
+
self.skip_centrality = True
|
|
103
|
+
self.skip_community_detection = True
|
|
104
|
+
|
|
91
105
|
|
|
92
106
|
@dataclass
|
|
93
107
|
class FilterConfig:
|
|
@@ -124,8 +124,9 @@ class FileAnalyzer:
|
|
|
124
124
|
# Calculate complexity with radon
|
|
125
125
|
self._calculate_complexity(content, file_path, result)
|
|
126
126
|
|
|
127
|
-
# Deep Analysis for refactoring
|
|
128
|
-
self.
|
|
127
|
+
# Deep Analysis for refactoring (skip when data flow not needed)
|
|
128
|
+
if not self.config.performance.skip_data_flow:
|
|
129
|
+
self._perform_deep_analysis(tree, module_name, file_path, result)
|
|
129
130
|
|
|
130
131
|
self.stats['files_processed'] += 1
|
|
131
132
|
return result
|
|
@@ -164,12 +165,18 @@ class FileAnalyzer:
|
|
|
164
165
|
result['mutations'] = dfg_res.mutations
|
|
165
166
|
result['data_flows'] = dfg_res.data_flows
|
|
166
167
|
|
|
167
|
-
# Update function calls from CG extractor which is more robust
|
|
168
|
+
# Update function calls from CG extractor which is more robust.
|
|
169
|
+
# Use set-based merge to avoid duplicate call entries (ast.walk
|
|
170
|
+
# in _process_function already extracts calls).
|
|
168
171
|
cg_ext = CallGraphExtractor(self.config)
|
|
169
172
|
cg_res = cg_ext.extract(tree, module_name, file_path)
|
|
170
173
|
for func_name, cg_func in cg_res.functions.items():
|
|
171
174
|
if func_name in result['functions']:
|
|
172
|
-
result['functions'][func_name].calls
|
|
175
|
+
existing = set(result['functions'][func_name].calls)
|
|
176
|
+
for c in cg_func.calls:
|
|
177
|
+
if c not in existing:
|
|
178
|
+
result['functions'][func_name].calls.append(c)
|
|
179
|
+
existing.add(c)
|
|
173
180
|
except Exception as e:
|
|
174
181
|
if self.config.verbose:
|
|
175
182
|
print(f"Error in deep analysis for {file_path}: {e}")
|
|
@@ -282,6 +282,52 @@ class PersistentCache:
|
|
|
282
282
|
except OSError:
|
|
283
283
|
return 0.0
|
|
284
284
|
|
|
285
|
+
def _cleanup_stale_exports(self, cutoff: float) -> int:
|
|
286
|
+
"""Remove export directories older than *cutoff*.
|
|
287
|
+
|
|
288
|
+
Returns the number of removed export directories.
|
|
289
|
+
"""
|
|
290
|
+
removed = 0
|
|
291
|
+
if not self._exports_dir.exists():
|
|
292
|
+
return removed
|
|
293
|
+
for export_dir in list(self._exports_dir.iterdir()):
|
|
294
|
+
if not export_dir.is_dir():
|
|
295
|
+
continue
|
|
296
|
+
complete = export_dir / "_complete"
|
|
297
|
+
try:
|
|
298
|
+
if complete.exists():
|
|
299
|
+
ts = float(complete.read_text())
|
|
300
|
+
else:
|
|
301
|
+
ts = export_dir.stat().st_mtime
|
|
302
|
+
if ts < cutoff:
|
|
303
|
+
shutil.rmtree(export_dir, ignore_errors=True)
|
|
304
|
+
removed += 1
|
|
305
|
+
except (ValueError, OSError):
|
|
306
|
+
pass
|
|
307
|
+
return removed
|
|
308
|
+
|
|
309
|
+
def _cleanup_orphaned_files(self, cutoff: float, known: set) -> int:
|
|
310
|
+
"""Remove orphaned file-level cache entries older than *cutoff*.
|
|
311
|
+
|
|
312
|
+
*known* is a set of hash stems still referenced by the manifest.
|
|
313
|
+
Returns the number of removed files.
|
|
314
|
+
"""
|
|
315
|
+
removed = 0
|
|
316
|
+
if not self._files_dir.exists():
|
|
317
|
+
return removed
|
|
318
|
+
for f in list(self._files_dir.iterdir()):
|
|
319
|
+
if not f.is_file():
|
|
320
|
+
continue
|
|
321
|
+
if f.stem in known:
|
|
322
|
+
continue # still referenced
|
|
323
|
+
try:
|
|
324
|
+
if f.stat().st_mtime < cutoff:
|
|
325
|
+
f.unlink()
|
|
326
|
+
removed += 1
|
|
327
|
+
except OSError:
|
|
328
|
+
pass
|
|
329
|
+
return removed
|
|
330
|
+
|
|
285
331
|
def auto_cleanup(self, ttl_days: float = _DEFAULT_TTL_DAYS) -> Dict[str, int]:
|
|
286
332
|
"""Remove stale cache artefacts older than *ttl_days*.
|
|
287
333
|
|
|
@@ -302,39 +348,11 @@ class PersistentCache:
|
|
|
302
348
|
Returns a dict summary `{"exports": n, "files": n}` for logging.
|
|
303
349
|
"""
|
|
304
350
|
cutoff = time.time() - (ttl_days * 86400)
|
|
305
|
-
removed = {"exports": 0, "files": 0}
|
|
306
|
-
|
|
307
|
-
# 1) Stale exports (complete or abandoned)
|
|
308
|
-
if self._exports_dir.exists():
|
|
309
|
-
for export_dir in list(self._exports_dir.iterdir()):
|
|
310
|
-
if not export_dir.is_dir():
|
|
311
|
-
continue
|
|
312
|
-
complete = export_dir / "_complete"
|
|
313
|
-
try:
|
|
314
|
-
if complete.exists():
|
|
315
|
-
ts = float(complete.read_text())
|
|
316
|
-
else:
|
|
317
|
-
ts = export_dir.stat().st_mtime
|
|
318
|
-
if ts < cutoff:
|
|
319
|
-
shutil.rmtree(export_dir, ignore_errors=True)
|
|
320
|
-
removed["exports"] += 1
|
|
321
|
-
except (ValueError, OSError):
|
|
322
|
-
pass
|
|
323
|
-
|
|
324
|
-
# 2) Orphaned file-level entries older than TTL
|
|
325
351
|
known = {v.get("hash") for v in self._manifest.get("files", {}).values()}
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
if f.stem in known:
|
|
331
|
-
continue # still referenced
|
|
332
|
-
try:
|
|
333
|
-
if f.stat().st_mtime < cutoff:
|
|
334
|
-
f.unlink()
|
|
335
|
-
removed["files"] += 1
|
|
336
|
-
except OSError:
|
|
337
|
-
pass
|
|
352
|
+
removed = {
|
|
353
|
+
"exports": self._cleanup_stale_exports(cutoff),
|
|
354
|
+
"files": self._cleanup_orphaned_files(cutoff, known),
|
|
355
|
+
}
|
|
338
356
|
|
|
339
357
|
if removed["exports"] or removed["files"]:
|
|
340
358
|
logger.debug(
|
|
@@ -15,11 +15,21 @@ class RefactoringAnalyzer:
|
|
|
15
15
|
self.file_filter = file_filter
|
|
16
16
|
|
|
17
17
|
def perform_refactoring_analysis(self, result: AnalysisResult) -> None:
|
|
18
|
-
"""Perform deep analysis and detect code smells.
|
|
18
|
+
"""Perform deep analysis and detect code smells.
|
|
19
|
+
|
|
20
|
+
Expensive operations (centrality, cycles, communities, vulture)
|
|
21
|
+
are skipped when the corresponding config flags are set. The
|
|
22
|
+
``fast_mode`` shortcut disables all of them at once via
|
|
23
|
+
``PerformanceConfig.apply_fast_mode()``.
|
|
24
|
+
"""
|
|
25
|
+
perf = self.config.performance
|
|
26
|
+
if perf.skip_refactoring_analysis:
|
|
27
|
+
return
|
|
28
|
+
|
|
19
29
|
if self.config.verbose:
|
|
20
30
|
print("Performing refactoring analysis...")
|
|
21
31
|
|
|
22
|
-
# 1. Calculate metrics (fan-in/fan-out)
|
|
32
|
+
# 1. Calculate metrics (fan-in/fan-out) — always needed for TOON
|
|
23
33
|
from ..analysis.call_graph import CallGraphExtractor
|
|
24
34
|
cg_ext = CallGraphExtractor(self.config)
|
|
25
35
|
cg_ext.result = result
|
|
@@ -29,13 +39,16 @@ class RefactoringAnalyzer:
|
|
|
29
39
|
G = self._build_call_graph(result)
|
|
30
40
|
|
|
31
41
|
# 3. Calculate Betweenness Centrality (Bottlenecks)
|
|
32
|
-
|
|
42
|
+
if not perf.skip_centrality:
|
|
43
|
+
self._calculate_centrality(G, result)
|
|
33
44
|
|
|
34
45
|
# 4. Detect Circular Dependencies
|
|
35
|
-
|
|
46
|
+
if not perf.skip_centrality:
|
|
47
|
+
self._detect_cycles(G, result)
|
|
36
48
|
|
|
37
49
|
# 5. Community Detection (Module groups)
|
|
38
|
-
|
|
50
|
+
if not perf.skip_community_detection:
|
|
51
|
+
self._detect_communities(G, result)
|
|
39
52
|
|
|
40
53
|
# 6. Analyze coupling
|
|
41
54
|
self._analyze_coupling(result)
|
|
@@ -43,8 +56,9 @@ class RefactoringAnalyzer:
|
|
|
43
56
|
# 7. Detect code smells
|
|
44
57
|
self._detect_smells(result)
|
|
45
58
|
|
|
46
|
-
# 8. Dead code detection with vulture
|
|
47
|
-
|
|
59
|
+
# 8. Dead code detection with vulture (slowest step — rescans all files)
|
|
60
|
+
if not perf.skip_dead_code_detection:
|
|
61
|
+
self._detect_dead_code(result)
|
|
48
62
|
|
|
49
63
|
if self.config.verbose:
|
|
50
64
|
print(f" Detected {len(result.smells)} code smells")
|
|
@@ -4,4 +4,4 @@ from .strategies import ScanStrategy, STRATEGY_QUICK, STRATEGY_STANDARD, STRATEG
|
|
|
4
4
|
from .cache import StreamingFileCache
|
|
5
5
|
from .prioritizer import SmartPrioritizer, FilePriority
|
|
6
6
|
from .scanner import StreamingScanner
|
|
7
|
-
from .incremental import
|
|
7
|
+
from .incremental import StreamingIncrementalAnalyzer
|
|
@@ -9,15 +9,15 @@ from typing import Dict, List, Optional, Tuple
|
|
|
9
9
|
from code2llm.core.config import Config, FAST_CONFIG
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
class
|
|
13
|
-
"""Incremental analysis with change detection."""
|
|
14
|
-
|
|
12
|
+
class StreamingIncrementalAnalyzer:
|
|
13
|
+
"""Incremental analysis with change detection for streaming analyzer."""
|
|
14
|
+
|
|
15
15
|
def __init__(self, config: Optional[Config] = None):
|
|
16
16
|
self.config = config or FAST_CONFIG
|
|
17
17
|
self.state_file = Path(".code2llm_state.json")
|
|
18
18
|
self.previous_state: Dict[str, str] = {}
|
|
19
19
|
self._load_state()
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
def _load_state(self) -> None:
|
|
22
22
|
"""Load previous analysis state."""
|
|
23
23
|
if self.state_file.exists():
|
|
@@ -27,7 +27,7 @@ class IncrementalAnalyzer:
|
|
|
27
27
|
self.previous_state = data.get('file_hashes', {})
|
|
28
28
|
except Exception:
|
|
29
29
|
pass
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
def _save_state(self, current_state: Dict[str, str]) -> None:
|
|
32
32
|
"""Save current analysis state."""
|
|
33
33
|
with open(self.state_file, 'w') as f:
|
|
@@ -35,7 +35,7 @@ class IncrementalAnalyzer:
|
|
|
35
35
|
'file_hashes': current_state,
|
|
36
36
|
'timestamp': time.time()
|
|
37
37
|
}, f)
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
def get_changed_files(
|
|
40
40
|
self,
|
|
41
41
|
project_path: Path
|
|
@@ -44,15 +44,15 @@ class IncrementalAnalyzer:
|
|
|
44
44
|
changed = []
|
|
45
45
|
unchanged = []
|
|
46
46
|
current_state = {}
|
|
47
|
-
|
|
47
|
+
|
|
48
48
|
for py_file in project_path.rglob("*.py"):
|
|
49
49
|
try:
|
|
50
50
|
content = py_file.read_bytes()
|
|
51
51
|
file_hash = hashlib.md5(content).hexdigest()
|
|
52
52
|
file_str = str(py_file)
|
|
53
|
-
|
|
53
|
+
|
|
54
54
|
current_state[file_str] = file_hash
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
if file_str in self.previous_state:
|
|
57
57
|
if self.previous_state[file_str] == file_hash:
|
|
58
58
|
unchanged.append((file_str, self._get_module_name(py_file, project_path)))
|
|
@@ -62,10 +62,10 @@ class IncrementalAnalyzer:
|
|
|
62
62
|
changed.append((file_str, self._get_module_name(py_file, project_path)))
|
|
63
63
|
except Exception:
|
|
64
64
|
pass
|
|
65
|
-
|
|
65
|
+
|
|
66
66
|
self._save_state(current_state)
|
|
67
67
|
return changed, unchanged
|
|
68
|
-
|
|
68
|
+
|
|
69
69
|
def _get_module_name(self, py_file: Path, project_path: Path) -> str:
|
|
70
70
|
"""Calculate module name."""
|
|
71
71
|
rel_path = py_file.relative_to(project_path)
|
|
@@ -15,7 +15,7 @@ from typing import Dict, Iterator, List, Optional, Tuple
|
|
|
15
15
|
from .config import Config, FAST_CONFIG
|
|
16
16
|
from .streaming import (
|
|
17
17
|
ScanStrategy, STRATEGY_STANDARD, StreamingFileCache,
|
|
18
|
-
SmartPrioritizer, FilePriority, StreamingScanner,
|
|
18
|
+
SmartPrioritizer, FilePriority, StreamingScanner, StreamingIncrementalAnalyzer
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
|
|
@@ -177,5 +177,5 @@ class StreamingAnalyzer:
|
|
|
177
177
|
# Re-export for backward compatibility
|
|
178
178
|
from .streaming import (
|
|
179
179
|
ScanStrategy, STRATEGY_QUICK, STRATEGY_STANDARD, STRATEGY_DEEP,
|
|
180
|
-
StreamingFileCache, SmartPrioritizer, FilePriority,
|
|
180
|
+
StreamingFileCache, SmartPrioritizer, FilePriority, StreamingIncrementalAnalyzer
|
|
181
181
|
)
|