cg-code-graph 0.23.6__tar.gz → 0.23.8__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 (416) hide show
  1. {cg_code_graph-0.23.6/cg_code_graph.egg-info → cg_code_graph-0.23.8}/PKG-INFO +1 -1
  2. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/__init__.py +1 -1
  3. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/bridges.py +165 -8
  4. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/cli.py +9 -5
  5. cg_code_graph-0.23.8/cg_code_graph/cmake_sources.py +322 -0
  6. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/config.py +37 -5
  7. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/coverage.py +2 -2
  8. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/mcp_server.py +5 -4
  9. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/parity.py +77 -9
  10. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/parity_structure.py +119 -0
  11. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/platforms.py +125 -3
  12. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/extract.mjs +59 -4
  13. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8/cg_code_graph.egg-info}/PKG-INFO +1 -1
  14. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/SOURCES.txt +5 -0
  15. cg_code_graph-0.23.8/tests/test_cmake_sources.py +129 -0
  16. cg_code_graph-0.23.8/tests/test_issue_222.py +168 -0
  17. cg_code_graph-0.23.8/tests/test_parity_fields.py +125 -0
  18. cg_code_graph-0.23.8/tests/test_tauri_events.py +128 -0
  19. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/LICENSE +0 -0
  20. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/MANIFEST.in +0 -0
  21. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/README.md +0 -0
  22. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/__main__.py +0 -0
  23. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/affected.py +0 -0
  24. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/agent_rules.py +0 -0
  25. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/agents.py +0 -0
  26. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/aitools.py +0 -0
  27. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/android_ipc.py +0 -0
  28. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/apple_ipc.py +0 -0
  29. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/apps.py +0 -0
  30. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/blindspots.py +0 -0
  31. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/brokers.py +0 -0
  32. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/concepts.py +0 -0
  33. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/__init__.py +0 -0
  34. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/cache.py +0 -0
  35. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/detect.py +0 -0
  36. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/env.py +0 -0
  37. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/extractors.py +0 -0
  38. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/fsutil.py +0 -0
  39. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/generated.py +0 -0
  40. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/model.py +0 -0
  41. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/paths.py +0 -0
  42. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/plugin.py +0 -0
  43. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/redact.py +0 -0
  44. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/store.py +0 -0
  45. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/core/syntax_errors.py +0 -0
  46. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/dart_isolates.py +0 -0
  47. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/doctor.py +0 -0
  48. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/explore.py +0 -0
  49. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/external.py +0 -0
  50. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/graphql.py +0 -0
  51. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/guard_facts.py +0 -0
  52. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/hooks.py +0 -0
  53. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/indexer.py +0 -0
  54. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/insecure_transport.py +0 -0
  55. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/install_rules.py +0 -0
  56. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/jobs.py +0 -0
  57. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/link.py +0 -0
  58. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/lint_async.py +0 -0
  59. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/local_ipc.py +0 -0
  60. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/local_sockets.py +0 -0
  61. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/mcp_graphs.py +0 -0
  62. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/mcp_install.py +0 -0
  63. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/payload.py +0 -0
  64. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plans.py +0 -0
  65. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/platform_scan.py +0 -0
  66. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/__init__.py +0 -0
  67. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/astro/__init__.py +0 -0
  68. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/astro/content.py +0 -0
  69. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/astro/plugin.py +0 -0
  70. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
  71. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
  72. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
  73. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/__init__.py +0 -0
  74. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/bridges.py +0 -0
  75. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
  76. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
  77. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
  78. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/http.py +0 -0
  79. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/models.py +0 -0
  80. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/plugin.py +0 -0
  81. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/program.py +0 -0
  82. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/__init__.py +0 -0
  83. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/extras.py +0 -0
  84. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/models.py +0 -0
  85. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/plugin.py +0 -0
  86. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/schemas.py +0 -0
  87. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/shapes.py +0 -0
  88. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/urls.py +0 -0
  89. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/express/__init__.py +0 -0
  90. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/express/plugin.py +0 -0
  91. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/flutter/__init__.py +0 -0
  92. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/flutter/plugin.py +0 -0
  93. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/java/__init__.py +0 -0
  94. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/java/exact.py +0 -0
  95. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/java/plugin.py +0 -0
  96. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/jvm/__init__.py +0 -0
  97. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/jvm/interop.py +0 -0
  98. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/jvm/spring.py +0 -0
  99. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
  100. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/exact.py +0 -0
  101. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/plugin.py +0 -0
  102. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
  103. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/__init__.py +0 -0
  104. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
  105. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/massassign.py +0 -0
  106. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/plugin.py +0 -0
  107. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/tests.py +0 -0
  108. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/values.py +0 -0
  109. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/__init__.py +0 -0
  110. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/gates.py +0 -0
  111. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/runner.py +0 -0
  112. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/scipread.py +0 -0
  113. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/ts.py +0 -0
  114. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nest/__init__.py +0 -0
  115. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nest/plugin.py +0 -0
  116. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
  117. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
  118. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
  119. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nuxt/plugin.py +0 -0
  120. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/__init__.py +0 -0
  121. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/external.py +0 -0
  122. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
  123. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
  124. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
  125. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/gating.py +0 -0
  126. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/http_client.py +0 -0
  127. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/inline_guards.py +0 -0
  128. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/plugin.py +0 -0
  129. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/strings.py +0 -0
  130. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/__init__.py +0 -0
  131. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/aitools.py +0 -0
  132. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/external.py +0 -0
  133. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/fields.py +0 -0
  134. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/plugin.py +0 -0
  135. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/refs.py +0 -0
  136. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/roots.py +0 -0
  137. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/socketio.py +0 -0
  138. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/subproc.py +0 -0
  139. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/tests.py +0 -0
  140. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/values.py +0 -0
  141. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
  142. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
  143. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/pyweb/values.py +0 -0
  144. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/__init__.py +0 -0
  145. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/cargo.py +0 -0
  146. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/plugin.py +0 -0
  147. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/syntax.py +0 -0
  148. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/__init__.py +0 -0
  149. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/importer.py +0 -0
  150. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/scip.proto +0 -0
  151. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
  152. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/stubs/__init__.py +0 -0
  153. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/stubs/plugins.py +0 -0
  154. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/__init__.py +0 -0
  155. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/baseurl.py +0 -0
  156. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/exact.py +0 -0
  157. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/indexstore.py +0 -0
  158. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/packages.py +0 -0
  159. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/plugin.py +0 -0
  160. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/__init__.py +0 -0
  161. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/baseurl.py +0 -0
  162. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
  163. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
  164. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
  165. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
  166. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/nav.py +0 -0
  167. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/plugin.py +0 -0
  168. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/react_router.py +0 -0
  169. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
  170. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/tsweb/common.py +0 -0
  171. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/plugins/tsweb/data.py +0 -0
  172. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/__init__.py +0 -0
  173. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/c_cpp.yaml +0 -0
  174. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/common.yaml +0 -0
  175. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/dart.yaml +0 -0
  176. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/django-ninja.yaml +0 -0
  177. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/django.yaml +0 -0
  178. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/djangorestframework.yaml +0 -0
  179. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/express.yaml +0 -0
  180. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/java.yaml +0 -0
  181. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/kotlin.yaml +0 -0
  182. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/laravel.yaml +0 -0
  183. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/nest.yaml +0 -0
  184. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/nextjs.yaml +0 -0
  185. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/nuxt.yaml +0 -0
  186. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/php.yaml +0 -0
  187. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/python.yaml +0 -0
  188. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/react-router.yaml +0 -0
  189. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/rust.yaml +0 -0
  190. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/spring.yaml +0 -0
  191. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/swift.yaml +0 -0
  192. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/presets/typescript.yaml +0 -0
  193. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/process_runs.py +0 -0
  194. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/protocols/__init__.py +0 -0
  195. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/protocols/builtin.py +0 -0
  196. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/protocols/matchers.py +0 -0
  197. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/protocols/view.py +0 -0
  198. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/query.py +0 -0
  199. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/realtime.py +0 -0
  200. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/realtime_events.py +0 -0
  201. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/realtime_native.py +0 -0
  202. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/realtime_ws.py +0 -0
  203. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/roundtrip.py +0 -0
  204. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/routes.py +0 -0
  205. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/rpc.py +0 -0
  206. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/sdk_systems.py +0 -0
  207. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/sockets.py +0 -0
  208. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/ssrf_input.py +0 -0
  209. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/starters.py +0 -0
  210. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/surface.py +0 -0
  211. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/tests_index.py +0 -0
  212. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/udp_apps.py +0 -0
  213. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/update_check.py +0 -0
  214. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/__init__.py +0 -0
  215. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/graph.py +0 -0
  216. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/server.py +0 -0
  217. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/app.css +0 -0
  218. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/app.js +0 -0
  219. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/index.html +0 -0
  220. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/layered.js +0 -0
  221. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
  222. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
  223. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
  224. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
  225. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
  226. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/tools/package-lock.json +0 -0
  227. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/tools/package.json +0 -0
  228. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/viz/tools/shoot.mjs +0 -0
  229. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/watch.py +0 -0
  230. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/webhook_subs.py +0 -0
  231. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/webhooks.py +0 -0
  232. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph/xcode.py +0 -0
  233. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/dependency_links.txt +0 -0
  234. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/entry_points.txt +0 -0
  235. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/requires.txt +0 -0
  236. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/top_level.txt +0 -0
  237. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/pyproject.toml +0 -0
  238. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/setup.cfg +0 -0
  239. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_affected.py +0 -0
  240. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_agents_install.py +0 -0
  241. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_agents_md.py +0 -0
  242. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_ai_tools.py +0 -0
  243. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_android_ipc.py +0 -0
  244. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_apple_ipc.py +0 -0
  245. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_astro.py +0 -0
  246. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_astro_content.py +0 -0
  247. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_astro_server.py +0 -0
  248. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_bridges.py +0 -0
  249. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_bridges_pigeon_monorepo.py +0 -0
  250. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_brokers.py +0 -0
  251. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_cache_clean.py +0 -0
  252. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_cache_invalidation.py +0 -0
  253. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_cache_migration.py +0 -0
  254. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_channels_tests.py +0 -0
  255. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_cli_output.py +0 -0
  256. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_completeness.py +0 -0
  257. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_config_extras.py +0 -0
  258. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_coverage.py +0 -0
  259. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_coverage_ts_hint.py +0 -0
  260. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_dart_isolates.py +0 -0
  261. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_db_connections.py +0 -0
  262. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_dead_wrappers.py +0 -0
  263. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_dispatch_interfaces.py +0 -0
  264. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_django_flutter.py +0 -0
  265. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_docs_languages.py +0 -0
  266. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_docs_links.py +0 -0
  267. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_echo_ref.py +0 -0
  268. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_echo_wrapper.py +0 -0
  269. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_elysia.py +0 -0
  270. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_enum_constants.py +0 -0
  271. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_env.py +0 -0
  272. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_explore.py +0 -0
  273. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_external.py +0 -0
  274. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_fp_batch.py +0 -0
  275. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_gating.py +0 -0
  276. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_generated.py +0 -0
  277. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_graphql.py +0 -0
  278. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_hooks.py +0 -0
  279. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_impact_overrides.py +0 -0
  280. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_index_isolation.py +0 -0
  281. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_inherited_overrides.py +0 -0
  282. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_inline_guards.py +0 -0
  283. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_install_rules.py +0 -0
  284. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_192.py +0 -0
  285. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_201.py +0 -0
  286. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_202.py +0 -0
  287. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_203.py +0 -0
  288. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_204.py +0 -0
  289. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_205.py +0 -0
  290. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_206.py +0 -0
  291. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_207.py +0 -0
  292. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_208.py +0 -0
  293. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_209.py +0 -0
  294. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_210.py +0 -0
  295. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_211.py +0 -0
  296. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_211_used_at.py +0 -0
  297. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_212.py +0 -0
  298. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_212_langs.py +0 -0
  299. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_218.py +0 -0
  300. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_issue_219.py +0 -0
  301. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_java.py +0 -0
  302. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_java_exact.py +0 -0
  303. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_jobs.py +0 -0
  304. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_js_refs.py +0 -0
  305. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_js_runtime.py +0 -0
  306. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_kotlin.py +0 -0
  307. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_kotlin_binding.py +0 -0
  308. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_kotlin_exact.py +0 -0
  309. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_kotlin_fields.py +0 -0
  310. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_kotlin_mixed.py +0 -0
  311. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_kotlin_nav_consts.py +0 -0
  312. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_kotlin_props.py +0 -0
  313. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_laravel_determinism.py +0 -0
  314. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_laravel_receiver_narrowing.py +0 -0
  315. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_laravel_resources.py +0 -0
  316. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_laravel_route_paths.py +0 -0
  317. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_link_origin.py +0 -0
  318. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_lint_async.py +0 -0
  319. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_listing_files.py +0 -0
  320. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_local_ipc.py +0 -0
  321. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_local_sockets.py +0 -0
  322. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_mass_assignment.py +0 -0
  323. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_mcp.py +0 -0
  324. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_mcp_index.py +0 -0
  325. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_mcp_install.py +0 -0
  326. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_mcp_instructions.py +0 -0
  327. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_mcp_multi_graph.py +0 -0
  328. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_native_cfamily.py +0 -0
  329. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_native_concurrency.py +0 -0
  330. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_native_rust.py +0 -0
  331. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_nuxt_i18n.py +0 -0
  332. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_nuxt_import_dirs.py +0 -0
  333. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_nuxt_nitro.py +0 -0
  334. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_nuxt_rootsrc.py +0 -0
  335. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_nuxt_side_dirs.py +0 -0
  336. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_packaging.py +0 -0
  337. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_parity.py +0 -0
  338. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_parity_structure.py +0 -0
  339. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_php_http.py +0 -0
  340. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_php_props.py +0 -0
  341. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_plain_js.py +0 -0
  342. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_plans.py +0 -0
  343. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_platform_gaps.py +0 -0
  344. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_platform_type_variants.py +0 -0
  345. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_platforms.py +0 -0
  346. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_platforms_apple.py +0 -0
  347. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_presets_config.py +0 -0
  348. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_process_ipc.py +0 -0
  349. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_process_runs.py +0 -0
  350. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_protocols.py +0 -0
  351. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_app_tests_module.py +0 -0
  352. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_collection_chains.py +0 -0
  353. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_compat.py +0 -0
  354. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_entry_refs.py +0 -0
  355. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_fields.py +0 -0
  356. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_infer_cycles.py +0 -0
  357. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_roots.py +0 -0
  358. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_subprocess_tests.py +0 -0
  359. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_tests.py +0 -0
  360. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_web_hosts.py +0 -0
  361. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_web_routes.py +0 -0
  362. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_python_web_routes_more.py +0 -0
  363. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_react_router.py +0 -0
  364. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_readers_writers_specs.py +0 -0
  365. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_realtime.py +0 -0
  366. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_realtime_native.py +0 -0
  367. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_redact_salt.py +0 -0
  368. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_request_keys.py +0 -0
  369. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_roundtrip.py +0 -0
  370. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_route_specs.py +0 -0
  371. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_route_tables.py +0 -0
  372. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_routes_search_explain.py +0 -0
  373. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_rpc.py +0 -0
  374. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_scip_health.py +0 -0
  375. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_sdk_external.py +0 -0
  376. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_sdk_external_infra.py +0 -0
  377. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_sdk_external_mail.py +0 -0
  378. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_snippet.py +0 -0
  379. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_sockets.py +0 -0
  380. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_spring.py +0 -0
  381. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_ssrf.py +0 -0
  382. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_starters_budget.py +0 -0
  383. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_surface.py +0 -0
  384. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_surface_transport.py +0 -0
  385. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift.py +0 -0
  386. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_binding.py +0 -0
  387. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_exact.py +0 -0
  388. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_facts.py +0 -0
  389. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_fields.py +0 -0
  390. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_modules.py +0 -0
  391. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_more.py +0 -0
  392. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_nav_values.py +0 -0
  393. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_parse_errors.py +0 -0
  394. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_props.py +0 -0
  395. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_sdk.py +0 -0
  396. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_testing.py +0 -0
  397. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_swift_values.py +0 -0
  398. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_tests_scope.py +0 -0
  399. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_ts_fields.py +0 -0
  400. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_ts_fields_js_vue.py +0 -0
  401. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_ts_file_specs.py +0 -0
  402. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_ts_frameworks.py +0 -0
  403. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_ts_node_http.py +0 -0
  404. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_ts_nuxt.py +0 -0
  405. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_ts_src_tsconfig.py +0 -0
  406. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_unguarded.py +0 -0
  407. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_update_check.py +0 -0
  408. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_values.py +0 -0
  409. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_viz.py +0 -0
  410. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_vue_nav.py +0 -0
  411. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_watch.py +0 -0
  412. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_webhooks.py +0 -0
  413. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_webhooks_152.py +0 -0
  414. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_webhooks_152b.py +0 -0
  415. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_websockets.py +0 -0
  416. {cg_code_graph-0.23.6 → cg_code_graph-0.23.8}/tests/test_workspace_link.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cg-code-graph
3
- Version: 0.23.6
3
+ Version: 0.23.8
4
4
  Summary: cg: a code graph of routes, calls, data access and platform boundaries for agents and humans (CLI + MCP server)
5
5
  Author: cyberchronos00
6
6
  License-Expression: MIT
@@ -1,2 +1,2 @@
1
1
  """code-graph: deterministic code knowledge graph (beta)."""
2
- __version__ = "0.23.6"
2
+ __version__ = "0.23.8"
@@ -31,6 +31,9 @@ Process protocols (one app, two processes; receivers carry attrs.process instead
31
31
  tauri endpoint:tauri:<command> (plugin commands: endpoint:tauri:plugin:<name>|<command>, external
32
32
  tauri-plugin-<name> unless the plugin crate is in the repo); invoke('cmd') from @tauri-apps/api ->
33
33
  #[tauri::command] fn in the Rust core; check unregistered: not listed in generate_handler!
34
+ tauri-event endpoint:tauri-event:<name>; emit / emit_to / emit_str / emit_filter with a literal name (Rust
35
+ `app.emit("x", ..)`, webview `emit('x')`, `getCurrentWindow().emit('x')`, `emitTo(label, 'x')`)
36
+ -> listen / listen_any / once (Rust closures, webview callbacks); `tauri://` names are Tauri's own
34
37
  no_receiver for these: the other side is in the repo (some channel / command is received) but not this one.
35
38
  """
36
39
  from __future__ import annotations
@@ -55,6 +58,8 @@ PROTOCOLS = {
55
58
  "ipcRenderer.on)",
56
59
  "electron-preload": "Electron context bridge member (window.<key>.<member>() -> contextBridge.exposeInMainWorld)",
57
60
  "tauri": "Tauri command (invoke('cmd') -> #[tauri::command] fn cmd registered in generate_handler!)",
61
+ "tauri-event": "Tauri event (emit / emit_to('name') in Rust or the webview -> listen / once('name') on the other "
62
+ "side; `tauri://` events are emitted by Tauri itself)",
58
63
  "react-native-event": "React Native event (native sendEvent / RCTDeviceEventEmitter.emit / sendEventWithName / Expo "
59
64
  "sendEvent -> NativeEventEmitter / DeviceEventEmitter addListener in JS)",
60
65
  "capacitor-event": "Capacitor plugin event (native notifyListeners('evt') -> Plugin.addListener('evt') in JS)",
@@ -64,8 +69,8 @@ PROTOCOLS = {
64
69
  # native -> app events: the JS listener is the receiver; no_sender only where the repo sends some event natively
65
70
  EVENT_PROTOCOLS = ("react-native-event", "capacitor-event")
66
71
  # protocols between processes of one app (no per-platform receivers)
67
- PROCESS_PROTOCOLS = ("electron-ipc", "electron-preload", "tauri")
68
- TRANSPORT = {"electron-ipc": "ipc", "tauri": "ipc", "electron-preload": "local"}
72
+ PROCESS_PROTOCOLS = ("electron-ipc", "electron-preload", "tauri", "tauri-event")
73
+ TRANSPORT = {"electron-ipc": "ipc", "tauri": "ipc", "tauri-event": "ipc", "electron-preload": "local"}
69
74
  MOBILE = ("android", "ios", "macos")
70
75
  APP_LANGS = ("dart", "ts") # the app side of a bridge (receivers there: a native -> app call)
71
76
  # Capacitor Plugin / CAPPlugin base-class methods: handled by the bridge on every platform unless a plugin overrides them
@@ -1162,11 +1167,134 @@ def tauri_receivers(project, builder) -> dict:
1162
1167
  return {"commands": n, "registered": len(registered)} if n else {}
1163
1168
 
1164
1169
 
1170
+ TAURI_EV_RS_SEND = re.compile(r"\.\s*(emit|emit_str|emit_all)\s*\(\s*\"([^\"]+)\"|"
1171
+ r"\.\s*(emit_to|emit_str_to|emit_filter|emit_str_filter)\s*\(\s*(?:[^,()]|\([^()]*\))+,\s*\"([^\"]+)\"")
1172
+ TAURI_EV_RS_RECV = re.compile(r"\.\s*(listen|listen_any|once|once_any)\s*\(\s*\"([^\"]+)\"\s*,\s*(?:move\s*)?(\|[^|]*\||[A-Za-z_][\w:]*)?")
1173
+ TAURI_EV_JS_SEND = re.compile(r"""(?<![\w$])(?:\.\s*)?(emit)\s*\(\s*(['"`])([^'"`$\n]+)\2|"""
1174
+ r"""(?<![\w$])(?:\.\s*)?(emitTo)\s*\(\s*[^,()]+,\s*(['"`])([^'"`$\n]+)\5""")
1175
+ TAURI_EV_JS_RECV = re.compile(r"""(?<![\w$])(?:\.\s*)?(listen|once)\s*(?:<[^>()]*>)?\s*\(\s*(['"`])([^'"`$\n]+)\2\s*,\s*([A-Za-z_$][\w$]*)?""")
1176
+ TAURI_EV_DYN_SEND = re.compile(r"""(?<![\w$])(?:\.\s*)?(?:emit|emit_str|emit_all)\s*\(\s*&?[A-Za-z_$][\w$.]*\s*[,)]""")
1177
+ TAURI_EV_DYN_RECV = re.compile(r"""(?<![\w$])(?:\.\s*)?(?:listen|listen_any|once)\s*(?:<[^>()]*>)?\s*\(\s*&?[A-Za-z_$][\w$.]*\s*,""")
1178
+ _JS_TOKEN = re.compile(r"""'(?:\\.|[^'\\\n])*'|"(?:\\.|[^"\\\n])*"|`(?:\\.|[^`\\])*`|//[^\n]*|/\*.*?\*/""", re.S)
1179
+ JS_LIKE = (".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts", ".vue", ".svelte")
1180
+
1181
+
1182
+ def _innermost(builder, by_file: dict, rel: str, line: int) -> str | None:
1183
+ """The innermost function / method / component node of `rel` around `line`, else its module / file node."""
1184
+ best, size = None, None
1185
+ for n in by_file.get(rel, ()):
1186
+ if n.line is None or n.line > line or (n.end_line or n.line) < line:
1187
+ continue
1188
+ sz = (n.end_line or n.line) - n.line
1189
+ if size is None or sz < size:
1190
+ best, size = n.id, sz
1191
+ return best
1192
+
1193
+
1194
+ def _uses_tauri(root: Path, depth: int = 4) -> bool:
1195
+ """A Cargo.toml depending on tauri or a package.json depending on @tauri-apps/* within `depth` directories."""
1196
+ from . import presets
1197
+ skip = presets.skip_dirs("common")
1198
+ for dp, dn, fn in os.walk(root):
1199
+ rel = Path(dp).relative_to(root)
1200
+ dn[:] = [] if len(rel.parts) >= depth else [d for d in dn if d not in skip and not d.startswith(".")]
1201
+ for name, rx in (("Cargo.toml", r"^\s*tauri\s*="), ("package.json", r'"@tauri-apps/')):
1202
+ if name in fn:
1203
+ try:
1204
+ if re.search(rx, (Path(dp) / name).read_text(encoding="utf-8", errors="replace"), re.M):
1205
+ return True
1206
+ except OSError:
1207
+ pass
1208
+ return False
1209
+
1210
+
1211
+ def tauri_events(project, builder) -> dict:
1212
+ """Tauri events (#111): a literal event name emitted on one side (Rust core or webview) and listened to on the
1213
+ other -> SENDS_TO / RECEIVED_BY over endpoint:tauri-event:<name>. The receiver is the named callback when the
1214
+ listener passes a function by name, else the function that registers the listener. Names built at run time
1215
+ (`window.emit(event_name, ..)`) are not followed."""
1216
+ root = Path(project.root)
1217
+ if not _uses_tauri(root):
1218
+ return {}
1219
+ by_file: dict[str, list] = defaultdict(list)
1220
+ kinds = ("function", "method", "component", "page", "layout", "module", "file", "closure")
1221
+ for n in builder.nodes.values():
1222
+ if n.file and n.kind in kinds:
1223
+ by_file[n.file].append(n)
1224
+ named: dict[str, dict[str, str]] = defaultdict(dict)
1225
+ for f, ns in by_file.items():
1226
+ for n in ns:
1227
+ if n.kind in ("function", "method"):
1228
+ named[f].setdefault(n.name.rsplit("::", 1)[-1].rsplit(".", 1)[-1], n.id)
1229
+ sent = recv = 0
1230
+ dyn = {"send": 0, "recv": 0} # names passed in a variable: a helper forwards them (`listen(eventName, ..)`)
1231
+ eps = set()
1232
+ for rel in sorted(by_file):
1233
+ is_rs = rel.endswith(".rs")
1234
+ if not (is_rs or rel.endswith(JS_LIKE)) or rel.endswith(".d.ts"):
1235
+ continue
1236
+ try:
1237
+ raw = (root / rel).read_text(encoding="utf-8", errors="replace")
1238
+ except OSError:
1239
+ continue
1240
+ if is_rs:
1241
+ if "emit" not in raw and "listen" not in raw and "once" not in raw:
1242
+ continue
1243
+ src = strip_comments(raw)
1244
+ if not re.search(r"\btauri\b", src):
1245
+ continue
1246
+ else:
1247
+ if "@tauri-apps/api" not in raw and "__TAURI__" not in raw:
1248
+ continue
1249
+ src = _JS_TOKEN.sub(lambda m: m.group(0) if m.group(0)[0] in "'\"`" else re.sub(r"[^\n]", " ", m.group(0)), raw)
1250
+ side = "core" if is_rs else "webview"
1251
+ lines = lambda pos: src.count("\n", 0, pos) + 1 # noqa: E731
1252
+ dyn["send"] += len(TAURI_EV_DYN_SEND.findall(src))
1253
+ dyn["recv"] += len(TAURI_EV_DYN_RECV.findall(src))
1254
+ for m in (TAURI_EV_RS_SEND if is_rs else TAURI_EV_JS_SEND).finditer(src):
1255
+ name = (m.group(2) or m.group(4)) if is_rs else (m.group(3) or m.group(6))
1256
+ ln = lines(m.start())
1257
+ who = _innermost(builder, by_file, rel, ln)
1258
+ if not who or not name:
1259
+ continue
1260
+ nid = protocol_send(builder, "tauri-event", name, None, who, rel, ln, "exact", process=side,
1261
+ via=(m.group(1) or m.group(3)) if is_rs else (m.group(1) or m.group(4)))
1262
+ if name.startswith("tauri://"):
1263
+ builder.nodes[nid].attrs["builtin"] = True
1264
+ eps.add(nid)
1265
+ sent += 1
1266
+ for m in (TAURI_EV_RS_RECV if is_rs else TAURI_EV_JS_RECV).finditer(src):
1267
+ name = m.group(2) if is_rs else m.group(3)
1268
+ cb = (m.group(3) or "") if is_rs else (m.group(4) or "")
1269
+ ln = lines(m.start())
1270
+ h = named[rel].get(cb.rsplit("::", 1)[-1]) if cb and not cb.startswith("|") else None
1271
+ h = h or _innermost(builder, by_file, rel, ln)
1272
+ if not h:
1273
+ continue
1274
+ nid = protocol_receive(builder, "tauri-event", name, None, h, rel, ln, "exact", process=side,
1275
+ via=m.group(1))
1276
+ if name.startswith("tauri://"):
1277
+ builder.nodes[nid].attrs["builtin"] = True
1278
+ eps.add(nid)
1279
+ recv += 1
1280
+ if dyn["send"] or dyn["recv"]:
1281
+ # the other side may be one of those: no no_receiver / no_sender claim for the literal names
1282
+ for nid in eps:
1283
+ builder.nodes[nid].attrs["dynamic_names"] = dict(dyn)
1284
+ out = {"event_sends": sent, "event_listeners": recv}
1285
+ if dyn["send"] or dyn["recv"]:
1286
+ out["event_dynamic_names"] = dyn
1287
+ return out if sent or recv else {}
1288
+
1289
+
1165
1290
  def apply(project, builder, scanned=None, sends_only: bool = False) -> dict:
1166
1291
  """Index pass: native receivers of every bridge protocol -> RECEIVED_BY edges (+ stub nodes for Java / ObjC) and
1167
1292
  platform marks on their files. Returns the bridges stats (empty when there is no bridge code)."""
1168
1293
  from .platforms import BIG, Cond, _plat_atom, mark
1169
1294
  tauri = tauri_receivers(project, builder)
1295
+ ev = tauri_events(project, builder)
1296
+ if ev:
1297
+ tauri = {**(tauri or {}), **ev}
1170
1298
  st0 = {"tauri": tauri} if tauri else {}
1171
1299
  st = _apply(project, builder, scanned, sends_only, mark, BIG, Cond, _plat_atom)
1172
1300
  if st0 or st:
@@ -1406,9 +1534,31 @@ def project_targets(project, builder) -> list[str]:
1406
1534
  return []
1407
1535
 
1408
1536
 
1409
- def _process_roles(builder, eps, recv, send) -> None:
1537
+ def _declared_role(declared: dict, f: str | None) -> str | None:
1538
+ if not f or not declared:
1539
+ return None
1540
+ return next((r for g, r in declared.items() if fnmatch.fnmatch(f, g)), None)
1541
+
1542
+
1543
+ def _process_roles(builder, eps, recv, send, declared: dict | None = None) -> None:
1410
1544
  """Electron / Tauri: process role of each file taking part in IPC (attrs.process on its module node): main,
1411
- preload (exposes a context bridge), renderer (Electron), webview / core (Tauri)."""
1545
+ preload (exposes a context bridge), renderer (Electron), webview / core (Tauri). `.cg.yaml`
1546
+ platforms.processes (glob -> role) wins over the inferred role, for the module and for each send / receive edge
1547
+ in its files (attrs.process_from: config)."""
1548
+ declared = declared or {}
1549
+ if declared:
1550
+ for nid, n in eps.items():
1551
+ if n.attrs.get("protocol") not in PROCESS_PROTOCOLS:
1552
+ continue
1553
+ for e in recv[nid]:
1554
+ dn = builder.nodes.get(e.dst)
1555
+ r = _declared_role(declared, dn.file if dn else None)
1556
+ if r:
1557
+ e.attrs = {**(e.attrs or {}), "process": r, "process_from": "config"}
1558
+ for e in send[nid]:
1559
+ r = _declared_role(declared, e.file)
1560
+ if r:
1561
+ e.attrs = {**(e.attrs or {}), "process": r, "process_from": "config"}
1412
1562
  roles = defaultdict(set)
1413
1563
  for nid, n in eps.items():
1414
1564
  if n.attrs.get("protocol") not in PROCESS_PROTOCOLS:
@@ -1421,10 +1571,16 @@ def _process_roles(builder, eps, recv, send) -> None:
1421
1571
  sn = builder.nodes.get(e.src)
1422
1572
  if sn and sn.file and e.attrs.get("process"):
1423
1573
  roles[sn.file].add(e.attrs["process"])
1424
- if not roles:
1574
+ if not roles and not declared:
1425
1575
  return
1426
1576
  for n in builder.nodes.values():
1427
- if n.kind in ("module", "file", "mod", "crate") and n.file in roles:
1577
+ if n.kind not in ("module", "file", "mod", "crate", "component"):
1578
+ continue
1579
+ d = _declared_role(declared, n.file)
1580
+ if d:
1581
+ # declared: also files that take no part in IPC themselves (the renderer's components, the core's services)
1582
+ n.attrs["process"], n.attrs["process_from"] = d, "config"
1583
+ elif n.file in roles and n.kind != "component":
1428
1584
  r = roles[n.file]
1429
1585
  n.attrs["process"] = "preload" if "preload" in r else next(iter(r)) if len(r) == 1 else "+".join(sorted(r))
1430
1586
 
@@ -1457,7 +1613,7 @@ def finalize(project, builder, st: dict, targets: list[str] | None) -> dict:
1457
1613
  proto_recv = defaultdict(set)
1458
1614
  for nid in recv:
1459
1615
  proto_recv[eps[nid].attrs["protocol"]].add(None)
1460
- _process_roles(builder, eps, recv, send)
1616
+ _process_roles(builder, eps, recv, send, ((project.options.get("config") or {}).get("platforms") or {}).get("processes"))
1461
1617
  # macOS counts only where some bridge module is implemented for it (a Flutter macos/ runner)
1462
1618
  used = {e.attrs.get("platform") for es in recv.values() for e in es}
1463
1619
  mobile = [p for p in (targets or []) if p in ("android", "ios") or (p == "macos" and p in used)]
@@ -1487,7 +1643,8 @@ def finalize(project, builder, st: dict, targets: list[str] | None) -> dict:
1487
1643
  # one app, two processes: a receiver-less channel is a miss when the other side is in the repo at all
1488
1644
  ext_pkg = any(e.attrs.get("external") for e in send[nid] + tsend[nid])
1489
1645
  impl = None if ext_pkg else (proto_recv.get(a["protocol"]) or None)
1490
- base = a.get("method") in BASE_METHODS.get(a["protocol"], ())
1646
+ base = (a.get("method") in BASE_METHODS.get(a["protocol"], ()) or bool(a.get("builtin"))
1647
+ or bool(a.get("dynamic_names")))
1491
1648
  if base:
1492
1649
  a["base_method"] = True # the framework's base class implements it on every platform; a module may override
1493
1650
  if a["protocol"] in EVENT_PROTOCOLS and (send[nid] or tsend[nid]) and not recv[nid]:
@@ -186,8 +186,9 @@ def main(argv=None):
186
186
  "(variants missing a target, API differences, references to code missing on a target)")
187
187
  p.add_argument("action", nargs="?", default="summary", choices=["summary", "divergence"])
188
188
  p.add_argument("--db", required=True); p.add_argument("--target", help="divergence: only findings that affect this target")
189
- p.add_argument("--kind", choices=["variants", "api_surface", "missing_callee", "missing_callee_tests"],
190
- help="divergence: one finding kind (missing_callee_tests: from test code on the project-default platforms)")
189
+ p.add_argument("--kind", choices=["variants", "api_surface", "missing_callee", "missing_callee_tests", "dead_branch"],
190
+ help="divergence: one finding kind (missing_callee_tests: from test code on the project-default platforms; "
191
+ "dead_branch: nested conditions no target meets together)")
191
192
  p.add_argument("--max-items", type=int, default=40); p.add_argument("--json", action="store_true")
192
193
  p = sub.add_parser("resolutions", help="every place a concept (e.g. timezone) is resolved, with fallback chains and divergence")
193
194
  p.add_argument("concept"); p.add_argument("--db", required=True); p.add_argument("--within", help="substring filter on the owning function fqn (e.g. Report)")
@@ -300,9 +301,12 @@ def main(argv=None):
300
301
  p.add_argument("--strip-prefix", action="append", default=[], help="a name prefix one side adds (`Vault` in "
301
302
  "VaultAddEditState for AddEditState), ignored when matching (repeatable)")
302
303
  p.add_argument("--structure", action="store_true", help="also pair symbols whose names differ by what they use: "
303
- "shared strings, localization keys, endpoints and already-paired callees, plus rename rules learned "
304
- "from the pairs found (#93); matches carry their evidence")
304
+ "shared strings, localization keys, resources, endpoints and already-paired callees, then types by "
305
+ "their declared fields, plus rename rules learned from the pairs found (#93); matches carry their "
306
+ "evidence")
305
307
  p.add_argument("--no-learn", action="store_true", help="with --structure: no learned rename rules")
308
+ p.add_argument("--both-sides", action="store_true", help="also list the matched pairs and what only --against "
309
+ "has (target symbols no source symbol matched)")
306
310
  p.add_argument("--write-map", help="with --structure: write the inferred pairs as a --map JSON file to review")
307
311
  p.add_argument("--json", action="store_true"); p.add_argument("--max-items", type=int, default=200)
308
312
  p = sub.add_parser("lint", help="heuristic lints (#88): `lint async-state` flags stale async results, state with "
@@ -573,7 +577,7 @@ def main(argv=None):
573
577
  from . import parity as PA
574
578
  mapping = json.loads(open(a.map, encoding="utf-8").read()) if a.map else None
575
579
  res = PA.parity(a.db, a.against, mapping=mapping, fuzzy=not a.no_fuzzy, strip_prefixes=a.strip_prefix,
576
- structure=a.structure, learn=not a.no_learn)
580
+ structure=a.structure, learn=not a.no_learn, both_sides=a.both_sides)
577
581
  if a.write_map:
578
582
  with open(a.write_map, "w", encoding="utf-8") as fh:
579
583
  json.dump(PA.rename_map(res), fh, indent=1, sort_keys=True)
@@ -0,0 +1,322 @@
1
+ """Per-platform C / C++ source lists from CMake (#111): `if(WIN32) list(APPEND srcs src/win/fs.c)`,
2
+ `if(CMAKE_SYSTEM_NAME MATCHES "Android|Linux") ...`, `target_sources(...)` under a condition. A source file that every
3
+ CMakeLists.txt mentions only under platform conditions is built only where one of them holds; that is the build's own
4
+ answer, so it replaces the directory / file-name guess (src/unix/, linux.c) for that file.
5
+
6
+ Read without running CMake: `if` / `elseif` / `else` / `endif` over WIN32, APPLE, UNIX, ANDROID, IOS, EMSCRIPTEN,
7
+ MSVC, MINGW, CYGWIN and `CMAKE_SYSTEM_NAME STREQUAL / MATCHES`, with NOT / AND / OR and parentheses. Anything else (an
8
+ option, a version check) is unknown and keeps the file live. Files are named in `list(APPEND|PREPEND ...)`, `set(...)`,
9
+ `target_sources(...)`, `add_library(...)` and `add_executable(...)`, relative to the CMakeLists.txt (a
10
+ `${CMAKE_CURRENT_SOURCE_DIR}/` prefix is understood); names built from other variables are not followed.
11
+
12
+ compile_db_membership: `.cg.yaml` platforms.compile_commands, one compile_commands.json per target build, is the exact
13
+ answer and wins over the CMake lists."""
14
+ from __future__ import annotations
15
+
16
+ import os
17
+ import re
18
+ from pathlib import Path
19
+
20
+ from . import presets
21
+
22
+ SYSTEM_NAME = {"windows": "Windows", "linux": "Linux", "macos": "Darwin", "ios": "iOS", "android": "Android",
23
+ "web": "Emscripten", "tvos": "tvOS", "watchos": "watchOS", "visionos": "visionOS"}
24
+ # operating systems outside the known targets, to tell whether a source list also builds the file there
25
+ OTHER = tuple("other:" + n for n in ("FreeBSD", "OpenBSD", "NetBSD", "DragonFly", "AIX", "SunOS", "OS390", "QNX",
26
+ "Haiku", "CYGWIN", "MSYS", "GNU", "OS400"))
27
+ BSDS = {"other:FreeBSD", "other:OpenBSD", "other:NetBSD", "other:DragonFly"}
28
+ SRC = re.compile(r"\.(c|cc|cpp|cxx|m|mm|h|hh|hpp|hxx)$", re.I)
29
+ LISTS = {"list", "set", "target_sources", "add_library", "add_executable"}
30
+
31
+
32
+ def _strip_comments(text: str) -> str:
33
+ text = re.sub(r"#\[(=*)\[.*?\]\1\]", " ", text, flags=re.S) # bracket comments
34
+ out = []
35
+ for line in text.split("\n"):
36
+ q = False
37
+ for i, ch in enumerate(line):
38
+ if ch == '"':
39
+ q = not q
40
+ elif ch == "#" and not q:
41
+ line = line[:i]
42
+ break
43
+ out.append(line)
44
+ return "\n".join(out)
45
+
46
+
47
+ def _commands(text: str):
48
+ """(name, args text, line) for every command call, args with nested parentheses."""
49
+ i, n = 0, len(text)
50
+ rx = re.compile(r"([A-Za-z_]\w*)\s*\(")
51
+ while True:
52
+ m = rx.search(text, i)
53
+ if not m:
54
+ return
55
+ depth, j, q = 1, m.end(), False
56
+ while j < n and depth:
57
+ ch = text[j]
58
+ if ch == '"':
59
+ q = not q
60
+ elif not q and ch == "(":
61
+ depth += 1
62
+ elif not q and ch == ")":
63
+ depth -= 1
64
+ j += 1
65
+ yield m.group(1).lower(), text[m.end():j - 1], text.count("\n", 0, m.start()) + 1
66
+ i = j
67
+
68
+
69
+ def _tokens(args: str) -> list[str]:
70
+ return [a[1:-1] if a.startswith('"') else a for a in re.findall(r'"[^"]*"|\(|\)|[^\s()"]+', args)]
71
+
72
+
73
+ # ------------------------------------------------------------------ three-valued condition evaluation per target
74
+ def _var(name: str, p: str):
75
+ name = re.sub(r"^\$\{(.*)\}$", r"\1", name)
76
+ u = name.upper()
77
+ if p.startswith("other:"):
78
+ if u in ("WIN32", "APPLE", "ANDROID", "IOS", "EMSCRIPTEN", "MSVC", "MINGW", "CMAKE_CL_64", "LINUX"):
79
+ return False
80
+ if u == "UNIX":
81
+ return True
82
+ if u in ("CYGWIN", "MSYS"):
83
+ return p == "other:" + u
84
+ if u == "BSD":
85
+ return p in BSDS
86
+ if u == "WIN32":
87
+ return p == "windows"
88
+ if u == "APPLE":
89
+ return p in ("macos", "ios", "tvos", "watchos", "visionos")
90
+ if u == "UNIX":
91
+ return p != "windows"
92
+ if u == "ANDROID":
93
+ return p == "android"
94
+ if u == "IOS":
95
+ return p == "ios"
96
+ if u == "EMSCRIPTEN":
97
+ return p == "web"
98
+ if u in ("MSVC", "MINGW", "CMAKE_CL_64"):
99
+ return None if p == "windows" else False
100
+ if u in ("CYGWIN", "MSYS", "BSD"):
101
+ return False
102
+ if u == "LINUX":
103
+ return p == "linux"
104
+ if u in ("ON", "TRUE", "YES", "Y") or (u.isdigit() and u != "0"):
105
+ return True
106
+ if u in ("OFF", "FALSE", "NO", "N", "0", "IGNORE", "NOTFOUND", ""):
107
+ return False
108
+ return None
109
+
110
+
111
+ def _system(tok: str) -> bool:
112
+ return re.sub(r"^\$\{(.*)\}$", r"\1", tok) == "CMAKE_SYSTEM_NAME"
113
+
114
+
115
+ class _Cond:
116
+ def __init__(self, toks: list[str]):
117
+ self.t, self.i = toks, 0
118
+
119
+ def peek(self):
120
+ return self.t[self.i] if self.i < len(self.t) else None
121
+
122
+ def take(self):
123
+ self.i += 1
124
+ return self.t[self.i - 1]
125
+
126
+ def parse(self, p: str):
127
+ self.i = 0
128
+ try:
129
+ v = self.p_or(p)
130
+ except (IndexError, re.error):
131
+ return None
132
+ return v if self.i >= len(self.t) else None
133
+
134
+ def p_or(self, p):
135
+ v = self.p_and(p)
136
+ while self.peek() == "OR":
137
+ self.take()
138
+ w = self.p_and(p)
139
+ v = True if (v is True or w is True) else (False if (v is False and w is False) else None)
140
+ return v
141
+
142
+ def p_and(self, p):
143
+ v = self.p_not(p)
144
+ while self.peek() == "AND":
145
+ self.take()
146
+ w = self.p_not(p)
147
+ v = False if (v is False or w is False) else (True if (v is True and w is True) else None)
148
+ return v
149
+
150
+ def p_not(self, p):
151
+ if self.peek() == "NOT":
152
+ self.take()
153
+ v = self.p_not(p)
154
+ return None if v is None else not v
155
+ return self.p_bin(p)
156
+
157
+ def p_bin(self, p):
158
+ tok = self.take()
159
+ if tok == "(":
160
+ v = self.p_or(p)
161
+ if self.take() != ")":
162
+ raise IndexError
163
+ return v
164
+ if tok in ("DEFINED", "EXISTS", "COMMAND", "TARGET", "POLICY", "IS_DIRECTORY", "IS_ABSOLUTE"):
165
+ self.take()
166
+ return None
167
+ op = self.peek()
168
+ if op in ("STREQUAL", "MATCHES", "EQUAL", "STRLESS", "STRGREATER", "LESS", "GREATER", "IN_LIST",
169
+ "VERSION_LESS", "VERSION_GREATER", "VERSION_EQUAL", "VERSION_GREATER_EQUAL", "VERSION_LESS_EQUAL",
170
+ "LESS_EQUAL", "GREATER_EQUAL", "STRLESS_EQUAL", "STRGREATER_EQUAL"):
171
+ self.take()
172
+ rhs = self.take()
173
+ sysname = SYSTEM_NAME.get(p) or p.split(":", 1)[-1]
174
+ if _system(tok) and op == "STREQUAL":
175
+ return sysname == rhs
176
+ if _system(tok) and op == "MATCHES":
177
+ return re.search(rhs, sysname) is not None
178
+ return None
179
+ return _var(tok, p)
180
+
181
+
182
+ def _values(toks: list[str]) -> dict:
183
+ from .platforms import KNOWN
184
+ c = _Cond(toks)
185
+ return {p: c.parse(p) for p in KNOWN + OTHER}
186
+
187
+
188
+ def _and(a: dict, b: dict) -> dict:
189
+ return {p: False if (a[p] is False or b[p] is False) else (True if (a[p] is True and b[p] is True) else None) for p in a}
190
+
191
+
192
+ def _not(a: dict) -> dict:
193
+ return {p: None if v is None else not v for p, v in a.items()}
194
+
195
+
196
+ def _or(a: dict, b: dict) -> dict:
197
+ return {p: True if (a[p] is True or b[p] is True) else (False if (a[p] is False and b[p] is False) else None) for p in a}
198
+
199
+
200
+ # ------------------------------------------------------------------ source membership
201
+ def membership(root: Path, files: set[str]) -> dict[str, dict]:
202
+ """rel file -> {"values": {target: True / False / None}, "text": first condition, "at": "CMakeLists.txt:12",
203
+ "mentions": n, "elsewhere": also built on another OS} for the indexed files the CMake lists mention only under
204
+ platform conditions."""
205
+ from .platforms import KNOWN
206
+ root = Path(root)
207
+ every = {p: True for p in KNOWN + OTHER}
208
+ skip = presets.skip_dirs("common")
209
+ seen: dict[str, dict] = {}
210
+ for d, dirs, names in os.walk(root):
211
+ dirs[:] = [x for x in dirs if x not in skip and not x.startswith(".")]
212
+ if "CMakeLists.txt" not in names and not any(n.endswith(".cmake") for n in names):
213
+ continue
214
+ for name in sorted(n for n in names if n == "CMakeLists.txt" or n.endswith(".cmake")):
215
+ path = Path(d) / name
216
+ try:
217
+ text = _strip_comments(path.read_text(encoding="utf-8", errors="replace"))
218
+ except OSError:
219
+ continue
220
+ base = Path(d).relative_to(root).as_posix()
221
+ rel_cm = path.relative_to(root).as_posix()
222
+ stack: list[list] = [] # [current branch values, values of previous branches, text]
223
+ body = 0 # inside function() / macro(): the lists are built where it is called
224
+ for cmd, args, line in _commands(text):
225
+ if cmd in ("function", "macro"):
226
+ body += 1
227
+ continue
228
+ if cmd in ("endfunction", "endmacro"):
229
+ body = max(0, body - 1)
230
+ continue
231
+ if body:
232
+ continue
233
+ if cmd == "if":
234
+ v = _values(_tokens(args))
235
+ stack.append([v, [v], f"if({args.strip()})"[:120]])
236
+ elif cmd == "elseif" and stack:
237
+ v = _values(_tokens(args))
238
+ prev = stack[-1][1]
239
+ cur = v
240
+ for pv in prev:
241
+ cur = _and(cur, _not(pv))
242
+ stack[-1] = [cur, prev + [v], f"elseif({args.strip()})"[:120]]
243
+ elif cmd == "else" and stack:
244
+ cur = dict(every)
245
+ for pv in stack[-1][1]:
246
+ cur = _and(cur, _not(pv))
247
+ stack[-1] = [cur, stack[-1][1], "else() of " + stack[-1][2]]
248
+ elif cmd == "endif" and stack:
249
+ stack.pop()
250
+ elif cmd in LISTS:
251
+ cond = dict(every)
252
+ for v, _, _ in stack:
253
+ cond = _and(cond, v)
254
+ for tok in _tokens(args):
255
+ tok = re.sub(r"^\$\{(?:CMAKE_CURRENT_SOURCE_DIR|CMAKE_CURRENT_LIST_DIR)\}/", "", tok)
256
+ if "$" in tok or not SRC.search(tok) or tok.startswith("/"):
257
+ continue
258
+ rel = os.path.normpath(os.path.join(base, tok)).replace(os.sep, "/") if base != "." else os.path.normpath(tok).replace(os.sep, "/")
259
+ if rel not in files:
260
+ continue
261
+ s = seen.get(rel)
262
+ text_c = " && ".join(t for _, _, t in stack) or "unconditional"
263
+ if s is None:
264
+ seen[rel] = {"values": cond, "text": text_c, "at": f"{rel_cm}:{line}", "mentions": 1}
265
+ else:
266
+ s["values"] = _or(s["values"], cond)
267
+ s["mentions"] += 1
268
+ out = {}
269
+ for f, s in seen.items():
270
+ vals = {p: s["values"][p] for p in KNOWN}
271
+ if any(v is False for v in vals.values()):
272
+ # also built on an OS outside the known targets (a BSD, AIX, Cygwin): its #else branches are live there
273
+ out[f] = {**s, "values": vals, "elsewhere": any(s["values"][p] is not False for p in OTHER)}
274
+ return out
275
+
276
+
277
+ def tree(values: dict):
278
+ """A platforms.Cond tree with these per-target values: True where it holds, unknown where it may."""
279
+ parts = [("atom", "platform", p) for p, v in values.items() if v is True]
280
+ parts += [("atom", "unknown_on", p) for p, v in values.items() if v is None]
281
+ if not parts:
282
+ return ("atom", "never", None)
283
+ return parts[0] if len(parts) == 1 else ("any", parts)
284
+
285
+
286
+ # ------------------------------------------------------------------ compile databases per target
287
+ def compile_db_membership(root: Path, dbs: dict[str, str], files: set[str]) -> dict[str, dict]:
288
+ """`.cg.yaml` platforms.compile_commands (target -> compile_commands.json of that target's build): a source file
289
+ is built on the targets whose database compiles it, not on the other listed targets, and unknown on targets
290
+ without a database. Headers are not compiled on their own and are left out."""
291
+ from .platforms import KNOWN
292
+ root = Path(root).resolve()
293
+ compiled: dict[str, set[str]] = {}
294
+ for target, path in dbs.items():
295
+ p = (root / path) if not os.path.isabs(path) else Path(path)
296
+ try:
297
+ entries = __import__("json").loads(p.read_text(encoding="utf-8", errors="replace"))
298
+ except (OSError, ValueError):
299
+ continue
300
+ got = set()
301
+ for e in entries if isinstance(entries, list) else ():
302
+ f = e.get("file") if isinstance(e, dict) else None
303
+ if not f:
304
+ continue
305
+ fp = Path(f) if os.path.isabs(f) else Path(e.get("directory") or root) / f
306
+ try:
307
+ rel = Path(os.path.normpath(fp)).resolve().relative_to(root).as_posix()
308
+ except (ValueError, OSError):
309
+ continue
310
+ got.add(rel)
311
+ compiled[target] = got
312
+ if not compiled:
313
+ return {}
314
+ out = {}
315
+ for f in files:
316
+ if not re.search(r"\.(c|cc|cpp|cxx|c\+\+|m|mm)$", f, re.I):
317
+ continue
318
+ vals = {p: (f in compiled[p]) if p in compiled else None for p in KNOWN}
319
+ if any(v is False for v in vals.values()):
320
+ on = [p for p in KNOWN if vals[p]]
321
+ out[f] = {"values": vals, "text": f"compile_commands ({', '.join(on) or 'no listed target'})"}
322
+ return out