cg-code-graph 0.23.7__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.7/cg_code_graph.egg-info → cg_code_graph-0.23.8}/PKG-INFO +1 -1
  2. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/__init__.py +1 -1
  3. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/cli.py +6 -3
  4. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/parity.py +77 -9
  5. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/parity_structure.py +119 -0
  6. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8/cg_code_graph.egg-info}/PKG-INFO +1 -1
  7. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/SOURCES.txt +1 -0
  8. cg_code_graph-0.23.8/tests/test_parity_fields.py +125 -0
  9. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/LICENSE +0 -0
  10. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/MANIFEST.in +0 -0
  11. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/README.md +0 -0
  12. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/__main__.py +0 -0
  13. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/affected.py +0 -0
  14. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/agent_rules.py +0 -0
  15. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/agents.py +0 -0
  16. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/aitools.py +0 -0
  17. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/android_ipc.py +0 -0
  18. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/apple_ipc.py +0 -0
  19. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/apps.py +0 -0
  20. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/blindspots.py +0 -0
  21. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/bridges.py +0 -0
  22. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/brokers.py +0 -0
  23. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/cmake_sources.py +0 -0
  24. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/concepts.py +0 -0
  25. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/config.py +0 -0
  26. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/__init__.py +0 -0
  27. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/cache.py +0 -0
  28. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/detect.py +0 -0
  29. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/env.py +0 -0
  30. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/extractors.py +0 -0
  31. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/fsutil.py +0 -0
  32. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/generated.py +0 -0
  33. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/model.py +0 -0
  34. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/paths.py +0 -0
  35. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/plugin.py +0 -0
  36. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/redact.py +0 -0
  37. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/store.py +0 -0
  38. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/core/syntax_errors.py +0 -0
  39. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/coverage.py +0 -0
  40. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/dart_isolates.py +0 -0
  41. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/doctor.py +0 -0
  42. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/explore.py +0 -0
  43. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/external.py +0 -0
  44. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/graphql.py +0 -0
  45. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/guard_facts.py +0 -0
  46. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/hooks.py +0 -0
  47. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/indexer.py +0 -0
  48. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/insecure_transport.py +0 -0
  49. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/install_rules.py +0 -0
  50. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/jobs.py +0 -0
  51. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/link.py +0 -0
  52. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/lint_async.py +0 -0
  53. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/local_ipc.py +0 -0
  54. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/local_sockets.py +0 -0
  55. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/mcp_graphs.py +0 -0
  56. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/mcp_install.py +0 -0
  57. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/mcp_server.py +0 -0
  58. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/payload.py +0 -0
  59. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plans.py +0 -0
  60. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/platform_scan.py +0 -0
  61. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/platforms.py +0 -0
  62. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/__init__.py +0 -0
  63. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/astro/__init__.py +0 -0
  64. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/astro/content.py +0 -0
  65. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/astro/plugin.py +0 -0
  66. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/cfamily/__init__.py +0 -0
  67. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/cfamily/plugin.py +0 -0
  68. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/cfamily/syntax.py +0 -0
  69. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/__init__.py +0 -0
  70. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/bridges.py +0 -0
  71. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/extractor/bin/extract.dart +0 -0
  72. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/extractor/pubspec.lock +0 -0
  73. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/extractor/pubspec.yaml +0 -0
  74. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/http.py +0 -0
  75. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/models.py +0 -0
  76. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/plugin.py +0 -0
  77. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/dart/program.py +0 -0
  78. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/__init__.py +0 -0
  79. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/extras.py +0 -0
  80. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/models.py +0 -0
  81. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/plugin.py +0 -0
  82. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/schemas.py +0 -0
  83. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/shapes.py +0 -0
  84. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/django/urls.py +0 -0
  85. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/express/__init__.py +0 -0
  86. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/express/plugin.py +0 -0
  87. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/flutter/__init__.py +0 -0
  88. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/flutter/plugin.py +0 -0
  89. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/java/__init__.py +0 -0
  90. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/java/exact.py +0 -0
  91. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/java/plugin.py +0 -0
  92. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/jvm/__init__.py +0 -0
  93. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/jvm/interop.py +0 -0
  94. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/jvm/spring.py +0 -0
  95. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/__init__.py +0 -0
  96. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/exact.py +0 -0
  97. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/plugin.py +0 -0
  98. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/kotlin/reparse.py +0 -0
  99. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/__init__.py +0 -0
  100. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/broadcast.py +0 -0
  101. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/massassign.py +0 -0
  102. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/plugin.py +0 -0
  103. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/tests.py +0 -0
  104. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/laravel/values.py +0 -0
  105. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/__init__.py +0 -0
  106. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/gates.py +0 -0
  107. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/runner.py +0 -0
  108. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/scipread.py +0 -0
  109. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/native/ts.py +0 -0
  110. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nest/__init__.py +0 -0
  111. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nest/plugin.py +0 -0
  112. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nextjs/__init__.py +0 -0
  113. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nextjs/plugin.py +0 -0
  114. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nuxt/__init__.py +0 -0
  115. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/nuxt/plugin.py +0 -0
  116. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/__init__.py +0 -0
  117. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/external.py +0 -0
  118. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/extractor/composer.json +0 -0
  119. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/extractor/composer.lock +0 -0
  120. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/extractor/extract.php +0 -0
  121. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/gating.py +0 -0
  122. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/http_client.py +0 -0
  123. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/inline_guards.py +0 -0
  124. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/plugin.py +0 -0
  125. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/php/strings.py +0 -0
  126. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/__init__.py +0 -0
  127. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/aitools.py +0 -0
  128. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/external.py +0 -0
  129. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/fields.py +0 -0
  130. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/plugin.py +0 -0
  131. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/refs.py +0 -0
  132. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/roots.py +0 -0
  133. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/socketio.py +0 -0
  134. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/subproc.py +0 -0
  135. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/tests.py +0 -0
  136. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/python/values.py +0 -0
  137. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/pyweb/__init__.py +0 -0
  138. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/pyweb/plugin.py +0 -0
  139. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/pyweb/values.py +0 -0
  140. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/__init__.py +0 -0
  141. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/cargo.py +0 -0
  142. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/plugin.py +0 -0
  143. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/rust/syntax.py +0 -0
  144. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/__init__.py +0 -0
  145. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/importer.py +0 -0
  146. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/scip.proto +0 -0
  147. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/scip/scip_pb2.py +0 -0
  148. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/stubs/__init__.py +0 -0
  149. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/stubs/plugins.py +0 -0
  150. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/__init__.py +0 -0
  151. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/baseurl.py +0 -0
  152. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/exact.py +0 -0
  153. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/indexstore.py +0 -0
  154. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/packages.py +0 -0
  155. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/swift/plugin.py +0 -0
  156. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/__init__.py +0 -0
  157. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/baseurl.py +0 -0
  158. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/extract.mjs +0 -0
  159. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/fw.mjs +0 -0
  160. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/package-lock.json +0 -0
  161. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/package.json +0 -0
  162. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/extractor/rr.mjs +0 -0
  163. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/nav.py +0 -0
  164. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/plugin.py +0 -0
  165. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/ts/react_router.py +0 -0
  166. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/tsweb/__init__.py +0 -0
  167. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/tsweb/common.py +0 -0
  168. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/plugins/tsweb/data.py +0 -0
  169. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/__init__.py +0 -0
  170. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/c_cpp.yaml +0 -0
  171. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/common.yaml +0 -0
  172. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/dart.yaml +0 -0
  173. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/django-ninja.yaml +0 -0
  174. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/django.yaml +0 -0
  175. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/djangorestframework.yaml +0 -0
  176. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/express.yaml +0 -0
  177. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/java.yaml +0 -0
  178. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/kotlin.yaml +0 -0
  179. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/laravel.yaml +0 -0
  180. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/nest.yaml +0 -0
  181. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/nextjs.yaml +0 -0
  182. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/nuxt.yaml +0 -0
  183. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/php.yaml +0 -0
  184. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/python.yaml +0 -0
  185. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/react-router.yaml +0 -0
  186. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/rust.yaml +0 -0
  187. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/spring.yaml +0 -0
  188. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/swift.yaml +0 -0
  189. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/presets/typescript.yaml +0 -0
  190. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/process_runs.py +0 -0
  191. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/protocols/__init__.py +0 -0
  192. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/protocols/builtin.py +0 -0
  193. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/protocols/matchers.py +0 -0
  194. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/protocols/view.py +0 -0
  195. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/query.py +0 -0
  196. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/realtime.py +0 -0
  197. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/realtime_events.py +0 -0
  198. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/realtime_native.py +0 -0
  199. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/realtime_ws.py +0 -0
  200. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/roundtrip.py +0 -0
  201. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/routes.py +0 -0
  202. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/rpc.py +0 -0
  203. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/sdk_systems.py +0 -0
  204. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/sockets.py +0 -0
  205. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/ssrf_input.py +0 -0
  206. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/starters.py +0 -0
  207. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/surface.py +0 -0
  208. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/tests_index.py +0 -0
  209. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/udp_apps.py +0 -0
  210. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/update_check.py +0 -0
  211. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/__init__.py +0 -0
  212. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/graph.py +0 -0
  213. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/server.py +0 -0
  214. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/app.css +0 -0
  215. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/app.js +0 -0
  216. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/index.html +0 -0
  217. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/layered.js +0 -0
  218. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/VERSIONS.txt +0 -0
  219. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/cose-base.js +0 -0
  220. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/cytoscape-fcose.js +0 -0
  221. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/cytoscape.min.js +0 -0
  222. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/static/vendor/layout-base.js +0 -0
  223. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/tools/package-lock.json +0 -0
  224. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/tools/package.json +0 -0
  225. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/viz/tools/shoot.mjs +0 -0
  226. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/watch.py +0 -0
  227. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/webhook_subs.py +0 -0
  228. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/webhooks.py +0 -0
  229. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph/xcode.py +0 -0
  230. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/dependency_links.txt +0 -0
  231. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/entry_points.txt +0 -0
  232. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/requires.txt +0 -0
  233. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/cg_code_graph.egg-info/top_level.txt +0 -0
  234. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/pyproject.toml +0 -0
  235. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/setup.cfg +0 -0
  236. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_affected.py +0 -0
  237. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_agents_install.py +0 -0
  238. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_agents_md.py +0 -0
  239. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ai_tools.py +0 -0
  240. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_android_ipc.py +0 -0
  241. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_apple_ipc.py +0 -0
  242. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_astro.py +0 -0
  243. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_astro_content.py +0 -0
  244. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_astro_server.py +0 -0
  245. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_bridges.py +0 -0
  246. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_bridges_pigeon_monorepo.py +0 -0
  247. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_brokers.py +0 -0
  248. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cache_clean.py +0 -0
  249. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cache_invalidation.py +0 -0
  250. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cache_migration.py +0 -0
  251. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_channels_tests.py +0 -0
  252. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cli_output.py +0 -0
  253. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_cmake_sources.py +0 -0
  254. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_completeness.py +0 -0
  255. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_config_extras.py +0 -0
  256. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_coverage.py +0 -0
  257. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_coverage_ts_hint.py +0 -0
  258. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_dart_isolates.py +0 -0
  259. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_db_connections.py +0 -0
  260. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_dead_wrappers.py +0 -0
  261. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_dispatch_interfaces.py +0 -0
  262. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_django_flutter.py +0 -0
  263. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_docs_languages.py +0 -0
  264. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_docs_links.py +0 -0
  265. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_echo_ref.py +0 -0
  266. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_echo_wrapper.py +0 -0
  267. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_elysia.py +0 -0
  268. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_enum_constants.py +0 -0
  269. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_env.py +0 -0
  270. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_explore.py +0 -0
  271. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_external.py +0 -0
  272. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_fp_batch.py +0 -0
  273. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_gating.py +0 -0
  274. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_generated.py +0 -0
  275. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_graphql.py +0 -0
  276. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_hooks.py +0 -0
  277. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_impact_overrides.py +0 -0
  278. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_index_isolation.py +0 -0
  279. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_inherited_overrides.py +0 -0
  280. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_inline_guards.py +0 -0
  281. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_install_rules.py +0 -0
  282. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_192.py +0 -0
  283. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_201.py +0 -0
  284. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_202.py +0 -0
  285. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_203.py +0 -0
  286. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_204.py +0 -0
  287. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_205.py +0 -0
  288. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_206.py +0 -0
  289. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_207.py +0 -0
  290. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_208.py +0 -0
  291. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_209.py +0 -0
  292. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_210.py +0 -0
  293. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_211.py +0 -0
  294. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_211_used_at.py +0 -0
  295. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_212.py +0 -0
  296. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_212_langs.py +0 -0
  297. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_218.py +0 -0
  298. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_219.py +0 -0
  299. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_issue_222.py +0 -0
  300. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_java.py +0 -0
  301. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_java_exact.py +0 -0
  302. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_jobs.py +0 -0
  303. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_js_refs.py +0 -0
  304. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_js_runtime.py +0 -0
  305. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin.py +0 -0
  306. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_binding.py +0 -0
  307. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_exact.py +0 -0
  308. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_fields.py +0 -0
  309. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_mixed.py +0 -0
  310. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_nav_consts.py +0 -0
  311. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_kotlin_props.py +0 -0
  312. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_laravel_determinism.py +0 -0
  313. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_laravel_receiver_narrowing.py +0 -0
  314. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_laravel_resources.py +0 -0
  315. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_laravel_route_paths.py +0 -0
  316. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_link_origin.py +0 -0
  317. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_lint_async.py +0 -0
  318. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_listing_files.py +0 -0
  319. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_local_ipc.py +0 -0
  320. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_local_sockets.py +0 -0
  321. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mass_assignment.py +0 -0
  322. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp.py +0 -0
  323. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp_index.py +0 -0
  324. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp_install.py +0 -0
  325. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp_instructions.py +0 -0
  326. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_mcp_multi_graph.py +0 -0
  327. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_native_cfamily.py +0 -0
  328. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_native_concurrency.py +0 -0
  329. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_native_rust.py +0 -0
  330. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_i18n.py +0 -0
  331. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_import_dirs.py +0 -0
  332. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_nitro.py +0 -0
  333. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_rootsrc.py +0 -0
  334. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_nuxt_side_dirs.py +0 -0
  335. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_packaging.py +0 -0
  336. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_parity.py +0 -0
  337. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_parity_structure.py +0 -0
  338. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_php_http.py +0 -0
  339. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_php_props.py +0 -0
  340. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_plain_js.py +0 -0
  341. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_plans.py +0 -0
  342. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_platform_gaps.py +0 -0
  343. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_platform_type_variants.py +0 -0
  344. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_platforms.py +0 -0
  345. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_platforms_apple.py +0 -0
  346. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_presets_config.py +0 -0
  347. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_process_ipc.py +0 -0
  348. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_process_runs.py +0 -0
  349. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_protocols.py +0 -0
  350. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_app_tests_module.py +0 -0
  351. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_collection_chains.py +0 -0
  352. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_compat.py +0 -0
  353. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_entry_refs.py +0 -0
  354. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_fields.py +0 -0
  355. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_infer_cycles.py +0 -0
  356. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_roots.py +0 -0
  357. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_subprocess_tests.py +0 -0
  358. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_tests.py +0 -0
  359. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_web_hosts.py +0 -0
  360. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_web_routes.py +0 -0
  361. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_python_web_routes_more.py +0 -0
  362. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_react_router.py +0 -0
  363. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_readers_writers_specs.py +0 -0
  364. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_realtime.py +0 -0
  365. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_realtime_native.py +0 -0
  366. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_redact_salt.py +0 -0
  367. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_request_keys.py +0 -0
  368. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_roundtrip.py +0 -0
  369. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_route_specs.py +0 -0
  370. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_route_tables.py +0 -0
  371. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_routes_search_explain.py +0 -0
  372. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_rpc.py +0 -0
  373. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_scip_health.py +0 -0
  374. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_sdk_external.py +0 -0
  375. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_sdk_external_infra.py +0 -0
  376. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_sdk_external_mail.py +0 -0
  377. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_snippet.py +0 -0
  378. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_sockets.py +0 -0
  379. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_spring.py +0 -0
  380. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ssrf.py +0 -0
  381. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_starters_budget.py +0 -0
  382. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_surface.py +0 -0
  383. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_surface_transport.py +0 -0
  384. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift.py +0 -0
  385. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_binding.py +0 -0
  386. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_exact.py +0 -0
  387. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_facts.py +0 -0
  388. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_fields.py +0 -0
  389. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_modules.py +0 -0
  390. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_more.py +0 -0
  391. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_nav_values.py +0 -0
  392. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_parse_errors.py +0 -0
  393. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_props.py +0 -0
  394. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_sdk.py +0 -0
  395. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_testing.py +0 -0
  396. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_swift_values.py +0 -0
  397. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_tauri_events.py +0 -0
  398. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_tests_scope.py +0 -0
  399. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_fields.py +0 -0
  400. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_fields_js_vue.py +0 -0
  401. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_file_specs.py +0 -0
  402. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_frameworks.py +0 -0
  403. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_node_http.py +0 -0
  404. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_nuxt.py +0 -0
  405. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_ts_src_tsconfig.py +0 -0
  406. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_unguarded.py +0 -0
  407. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_update_check.py +0 -0
  408. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_values.py +0 -0
  409. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_viz.py +0 -0
  410. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_vue_nav.py +0 -0
  411. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_watch.py +0 -0
  412. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_webhooks.py +0 -0
  413. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_webhooks_152.py +0 -0
  414. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_webhooks_152b.py +0 -0
  415. {cg_code_graph-0.23.7 → cg_code_graph-0.23.8}/tests/test_websockets.py +0 -0
  416. {cg_code_graph-0.23.7 → 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.7
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.7"
2
+ __version__ = "0.23.8"
@@ -301,9 +301,12 @@ def main(argv=None):
301
301
  p.add_argument("--strip-prefix", action="append", default=[], help="a name prefix one side adds (`Vault` in "
302
302
  "VaultAddEditState for AddEditState), ignored when matching (repeatable)")
303
303
  p.add_argument("--structure", action="store_true", help="also pair symbols whose names differ by what they use: "
304
- "shared strings, localization keys, endpoints and already-paired callees, plus rename rules learned "
305
- "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")
306
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)")
307
310
  p.add_argument("--write-map", help="with --structure: write the inferred pairs as a --map JSON file to review")
308
311
  p.add_argument("--json", action="store_true"); p.add_argument("--max-items", type=int, default=200)
309
312
  p = sub.add_parser("lint", help="heuristic lints (#88): `lint async-state` flags stale async results, state with "
@@ -574,7 +577,7 @@ def main(argv=None):
574
577
  from . import parity as PA
575
578
  mapping = json.loads(open(a.map, encoding="utf-8").read()) if a.map else None
576
579
  res = PA.parity(a.db, a.against, mapping=mapping, fuzzy=not a.no_fuzzy, strip_prefixes=a.strip_prefix,
577
- structure=a.structure, learn=not a.no_learn)
580
+ structure=a.structure, learn=not a.no_learn, both_sides=a.both_sides)
578
581
  if a.write_map:
579
582
  with open(a.write_map, "w", encoding="utf-8") as fh:
580
583
  json.dump(PA.rename_map(res), fh, indent=1, sort_keys=True)
@@ -220,21 +220,27 @@ def _cat(sym: dict, is_type: bool) -> str:
220
220
  return "type" if is_type else "const" if sym["kind"] in ("constant", "enum_case") else "func"
221
221
 
222
222
 
223
+ INFERRED = ("structure", "fields", "learned")
224
+ PREVIEW_NAME = re.compile(r"Preview")
225
+
226
+
223
227
  def parity(source_db: str, target_db: str, mapping: dict | None = None, fuzzy: bool = True,
224
- strip_prefixes: list[str] | None = None, structure: bool = False, learn: bool = True) -> dict:
228
+ strip_prefixes: list[str] | None = None, structure: bool = False, learn: bool = True,
229
+ both_sides: bool = False) -> dict:
225
230
  """See the module docstring. `strip_prefixes`: name prefixes one side adds (`Vault` in `VaultAddEditState`
226
231
  for `AddEditState`), dropped before normalized matching on both sides. `structure` (#93): after the name rules,
227
232
  pair the rest by shared strings, localization keys, endpoints and paired callees, and (`learn`) apply rename
228
- rules learned from the pairs found (cg_code_graph/parity_structure.py); off, the output is the name matching alone."""
233
+ rules learned from the pairs found (cg_code_graph/parity_structure.py); off, the output is the name matching alone.
234
+ `both_sides`: also list what only the target has (`target_only`)."""
229
235
  _PREFIXES[:] = [p.lower() for p in strip_prefixes or ()]
230
236
  try:
231
- return _parity(source_db, target_db, mapping, fuzzy, structure, learn)
237
+ return _parity(source_db, target_db, mapping, fuzzy, structure, learn, both_sides)
232
238
  finally:
233
239
  _PREFIXES.clear()
234
240
 
235
241
 
236
242
  def _parity(source_db: str, target_db: str, mapping: dict | None, fuzzy: bool, structure: bool = False,
237
- learn: bool = True) -> dict:
243
+ learn: bool = True, both_sides: bool = False) -> dict:
238
244
  S, T = load(source_db), load(target_db)
239
245
  mapping = mapping or {}
240
246
  exact_ix, norm_ix, comp_ix, all_short = defaultdict(list), defaultdict(list), defaultdict(list), defaultdict(list)
@@ -357,7 +363,7 @@ def _parity(source_db: str, target_db: str, mapping: dict | None, fuzzy: bool, s
357
363
  tm.setdefault(_short(nt), T["types"][nt])
358
364
  tm_norm = {norm_member(k): k for k in tm}
359
365
  for nm, sym in sorted(S["members"].get(sfq, {}).items()):
360
- if nm in ("body", "init", "deinit", "hash", "description", "encode", "hashValue") or sym["override"]:
366
+ if nm in BOILERPLATE or sym["override"]:
361
367
  out["skipped"] += 1 # lifecycle / platform overrides (viewDidLoad, onCreate) and boilerplate
362
368
  continue
363
369
  if nm in tm:
@@ -375,7 +381,7 @@ def _parity(source_db: str, target_db: str, mapping: dict | None, fuzzy: bool, s
375
381
  match_members(tmap)
376
382
  if structure:
377
383
  _structure(S, T, out, tmap, learn)
378
- inferred = {r["symbol"]: r["target"] for r in out["matched"] if r.get("confidence") in ("structure", "learned")
384
+ inferred = {r["symbol"]: r["target"] for r in out["matched"] if r.get("confidence") in INFERRED
379
385
  and r["symbol"] in S["types"] and r["target"] in T["types"]}
380
386
  match_members(inferred)
381
387
  counts = defaultdict(int)
@@ -387,10 +393,44 @@ def _parity(source_db: str, target_db: str, mapping: dict | None, fuzzy: bool, s
387
393
  "missing": len(out["missing"]), "unknown": len(out["unknown"]),
388
394
  "platform_only": len(out["platform_only"])}
389
395
  if structure:
390
- out["summary"]["inferred"] = sum(1 for r in out["matched"] if r["confidence"] in ("structure", "learned"))
396
+ out["summary"]["inferred"] = sum(1 for r in out["matched"] if r["confidence"] in INFERRED)
397
+ if both_sides:
398
+ _target_only(T, out, t_nested)
399
+ out["summary"]["target_only"] = len(out["target_only"])
391
400
  return out
392
401
 
393
402
 
403
+ BOILERPLATE = ("body", "init", "deinit", "hash", "description", "encode", "hashValue")
404
+
405
+
406
+ def _target_only(T, out, t_nested):
407
+ """`--both-sides`: target types and top-level symbols no source symbol matched, and the unmatched members of
408
+ target types that were matched. Members of an unmatched type are counted under it, not listed."""
409
+ used = {r["target"] for r in out["matched"]}
410
+ rows, hidden = [], 0
411
+ for coll in (T["types"], T["top"]):
412
+ for fq, sym in sorted(coll.items()):
413
+ if fq in used:
414
+ continue
415
+ owner = fq.rsplit(".", 1)[0] if "." in fq else None
416
+ if owner in T["types"] and owner not in used:
417
+ continue # a nested type of an unmatched type: the type is listed
418
+ if PREVIEW_NAME.search(_short(fq)) or sym["file"] in T["err_files"]:
419
+ hidden += 1
420
+ continue
421
+ rows.append(_row(sym, None, None))
422
+ for o in sorted(o for o in T["members"] if o in used):
423
+ for nm, sym in sorted(T["members"][o].items()):
424
+ if f"{o}.{nm}" in used:
425
+ continue
426
+ if nm in BOILERPLATE or sym["override"] or sym["file"] in T["err_files"]:
427
+ hidden += 1
428
+ continue
429
+ rows.append(_row(sym, None, None))
430
+ out["target_only"] = rows
431
+ out["target_only_hidden"] = hidden
432
+
433
+
394
434
  def _structure(S, T, out, tmap, learn):
395
435
  from . import parity_structure as PS
396
436
  sym_of, cat_of, t_syms, t_cat = {}, {}, {}, {}
@@ -409,7 +449,7 @@ def _structure(S, T, out, tmap, learn):
409
449
 
410
450
  def rename_map(res: dict) -> dict:
411
451
  """The structure / learned matches as a `--map` file ({source: target}) to review and commit."""
412
- return {r["symbol"]: r["target"] for r in res["matched"] if r.get("confidence") in ("structure", "learned")}
452
+ return {r["symbol"]: r["target"] for r in res["matched"] if r.get("confidence") in INFERRED}
413
453
 
414
454
 
415
455
  def _row(sym, target, how, owner_match=None) -> dict:
@@ -435,6 +475,25 @@ def _group(file: str) -> str:
435
475
  return "/".join(parts[:2]) if len(parts) > 2 else (parts[0] if parts else "")
436
476
 
437
477
 
478
+ def _grouped(lines, title, rows, total, max_items):
479
+ by = defaultdict(list)
480
+ for r in rows:
481
+ by[r["module"]].append(r)
482
+ if not by:
483
+ return
484
+ lines += ["", f"== {title}: {total}"]
485
+ shown = 0
486
+ for mod in sorted(by, key=lambda k: -len(by[k])):
487
+ lines.append(f" {mod or '.'} ({len(by[mod])})")
488
+ for r in by[mod]:
489
+ if shown >= max_items:
490
+ break
491
+ shown += 1
492
+ lines.append(f" {r['symbol']} [{r['kind']}] {r['file']}:{r['line']}")
493
+ if shown < total:
494
+ lines.append(f" ... {total - shown} more (--json for all)")
495
+
496
+
438
497
  def render(res: dict, max_items: int = 200) -> str:
439
498
  s = res["summary"]
440
499
  m = s["matched"]
@@ -457,7 +516,14 @@ def render(res: dict, max_items: int = 200) -> str:
457
516
  lines.append(f" {r['symbol']} [{r['kind']}] {r['file']}:{r['line']}")
458
517
  if shown < s["missing"]:
459
518
  lines.append(f" ... {s['missing'] - shown} more (--json for all)")
460
- inferred = [r for r in res["matched"] if r.get("confidence") in ("structure", "learned")]
519
+ if "target_only" in res:
520
+ lines[1] += f"; {s['target_only']} only in the target"
521
+ lines += ["", f"== MATCHED pairs: {sum(m.values())}"]
522
+ for r in sorted(res["matched"], key=lambda r: (r["confidence"] != "explicit", r["symbol"]))[:max_items]:
523
+ lines.append(f" {r['symbol']} -> {r['target']} [{r['confidence']}]")
524
+ if sum(m.values()) > max_items:
525
+ lines.append(f" ... {sum(m.values()) - max_items} more (--json for all)")
526
+ inferred = [r for r in res["matched"] if r.get("confidence") in INFERRED]
461
527
  if inferred:
462
528
  lines += ["", f"== INFERRED matches (not by name): {len(inferred)}"]
463
529
  for r in inferred[:max_items]:
@@ -467,6 +533,8 @@ def render(res: dict, max_items: int = 200) -> str:
467
533
  if rule is (res.get("learned_rules") or [None])[0]:
468
534
  lines += ["", "== LEARNED rename rules"]
469
535
  lines.append(f" {rule['at']}: {rule['from']!r} -> {rule['to']!r} (seen {rule['support']}x)")
536
+ if "target_only" in res:
537
+ _grouped(lines, "ONLY IN TARGET (no source counterpart)", res["target_only"], s["target_only"], max_items)
470
538
  if res["unknown"]:
471
539
  lines += ["", f"== UNKNOWN (file parsed with syntax errors): {s['unknown']}"]
472
540
  lines += [f" {r['symbol']} {r['file']}:{r['line']}" for r in res["unknown"][:max_items]]
@@ -11,8 +11,21 @@ its outgoing edges:
11
11
  sym:<target> symbols it calls / instantiates / navigates to that are already paired (the source side is
12
12
  rewritten to the target's name, so a call to a paired API on both sides is a shared feature)
13
13
  call:<name> the names of the members it calls (two words or more)
14
+ res:<name> image and raw resources it uses (`Image("ic_lock")`, `UIImage(named:)`, `Asset.Images.icLock`,
15
+ `Image(.icLock)`, `R.drawable.ic_lock`, `Res.drawable.x`), case and `_` folded; colors are design
16
+ tokens shared by every screen and are left out
14
17
  w:<stem> the stemmed content words of its own name
15
18
 
19
+ A use is specific when it appears in at most SPECIFIC_FILES files on each side (files, not symbols, since a type's span
20
+ holds its members'); a pair whose shared uses are all generic needs two shared name words, so two screens that only
21
+ share `l10n:cancel` / `l10n:yes` and one word do not pair.
22
+
23
+ Types that are still missing after that are paired by their declared fields (`fields`): stored properties, each under
24
+ its wire name when one is declared (Swift `CodingKeys` raw values, Kotlin `@SerialName` / `@SerializedName` /
25
+ `@Json(name =)`), and enum cases, kept apart from properties; case and `_` folded. A pair needs MIN_FIELDS shared
26
+ fields, an IDF-weighted overlap of at least MIN_FIELD_SCORE, a shared name word or a higher overlap, mutual best and
27
+ the margin.
28
+
16
29
  A pair is accepted when it shares a use (any feature but w:) and either two uses or two name words, its IDF-weighted
17
30
  cosine is at least MIN_SCORE, both symbols are each other's best candidate, the runner-up scores below MARGIN times
18
31
  the best, and category, UI-ness and architecture role agree (`compatible`). Learned rules come from the
@@ -21,6 +34,7 @@ MIN_SUPPORT times, two thirds of the time for that source tail, is applied to th
21
34
  top-level symbols. Every match carries its evidence; name matches are left as they are."""
22
35
  from __future__ import annotations
23
36
 
37
+ import json
24
38
  import math
25
39
  import re
26
40
  import sqlite3
@@ -32,9 +46,16 @@ MIN_SHARED = 2
32
46
  MARGIN = 0.8 # the runner-up must score below MARGIN * best
33
47
  MIN_SUPPORT = 2
34
48
  MAX_DF = 40
49
+ SPECIFIC_FILES = 3 # a shared use found in more files than this on either side is generic (`l10n:cancel`)
50
+ MIN_FIELDS = 3
51
+ MIN_FIELD_SCORE = 0.5
35
52
  PREVIEW = re.compile(r"Preview") # Compose @Preview functions / PreviewParameterProviders, SwiftUI previews # features shared by more symbols than this do not propose candidates
36
53
  L10N = re.compile(r"\b(?:Localizations|L10n|R\.string|BitwardenString|CommonStrings|[A-Z]\w*Strings)\.([A-Za-z_]\w*)")
37
54
  STR = re.compile(r'"((?:[^"\\\n]|\\.){5,80})"')
55
+ RES = re.compile(r"""\b(?:UI|NS)?Image\(\s*(?:named:\s*)?"([^"\n]+)"|\bAsset\.(?:Images|Assets)\.(\w+)|"""
56
+ r"""\bImage\(\s*\.(\w+)\s*\)|\b(?:R|Res)\.(?:drawable|mipmap|raw)\.(\w+)""")
57
+ WIRE = re.compile(r'@(?:SerialName|SerializedName|JsonProperty|Json\(\s*name\s*=)\s*\(?\s*(?:value\s*=\s*)?"([^"\n]+)"')
58
+ RAW_CASE = re.compile(r'\bcase\s+`?(\w+)`?\s*=\s*"([^"\n]+)"')
38
59
  EDGE_KINDS = ("CALLS", "INSTANTIATES", "NAVIGATES_TO", "HTTP_CALLS", "USES_VALUE", "REFERENCES_FN", "USES_TYPE")
39
60
 
40
61
 
@@ -123,8 +144,40 @@ class Side:
123
144
  for r in c.execute(q, EDGE_KINDS):
124
145
  self.out[r["src"]].append((r["dst"], r["kind"]))
125
146
  self.http = {r["id"]: (r["name"] or r["id"]) for r in c.execute("SELECT id, name FROM nodes WHERE kind='http'")}
147
+ self.decl = defaultdict(list) # owner fqn -> [(name, kind, file, line)] of stored fields / enum cases
148
+ for r in c.execute("SELECT kind, fqn, file, line, attrs FROM nodes WHERE kind IN ('field', 'enum_case') "
149
+ "AND fqn IS NOT NULL AND file IS NOT NULL"):
150
+ if ".Companion." in r["fqn"] or "." not in r["fqn"]:
151
+ continue
152
+ if r["kind"] == "field" and (json.loads(r["attrs"] or "{}").get("property") or "stored") != "stored":
153
+ continue
154
+ o, nm = r["fqn"].rsplit(".", 1)
155
+ self.decl[o].append((nm, r["kind"], r["file"], r["line"]))
126
156
  c.close()
127
157
 
158
+ def fields(self, fq: str) -> set:
159
+ """`field:<wire name>` for each stored property declared directly on the type: the explicit wire name
160
+ (`@SerialName("item_title")`, a `CodingKeys` case `title = "item_title"`) or else the property name; `case:<name>`
161
+ for each enum case, so an enum of field names does not meet the type that has those fields."""
162
+ raw = {}
163
+ for nm, kind, file, line in self.decl.get(fq + ".CodingKeys", ()):
164
+ m = RAW_CASE.search(self.text(file, line, line))
165
+ if m:
166
+ raw[m.group(1)] = m.group(2)
167
+ out = set()
168
+ for nm, kind, file, line in self.decl.get(fq, ()):
169
+ wire = raw.get(nm)
170
+ if not wire and kind == "field":
171
+ m = WIRE.search(self.text(file, line, line))
172
+ if not m and line > 1: # an annotation on its own line above
173
+ prev = self.text(file, line - 1, line - 1)
174
+ m = None if re.search(r"\b(?:val|var|let)\s", prev) else WIRE.search(prev)
175
+ wire = m.group(1) if m else None
176
+ k = _fold(wire or nm)
177
+ if len(k) > 1:
178
+ out.add(("case:" if kind == "enum_case" else "field:") + k)
179
+ return out
180
+
128
181
  def text(self, file: str, a: int, b: int) -> str:
129
182
  if file not in self.lines:
130
183
  try:
@@ -139,6 +192,9 @@ class Side:
139
192
  if file and a:
140
193
  src = self.text(file, a, b)
141
194
  f |= {"l10n:" + _fold(m) for m in L10N.findall(src)}
195
+ for m in RES.finditer(src):
196
+ f.add("res:" + _fold(next(g for g in m.groups() if g)))
197
+ src = RES.sub(" ", src)
142
198
  for m in STR.findall(src):
143
199
  s = m.strip().lstrip("/")
144
200
  if len(s) >= 5 and re.search(r"[A-Za-z]{3}", s) and not re.search(r"\\\(|\$\{|%[@sd]", s):
@@ -250,6 +306,60 @@ def _apply_rules(rules, out, sym_of, cat_of, t_syms, t_cat, used):
250
306
  out["missing"] = keep
251
307
 
252
308
 
309
+ def _by_fields(sS, sT, out, sym_of, cat_of, t_syms, t_cat, used, S, T):
310
+ """Types still missing, paired by the fields they declare (`ViewItemState` / `VaultItemState`, a Swift
311
+ `Codable` model and its Kotlin `@Serializable` port)."""
312
+ src = {r["symbol"]: sS.fields(r["symbol"]) for r in out["missing"] if cat_of.get(r["symbol"]) == "type"
313
+ and "owner_matched" not in r}
314
+ src = {k: v for k, v in src.items() if len(v) >= MIN_FIELDS and _short(k) != "CodingKeys"}
315
+ tgt = {fq: sT.fields(fq) for fq in t_syms if t_cat.get(fq) == "type" and fq not in used}
316
+ tgt = {k: v for k, v in tgt.items() if len(v) >= MIN_FIELDS and _short(k) != "CodingKeys"}
317
+ if not src or not tgt:
318
+ return
319
+ df = Counter()
320
+ for fs in list(src.values()) + list(tgt.values()):
321
+ df.update(fs)
322
+ n = len(src) + len(tgt)
323
+ w = {f: math.log(1 + n / c) for f, c in df.items()}
324
+ inv = defaultdict(list)
325
+ for fq, fs in tgt.items():
326
+ for f in fs:
327
+ inv[f].append(fq)
328
+
329
+ def score(fq, t):
330
+ a, b = src[fq], tgt[t]
331
+ sh = a & b
332
+ if len(sh) < MIN_FIELDS:
333
+ return 0.0, sh
334
+ sc = sum(w[f] for f in sh) / sum(w[f] for f in a | b)
335
+ words = name_words(fq) & name_words(t)
336
+ if sc < MIN_FIELD_SCORE or (not words and sc < 0.75):
337
+ return 0.0, sh
338
+ return sc, sh | words
339
+
340
+ best = {}
341
+ for fq, fs in src.items():
342
+ cands = {t for f in fs if df[f] <= MAX_DF for t in inv[f]
343
+ if compatible(fq, "type", t, "type", S["_ui"].get(fq), T["_ui"].get(t))}
344
+ scored = sorted(((score(fq, t), t) for t in cands), key=lambda x: -x[0][0])
345
+ if scored and scored[0][0][0] > 0 and (len(scored) == 1 or scored[1][0][0] < MARGIN * scored[0][0][0]):
346
+ best[fq] = (scored[0][1], scored[0][0][0], scored[0][0][1])
347
+ by_t = defaultdict(list)
348
+ for fq, (t, sc, sh) in best.items():
349
+ by_t[t].append((sc, fq))
350
+ keep = []
351
+ for row in out["missing"]:
352
+ got = best.get(row["symbol"])
353
+ if got and max(by_t[got[0]])[1] == row["symbol"] and got[0] not in used:
354
+ t, sc, sh = got
355
+ used.add(t)
356
+ ev = sorted(sh, key=lambda f: (f.startswith("w:"), -w.get(f, 0), f))[:6]
357
+ out["matched"].append(dict(row, target=t, confidence="fields", score=round(sc, 2), evidence=ev))
358
+ else:
359
+ keep.append(row)
360
+ out["missing"] = keep
361
+
362
+
253
363
  def _structure(S, T, out, sym_of, cat_of, t_syms, t_cat, used):
254
364
  sS, sT = Side(S), Side(T)
255
365
  pairs = {r["symbol"]: r["target"] for r in out["matched"]}
@@ -264,6 +374,12 @@ def _structure(S, T, out, sym_of, cat_of, t_syms, t_cat, used):
264
374
  df = Counter()
265
375
  for fs in list(src_f.values()) + list(tgt_f.values()):
266
376
  df.update(fs)
377
+ spread = [defaultdict(set), defaultdict(set)] # feature -> files having it, per side
378
+ for k, (fsets, syms) in enumerate(((src_f, sym_of), (tgt_f, t_syms))):
379
+ for fq, fs in fsets.items():
380
+ for f in fs:
381
+ spread[k][f].add(syms[fq]["file"])
382
+ specific = {f for f in df if len(spread[0][f]) <= SPECIFIC_FILES and len(spread[1][f]) <= SPECIFIC_FILES}
267
383
  n = max(1, len(src_f) + len(tgt_f))
268
384
  w = {f: math.log(1 + n / c) for f, c in df.items()}
269
385
  inv = defaultdict(list)
@@ -278,6 +394,8 @@ def _structure(S, T, out, sym_of, cat_of, t_syms, t_cat, used):
278
394
  # what they use must carry the match: two shared uses, or one use and two shared name words
279
395
  if nw < 1 or (nw < MIN_SHARED and len(sh) - nw < 2):
280
396
  return 0.0, sh
397
+ if len(sh) - nw < 2 and not any(f in specific for f in sh if not f.startswith("w:")):
398
+ return 0.0, sh # only generic uses (`l10n:cancel`, `l10n:yes`) and one name word
281
399
  return sum(w[f] for f in sh) / math.sqrt(sum(w[f] for f in a) * sum(w[f] for f in b)), sh
282
400
 
283
401
  best_s = {}
@@ -305,3 +423,4 @@ def _structure(S, T, out, sym_of, cat_of, t_syms, t_cat, used):
305
423
  else:
306
424
  keep.append(row)
307
425
  out["missing"] = keep
426
+ _by_fields(sS, sT, out, sym_of, cat_of, t_syms, t_cat, used, S, T)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cg-code-graph
3
- Version: 0.23.7
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
@@ -331,6 +331,7 @@ tests/test_nuxt_rootsrc.py
331
331
  tests/test_nuxt_side_dirs.py
332
332
  tests/test_packaging.py
333
333
  tests/test_parity.py
334
+ tests/test_parity_fields.py
334
335
  tests/test_parity_structure.py
335
336
  tests/test_php_http.py
336
337
  tests/test_php_props.py
@@ -0,0 +1,125 @@
1
+ """`cg parity --structure` part 2 (#93): types paired by their declared fields and wire names, views paired by the
2
+ image resources they use, generic shared keys not enough, and `--both-sides` (matched pairs plus what only the
3
+ target has). Invented app: a hiking app in Swift and its Kotlin port."""
4
+ import json
5
+ import subprocess
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ import pytest
10
+
11
+ sys.path.insert(0, str(Path(__file__).parent))
12
+ pytest.importorskip("tree_sitter_swift")
13
+ pytest.importorskip("tree_sitter_kotlin")
14
+ from test_parity import ROOT, build # noqa: E402
15
+ from cg_code_graph import parity as P # noqa: E402
16
+ from cg_code_graph import parity_structure as PS # noqa: E402
17
+
18
+ IOS = {
19
+ "Trails/Models/TrailSummaryResponse.swift":
20
+ "struct TrailSummaryResponse: Codable {\n let trailId: String\n let displayName: String\n"
21
+ " let elevationGain: Int\n let loopKind: String\n\n enum CodingKeys: String, CodingKey {\n"
22
+ ' case trailId = "trail_id"\n case displayName = "display_name"\n'
23
+ ' case elevationGain = "elevation_gain"\n case loopKind = "loop_kind"\n }\n}\n',
24
+ "Trails/Detail/HikeDetailState.swift":
25
+ "struct HikeDetailState {\n var title: String = \"\"\n var isFavorite = false\n var distanceText = \"\"\n"
26
+ " var difficulty = 0\n var photoCount = 0\n}\n",
27
+ "Trails/Badges/BadgeShelfView.swift":
28
+ "import SwiftUI\n\nstruct BadgeShelfView: View {\n var body: some View {\n HStack {\n"
29
+ ' Image("badge_summit")\n Image("badge_sunrise")\n }\n }\n}\n',
30
+ "Trails/Trip/HikeShareSheet.swift":
31
+ "import SwiftUI\n\nstruct HikeShareSheet: View {\n var body: some View {\n HStack {\n"
32
+ " Text(Localizations.cancel)\n Text(Localizations.yes)\n }\n }\n}\n",
33
+ "Trails/Settings/SettingsStore.swift":
34
+ "final class SettingsStore {\n func reset() {}\n}\n",
35
+ "Trails/Widgets/LiveActivityWidget.swift":
36
+ 'struct LiveActivityWidget {\n func kind() -> String { "live-activity-hike" }\n}\n',
37
+ }
38
+ ANDROID = {
39
+ "app/src/main/java/com/trailmate/data/TrailOverviewJson.kt":
40
+ "package com.trailmate.data\n\n@Serializable\ndata class TrailOverviewJson(\n"
41
+ ' @SerialName("trail_id") val id: String,\n @SerialName("display_name") val name: String,\n'
42
+ ' @SerialName("elevation_gain") val gain: Int,\n @SerialName("loop_kind") val loop: String,\n)\n',
43
+ "app/src/main/java/com/trailmate/detail/RouteDetailViewState.kt":
44
+ "package com.trailmate.detail\n\ndata class RouteDetailViewState(\n val title: String,\n"
45
+ " val isFavorite: Boolean,\n val distanceText: String,\n val difficulty: Int,\n val elevationText: String,\n)\n",
46
+ "app/src/main/java/com/trailmate/badges/AchievementRow.kt":
47
+ "package com.trailmate.badges\n\nimport androidx.compose.runtime.Composable\n\n@Composable\nfun AchievementRow() {\n"
48
+ " Image(painterResource(R.drawable.badge_summit), null)\n Image(painterResource(R.drawable.badge_sunrise), null)\n}\n",
49
+ "app/src/main/java/com/trailmate/trip/HikeDeleteDialog.kt":
50
+ "package com.trailmate.trip\n\nimport androidx.compose.runtime.Composable\n\n@Composable\nfun HikeDeleteDialog() {\n"
51
+ " Text(stringResource(R.string.cancel))\n Text(stringResource(R.string.yes))\n}\n",
52
+ # cancel / yes are on every prompt: generic keys
53
+ **{f"app/src/main/java/com/trailmate/common/{n}Prompt.kt":
54
+ f"package com.trailmate.common\n\nclass {n}Prompt {{\n fun confirm{n}() {{\n show(R.string.cancel)\n"
55
+ f" show(R.string.yes)\n }}\n}}\n" for n in ("Exit", "Logout", "Unfollow", "Archive")},
56
+ "app/src/main/java/com/trailmate/settings/SettingsStore.kt":
57
+ "package com.trailmate.settings\n\nclass SettingsStore {\n fun reset() {}\n fun exportBackup() {}\n}\n",
58
+ "app/src/main/java/com/trailmate/wear/WearTileService.kt":
59
+ "package com.trailmate.wear\n\nclass WearTileService {\n fun onTileRequest() {}\n}\n",
60
+ }
61
+
62
+
63
+ @pytest.fixture(scope="module")
64
+ def dbs():
65
+ return build(IOS, "fios"), build(ANDROID, "fandroid")
66
+
67
+
68
+ def test_default_output_unchanged(dbs):
69
+ res = P.parity(*dbs)
70
+ assert "target_only" not in res and "inferred" not in res["summary"]
71
+ assert not [r for r in res["matched"] if r["confidence"] in P.INFERRED]
72
+
73
+
74
+ def test_fields_resources_and_generic_keys(dbs):
75
+ res = P.parity(*dbs, structure=True)
76
+ m = {r["symbol"]: r for r in res["matched"]}
77
+ # wire names: CodingKeys raw values meet @SerialName, although every property is renamed
78
+ t = m["TrailSummaryResponse"]
79
+ assert t["target"] == "com.trailmate.data.TrailOverviewJson", t
80
+ assert {"str:trail_id", "field:trailid"} & set(t["evidence"]), t
81
+ # screen state by its stored properties
82
+ h = m["HikeDetailState"]
83
+ assert h["target"] == "com.trailmate.detail.RouteDetailViewState" and h["confidence"] == "fields", h
84
+ # image resources: Image("badge_summit") / R.drawable.badge_summit
85
+ b = m["BadgeShelfView"]
86
+ assert b["target"] == "com.trailmate.badges.AchievementRow" and b["confidence"] == "structure", b
87
+ assert "res:badgesummit" in b["evidence"]
88
+ # only generic keys (cancel / yes on every prompt) in common: no match
89
+ missing = {r["symbol"] for r in res["missing"]}
90
+ assert "HikeShareSheet" in missing and "LiveActivityWidget" in missing, missing
91
+
92
+
93
+ def test_generic_guard_is_what_keeps_them_apart(dbs, monkeypatch):
94
+ monkeypatch.setattr(PS, "SPECIFIC_FILES", 10 ** 6)
95
+ m = {r["symbol"]: r["target"] for r in P.parity(*dbs, structure=True)["matched"]}
96
+ # one name word and two generic keys in common: IDF alone would pair a share sheet with a delete dialog
97
+ assert m.get("HikeShareSheet") == "com.trailmate.trip.HikeDeleteDialog"
98
+
99
+
100
+ def test_both_sides(dbs):
101
+ res = P.parity(*dbs, structure=True, both_sides=True)
102
+ only = {r["symbol"] for r in res["target_only"]}
103
+ assert "com.trailmate.wear.WearTileService" in only
104
+ assert "com.trailmate.settings.SettingsStore.exportBackup" in only # member of a matched type
105
+ assert "com.trailmate.wear.WearTileService.onTileRequest" not in only # counted under its type
106
+ assert "com.trailmate.data.TrailOverviewJson" not in only
107
+ assert res["summary"]["target_only"] == len(res["target_only"])
108
+
109
+
110
+ def test_cli_both_sides(dbs):
111
+ r = subprocess.run([sys.executable, "-m", "cg_code_graph.cli", "parity", "--db", dbs[0], "--against", dbs[1],
112
+ "--structure", "--both-sides"], capture_output=True, text=True, cwd=ROOT)
113
+ assert r.returncode == 0, r.stderr
114
+ assert "== MATCHED pairs:" in r.stdout and "== ONLY IN TARGET (no source counterpart):" in r.stdout
115
+ assert "SettingsStore -> com.trailmate.settings.SettingsStore [exact]" in r.stdout
116
+ assert "[fields" in r.stdout
117
+ j = json.loads(subprocess.run([sys.executable, "-m", "cg_code_graph.cli", "parity", "--db", dbs[0], "--against",
118
+ dbs[1], "--both-sides", "--json"], capture_output=True, text=True, cwd=ROOT).stdout)
119
+ assert "target_only" in j and "inferred" not in j["summary"]
120
+
121
+
122
+ def test_wire_names(dbs):
123
+ want = {"field:trailid", "field:displayname", "field:elevationgain", "field:loopkind"}
124
+ assert PS.Side(P.load(dbs[0])).fields("TrailSummaryResponse") == want # CodingKeys raw values
125
+ assert PS.Side(P.load(dbs[1])).fields("com.trailmate.data.TrailOverviewJson") == want # @SerialName
File without changes
File without changes