code2llm 0.5.153__tar.gz → 0.5.154__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.
Files changed (204) hide show
  1. {code2llm-0.5.153/code2llm.egg-info → code2llm-0.5.154}/PKG-INFO +5 -5
  2. {code2llm-0.5.153 → code2llm-0.5.154}/README.md +4 -4
  3. code2llm-0.5.154/VERSION +1 -0
  4. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/__init__.py +1 -1
  5. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_exports/orchestrator.py +30 -21
  6. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_parser.py +2 -5
  7. code2llm-0.5.153/code2llm/core/lang/base.py → code2llm-0.5.154/code2llm/core/lang/_c_parser.py +101 -332
  8. code2llm-0.5.154/code2llm/core/lang/_calls.py +96 -0
  9. code2llm-0.5.154/code2llm/core/lang/_complexity.py +73 -0
  10. code2llm-0.5.154/code2llm/core/lang/base.py +76 -0
  11. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/evolution/computation.py +35 -33
  12. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/nlp/__init__.py +1 -1
  13. {code2llm-0.5.153 → code2llm-0.5.154/code2llm.egg-info}/PKG-INFO +5 -5
  14. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm.egg-info/SOURCES.txt +3 -0
  15. {code2llm-0.5.153 → code2llm-0.5.154}/pyproject.toml +1 -1
  16. code2llm-0.5.153/VERSION +0 -1
  17. {code2llm-0.5.153 → code2llm-0.5.154}/LICENSE +0 -0
  18. {code2llm-0.5.153 → code2llm-0.5.154}/MANIFEST.in +0 -0
  19. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/__main__.py +0 -0
  20. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/__init__.py +0 -0
  21. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/call_graph.py +0 -0
  22. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/cfg.py +0 -0
  23. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/coupling.py +0 -0
  24. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/data_analysis.py +0 -0
  25. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/dfg.py +0 -0
  26. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/pipeline_classifier.py +0 -0
  27. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/pipeline_detector.py +0 -0
  28. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/pipeline_resolver.py +0 -0
  29. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/side_effects.py +0 -0
  30. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/smells.py +0 -0
  31. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/type_inference.py +0 -0
  32. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/utils/__init__.py +0 -0
  33. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/analysis/utils/ast_helpers.py +0 -0
  34. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/api.py +0 -0
  35. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli.py +0 -0
  36. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_analysis.py +0 -0
  37. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_commands.py +0 -0
  38. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_exports/__init__.py +0 -0
  39. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_exports/code2logic.py +0 -0
  40. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_exports/formats.py +0 -0
  41. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_exports/orchestrator_chunked.py +0 -0
  42. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_exports/orchestrator_constants.py +0 -0
  43. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_exports/orchestrator_handlers.py +0 -0
  44. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/cli_exports/prompt.py +0 -0
  45. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/__init__.py +0 -0
  46. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/analyzer.py +0 -0
  47. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/ast_registry.py +0 -0
  48. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/config.py +0 -0
  49. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/export_pipeline.py +0 -0
  50. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/file_analyzer.py +0 -0
  51. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/file_cache.py +0 -0
  52. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/file_filter.py +0 -0
  53. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/gitignore.py +0 -0
  54. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/incremental.py +0 -0
  55. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/__init__.py +0 -0
  56. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/cpp.py +0 -0
  57. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/csharp.py +0 -0
  58. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/generic.py +0 -0
  59. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/go_lang.py +0 -0
  60. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/java.py +0 -0
  61. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/php.py +0 -0
  62. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/ruby.py +0 -0
  63. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/rust.py +0 -0
  64. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/ts_extractors.py +0 -0
  65. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/ts_parser.py +0 -0
  66. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/lang/typescript.py +0 -0
  67. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/large_repo.py +0 -0
  68. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/models.py +0 -0
  69. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/persistent_cache.py +0 -0
  70. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/refactoring.py +0 -0
  71. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/repo_files.py +0 -0
  72. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/source_classifier.py +0 -0
  73. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/streaming/__init__.py +0 -0
  74. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/streaming/cache.py +0 -0
  75. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/streaming/incremental.py +0 -0
  76. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/streaming/prioritizer.py +0 -0
  77. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/streaming/scanner.py +0 -0
  78. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/streaming/strategies.py +0 -0
  79. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/streaming_analyzer.py +0 -0
  80. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/core/toon_size_manager.py +0 -0
  81. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/__init__.py +0 -0
  82. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/article_view.py +0 -0
  83. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/base.py +0 -0
  84. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/context_exporter.py +0 -0
  85. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/context_view.py +0 -0
  86. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/dashboard_data.py +0 -0
  87. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/dashboard_renderer.py +0 -0
  88. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/evolution/__init__.py +0 -0
  89. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/evolution/constants.py +0 -0
  90. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/evolution/exclusion.py +0 -0
  91. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/evolution/render.py +0 -0
  92. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/evolution/yaml_export.py +0 -0
  93. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/evolution_exporter.py +0 -0
  94. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/flow_constants.py +0 -0
  95. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/flow_exporter.py +0 -0
  96. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/flow_renderer.py +0 -0
  97. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/html_dashboard.py +0 -0
  98. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/index_generator/__init__.py +0 -0
  99. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/index_generator/renderer.py +0 -0
  100. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/index_generator/scanner.py +0 -0
  101. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/index_generator.py +0 -0
  102. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/json_exporter.py +0 -0
  103. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/llm_exporter.py +0 -0
  104. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/map/__init__.py +0 -0
  105. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/map/alerts.py +0 -0
  106. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/map/details.py +0 -0
  107. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/map/header.py +0 -0
  108. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/map/module_list.py +0 -0
  109. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/map/utils.py +0 -0
  110. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/map/yaml_export.py +0 -0
  111. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/map_exporter.py +0 -0
  112. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid/__init__.py +0 -0
  113. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid/calls.py +0 -0
  114. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid/classic.py +0 -0
  115. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid/compact.py +0 -0
  116. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid/flow_compact.py +0 -0
  117. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid/flow_detailed.py +0 -0
  118. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid/flow_full.py +0 -0
  119. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid/utils.py +0 -0
  120. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid_exporter.py +0 -0
  121. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/mermaid_flow_helpers.py +0 -0
  122. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/planfile_tickets.py +0 -0
  123. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/project_yaml/__init__.py +0 -0
  124. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/project_yaml/constants.py +0 -0
  125. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/project_yaml/core.py +0 -0
  126. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/project_yaml/evolution.py +0 -0
  127. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/project_yaml/health.py +0 -0
  128. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/project_yaml/hotspots.py +0 -0
  129. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/project_yaml/modules.py +0 -0
  130. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/project_yaml_exporter.py +0 -0
  131. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/readme/__init__.py +0 -0
  132. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/readme/content.py +0 -0
  133. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/readme/files.py +0 -0
  134. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/readme/insights.py +0 -0
  135. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/readme/sections.py +0 -0
  136. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/readme_exporter.py +0 -0
  137. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/report_generators.py +0 -0
  138. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon/__init__.py +0 -0
  139. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon/helpers.py +0 -0
  140. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon/metrics.py +0 -0
  141. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon/metrics_core.py +0 -0
  142. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon/metrics_duplicates.py +0 -0
  143. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon/metrics_health.py +0 -0
  144. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon/module_detail.py +0 -0
  145. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon/renderer.py +0 -0
  146. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon.py +0 -0
  147. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/toon_view.py +0 -0
  148. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/validate_project.py +0 -0
  149. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/exporters/yaml_exporter.py +0 -0
  150. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/__init__.py +0 -0
  151. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/_utils.py +0 -0
  152. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/llm_flow/__init__.py +0 -0
  153. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/llm_flow/analysis.py +0 -0
  154. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/llm_flow/cli.py +0 -0
  155. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/llm_flow/generator.py +0 -0
  156. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/llm_flow/nodes.py +0 -0
  157. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/llm_flow/parsing.py +0 -0
  158. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/llm_flow/utils.py +0 -0
  159. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/llm_flow.py +0 -0
  160. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/llm_task.py +0 -0
  161. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/mermaid/__init__.py +0 -0
  162. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/mermaid/fix.py +0 -0
  163. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/mermaid/png.py +0 -0
  164. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/mermaid/validation.py +0 -0
  165. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/generators/mermaid.py +0 -0
  166. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/nlp/config.py +0 -0
  167. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/nlp/entity_resolution.py +0 -0
  168. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/nlp/intent_matching.py +0 -0
  169. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/nlp/normalization.py +0 -0
  170. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/nlp/pipeline.py +0 -0
  171. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/parsers/toon_parser.py +0 -0
  172. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/patterns/__init__.py +0 -0
  173. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/patterns/detector.py +0 -0
  174. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/refactor/__init__.py +0 -0
  175. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm/refactor/prompt_engine.py +0 -0
  176. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm.egg-info/dependency_links.txt +0 -0
  177. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm.egg-info/entry_points.txt +0 -0
  178. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm.egg-info/requires.txt +0 -0
  179. {code2llm-0.5.153 → code2llm-0.5.154}/code2llm.egg-info/top_level.txt +0 -0
  180. {code2llm-0.5.153 → code2llm-0.5.154}/setup.cfg +0 -0
  181. {code2llm-0.5.153 → code2llm-0.5.154}/setup.py +0 -0
  182. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_advanced_analysis.py +0 -0
  183. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_analyzer.py +0 -0
  184. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_cache_invalidation_e2e.py +0 -0
  185. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_calls_toon_export.py +0 -0
  186. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_declarative_collection.py +0 -0
  187. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_deep_analysis.py +0 -0
  188. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_edge_cases.py +0 -0
  189. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_export_cache_flags.py +0 -0
  190. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_file_analyzer_tagging.py +0 -0
  191. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_flow_exporter.py +0 -0
  192. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_format_quality.py +0 -0
  193. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_multilanguage_e2e.py +0 -0
  194. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_nlp_pipeline.py +0 -0
  195. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_nonpython_cc_calls.py +0 -0
  196. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_orchestrator_cache_mtime.py +0 -0
  197. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_persistent_cache.py +0 -0
  198. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_pipeline_detector.py +0 -0
  199. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_planfile_tickets_exporter.py +0 -0
  200. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_project_toon_export.py +0 -0
  201. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_prompt_engine.py +0 -0
  202. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_prompt_txt.py +0 -0
  203. {code2llm-0.5.153 → code2llm-0.5.154}/tests/test_refactoring_engine.py +0 -0
  204. {code2llm-0.5.153 → code2llm-0.5.154}/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.153
3
+ Version: 0.5.154
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
@@ -66,11 +66,11 @@ Dynamic: requires-python
66
66
 
67
67
  ## AI Cost Tracking
68
68
 
69
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.153-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
70
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-77.3h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
69
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.154-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
70
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-78.3h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
71
71
 
72
- - 🤖 **LLM usage:** $7.5000 (206 commits)
73
- - 👤 **Human dev:** ~$7734 (77.3h @ $100/h, 30min dedup)
72
+ - 🤖 **LLM usage:** $7.5000 (207 commits)
73
+ - 👤 **Human dev:** ~$7834 (78.3h @ $100/h, 30min dedup)
74
74
 
75
75
  Generated on 2026-05-24 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
76
76
 
@@ -2,11 +2,11 @@
2
2
 
3
3
  ## AI Cost Tracking
4
4
 
5
- ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.153-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
6
- ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-77.3h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
5
+ ![PyPI](https://img.shields.io/badge/pypi-costs-blue) ![Version](https://img.shields.io/badge/version-0.5.154-blue) ![Python](https://img.shields.io/badge/python-3.9+-blue) ![License](https://img.shields.io/badge/license-Apache--2.0-green)
6
+ ![AI Cost](https://img.shields.io/badge/AI%20Cost-$7.50-orange) ![Human Time](https://img.shields.io/badge/Human%20Time-78.3h-blue) ![Model](https://img.shields.io/badge/Model-openrouter%2Fqwen%2Fqwen3--coder--next-lightgrey)
7
7
 
8
- - 🤖 **LLM usage:** $7.5000 (206 commits)
9
- - 👤 **Human dev:** ~$7734 (77.3h @ $100/h, 30min dedup)
8
+ - 🤖 **LLM usage:** $7.5000 (207 commits)
9
+ - 👤 **Human dev:** ~$7834 (78.3h @ $100/h, 30min dedup)
10
10
 
11
11
  Generated on 2026-05-24 using [openrouter/qwen/qwen3-coder-next](https://openrouter.ai/qwen/qwen3-coder-next)
12
12
 
@@ -0,0 +1 @@
1
+ 0.5.154
@@ -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.153"
11
+ __version__ = "0.5.154"
12
12
  __author__ = "STTS Project"
13
13
 
14
14
  # Core analysis components (lightweight, always needed)
@@ -100,6 +100,33 @@ def _should_skip_export_cache(args, is_chunked: bool) -> bool:
100
100
  )
101
101
 
102
102
 
103
+ def _try_serve_from_cache(
104
+ args, formats: list, output_dir: Path, source_path: Path
105
+ ) -> bool:
106
+ """Return True and restore output from cache if a valid cached export exists."""
107
+ cache = PersistentCache(str(source_path))
108
+ config_dict = _build_export_config(args, formats)
109
+ cached_export_dir = cache.get_export_cache_dir(config_dict)
110
+ if not cached_export_dir:
111
+ return False
112
+ if args.verbose:
113
+ print(f" Using cached export from: {cached_export_dir}")
114
+ _copy_cached_export(cached_export_dir, output_dir, verbose=args.verbose)
115
+ return True
116
+
117
+
118
+ def _save_to_export_cache(args, formats: list, output_dir: Path, source_path: Path) -> None:
119
+ """Persist the just-produced output_dir contents into the export cache."""
120
+ cache = PersistentCache(str(source_path))
121
+ config_dict = _build_export_config(args, formats)
122
+ export_cache_dir = cache.create_export_cache_dir(config_dict)
123
+ _copy_to_cache(output_dir, export_cache_dir, verbose=args.verbose)
124
+ cache.mark_export_complete(export_cache_dir)
125
+ cache.save()
126
+ if args.verbose:
127
+ print(f" Export cached at: {export_cache_dir}")
128
+
129
+
103
130
  def _run_exports(args, result, output_dir: Path, source_path: Optional[Path] = None):
104
131
  """Export analysis results in requested formats.
105
132
 
@@ -112,10 +139,8 @@ def _run_exports(args, result, output_dir: Path, source_path: Optional[Path] = N
112
139
  if getattr(args, "planfile_apply", False) and "planfile" not in formats:
113
140
  formats.append("planfile")
114
141
  is_chunked = getattr(args, "chunk", False)
115
- dry_run = getattr(args, "dry_run", False)
116
142
 
117
- # Dry-run: show what would be exported without writing
118
- if dry_run:
143
+ if getattr(args, "dry_run", False):
119
144
  _show_dry_run_plan(formats, output_dir, is_chunked, result)
120
145
  return
121
146
 
@@ -124,15 +149,7 @@ def _run_exports(args, result, output_dir: Path, source_path: Optional[Path] = N
124
149
  skip_cache = _should_skip_export_cache(args, is_chunked)
125
150
 
126
151
  if not skip_cache and source_path:
127
- cache = PersistentCache(str(source_path))
128
- config_dict = _build_export_config(args, formats)
129
- cached_export_dir = cache.get_export_cache_dir(config_dict)
130
-
131
- if cached_export_dir:
132
- if args.verbose:
133
- print(f" Using cached export from: {cached_export_dir}")
134
- # Copy cached files to output_dir
135
- _copy_cached_export(cached_export_dir, output_dir, verbose=args.verbose)
152
+ if _try_serve_from_cache(args, formats, output_dir, source_path):
136
153
  return
137
154
 
138
155
  try:
@@ -145,16 +162,8 @@ def _run_exports(args, result, output_dir: Path, source_path: Optional[Path] = N
145
162
  args, result, output_dir, formats, requested_formats, source_path
146
163
  )
147
164
 
148
- # Mark export as complete in cache
149
165
  if not skip_cache and source_path:
150
- cache = PersistentCache(str(source_path))
151
- config_dict = _build_export_config(args, formats)
152
- export_cache_dir = cache.create_export_cache_dir(config_dict)
153
- _copy_to_cache(output_dir, export_cache_dir, verbose=args.verbose)
154
- cache.mark_export_complete(export_cache_dir)
155
- cache.save()
156
- if args.verbose:
157
- print(f" Export cached at: {export_cache_dir}")
166
+ _save_to_export_cache(args, formats, output_dir, source_path)
158
167
 
159
168
  except Exception as e:
160
169
  print(f"Error during export: {e}", file=sys.stderr)
@@ -56,11 +56,8 @@ Format Options (-f):
56
56
  flow — Data-flow analysis (flow.toon) — legacy, explicit opt-in
57
57
  code2logic — Generate project logic (legacy project.toon) via external code2logic
58
58
  project-yaml — Legacy project.yaml export (single source of truth) + generated views
59
- planfile — Planfile ticket suggestions (planfile-tickets.yaml);
60
- use --planfile-apply to create tickets
61
- all — Generate core formats (analysis.toon, map.toon.yaml,
62
- evolution.toon.yaml, context, mermaid, planfile-tickets.yaml)
63
- plus project.toon.yaml and prompt.txt; PNG remains opt-in via --png
59
+ planfile — Planfile ticket suggestions (planfile-tickets.yaml); use --planfile-apply to create tickets
60
+ all — Generate core formats (analysis.toon, map.toon.yaml, evolution.toon.yaml, context, mermaid, planfile-tickets.yaml) plus project.toon.yaml and prompt.txt; PNG remains opt-in via --png
64
61
 
65
62
  Strategy Options (--strategy):
66
63
  quick — Fast overview, fewer files analyzed
@@ -1,301 +1,6 @@
1
- """Shared utilities for regex-based language analyzers."""
2
-
3
- import re
4
- from typing import Dict, List
5
-
6
- from code2llm.core.config import (
7
- CC_LOW_THRESHOLD,
8
- CC_MEDIUM_THRESHOLD,
9
- CC_HIGH_THRESHOLD,
10
- )
11
-
12
-
13
- # Branching keywords per language family
14
- CC_PATTERNS = {
15
- "c_family": re.compile(
16
- r"\b(?:if|else\s+if|for|while|do|switch|case|catch)\b"
17
- r"|&&|\|\||\?\?|\?\." # logical operators (not word chars)
18
- r"|\?\s*[^:]*\s*:" # ternary
19
- ),
20
- "go": re.compile(
21
- r"\b(?:if|for|switch|case|select|go|defer)\b"
22
- r"|&&|\|\|"
23
- ),
24
- "rust": re.compile(
25
- r"\b(?:if|else\s+if|for|while|loop|match)\b"
26
- r"|&&|\|\||\?"
27
- ),
28
- }
29
-
30
- CALL_PATTERN_C_FAMILY = re.compile(
31
- r"(?<!\bfunction\b\s)" # not a function declaration
32
- r"(?<!\bclass\b\s)" # not a class declaration
33
- r"\b([a-zA-Z_]\w*)\s*\(" # simple call: foo(
34
- r"|"
35
- r"(?:this|self)\s*\.\s*(\w+)\s*\(" # this.method( / self.method(
36
- r"|"
37
- r"\b(\w+)\s*\.\s*(\w+)\s*\(" # obj.method(
38
- )
39
-
40
-
41
- def extract_function_body(content: str, start_line: int) -> str:
42
- """Extract the body of a function between braces from a start line (1-indexed)."""
43
- lines = content.split("\n")
44
- if start_line < 1 or start_line > len(lines):
45
- return ""
46
- depth = 0
47
- body_lines = []
48
- started = False
49
- for line in lines[start_line - 1 :]:
50
- for ch in line:
51
- if ch == "{":
52
- depth += 1
53
- started = True
54
- elif ch == "}":
55
- depth -= 1
56
- if started:
57
- body_lines.append(line)
58
- if started and depth <= 0:
59
- break
60
- return "\n".join(body_lines)
61
-
62
-
63
- def calculate_complexity_regex(
64
- content: str, result: Dict, lang: str = "c_family"
65
- ) -> None:
66
- """Estimate cyclomatic complexity for every function using regex keyword counting."""
67
- pattern = CC_PATTERNS.get(lang, CC_PATTERNS["c_family"])
68
- for func_info in result["functions"].values():
69
- body = extract_function_body(content, func_info.line)
70
- if not body:
71
- cc = 1
72
- else:
73
- cc = 1 + len(pattern.findall(body))
74
- rank = (
75
- "A"
76
- if cc <= CC_LOW_THRESHOLD
77
- else (
78
- "B"
79
- if cc <= CC_MEDIUM_THRESHOLD
80
- else ("C" if cc <= CC_HIGH_THRESHOLD else "D")
81
- )
82
- )
83
- func_info.complexity = {
84
- "cyclomatic_complexity": cc,
85
- "cc_rank": rank,
86
- }
87
-
88
-
89
- _CALL_KEYWORDS = frozenset(
90
- {
91
- "if",
92
- "for",
93
- "while",
94
- "switch",
95
- "catch",
96
- "return",
97
- "throw",
98
- "new",
99
- "typeof",
100
- "instanceof",
101
- "import",
102
- "export",
103
- "require",
104
- "console",
105
- "super",
106
- "class",
107
- "function",
108
- "async",
109
- "await",
110
- "delete",
111
- "void",
112
- "case",
113
- "default",
114
- }
115
- )
1
+ """C-family declaration parser helpers (classes, functions, methods, decorators)."""
116
2
 
117
-
118
- def _resolve_call(
119
- simple_call: str,
120
- func_qname: str,
121
- module_name: str,
122
- known_simple: Dict[str, List[str]],
123
- calls_seen: set,
124
- func_info,
125
- ) -> None:
126
- """Resolve a single call name and append to func_info.calls if novel."""
127
- if simple_call in known_simple:
128
- candidates = known_simple[simple_call]
129
- my_module = func_qname.rsplit(".", 1)[0]
130
- resolved = next(
131
- (c for c in candidates if c.rsplit(".", 1)[0] == my_module),
132
- candidates[0],
133
- )
134
- if resolved != func_qname and resolved not in calls_seen:
135
- func_info.calls.append(resolved)
136
- calls_seen.add(resolved)
137
- else:
138
- ext_name = f"{module_name}.{simple_call}"
139
- if ext_name not in calls_seen:
140
- func_info.calls.append(ext_name)
141
- calls_seen.add(ext_name)
142
-
143
-
144
- def extract_calls_regex(content: str, module_name: str, result: Dict) -> None:
145
- """Extract function calls from function bodies using regex."""
146
- known_simple: Dict[str, List[str]] = {}
147
- for qname in result["functions"]:
148
- simple = qname.rsplit(".", 1)[-1]
149
- known_simple.setdefault(simple, []).append(qname)
150
-
151
- for func_qname, func_info in result["functions"].items():
152
- body = extract_function_body(content, func_info.line)
153
- if not body:
154
- continue
155
- calls_seen: set = set()
156
- for m in CALL_PATTERN_C_FAMILY.finditer(body):
157
- simple_call = m.group(1) or m.group(2) or m.group(4)
158
- if not simple_call or simple_call in _CALL_KEYWORDS:
159
- continue
160
- _resolve_call(
161
- simple_call,
162
- func_qname,
163
- module_name,
164
- known_simple,
165
- calls_seen,
166
- func_info,
167
- )
168
-
169
-
170
- # Shared declaration extraction for language parsers
171
- def _extract_declarations(
172
- content: str,
173
- file_path: str,
174
- module_name: str,
175
- patterns: Dict,
176
- stats: Dict,
177
- lang_config: Dict,
178
- ) -> Dict:
179
- """Shared extraction logic for language parsers.
180
-
181
- Args:
182
- content: File content
183
- file_path: Path to file
184
- module_name: Module name
185
- patterns: Dict of compiled regex patterns
186
- stats: Statistics dict to update
187
- lang_config: Language-specific config dict
188
- """
189
- from ..models import ModuleInfo
190
- from pathlib import Path
191
-
192
- result = {
193
- "module": ModuleInfo(
194
- name=module_name,
195
- file=file_path,
196
- is_package=Path(file_path).name in lang_config.get("index_files", []),
197
- ),
198
- "functions": {},
199
- "classes": {},
200
- "nodes": {},
201
- "edges": [],
202
- }
203
-
204
- lines = content.split("\n")
205
- current_class = None
206
- class_brace_depth = 0
207
- brace_depth = 0
208
- pending_decorators = []
209
-
210
- import_re = patterns.get("import")
211
- decorator_re = patterns.get("decorator")
212
- class_re = patterns.get("class")
213
- interface_re = patterns.get("interface")
214
- func_re = patterns.get("function")
215
- arrow_re = patterns.get("arrow_func")
216
- method_re = patterns.get("method")
217
- arrow_prop_re = patterns.get("arrow_prop")
218
-
219
- track_braces = lang_config.get("brace_track", True)
220
- reserved = lang_config.get(
221
- "reserved", {"if", "for", "while", "switch", "return", "catch"}
222
- )
223
-
224
- for line_no, line in enumerate(lines, 1):
225
- raw_line = line
226
- line = line.strip()
227
- # Skip empty lines and comments, but NOT preprocessor directives like #include
228
- if not line:
229
- continue
230
- if line.startswith(("//", "/*", "*")):
231
- continue
232
- # Skip # comments (Python, Ruby, shell) but NOT #include/#define (C-family)
233
- if (
234
- line.startswith("#")
235
- and not line.startswith("#include")
236
- and not line.startswith("#define")
237
- ):
238
- continue
239
-
240
- # Update brace tracking
241
- brace_depth, current_class, class_brace_depth = _update_brace_tracking(
242
- raw_line, brace_depth, current_class, class_brace_depth, track_braces
243
- )
244
-
245
- # Process decorators
246
- pending_decorators = _process_decorators(decorator_re, line, pending_decorators)
247
-
248
- # Process imports
249
- if import_re:
250
- im = import_re.match(line)
251
- if im:
252
- result["module"].imports.append(im.group(1))
253
- continue
254
-
255
- # Process classes and interfaces
256
- current_class, class_brace_depth, pending_decorators = _process_classes(
257
- class_re,
258
- interface_re,
259
- line,
260
- line_no,
261
- file_path,
262
- module_name,
263
- result,
264
- stats,
265
- current_class,
266
- class_brace_depth,
267
- pending_decorators,
268
- )
269
-
270
- # Process functions
271
- pending_decorators = _process_functions(
272
- func_re,
273
- arrow_re,
274
- method_re,
275
- arrow_prop_re,
276
- line,
277
- line_no,
278
- file_path,
279
- module_name,
280
- result,
281
- stats,
282
- current_class,
283
- pending_decorators,
284
- reserved,
285
- )
286
-
287
- # Clear orphaned decorators
288
- pending_decorators = _clear_orphaned_decorators(
289
- line,
290
- pending_decorators,
291
- func_re,
292
- arrow_re,
293
- class_re,
294
- interface_re,
295
- method_re,
296
- )
297
-
298
- return result
3
+ from typing import Dict
299
4
 
300
5
 
301
6
  def _update_brace_tracking(
@@ -340,7 +45,6 @@ def _process_classes(
340
45
  """Process class and interface declarations."""
341
46
  from ..models import ClassInfo
342
47
 
343
- # Process classes
344
48
  if class_re:
345
49
  cm = class_re.match(line)
346
50
  if cm:
@@ -364,11 +68,9 @@ def _process_classes(
364
68
  result["module"].classes.append(qual)
365
69
  stats["classes_found"] += 1
366
70
  current_class = qual
367
- class_brace_depth = class_brace_depth # Will be updated by caller
368
71
  pending_decorators.clear()
369
72
  return current_class, class_brace_depth, pending_decorators
370
73
 
371
- # Process interfaces
372
74
  if interface_re:
373
75
  imt = interface_re.match(line)
374
76
  if imt:
@@ -575,48 +277,115 @@ def _clear_orphaned_decorators(
575
277
  return pending_decorators
576
278
 
577
279
 
578
- def analyze_c_family(
280
+ def _extract_declarations(
579
281
  content: str,
580
282
  file_path: str,
581
283
  module_name: str,
582
- stats: Dict,
583
284
  patterns: Dict,
285
+ stats: Dict,
584
286
  lang_config: Dict,
585
- cc_lang: str = "c_family",
586
- ext: str = "",
587
287
  ) -> Dict:
588
- """Shared analyzer for C-family languages (Java, C#, C++, etc.).
288
+ """Shared extraction logic for language parsers."""
289
+ from pathlib import Path
589
290
 
590
- Uses tree-sitter when available (10× faster), falls back to regex.
591
- """
592
- result = None
593
-
594
- # Try tree-sitter first (much faster)
595
- if ext:
596
- try:
597
- from .ts_parser import parse_source
598
- from .ts_extractors import extract_declarations_ts
599
-
600
- tree = parse_source(content, ext)
601
- if tree:
602
- result = extract_declarations_ts(
603
- tree, content.encode("utf-8"), ext, file_path, module_name
604
- )
605
- except ImportError:
606
- pass # tree-sitter not installed
607
-
608
- # Fallback to regex
609
- if result is None:
610
- result = _extract_declarations(
611
- content,
291
+ from ..models import ModuleInfo
292
+
293
+ result = {
294
+ "module": ModuleInfo(
295
+ name=module_name,
296
+ file=file_path,
297
+ is_package=Path(file_path).name in lang_config.get("index_files", []),
298
+ ),
299
+ "functions": {},
300
+ "classes": {},
301
+ "nodes": {},
302
+ "edges": [],
303
+ }
304
+
305
+ lines = content.split("\n")
306
+ current_class = None
307
+ class_brace_depth = 0
308
+ brace_depth = 0
309
+ pending_decorators = []
310
+
311
+ import_re = patterns.get("import")
312
+ decorator_re = patterns.get("decorator")
313
+ class_re = patterns.get("class")
314
+ interface_re = patterns.get("interface")
315
+ func_re = patterns.get("function")
316
+ arrow_re = patterns.get("arrow_func")
317
+ method_re = patterns.get("method")
318
+ arrow_prop_re = patterns.get("arrow_prop")
319
+
320
+ track_braces = lang_config.get("brace_track", True)
321
+ reserved = lang_config.get(
322
+ "reserved", {"if", "for", "while", "switch", "return", "catch"}
323
+ )
324
+
325
+ for line_no, line in enumerate(lines, 1):
326
+ raw_line = line
327
+ line = line.strip()
328
+ if not line:
329
+ continue
330
+ if line.startswith(("//", "/*", "*")):
331
+ continue
332
+ if (
333
+ line.startswith("#")
334
+ and not line.startswith("#include")
335
+ and not line.startswith("#define")
336
+ ):
337
+ continue
338
+
339
+ brace_depth, current_class, class_brace_depth = _update_brace_tracking(
340
+ raw_line, brace_depth, current_class, class_brace_depth, track_braces
341
+ )
342
+
343
+ pending_decorators = _process_decorators(decorator_re, line, pending_decorators)
344
+
345
+ if import_re:
346
+ im = import_re.match(line)
347
+ if im:
348
+ result["module"].imports.append(im.group(1))
349
+ continue
350
+
351
+ current_class, class_brace_depth, pending_decorators = _process_classes(
352
+ class_re,
353
+ interface_re,
354
+ line,
355
+ line_no,
356
+ file_path,
357
+ module_name,
358
+ result,
359
+ stats,
360
+ current_class,
361
+ class_brace_depth,
362
+ pending_decorators,
363
+ )
364
+
365
+ pending_decorators = _process_functions(
366
+ func_re,
367
+ arrow_re,
368
+ method_re,
369
+ arrow_prop_re,
370
+ line,
371
+ line_no,
612
372
  file_path,
613
373
  module_name,
614
- patterns,
374
+ result,
615
375
  stats,
616
- lang_config,
376
+ current_class,
377
+ pending_decorators,
378
+ reserved,
379
+ )
380
+
381
+ pending_decorators = _clear_orphaned_decorators(
382
+ line,
383
+ pending_decorators,
384
+ func_re,
385
+ arrow_re,
386
+ class_re,
387
+ interface_re,
388
+ method_re,
617
389
  )
618
390
 
619
- calculate_complexity_regex(content, result, lang=cc_lang)
620
- extract_calls_regex(content, module_name, result)
621
- stats["files_processed"] += 1
622
391
  return result