cg-code-graph 0.23.10__tar.gz → 0.23.12__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 (423) hide show
  1. {cg_code_graph-0.23.10/cg_code_graph.egg-info → cg_code_graph-0.23.12}/PKG-INFO +1 -1
  2. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/__init__.py +1 -1
  3. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/cli.py +10 -3
  4. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/model.py +1 -0
  5. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/plugin.py +4 -1
  6. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/lint_async.py +47 -10
  7. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/mcp_server.py +5 -2
  8. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/java/exact.py +82 -24
  9. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/kotlin/exact.py +108 -7
  10. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/kotlin/plugin.py +138 -10
  11. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/swift/exact.py +23 -1
  12. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/swift/plugin.py +34 -7
  13. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/extractor/extract.mjs +19 -1
  14. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/roundtrip.py +71 -7
  15. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12/cg_code_graph.egg-info}/PKG-INFO +1 -1
  16. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph.egg-info/SOURCES.txt +4 -0
  17. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_kotlin_exact.py +5 -1
  18. cg_code_graph-0.23.12/tests/test_kotlin_local_state.py +79 -0
  19. cg_code_graph-0.23.12/tests/test_kotlin_prop_exact.py +146 -0
  20. cg_code_graph-0.23.12/tests/test_kotlin_prop_overrides.py +57 -0
  21. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_lint_async.py +21 -4
  22. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_roundtrip.py +12 -0
  23. cg_code_graph-0.23.12/tests/test_state_tracking_235.py +111 -0
  24. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_ts_fields_js_vue.py +22 -5
  25. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/LICENSE +0 -0
  26. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/MANIFEST.in +0 -0
  27. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/README.md +0 -0
  28. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/__main__.py +0 -0
  29. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/affected.py +0 -0
  30. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/agent_rules.py +0 -0
  31. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/agents.py +0 -0
  32. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/aitools.py +0 -0
  33. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/android_ipc.py +0 -0
  34. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/apple_ipc.py +0 -0
  35. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/apps.py +0 -0
  36. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/blindspots.py +0 -0
  37. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/bridges.py +0 -0
  38. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/brokers.py +0 -0
  39. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/cmake_sources.py +0 -0
  40. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/concepts.py +0 -0
  41. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/config.py +0 -0
  42. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/__init__.py +0 -0
  43. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/cache.py +0 -0
  44. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/detect.py +0 -0
  45. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/env.py +0 -0
  46. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/extractors.py +0 -0
  47. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/fsutil.py +0 -0
  48. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/generated.py +0 -0
  49. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/paths.py +0 -0
  50. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/redact.py +0 -0
  51. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/store.py +0 -0
  52. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/core/syntax_errors.py +0 -0
  53. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/coverage.py +0 -0
  54. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/dart_isolates.py +0 -0
  55. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/doctor.py +0 -0
  56. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/explore.py +0 -0
  57. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/external.py +0 -0
  58. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/graphql.py +0 -0
  59. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/guard_facts.py +0 -0
  60. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/hooks.py +0 -0
  61. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/indexer.py +0 -0
  62. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/insecure_transport.py +0 -0
  63. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/install_rules.py +0 -0
  64. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/jobs.py +0 -0
  65. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/link.py +0 -0
  66. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/local_ipc.py +0 -0
  67. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/local_sockets.py +0 -0
  68. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/mcp_graphs.py +0 -0
  69. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/mcp_install.py +0 -0
  70. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/parity.py +0 -0
  71. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/parity_structure.py +0 -0
  72. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/payload.py +0 -0
  73. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plans.py +0 -0
  74. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/platform_scan.py +0 -0
  75. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/platforms.py +0 -0
  76. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/__init__.py +0 -0
  77. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/astro/__init__.py +0 -0
  78. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/astro/content.py +0 -0
  79. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/astro/plugin.py +0 -0
  80. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
  81. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
  82. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
  83. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/dart/__init__.py +0 -0
  84. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/dart/bridges.py +0 -0
  85. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
  86. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
  87. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
  88. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/dart/http.py +0 -0
  89. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/dart/models.py +0 -0
  90. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/dart/plugin.py +0 -0
  91. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/dart/program.py +0 -0
  92. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/django/__init__.py +0 -0
  93. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/django/extras.py +0 -0
  94. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/django/models.py +0 -0
  95. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/django/plugin.py +0 -0
  96. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/django/schemas.py +0 -0
  97. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/django/shapes.py +0 -0
  98. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/django/urls.py +0 -0
  99. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/express/__init__.py +0 -0
  100. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/express/plugin.py +0 -0
  101. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/flutter/__init__.py +0 -0
  102. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/flutter/plugin.py +0 -0
  103. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/java/__init__.py +0 -0
  104. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/java/plugin.py +0 -0
  105. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/jvm/__init__.py +0 -0
  106. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/jvm/interop.py +0 -0
  107. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/jvm/spring.py +0 -0
  108. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
  109. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
  110. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/laravel/__init__.py +0 -0
  111. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
  112. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/laravel/massassign.py +0 -0
  113. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/laravel/plugin.py +0 -0
  114. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/laravel/tests.py +0 -0
  115. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/laravel/values.py +0 -0
  116. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/native/__init__.py +0 -0
  117. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/native/gates.py +0 -0
  118. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/native/runner.py +0 -0
  119. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/native/scipread.py +0 -0
  120. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/native/ts.py +0 -0
  121. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/nest/__init__.py +0 -0
  122. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/nest/plugin.py +0 -0
  123. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
  124. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
  125. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
  126. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/nuxt/plugin.py +0 -0
  127. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/__init__.py +0 -0
  128. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/external.py +0 -0
  129. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
  130. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
  131. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
  132. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/gating.py +0 -0
  133. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/http_client.py +0 -0
  134. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/inline_guards.py +0 -0
  135. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/plugin.py +0 -0
  136. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/php/strings.py +0 -0
  137. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/__init__.py +0 -0
  138. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/aitools.py +0 -0
  139. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/external.py +0 -0
  140. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/fields.py +0 -0
  141. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/plugin.py +0 -0
  142. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/refs.py +0 -0
  143. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/roots.py +0 -0
  144. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/socketio.py +0 -0
  145. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/subproc.py +0 -0
  146. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/tests.py +0 -0
  147. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/python/values.py +0 -0
  148. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
  149. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
  150. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/pyweb/values.py +0 -0
  151. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/rust/__init__.py +0 -0
  152. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/rust/cargo.py +0 -0
  153. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/rust/plugin.py +0 -0
  154. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/rust/syntax.py +0 -0
  155. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/scip/__init__.py +0 -0
  156. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/scip/importer.py +0 -0
  157. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/scip/scip.proto +0 -0
  158. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
  159. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/stubs/__init__.py +0 -0
  160. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/stubs/plugins.py +0 -0
  161. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/swift/__init__.py +0 -0
  162. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/swift/baseurl.py +0 -0
  163. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/swift/indexstore.py +0 -0
  164. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/swift/packages.py +0 -0
  165. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/__init__.py +0 -0
  166. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/baseurl.py +0 -0
  167. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
  168. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
  169. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
  170. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
  171. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/nav.py +0 -0
  172. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/plugin.py +0 -0
  173. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/ts/react_router.py +0 -0
  174. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
  175. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/tsweb/common.py +0 -0
  176. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/plugins/tsweb/data.py +0 -0
  177. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/__init__.py +0 -0
  178. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/c_cpp.yaml +0 -0
  179. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/common.yaml +0 -0
  180. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/dart.yaml +0 -0
  181. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/django-ninja.yaml +0 -0
  182. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/django.yaml +0 -0
  183. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/djangorestframework.yaml +0 -0
  184. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/express.yaml +0 -0
  185. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/java.yaml +0 -0
  186. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/kotlin.yaml +0 -0
  187. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/laravel.yaml +0 -0
  188. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/nest.yaml +0 -0
  189. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/nextjs.yaml +0 -0
  190. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/nuxt.yaml +0 -0
  191. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/php.yaml +0 -0
  192. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/python.yaml +0 -0
  193. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/react-router.yaml +0 -0
  194. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/rust.yaml +0 -0
  195. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/spring.yaml +0 -0
  196. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/swift.yaml +0 -0
  197. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/presets/typescript.yaml +0 -0
  198. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/process_runs.py +0 -0
  199. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/protocols/__init__.py +0 -0
  200. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/protocols/builtin.py +0 -0
  201. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/protocols/matchers.py +0 -0
  202. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/protocols/view.py +0 -0
  203. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/query.py +0 -0
  204. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/realtime.py +0 -0
  205. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/realtime_events.py +0 -0
  206. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/realtime_native.py +0 -0
  207. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/realtime_ws.py +0 -0
  208. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/routes.py +0 -0
  209. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/rpc.py +0 -0
  210. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/sdk_systems.py +0 -0
  211. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/sockets.py +0 -0
  212. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/ssrf_input.py +0 -0
  213. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/starters.py +0 -0
  214. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/surface.py +0 -0
  215. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/tests_index.py +0 -0
  216. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/udp_apps.py +0 -0
  217. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/update_check.py +0 -0
  218. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/__init__.py +0 -0
  219. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/graph.py +0 -0
  220. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/server.py +0 -0
  221. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/static/app.css +0 -0
  222. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/static/app.js +0 -0
  223. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/static/index.html +0 -0
  224. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/static/layered.js +0 -0
  225. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
  226. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
  227. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
  228. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
  229. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
  230. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/tools/package-lock.json +0 -0
  231. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/tools/package.json +0 -0
  232. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/viz/tools/shoot.mjs +0 -0
  233. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/watch.py +0 -0
  234. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/webhook_subs.py +0 -0
  235. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/webhooks.py +0 -0
  236. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph/xcode.py +0 -0
  237. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph.egg-info/dependency_links.txt +0 -0
  238. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph.egg-info/entry_points.txt +0 -0
  239. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph.egg-info/requires.txt +0 -0
  240. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/cg_code_graph.egg-info/top_level.txt +0 -0
  241. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/pyproject.toml +0 -0
  242. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/setup.cfg +0 -0
  243. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_affected.py +0 -0
  244. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_agents_install.py +0 -0
  245. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_agents_md.py +0 -0
  246. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_ai_tools.py +0 -0
  247. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_android_ipc.py +0 -0
  248. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_apple_ipc.py +0 -0
  249. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_astro.py +0 -0
  250. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_astro_content.py +0 -0
  251. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_astro_server.py +0 -0
  252. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_bridges.py +0 -0
  253. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_bridges_pigeon_monorepo.py +0 -0
  254. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_brokers.py +0 -0
  255. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_cache_clean.py +0 -0
  256. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_cache_invalidation.py +0 -0
  257. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_cache_migration.py +0 -0
  258. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_channels_tests.py +0 -0
  259. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_cli_output.py +0 -0
  260. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_cmake_sources.py +0 -0
  261. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_completeness.py +0 -0
  262. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_config_extras.py +0 -0
  263. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_coverage.py +0 -0
  264. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_coverage_ts_hint.py +0 -0
  265. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_dart_isolates.py +0 -0
  266. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_db_connections.py +0 -0
  267. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_dead_wrappers.py +0 -0
  268. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_dispatch_interfaces.py +0 -0
  269. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_dispatch_part3.py +0 -0
  270. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_django_flutter.py +0 -0
  271. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_docs_languages.py +0 -0
  272. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_docs_links.py +0 -0
  273. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_echo_ref.py +0 -0
  274. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_echo_wrapper.py +0 -0
  275. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_elysia.py +0 -0
  276. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_enum_constants.py +0 -0
  277. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_env.py +0 -0
  278. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_explore.py +0 -0
  279. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_external.py +0 -0
  280. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_fp_batch.py +0 -0
  281. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_gating.py +0 -0
  282. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_generated.py +0 -0
  283. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_graphql.py +0 -0
  284. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_hooks.py +0 -0
  285. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_impact_overrides.py +0 -0
  286. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_index_isolation.py +0 -0
  287. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_inherited_overrides.py +0 -0
  288. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_inline_guards.py +0 -0
  289. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_install_rules.py +0 -0
  290. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_192.py +0 -0
  291. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_201.py +0 -0
  292. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_202.py +0 -0
  293. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_203.py +0 -0
  294. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_204.py +0 -0
  295. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_205.py +0 -0
  296. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_206.py +0 -0
  297. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_207.py +0 -0
  298. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_208.py +0 -0
  299. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_209.py +0 -0
  300. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_210.py +0 -0
  301. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_211.py +0 -0
  302. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_211_used_at.py +0 -0
  303. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_212.py +0 -0
  304. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_212_langs.py +0 -0
  305. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_218.py +0 -0
  306. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_219.py +0 -0
  307. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_issue_222.py +0 -0
  308. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_java.py +0 -0
  309. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_java_exact.py +0 -0
  310. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_jobs.py +0 -0
  311. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_js_refs.py +0 -0
  312. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_js_runtime.py +0 -0
  313. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_kotlin.py +0 -0
  314. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_kotlin_binding.py +0 -0
  315. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_kotlin_fields.py +0 -0
  316. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_kotlin_mixed.py +0 -0
  317. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_kotlin_nav_consts.py +0 -0
  318. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_kotlin_props.py +0 -0
  319. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_laravel_determinism.py +0 -0
  320. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_laravel_receiver_narrowing.py +0 -0
  321. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_laravel_resources.py +0 -0
  322. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_laravel_route_paths.py +0 -0
  323. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_link_origin.py +0 -0
  324. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_listing_files.py +0 -0
  325. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_local_ipc.py +0 -0
  326. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_local_sockets.py +0 -0
  327. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_mass_assignment.py +0 -0
  328. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_mcp.py +0 -0
  329. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_mcp_index.py +0 -0
  330. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_mcp_install.py +0 -0
  331. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_mcp_instructions.py +0 -0
  332. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_mcp_multi_graph.py +0 -0
  333. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_native_cfamily.py +0 -0
  334. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_native_concurrency.py +0 -0
  335. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_native_rust.py +0 -0
  336. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_nuxt_i18n.py +0 -0
  337. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_nuxt_import_dirs.py +0 -0
  338. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_nuxt_nitro.py +0 -0
  339. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_nuxt_rootsrc.py +0 -0
  340. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_nuxt_side_dirs.py +0 -0
  341. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_packaging.py +0 -0
  342. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_parity.py +0 -0
  343. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_parity_fields.py +0 -0
  344. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_parity_members.py +0 -0
  345. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_parity_structure.py +0 -0
  346. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_php_http.py +0 -0
  347. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_php_props.py +0 -0
  348. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_plain_js.py +0 -0
  349. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_plans.py +0 -0
  350. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_platform_gaps.py +0 -0
  351. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_platform_type_variants.py +0 -0
  352. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_platforms.py +0 -0
  353. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_platforms_apple.py +0 -0
  354. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_presets_config.py +0 -0
  355. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_process_ipc.py +0 -0
  356. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_process_runs.py +0 -0
  357. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_protocols.py +0 -0
  358. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_app_tests_module.py +0 -0
  359. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_collection_chains.py +0 -0
  360. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_compat.py +0 -0
  361. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_entry_refs.py +0 -0
  362. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_fields.py +0 -0
  363. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_infer_cycles.py +0 -0
  364. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_roots.py +0 -0
  365. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_subprocess_tests.py +0 -0
  366. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_tests.py +0 -0
  367. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_web_hosts.py +0 -0
  368. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_web_routes.py +0 -0
  369. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_python_web_routes_more.py +0 -0
  370. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_react_router.py +0 -0
  371. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_readers_writers_specs.py +0 -0
  372. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_realtime.py +0 -0
  373. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_realtime_native.py +0 -0
  374. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_redact_salt.py +0 -0
  375. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_request_keys.py +0 -0
  376. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_route_specs.py +0 -0
  377. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_route_tables.py +0 -0
  378. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_routes_search_explain.py +0 -0
  379. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_rpc.py +0 -0
  380. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_scip_health.py +0 -0
  381. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_sdk_external.py +0 -0
  382. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_sdk_external_infra.py +0 -0
  383. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_sdk_external_mail.py +0 -0
  384. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_snippet.py +0 -0
  385. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_sockets.py +0 -0
  386. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_spring.py +0 -0
  387. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_ssrf.py +0 -0
  388. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_starters_budget.py +0 -0
  389. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_surface.py +0 -0
  390. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_surface_transport.py +0 -0
  391. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift.py +0 -0
  392. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_binding.py +0 -0
  393. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_exact.py +0 -0
  394. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_facts.py +0 -0
  395. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_fields.py +0 -0
  396. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_modules.py +0 -0
  397. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_more.py +0 -0
  398. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_nav_values.py +0 -0
  399. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_parse_errors.py +0 -0
  400. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_platform_files.py +0 -0
  401. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_props.py +0 -0
  402. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_sdk.py +0 -0
  403. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_testing.py +0 -0
  404. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_swift_values.py +0 -0
  405. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_tauri_events.py +0 -0
  406. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_tests_scope.py +0 -0
  407. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_ts_fields.py +0 -0
  408. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_ts_file_specs.py +0 -0
  409. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_ts_frameworks.py +0 -0
  410. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_ts_node_http.py +0 -0
  411. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_ts_nuxt.py +0 -0
  412. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_ts_src_tsconfig.py +0 -0
  413. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_unguarded.py +0 -0
  414. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_update_check.py +0 -0
  415. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_values.py +0 -0
  416. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_viz.py +0 -0
  417. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_vue_nav.py +0 -0
  418. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_watch.py +0 -0
  419. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_webhooks.py +0 -0
  420. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_webhooks_152.py +0 -0
  421. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_webhooks_152b.py +0 -0
  422. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/tests/test_websockets.py +0 -0
  423. {cg_code_graph-0.23.10 → cg_code_graph-0.23.12}/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.10
3
+ Version: 0.23.12
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.10"
2
+ __version__ = "0.23.12"
@@ -317,7 +317,8 @@ def main(argv=None):
317
317
  p.add_argument("--json", action="store_true"); p.add_argument("--tests", action="store_true", help="include test code")
318
318
  p = sub.add_parser("roundtrip", help="heuristic: writes of a stored property `Type.prop` through a lossy transform, "
319
319
  "read back to seed UI state (#88)")
320
- p.add_argument("spec"); p.add_argument("--db", required=True); p.add_argument("--json", action="store_true")
320
+ p.add_argument("spec", nargs="?"); p.add_argument("--db", required=True); p.add_argument("--json", action="store_true")
321
+ p.add_argument("--all", action="store_true", help="every stored property in one pass: only the round trips")
321
322
  p.add_argument("--tests", action="store_true", help="include test code's reads and writes")
322
323
  p = sub.add_parser("viz-plan", help="self-contained HTML overlay of a plan on the real graph")
323
324
  p.add_argument("name"); p.add_argument("--db", required=True); p.add_argument("-o", "--out", required=True); p.add_argument("--plans-dir")
@@ -769,8 +770,14 @@ def main(argv=None):
769
770
  print(json.dumps(res, indent=1) if a.json else LA.render(res))
770
771
  elif a.cmd == "roundtrip":
771
772
  from . import roundtrip as RT
772
- res = RT.roundtrip(st, a.spec, include_tests=a.tests)
773
- print(RT.to_json(res) if a.json else RT.render(res))
773
+ if a.all or not a.spec:
774
+ if not a.all:
775
+ sys.exit("cg roundtrip: give a property `Type.prop`, or --all")
776
+ res = RT.roundtrip_all(st, include_tests=a.tests)
777
+ print(RT.to_json(res) if a.json else RT.render_all(res))
778
+ else:
779
+ res = RT.roundtrip(st, a.spec, include_tests=a.tests)
780
+ print(RT.to_json(res) if a.json else RT.render(res))
774
781
  elif a.cmd in ("writers", "readers"):
775
782
  groups = Q.access(st, a.spec, a.cmd, a.connection)
776
783
  rows = [r for g in groups for r in g["rows"]]
@@ -71,6 +71,7 @@ EDGE_KINDS: dict[str, tuple[bool, str]] = {
71
71
  "ACCESSES_FIELD": (True, "code reads/writes a struct/class field or enum variant"),
72
72
  "READS_PROP": (True, "code reads a stored property (field node: Swift `var x`, `@State`, `@Published`)"),
73
73
  "WRITES_PROP": (True, "code writes a stored property (assignment, compound assignment)"),
74
+ "SHARES_STORAGE": (False, "two stored properties persist under the same @AppStorage / @SceneStorage key"),
74
75
  "USES_VALUE": (True, "code refers to an enum case, a constant, a static/global variable or an object-like macro"),
75
76
  "REGISTERS_CALLBACK": (False, "function builds a callback URL for one of the app's own routes and registers it with an external party (attrs.body_key, endpoint)"),
76
77
  "REFERENCES_FN": (True, "code/data takes a function as a value (callback, dispatch table, handler registration)"),
@@ -88,7 +88,10 @@ class GraphBuilder:
88
88
  g = self.current_gate
89
89
  if g and g.get("src") != src:
90
90
  g = None # only references made by the gated function itself carry the gate
91
- key = (src, dst, kind, file, line, g["gate"] if g else None)
91
+ gate = g["gate"] if g else None
92
+ # a second branch of the same call on one line is its own edge (#235)
93
+ br = attrs.get("branch")
94
+ key = (src, dst, kind, file, line, gate, br) if br else (src, dst, kind, file, line, gate)
92
95
  if key in self.edges:
93
96
  return
94
97
  if g:
@@ -61,6 +61,24 @@ def _input_dependent(text: str) -> bool:
61
61
  t = re.sub(r"(?<![\w$])[A-Za-z_$][\w$]*\s*(?:<[^<>]*>)?\s*\(", " (", t) # call names
62
62
  ids = re.findall(r"(?<![\w$])[A-Za-z_$][\w$]*", t)
63
63
  return any(i.startswith("SELFREF_") or (i not in KEYWORDS and not i[0].isupper()) for i in ids)
64
+ _SUSP: dict = {} # file -> lines with a call of a Kotlin `suspend` function (an await point with no marker)
65
+
66
+
67
+ def _load_suspend(st: GraphStore) -> None:
68
+ """A plain call of a project `suspend` function inside `launch { }` (`val x = repo.load()`) suspends like
69
+ `.await()`: the indexed CALLS edges to nodes marked `suspend` give those lines."""
70
+ _SUSP.clear()
71
+ for r in st.q("""SELECT e.file, e.line FROM edges e JOIN nodes n ON n.id = e.dst
72
+ WHERE e.kind = 'CALLS' AND n.attrs LIKE '%"suspend": true%' AND e.file IS NOT NULL"""):
73
+ _SUSP.setdefault(r["file"], set()).add(r["line"])
74
+
75
+
76
+ def _aw(t: str, file: str | None = None, line: int | None = None) -> bool:
77
+ """Is there an await point in this line of source: a marker (`await`, `.await()`, `withContext`, `delay`) or,
78
+ in Kotlin, a call of a `suspend` function?"""
79
+ return bool(AWAIT_RE.search(t)) or (line is not None and line in _SUSP.get(file, ()))
80
+
81
+
64
82
  TEST_PATH_RE = re.compile(r"(?:^|/)(?:tests?|__tests__|spec|testing|fixtures?|factories|Tests|UITests)/|"
65
83
  r"[._-](?:test|spec)s?\.\w+:|Tests?\.swift:|Test\.kt:|(?:^|/)test_\w+\.py:")
66
84
 
@@ -104,6 +122,7 @@ def _opener(ls: list[str], line: int, lo: int):
104
122
 
105
123
 
106
124
  def stale_async(st: GraphStore, include_tests: bool = False, limit: int = 500) -> list[dict]:
125
+ _load_suspend(st)
107
126
  root = st.meta().get("root")
108
127
  cache: dict = {}
109
128
  fields = {r["id"]: json.loads(r["attrs"] or "{}") for r in st.q("SELECT id, attrs FROM nodes WHERE kind IN ('field','property')")}
@@ -122,7 +141,8 @@ def stale_async(st: GraphStore, include_tests: bool = False, limit: int = 500) -
122
141
  continue
123
142
  kind, o = op
124
143
  body = ls[o - 1:r["line"] - 1]
125
- aw = next((o + i for i, t in enumerate(body) if AWAIT_RE.search(t if i else t[t.find("{") + 1:] if "{" in t else t)), None)
144
+ aw = next((o + i for i, t in enumerate(body) if _aw(t if i else t[t.find("{") + 1:] if "{" in t else t,
145
+ r["file"], o + i if i else None)), None)
126
146
  if aw is None:
127
147
  continue
128
148
  before = "\n".join(ls[o - 1:aw - 1]) + "\n" + ls[aw - 1].split("await")[0]
@@ -131,7 +151,10 @@ def stale_async(st: GraphStore, include_tests: bool = False, limit: int = 500) -
131
151
  if GUARD_RE.search(after) or SINGLE_FLIGHT_RE.search(ls[o - 1]):
132
152
  continue
133
153
  aw_line = ls[aw - 1]
134
- k = max(aw_line.find("await"), 0)
154
+ k = aw_line.find("await")
155
+ if k < 0: # a Kotlin suspend call: the request is the right-hand side
156
+ m = re.search(r"(?<![=!<>])=(?!=)", aw_line)
157
+ k = m.end() if m else 0
135
158
  stmt, depth = [], 0
136
159
  for i in range(aw - 1, min(len(ls), aw + 5)):
137
160
  x = ls[i][k:] if i == aw - 1 else ls[i]
@@ -144,10 +167,10 @@ def stale_async(st: GraphStore, include_tests: bool = False, limit: int = 500) -
144
167
  # the written value must come from the awaited result: a name bound on the await line (or derived from one
145
168
  # after it), or the await itself on the write line; a loading flag reset after the await is not a stale result
146
169
  res_vars = set()
147
- for t in ls[aw - 1:r["line"] - 1]:
170
+ for j, t in enumerate(ls[aw - 1:r["line"] - 1]):
148
171
  m = DECL_RE.search(t) or re.search(r"^\s*(?:self\.)?([A-Za-z_$][\w$]*)\s*=(?!=)", t)
149
172
  nm = m and (m.group(1) or (m.group(2) if m.lastindex and m.lastindex >= 2 else None))
150
- if nm and (AWAIT_RE.search(t) or any(re.search(rf"(?<![\w$.]){re.escape(v)}\b", t.split("=", 1)[-1]) for v in res_vars)):
173
+ if nm and (_aw(t, r["file"], aw + j) or any(re.search(rf"(?<![\w$.]){re.escape(v)}\b", t.split("=", 1)[-1]) for v in res_vars)):
151
174
  res_vars.add(nm)
152
175
  wl = ls[r["line"] - 1]
153
176
  if r["line"] - 1 == aw - 1:
@@ -182,7 +205,8 @@ LIFECYCLE_RE = re.compile(r"\.onAppear\b|\bonAppear\s*\(|\.task\s*[({]|\bonMount
182
205
  CALLBACK_RE = re.compile(r"\.sink\s*\{|\.onReceive\s*\(|\.subscribe\s*[({]|\.collect(?:Latest)?\s*\{|\.observe\w*\s*\(|"
183
206
  r"\bcompletion(?:Handler)?\s*:\s*\{|\{\s*\[?\s*(?:weak|unowned)\s+self\s*\]?|\.then\s*\(|\.on\s*\(\s*['\"]")
184
207
  LITERAL_RHS_RE = re.compile(r"(?<![=!<>])=\s*(?:\[\s*\]|\[:\]|\{\s*\}|nil|null|None|undefined|0(?:\.0+)?[fFdDL]?|false|False|true|True|"
185
- r"''|\"\"|emptyList\(\)|emptyMap\(\)|mutableListOf\(\)|\.init\(\)|\w+\(\)|\.\w+)\s*;?\s*$")
208
+ r"''|\"\"|emptyList\(\)|emptyMap\(\)|mutableListOf\(\)|\.init\(\)|\w+\(\)|\.\w+|"
209
+ r"[A-Z]\w*(?:\.[A-Z]\w*)+(?:\(\))?)\s*;?\s*$") # a sentinel: `AsyncData.Loading()`, `UiState.Idle`
186
210
  LITERAL_ARG_RE = re.compile(r"\(\s*(?:nil|null|None|undefined|true|false|True|False|-?\d+(?:\.\d+)?|'[^']*'|\"[^\"]*\"|\[\s*\]|\{\s*\})\s*\)\s*;?\s*$")
187
211
  INIT_NAMES = {"init", "__init__", "constructor", "<init>", "viewDidLoad", "onCreate", "initState", "mounted", "created", "setup"}
188
212
 
@@ -198,7 +222,7 @@ def _lifecycle(st, ls, r, node) -> str | None:
198
222
  """Is this write lifecycle code: an initializer with a real (non-default) value, or code directly inside
199
223
  onAppear / .task (before any await) / onMounted / LaunchedEffect / useEffect / viewDidLoad?"""
200
224
  t = ls[r["line"] - 1]
201
- if AWAIT_RE.search(t):
225
+ if _aw(t, r["file"], r["line"]):
202
226
  return None
203
227
  nm = ((node["name"] if node is not None else "") or "").split(".")[-1]
204
228
  if nm in INIT_NAMES or (node is not None and node["kind"] == "class"):
@@ -212,7 +236,7 @@ def _lifecycle(st, ls, r, node) -> str | None:
212
236
  lo = max(1, r["line"] - 6)
213
237
  for i in range(r["line"], lo - 1, -1):
214
238
  x = ls[i - 1]
215
- if i < r["line"] and AWAIT_RE.search(x):
239
+ if i < r["line"] and _aw(x, r["file"], i):
216
240
  return None
217
241
  m = LIFECYCLE_RE.search(x)
218
242
  if m:
@@ -225,7 +249,8 @@ def _async_callback(ls, r, lo) -> str | None:
225
249
  op = _opener(ls, r["line"], lo)
226
250
  if op is not None:
227
251
  body = ls[op[1] - 1:r["line"] - 1]
228
- if any(AWAIT_RE.search(x) for x in body[1:]) or AWAIT_RE.search(body[0][body[0].find("{") + 1:] if body else ""):
252
+ if any(_aw(x, r["file"], op[1] + j) for j, x in enumerate(body) if j) or \
253
+ (body and AWAIT_RE.search(body[0][body[0].find("{") + 1:])):
229
254
  return f"after await in {op[0]}"
230
255
  for i in range(r["line"] - 1, max(lo, r["line"] - 8) - 1, -1):
231
256
  m = CALLBACK_RE.search(ls[i - 1]) if i >= 1 else None
@@ -235,6 +260,7 @@ def _async_callback(ls, r, lo) -> str | None:
235
260
 
236
261
 
237
262
  def two_writers(st: GraphStore, include_tests: bool = False) -> list[dict]:
263
+ _load_suspend(st)
238
264
  root = st.meta().get("root")
239
265
  cache: dict = {}
240
266
  rows = st.q("""SELECT e.src, e.dst, e.file, e.line, e.attrs, n.line AS fl FROM edges e JOIN nodes n ON n.id = e.src
@@ -361,6 +387,14 @@ def incomplete_cache_key(st: GraphStore, include_tests: bool = False) -> list[di
361
387
  sig = "\n".join(body[:3])
362
388
  sig = sig[sig.find("("):] if "(" in sig else ""
363
389
  params = _idents(_split_args(sig[1:]) and ",".join(re.sub(r"[:=].*", "", a, flags=re.S) for a in _split_args(sig[1:])) or "")
390
+ # instance fields used without `self.` / `this.` (Swift, Kotlin): the READS_PROP edges bind them
391
+ own = {e["dst"].rsplit(".", 1)[-1] for e in st.q("SELECT dst, attrs FROM edges WHERE kind = 'READS_PROP' AND src = ?",
392
+ (fn["id"],))
393
+ if json.loads(e["attrs"] or "{}").get("receiver") in (None, "self", "this")}
394
+ text = "\n".join(body)
395
+ # ... unless the field is an object the function calls (`client.get(…)`, `mediaLoader.load(…)`): a dependency,
396
+ # not an input of the cached value
397
+ own = {f for f in own if not re.search(rf"(?<![\w$.]){re.escape(f)}\s*[?!]?\.\s*\w+\s*[({{]", text)}
364
398
  assigns: dict = {}
365
399
  for off, t in enumerate(body):
366
400
  m = re.search(r"\b(?:let|var|val|const)\s+([A-Za-z_$][\w$]*)\s*(?::[^=]+)?=(?!=)(.*)|^\s*([a-z_$][\w$]*)\s*=(?!=)(.*)", t)
@@ -384,8 +418,10 @@ def incomplete_cache_key(st: GraphStore, include_tests: bool = False) -> list[di
384
418
  vb = val.strip().rstrip(";")
385
419
  if re.fullmatch(r"[A-Za-z_$][\w$]*", vb) and vb not in assigns:
386
420
  continue # `put(key, value)` passes a value through; nothing is computed here
387
- kids = _expand(_idents(key), assigns)
388
- vids = _expand(_idents(val), assigns) - {vb}
421
+ bare = lambda ids: {f"self_{i}" if i in own and i not in params and i not in assigns else i # noqa: E731
422
+ for i in ids}
423
+ kids = bare(_expand(_idents(key), assigns))
424
+ vids = bare(_expand(_idents(val), assigns)) - {vb}
389
425
  setter = re.match(r"(?:set|put|insert|store|save|cache|add|update|write|remember|record)(?![a-z])",
390
426
  (fn["fqn"] or "").split(".")[-1].split("(")[0])
391
427
  inputs = {i for i in vids if (i in params and not setter and not PAYLOAD_RE.fullmatch(i.lstrip("$")))
@@ -421,6 +457,7 @@ def echo_suppression(st: GraphStore, include_tests: bool = False, patterns: list
421
457
  programmatic writes of some state so the change observer, which checks the guard and returns early, does not
422
458
  echo them back. Reports state of that pattern that is also written from an async path / callback *without*
423
459
  setting the guard: that write reaches the observer and is sent back (a loop or a clobbered edit)."""
460
+ _load_suspend(st)
424
461
  root = st.meta().get("root")
425
462
  cache: dict = {}
426
463
  guards = [r["id"] for r in st.q("SELECT id, name FROM nodes WHERE kind = 'field'") if GUARD_FIELD_RE.fullmatch((r["name"] or "").rsplit(".", 1)[-1].replace("_", ""))]
@@ -877,13 +877,16 @@ def _access_text(st, spec: str, what: str, limit: int, connection: str | None =
877
877
 
878
878
 
879
879
  @tool
880
- def roundtrip(prop: str, include_tests: bool = False) -> str:
880
+ def roundtrip(prop: str = "", include_tests: bool = False) -> str:
881
881
  """Heuristic (#88): does a stored property `Type.prop` round-trip through a lossy transform? Each write site with
882
882
  the lossy call it passes through (clamp, min/max, round, truncating casts, `fit*`, `.cg.yaml` `lossy:` names,
883
883
  `@cg-lossy` functions; within the function plus one hop through direct callers), each read site that seeds UI
884
884
  state (init, onAppear, remember, useState(initial), mounted), and un-narrowed ranges drawn next to such a read.
885
- Findings are heuristic evidence with file:line, not proof."""
885
+ Findings are heuristic evidence with file:line, not proof. An empty `prop` (or `*`) checks every stored property
886
+ in one pass and lists only the round trips."""
886
887
  from . import roundtrip as RT
888
+ if prop.strip() in ("", "*"):
889
+ return RT.render_all(RT.roundtrip_all(_st(), include_tests=include_tests))
887
890
  return RT.render(RT.roundtrip(_st(), prop, include_tests=include_tests))
888
891
 
889
892
 
@@ -57,6 +57,14 @@ _ANON_SEG = re.compile(r"^\$?anon\d*$")
57
57
  _ACCESSOR = re.compile(r"^(get|set|is)([A-Z]\w*)$")
58
58
 
59
59
 
60
+ def _accessor_kind(symbol: str) -> str | None:
61
+ dd = scipread.descriptors(symbol)
62
+ if not dd or not dd[1]:
63
+ return None
64
+ m = _ACCESSOR.fullmatch(dd[1][-1][0])
65
+ return m.group(1) if m else None
66
+
67
+
60
68
  def is_anon_id(nid: str) -> bool:
61
69
  """True when a mapped id still contains a scip-java anonymous type segment (`$anon`)."""
62
70
  return any(_ANON_SEG.match(part) for part in nid.split(":", 1)[-1].split("."))
@@ -105,35 +113,25 @@ def bind_java_symbol(symbol: str, nodes, file: str, line: int) -> tuple[str, str
105
113
  return nid, kind
106
114
 
107
115
 
108
- def kotlin_accessor_target(symbol: str, nodes) -> tuple[str, str] | None:
109
- """`(kotlin node id, edge kind)` for a JVM accessor call (`getX` / `setX` / `isX`).
110
-
111
- `Widget#getName().` is `field:demo.Widget.name` with `READS_PROP`. `setX` is `WRITES_PROP`.
112
- A custom accessor that is already a Kotlin method node is `CALLS`.
113
- """
114
- dd = scipread.descriptors(symbol)
115
- if not dd or not dd[1]:
116
- return None
117
- names = [n for n in dd[1] if n[1] != ")"]
118
- if not names or names[-1][1] != "(":
119
- return None
120
- m = _ACCESSOR.fullmatch(names[-1][0])
121
- if not m:
122
- return None
123
- kind, raw = m.group(1), m.group(2)
116
+ def _property_names(kind: str, raw: str) -> list[str]:
124
117
  prop = raw[:1].lower() + raw[1:]
125
- owner = ".".join([n for n, s in names if s == "/"] + [n for n, s in names[:-1] if s == "#"])
126
- if not owner:
127
- return None
128
- props = [prop]
118
+ names = [prop]
129
119
  if kind == "is":
130
- props.append("is" + raw)
131
- edge = "WRITES_PROP" if kind == "set" else "READS_PROP"
120
+ names.append("is" + raw)
121
+ return names
122
+
123
+
124
+ def _owner_of(names: list[tuple[str, str]]) -> str:
125
+ return ".".join([n for n, s in names if s == "/"] + [n for n, s in names if s == "#"])
126
+
127
+
128
+ def _find_kotlin_property(nodes, owner: str, props: list[str]) -> tuple[str, str] | None:
129
+ """`(node id, READS_PROP | CALLS)` for a stored field or a custom property node."""
132
130
  for p in props:
133
131
  fid = f"field:{owner}.{p}"
134
132
  node = nodes.get(fid)
135
133
  if node is not None and node.lang == "kotlin" and node.kind == "field":
136
- return fid, edge
134
+ return fid, "READS_PROP"
137
135
  for p in props:
138
136
  for n in nodes.values():
139
137
  if (n.lang == "kotlin" and n.attrs.get("property") and (n.fqn or "").rsplit(".", 1)[0] == owner
@@ -142,6 +140,57 @@ def kotlin_accessor_target(symbol: str, nodes) -> tuple[str, str] | None:
142
140
  return None
143
141
 
144
142
 
143
+ def kotlin_property_ref(symbol: str, nodes, spelling: str | None = None) -> tuple[str, str] | None:
144
+ """`(node id, edge kind)` for a property term (`Cart#label.`) or accessor (`getLabel().` / `setItems().` / `isReady().`).
145
+
146
+ A stored property is `READS_PROP` (`WRITES_PROP` for `setX`). A custom accessor node is `CALLS`.
147
+ `spelling` is the identifier at the occurrence: when it is the property (`label`, `items`) the
148
+ reference is a property use. When it is the accessor name itself (`getShapes`) this returns None,
149
+ so a declared `fun getShapes()` stays a call. Java passes no spelling and matches `getLabel`.
150
+ """
151
+ dd = scipread.descriptors(symbol)
152
+ if not dd or not dd[1]:
153
+ return None
154
+ names = [n for n in dd[1] if n[1] != ")"]
155
+ if not names:
156
+ return None
157
+ last, suf = names[-1]
158
+ if suf == ".":
159
+ props, write = [last], False
160
+ elif suf == "(":
161
+ m = _ACCESSOR.fullmatch(last)
162
+ if not m:
163
+ return None
164
+ kind, raw = m.group(1), m.group(2)
165
+ props, write = _property_names(kind, raw), kind == "set"
166
+ else:
167
+ return None
168
+ if spelling is not None and spelling not in props:
169
+ return None
170
+ owner = _owner_of(names[:-1])
171
+ if not owner:
172
+ return None
173
+ found = _find_kotlin_property(nodes, owner, props)
174
+ if found is None:
175
+ return None
176
+ nid, edge = found
177
+ if edge == "READS_PROP" and write:
178
+ return nid, "WRITES_PROP"
179
+ return nid, edge
180
+
181
+
182
+ def kotlin_accessor_target(symbol: str, nodes) -> tuple[str, str] | None:
183
+ """`(kotlin node id, edge kind)` for a JVM accessor call (`getX` / `setX` / `isX`).
184
+
185
+ `Widget#getName().` is `field:demo.Widget.name` with `READS_PROP`. `setX` is `WRITES_PROP`.
186
+ A custom accessor that is already a Kotlin method node is `CALLS`.
187
+ """
188
+ dd = scipread.descriptors(symbol)
189
+ if not dd or not dd[1] or dd[1][-1][1] != "(":
190
+ return None
191
+ return kotlin_property_ref(symbol, nodes)
192
+
193
+
145
194
  class ExactLayer:
146
195
  def __init__(self, plugin):
147
196
  self.p = plugin
@@ -222,7 +271,16 @@ class ExactLayer:
222
271
  st["scip_refs_external"] = st.get("scip_refs_external", 0) + 1
223
272
  continue
224
273
  if dst is None:
225
- if kotlin_accessor_target(o.symbol, self.b.nodes):
274
+ acc = kotlin_accessor_target(o.symbol, self.b.nodes)
275
+ if acc is not None:
276
+ src = self._owner(owners, rel, o.line + 1)
277
+ if src is not None and src != acc[0]:
278
+ extra = {"binding": "kotlin-accessor"}
279
+ if acc[1] == "CALLS":
280
+ extra["property"] = "write" if _accessor_kind(o.symbol) == "set" else "read"
281
+ self.b.add_edge(src, acc[0], acc[1], rel, o.line + 1, EXACT, source="scip", **extra)
282
+ if acc[1] == "CALLS":
283
+ exact.add((src, acc[0], "CALLS"))
226
284
  continue
227
285
  st["scip_refs_external"] = st.get("scip_refs_external", 0) + 1
228
286
  continue
@@ -38,6 +38,7 @@ from pathlib import Path
38
38
 
39
39
  from ...core.model import EXACT, HEURISTIC
40
40
  from ...core.env import get as cg_env
41
+ from ..java.exact import _accessor_kind, kotlin_property_ref
41
42
  from ..native import runner, scipread
42
43
 
43
44
  BUILD_FILES = ("build.gradle.kts", "build.gradle", "settings.gradle.kts", "settings.gradle", "pom.xml")
@@ -443,10 +444,13 @@ class ExactLayer:
443
444
  owners.update(jowners)
444
445
  for rel, doc in list(kdocs.items()) + list(jdocs.items()):
445
446
  java = rel in jdocs
446
- # a property access `x.pets` is reported as the term `C#pets.` plus the synthetic accessor `C#getPets().`,
447
- # which collides with a declared `fun getPets()`: accessors at a property reference are not calls
447
+ # a property access `x.pets` is the term `C#pets.` plus synthetic `getPets().` / `setPets().` at the
448
+ # property's spelling. That accessor symbol collides with a declared `fun getPets()`. Map the spelling
449
+ # to the property node; a call that spells `getPets` stays a call (#105).
448
450
  prop_at = {(o.line, o.col) for o in doc.occs if not (o.roles & scipread.DEFINITION)
449
451
  and o.symbol.endswith(".") and not o.symbol.endswith(").")}
452
+ handled = set() if java else self._map_kotlin_properties(rel, doc, owners, st)
453
+ prop_at |= handled
450
454
  for o in doc.occs:
451
455
  if o.roles & scipread.DEFINITION:
452
456
  continue
@@ -473,7 +477,10 @@ class ExactLayer:
473
477
  if acc is not None:
474
478
  src = self._owner(owners, rel, o.line + 1)
475
479
  if src is not None and src != acc[0]:
476
- self._upgrade(src, acc[0], acc[1], rel, o.line + 1)
480
+ extra = {"binding": "kotlin-accessor"}
481
+ if acc[1] == "CALLS":
482
+ extra["property"] = "write" if _accessor_kind(o.symbol) == "set" else "read"
483
+ self._mark_exact(src, acc[0], acc[1], rel, o.line + 1, **extra)
477
484
  st["java"]["references"] += 1
478
485
  continue
479
486
  kind = "CALLS"
@@ -508,6 +515,7 @@ class ExactLayer:
508
515
  "recall": round(agree / len(exact), 3) if exact else None,
509
516
  # candidate edges (receiver type unknown, one per same-name method, #83) are compared on their own
510
517
  "candidate_edges": len(self.candidates), "candidate_agree": len(self.candidates & exact)}
518
+ self._drop_heuristic_properties(covered)
511
519
  rep = getattr(self.p, "file_report", None) or {}
512
520
  seen = set(getattr(self.p, "_seen_files", None) or rep.get("seen") or covered)
513
521
  st["scip_files"] = len({f for f in covered & seen if f.endswith(".kt")})
@@ -517,15 +525,108 @@ class ExactLayer:
517
525
  from ..java.exact import kotlin_accessor_target
518
526
  return kotlin_accessor_target(symbol, self.b.nodes)
519
527
 
520
- def _upgrade(self, src: str, dst: str, kind: str, file: str, line: int) -> None:
521
- """Replace a heuristic property edge in a covered file with the exact accessor edge."""
528
+ def _mark_exact(self, src: str, dst: str, kind: str, file: str, line: int, **attrs) -> None:
529
+ """Upgrade a syntax-layer property edge, or add the exact one."""
522
530
  key = (src, dst, kind, file, line, None)
523
531
  e = self.b.edges.get(key)
524
532
  if e is not None:
525
533
  e.confidence = EXACT
526
534
  e.attrs["source"] = "scip"
535
+ e.attrs.update(attrs)
527
536
  return
528
- self.b.add_edge(src, dst, kind, file, line, EXACT, source="scip", binding="kotlin-accessor")
537
+ self.b.add_edge(src, dst, kind, file, line, EXACT, source="scip", **attrs)
538
+
539
+ def _map_kotlin_properties(self, rel: str, doc, owners: dict, st: dict) -> set:
540
+ """Property term and synthetic accessor occurrences at one spelling become exact read / write edges."""
541
+ buckets = defaultdict(list)
542
+ for o in doc.occs:
543
+ if o.roles & scipread.DEFINITION:
544
+ continue
545
+ buckets[(o.line, o.col)].append(o)
546
+ handled = set()
547
+ for (line, col), occs in buckets.items():
548
+ spell = self._spelling(rel, line, col)
549
+ if not spell:
550
+ continue
551
+ ref = None
552
+ for o in occs:
553
+ ref = kotlin_property_ref(o.symbol, self.b.nodes, spelling=spell)
554
+ if ref is not None:
555
+ break
556
+ if ref is None:
557
+ continue
558
+ src = self._owner(owners, rel, line + 1)
559
+ handled.add((line, col))
560
+ if src is None or src == ref[0]:
561
+ continue
562
+ self._emit_kotlin_property(src, ref[0], rel, line, col, spell)
563
+ st["scip_property_edges"] = st.get("scip_property_edges", 0) + 1
564
+ return handled
565
+
566
+ def _emit_kotlin_property(self, src: str, dst: str, rel: str, line: int, col: int, spell: str) -> None:
567
+ node = self.b.nodes.get(dst)
568
+ if node is None:
569
+ return
570
+ mode = self._mode_at(rel, line, col, spell)
571
+ if node.kind == "field":
572
+ kinds = {"read": ("READS_PROP",), "write": ("WRITES_PROP",),
573
+ "read_write": ("READS_PROP", "WRITES_PROP")}[mode]
574
+ for kind in kinds:
575
+ self._mark_exact(src, dst, kind, rel, line + 1)
576
+ return
577
+ acc = set(node.attrs.get("accessors") or [])
578
+ if mode == "write" and not ({"set", "delegate"} & acc):
579
+ mode = "read"
580
+ elif mode == "read_write" and not ({"set", "delegate"} & acc):
581
+ mode = "read"
582
+ self._mark_exact(src, dst, "CALLS", rel, line + 1, property=mode)
583
+
584
+ def _spelling(self, rel: str, line: int, col: int) -> str | None:
585
+ kf = getattr(self.p, "_kf_by_rel", {}).get(rel)
586
+ if kf is None or line < 0:
587
+ return None
588
+ lines = kf.src.splitlines()
589
+ if line >= len(lines):
590
+ return None
591
+ raw = lines[line]
592
+ if isinstance(raw, str):
593
+ raw = raw.encode()
594
+ if col < 0 or col >= len(raw):
595
+ return None
596
+ m = re.match(rb"[A-Za-z_][A-Za-z0-9_]*", raw[col:])
597
+ return m.group(0).decode() if m else None
598
+
599
+ def _mode_at(self, rel: str, line: int, col: int, spell: str) -> str:
600
+ """`read`, `write` (`name =`), or `read_write` (`+=`, `++`, `--`). scip-java emits get and set together."""
601
+ kf = getattr(self.p, "_kf_by_rel", {}).get(rel)
602
+ if kf is None or line < 0:
603
+ return "read"
604
+ lines = kf.src.splitlines()
605
+ if line >= len(lines):
606
+ return "read"
607
+ raw = lines[line]
608
+ if isinstance(raw, str):
609
+ raw = raw.encode()
610
+ if col < 0 or col + len(spell) > len(raw):
611
+ return "read"
612
+ after = raw[col + len(spell):]
613
+ before = raw[:col]
614
+ if re.match(br"\s*(\+\+|--)", after) or re.search(br"(\+\+|--)\s*$", before):
615
+ return "read_write"
616
+ if re.match(br"\s*[-+*/%]=", after):
617
+ return "read_write"
618
+ if re.match(br"\s*=(?!=)", after):
619
+ return "write"
620
+ return "read"
621
+
622
+ def _drop_heuristic_properties(self, covered: set) -> None:
623
+ """Covered Kotlin files keep the exact property edges, not the heuristic accessor calls."""
624
+ for key, e in list(self.b.edges.items()):
625
+ if e.confidence != HEURISTIC or e.file not in covered or not e.attrs.get("property"):
626
+ continue
627
+ n = self.b.nodes.get(e.src)
628
+ if n is not None and n.lang == "kotlin":
629
+ del self.b.edges[key]
529
630
 
530
631
  def _jvm_name_facade(self, symbol: str, sym: dict) -> str | None:
531
632
  """`pkg/JvmName#fn().` → the top-level `pkg/fn().` when `JvmName` is a Kotlin file's JVM facade."""
@@ -626,7 +727,7 @@ class ExactLayer:
626
727
  if e.confidence != HEURISTIC or e.file not in covered:
627
728
  continue
628
729
  if e.attrs.get("property"):
629
- continue # property reads / writes (#89): scip-java reports them as accessors, not mapped yet
730
+ continue # compared on their own; exact property edges replace them after mapping (#105)
630
731
  if e.kind == "REFERENCES_FN" and e.attrs.get("how") == "callback":
631
732
  n = self.b.nodes.get(e.src)
632
733
  if n is not None and n.lang == "kotlin":