entrygraph 0.1.20__tar.gz → 0.1.22__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 (188) hide show
  1. {entrygraph-0.1.20 → entrygraph-0.1.22}/PKG-INFO +1 -1
  2. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/_version.py +2 -2
  3. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/csharp.py +26 -1
  4. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/golang.py +25 -1
  5. entrygraph-0.1.22/tests/fixtures/csharp/minimalapi_app/Program.cs +15 -0
  6. entrygraph-0.1.22/tests/fixtures/csharp/minimalapi_app/app.csproj +5 -0
  7. entrygraph-0.1.22/tests/fixtures/go/nethttp_app/go.mod +3 -0
  8. entrygraph-0.1.22/tests/fixtures/go/nethttp_app/main.go +15 -0
  9. entrygraph-0.1.22/tests/test_csharp_callbacks.py +46 -0
  10. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_csharp.py +21 -0
  11. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_go.py +23 -0
  12. entrygraph-0.1.22/tests/test_go_callbacks.py +45 -0
  13. {entrygraph-0.1.20 → entrygraph-0.1.22}/.github/workflows/ci.yml +0 -0
  14. {entrygraph-0.1.20 → entrygraph-0.1.22}/.github/workflows/release.yml +0 -0
  15. {entrygraph-0.1.20 → entrygraph-0.1.22}/.gitignore +0 -0
  16. {entrygraph-0.1.20 → entrygraph-0.1.22}/LICENSE +0 -0
  17. {entrygraph-0.1.20 → entrygraph-0.1.22}/README.md +0 -0
  18. {entrygraph-0.1.20 → entrygraph-0.1.22}/RELEASING.md +0 -0
  19. {entrygraph-0.1.20 → entrygraph-0.1.22}/pyproject.toml +0 -0
  20. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/__init__.py +0 -0
  21. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/__main__.py +0 -0
  22. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/api.py +0 -0
  23. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/cli/__init__.py +0 -0
  24. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/cli/main.py +0 -0
  25. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/cli/render.py +0 -0
  26. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/csharp.toml +0 -0
  27. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/go.toml +0 -0
  28. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/java.toml +0 -0
  29. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/javascript.toml +0 -0
  30. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/lib_javascript.toml +0 -0
  31. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/lib_python.toml +0 -0
  32. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/php.toml +0 -0
  33. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/python.toml +0 -0
  34. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/ruby.toml +0 -0
  35. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/rust.toml +0 -0
  36. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/__init__.py +0 -0
  37. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/engine.py +0 -0
  38. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/meta.py +0 -0
  39. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/models.py +0 -0
  40. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/queries.py +0 -0
  41. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/__init__.py +0 -0
  42. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/__init__.py +0 -0
  43. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/base.py +0 -0
  44. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/configs.py +0 -0
  45. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/csharp.py +0 -0
  46. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/golang.py +0 -0
  47. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/java.py +0 -0
  48. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/javascript.py +0 -0
  49. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/php.py +0 -0
  50. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/python.py +0 -0
  51. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/ruby.py +0 -0
  52. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/rust.py +0 -0
  53. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/frameworks.py +0 -0
  54. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/manifests.py +0 -0
  55. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/taint.py +0 -0
  56. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/errors.py +0 -0
  57. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/__init__.py +0 -0
  58. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/base.py +0 -0
  59. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/ir.py +0 -0
  60. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/java.py +0 -0
  61. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/javascript.py +0 -0
  62. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/php.py +0 -0
  63. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/python.py +0 -0
  64. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/registry.py +0 -0
  65. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/ruby.py +0 -0
  66. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/rust.py +0 -0
  67. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/fs/__init__.py +0 -0
  68. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/fs/hashing.py +0 -0
  69. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/fs/lang.py +0 -0
  70. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/fs/walker.py +0 -0
  71. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/graph/__init__.py +0 -0
  72. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/graph/adjacency.py +0 -0
  73. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/graph/cte.py +0 -0
  74. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/graph/scoring.py +0 -0
  75. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/kinds.py +0 -0
  76. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/parsing/__init__.py +0 -0
  77. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/parsing/parsers.py +0 -0
  78. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/parsing/queries.py +0 -0
  79. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/pipeline/__init__.py +0 -0
  80. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/pipeline/scanner.py +0 -0
  81. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/pipeline/worker.py +0 -0
  82. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/pipeline/writer.py +0 -0
  83. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/py.typed +0 -0
  84. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/csharp/calls.scm +0 -0
  85. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/csharp/definitions.scm +0 -0
  86. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/csharp/imports.scm +0 -0
  87. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/go/calls.scm +0 -0
  88. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/go/definitions.scm +0 -0
  89. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/go/imports.scm +0 -0
  90. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/java/calls.scm +0 -0
  91. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/java/definitions.scm +0 -0
  92. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/java/imports.scm +0 -0
  93. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/javascript/calls.scm +0 -0
  94. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/javascript/definitions.scm +0 -0
  95. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/javascript/imports.scm +0 -0
  96. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/php/calls.scm +0 -0
  97. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/php/definitions.scm +0 -0
  98. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/php/imports.scm +0 -0
  99. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/python/calls.scm +0 -0
  100. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/python/definitions.scm +0 -0
  101. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/python/imports.scm +0 -0
  102. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/ruby/calls.scm +0 -0
  103. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/ruby/definitions.scm +0 -0
  104. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/ruby/imports.scm +0 -0
  105. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/rust/calls.scm +0 -0
  106. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/rust/definitions.scm +0 -0
  107. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/rust/imports.scm +0 -0
  108. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/__init__.py +0 -0
  109. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/externals.py +0 -0
  110. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/hierarchy.py +0 -0
  111. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/resolver.py +0 -0
  112. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/symbol_table.py +0 -0
  113. {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/results.py +0 -0
  114. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/conftest.py +0 -0
  115. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/csharp/aspnet_app/Controllers/ReportsController.cs +0 -0
  116. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/csharp/aspnet_app/Program.cs +0 -0
  117. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/csharp/aspnet_app/Services/ReportService.cs +0 -0
  118. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/csharp/aspnet_app/app.csproj +0 -0
  119. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/go/gin_app/go.mod +0 -0
  120. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/go/gin_app/main.go +0 -0
  121. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/go/gin_app/service.go +0 -0
  122. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/pom.xml +0 -0
  123. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/src/main/java/com/example/Application.java +0 -0
  124. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/src/main/java/com/example/ReportRunner.java +0 -0
  125. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/src/main/java/com/example/ReportService.java +0 -0
  126. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/src/main/java/com/example/UserController.java +0 -0
  127. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/javascript/commonjs_app/server.js +0 -0
  128. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/javascript/express_app/package.json +0 -0
  129. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/javascript/express_app/src/routes.js +0 -0
  130. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/javascript/express_app/src/services.js +0 -0
  131. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/php/laravel_app/app/Http/Controllers/ReportController.php +0 -0
  132. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/php/laravel_app/artisan +0 -0
  133. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/php/laravel_app/composer.json +0 -0
  134. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/php/laravel_app/routes/web.php +0 -0
  135. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/chained_sinks/app.py +0 -0
  136. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/app/__init__.py +0 -0
  137. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/app/db.py +0 -0
  138. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/app/routes.py +0 -0
  139. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/app/services.py +0 -0
  140. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/cli.py +0 -0
  141. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/requirements.txt +0 -0
  142. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/fuzzy_sink/app.py +0 -0
  143. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/heal_fidelity/caller.py +0 -0
  144. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/heal_fidelity/worker.py +0 -0
  145. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/may_continue/app.py +0 -0
  146. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/sanitizer/app.py +0 -0
  147. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/taint_source/handler.py +0 -0
  148. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/ruby/sinatra_app/Gemfile +0 -0
  149. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/ruby/sinatra_app/app.rb +0 -0
  150. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/ruby/sinatra_app/services/runner.rb +0 -0
  151. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/rust/axum_app/Cargo.toml +0 -0
  152. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/rust/axum_app/src/handlers.rs +0 -0
  153. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/rust/axum_app/src/main.rs +0 -0
  154. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_api.py +0 -0
  155. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_cli.py +0 -0
  156. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_commonjs.py +0 -0
  157. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_cte_bounds.py +0 -0
  158. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_engine_pragmas.py +0 -0
  159. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_entrypoint_expansion.py +0 -0
  160. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_entrypoints.py +0 -0
  161. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_java.py +0 -0
  162. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_javascript.py +0 -0
  163. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_php.py +0 -0
  164. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_python.py +0 -0
  165. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_ruby.py +0 -0
  166. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_rust.py +0 -0
  167. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_frameworks.py +0 -0
  168. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_fuzzy_sink.py +0 -0
  169. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_hardening.py +0 -0
  170. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_heal_fidelity.py +0 -0
  171. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_incremental.py +0 -0
  172. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_indexer.py +0 -0
  173. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_lang.py +0 -0
  174. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_manifests.py +0 -0
  175. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_may_continue.py +0 -0
  176. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_models.py +0 -0
  177. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_pool.py +0 -0
  178. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_reachability.py +0 -0
  179. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_registry_cache.py +0 -0
  180. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_render.py +0 -0
  181. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_resolver.py +0 -0
  182. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_scoring.py +0 -0
  183. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_sink_catalog.py +0 -0
  184. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_taint.py +0 -0
  185. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_taint_sanitizers.py +0 -0
  186. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_taint_sources.py +0 -0
  187. {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_walker.py +0 -0
  188. {entrygraph-0.1.20 → entrygraph-0.1.22}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: entrygraph
3
- Version: 0.1.20
3
+ Version: 0.1.22
4
4
  Summary: Language-agnostic code graph: query symbols, entrypoints, and source-to-sink call paths from a SQLite index
5
5
  Project-URL: Repository, https://github.com/brettbergin/entrygraph
6
6
  Author-email: Brett Bergin <brettberginbc@yahoo.com>
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '0.1.20'
22
- __version_tuple__ = version_tuple = (0, 1, 20)
21
+ __version__ = version = '0.1.22'
22
+ __version_tuple__ = version_tuple = (0, 1, 22)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -329,6 +329,7 @@ class CSharpExtractor:
329
329
  receiver = None
330
330
  callee_text = node_text(fn)
331
331
  args = node.child_by_field_name("arguments")
332
+ caller = self._caller(node, ctx)
332
333
  out.references.append(
333
334
  RawReference(
334
335
  kind="call",
@@ -336,11 +337,35 @@ class CSharpExtractor:
336
337
  callee_name=callee_name,
337
338
  receiver_text=receiver,
338
339
  span=span_of(node),
339
- caller_qualified_name=self._caller(node, ctx),
340
+ caller_qualified_name=caller,
340
341
  arg_count=len(args.named_children) if args is not None else 0,
341
342
  arg_preview=truncate(node_text(args)) if args is not None else None,
342
343
  )
343
344
  )
345
+ self._emit_callbacks(args, caller, out)
346
+
347
+ def _emit_callbacks(self, args: Node | None, caller: str | None, out: FileExtraction) -> None:
348
+ """Method-group arguments passed to a call — a function value invoked later,
349
+ e.g. ``app.MapPost("/run", Handler)`` (minimal APIs). Each C# argument wraps
350
+ its expression; a bare identifier is a method group. Resolution keeps only
351
+ those binding to a project method."""
352
+ if args is None:
353
+ return
354
+ for arg in args.named_children:
355
+ expr = arg.named_children[0] if arg.type == "argument" and arg.named_children else arg
356
+ if expr is None or expr.type != "identifier":
357
+ continue
358
+ name = node_text(expr)
359
+ out.references.append(
360
+ RawReference(
361
+ kind="callback",
362
+ callee_text=name,
363
+ callee_name=name,
364
+ receiver_text=None,
365
+ span=span_of(expr),
366
+ caller_qualified_name=caller,
367
+ )
368
+ )
344
369
 
345
370
  def _add_object_creation(self, node: Node, ctx: FileContext, out: FileExtraction) -> None:
346
371
  type_node = node.child_by_field_name("type")
@@ -252,6 +252,7 @@ class GoExtractor:
252
252
  else:
253
253
  continue # call of a call / index expr / etc. — not statically resolvable
254
254
  args = node.child_by_field_name("arguments")
255
+ caller = self._caller(node, ctx)
255
256
  out.references.append(
256
257
  RawReference(
257
258
  kind="call",
@@ -259,11 +260,12 @@ class GoExtractor:
259
260
  callee_name=callee_name,
260
261
  receiver_text=receiver,
261
262
  span=span_of(node),
262
- caller_qualified_name=self._caller(node, ctx),
263
+ caller_qualified_name=caller,
263
264
  arg_count=len(args.named_children) if args is not None else 0,
264
265
  arg_preview=truncate(node_text(args)) if args is not None else None,
265
266
  )
266
267
  )
268
+ self._emit_callbacks(args, caller, out)
267
269
 
268
270
  for node in caps.get("composite.type", []):
269
271
  text = node_text(node) # e.g. "cobra.Command"
@@ -278,6 +280,28 @@ class GoExtractor:
278
280
  )
279
281
  )
280
282
 
283
+ def _emit_callbacks(self, args: Node | None, caller: str | None, out: FileExtraction) -> None:
284
+ """Bare-identifier arguments passed to a call — a function value that may be
285
+ invoked later, e.g. ``http.HandleFunc("/", handler)``. Resolution keeps only
286
+ those binding to a project function, so passing a plain data value is a
287
+ harmless no-op edge."""
288
+ if args is None:
289
+ return
290
+ for arg in args.named_children:
291
+ if arg.type != "identifier":
292
+ continue
293
+ name = node_text(arg)
294
+ out.references.append(
295
+ RawReference(
296
+ kind="callback",
297
+ callee_text=name,
298
+ callee_name=name,
299
+ receiver_text=None,
300
+ span=span_of(arg),
301
+ caller_qualified_name=caller,
302
+ )
303
+ )
304
+
281
305
  # ---------------- walking helpers ----------------
282
306
 
283
307
  def _receiver_type(self, method: Node) -> str | None:
@@ -0,0 +1,15 @@
1
+ class Program
2
+ {
3
+ static void Main()
4
+ {
5
+ var app = Build();
6
+ app.MapPost("/run", Handler);
7
+ }
8
+
9
+ static void Handler()
10
+ {
11
+ System.Diagnostics.Process.Start("sh", "-c");
12
+ }
13
+
14
+ static object Build() { return null; }
15
+ }
@@ -0,0 +1,5 @@
1
+ <Project Sdk="Microsoft.NET.Sdk.Web">
2
+ <PropertyGroup>
3
+ <TargetFramework>net8.0</TargetFramework>
4
+ </PropertyGroup>
5
+ </Project>
@@ -0,0 +1,3 @@
1
+ module example.com/app
2
+
3
+ go 1.21
@@ -0,0 +1,15 @@
1
+ package main
2
+
3
+ import (
4
+ "net/http"
5
+ "os/exec"
6
+ )
7
+
8
+ func handler(w http.ResponseWriter, r *http.Request) {
9
+ exec.Command("sh", "-c", r.URL.Query().Get("cmd"))
10
+ }
11
+
12
+ func main() {
13
+ http.HandleFunc("/run", handler)
14
+ http.ListenAndServe(":8080", nil)
15
+ }
@@ -0,0 +1,46 @@
1
+ """End-to-end: C# method-group callbacks connect minimal-API handlers to their
2
+ registration site (Phase 4).
3
+
4
+ Regression: the C# extractor emitted no callback references, so a handler passed
5
+ to `app.MapPost("/run", Handler)` had no inbound edge and was unreachable.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from pathlib import Path
11
+
12
+ import pytest
13
+
14
+ from entrygraph import CodeGraph
15
+
16
+ MINIMALAPI_APP = Path(__file__).parent / "fixtures" / "csharp" / "minimalapi_app"
17
+
18
+
19
+ @pytest.fixture(scope="module")
20
+ def graph(tmp_path_factory) -> CodeGraph:
21
+ db = tmp_path_factory.mktemp("db") / "graph.db"
22
+ g = CodeGraph.index(MINIMALAPI_APP, db=db)
23
+ yield g
24
+ g.close()
25
+
26
+
27
+ def test_callback_edge_created(graph):
28
+ rows = graph.sql(
29
+ "SELECT src.qname AS src, e.dst_qname AS dst FROM edges e "
30
+ "JOIN symbols src ON e.src_symbol_id = src.id WHERE e.kind = 'callback'"
31
+ )
32
+ pairs = {(r["src"], r["dst"]) for r in rows}
33
+ assert ("Program.Program.Main", "Program.Program.Handler") in pairs
34
+
35
+
36
+ def test_handler_reachable_only_with_callbacks(graph):
37
+ kw = {
38
+ "source": "Program.Program.Main",
39
+ "sink_category": "command_exec",
40
+ "include_unresolved": True,
41
+ }
42
+ assert graph.paths(**kw) == []
43
+ withcb = graph.paths(**kw, include_callbacks=True)
44
+ assert withcb
45
+ assert "Program.Program.Handler" in [s.qname for s in withcb[0].symbols]
46
+ assert withcb[0].symbols[-1].qname == "cs:System.Diagnostics.Process.Start"
@@ -202,6 +202,27 @@ public class C
202
202
  assert calls["SqlCommand"].receiver_text is None
203
203
 
204
204
 
205
+ def test_method_group_argument_is_a_callback():
206
+ # app.MapPost("/run", Handler) passes `Handler` as a method group; it must be
207
+ # a callback so the handler is reachable from the registration site.
208
+ x = extract(
209
+ """
210
+ namespace App {
211
+ class Program {
212
+ static void Setup(object app) {
213
+ app.MapPost("/run", Handler);
214
+ }
215
+ static void Handler() {}
216
+ }
217
+ }
218
+ """
219
+ )
220
+ callbacks = {r.callee_name: r for r in x.references if r.kind == "callback"}
221
+ assert "Handler" in callbacks
222
+ assert callbacks["Handler"].caller_qualified_name == "App.Program.Setup"
223
+ assert "/run" not in callbacks # string literal arg is not a callback
224
+
225
+
205
226
  # ---------------- unit: partial class (duplicate qnames) ----------------
206
227
 
207
228
 
@@ -167,6 +167,29 @@ func helper() {}
167
167
  assert "ls" in exec_call.arg_preview
168
168
 
169
169
 
170
+ def test_function_value_argument_is_a_callback():
171
+ # http.HandleFunc("/", handler) passes `handler` as a value; it must be
172
+ # emitted as a callback so the handler is reachable from the registration site.
173
+ x = extract(
174
+ """
175
+ package server
176
+
177
+ import "net/http"
178
+
179
+ func register() {
180
+ http.HandleFunc("/run", handler)
181
+ }
182
+
183
+ func handler(w http.ResponseWriter, r *http.Request) {}
184
+ """
185
+ )
186
+ callbacks = {r.callee_name: r for r in x.references if r.kind == "callback"}
187
+ assert "handler" in callbacks
188
+ assert callbacks["handler"].caller_qualified_name == "cmd.server.register"
189
+ # string/other literal args are not callbacks
190
+ assert "/run" not in callbacks
191
+
192
+
170
193
  def test_partial_tree_still_extracts():
171
194
  x = extract("package p\n\nfunc good() {}\n\nfunc broken( {\n")
172
195
  assert not x.parse_ok
@@ -0,0 +1,45 @@
1
+ """End-to-end: Go function-value callbacks connect handlers to their registration
2
+ site (Phase 4).
3
+
4
+ Regression: the Go extractor emitted no callback references, so a handler passed
5
+ to `http.HandleFunc("/", handler)` had no inbound edge — its body (and any sink it
6
+ reached) was unreachable in the call graph.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from pathlib import Path
12
+
13
+ import pytest
14
+
15
+ from entrygraph import CodeGraph
16
+
17
+ NETHTTP_APP = Path(__file__).parent / "fixtures" / "go" / "nethttp_app"
18
+
19
+
20
+ @pytest.fixture(scope="module")
21
+ def graph(tmp_path_factory) -> CodeGraph:
22
+ db = tmp_path_factory.mktemp("db") / "graph.db"
23
+ g = CodeGraph.index(NETHTTP_APP, db=db)
24
+ yield g
25
+ g.close()
26
+
27
+
28
+ def test_callback_edge_created(graph):
29
+ rows = graph.sql(
30
+ "SELECT src.qname AS src, e.dst_qname AS dst FROM edges e "
31
+ "JOIN symbols src ON e.src_symbol_id = src.id WHERE e.kind = 'callback'"
32
+ )
33
+ pairs = {(r["src"], r["dst"]) for r in rows}
34
+ assert ("_root.main", "_root.handler") in pairs
35
+
36
+
37
+ def test_handler_reachable_only_with_callbacks(graph):
38
+ kw = {"source": "_root.main", "sink_category": "command_exec", "include_unresolved": True}
39
+ # without callback traversal the handler is severed from main
40
+ assert graph.paths(**kw) == []
41
+ # with it, main -> handler -> exec.Command resolves
42
+ withcb = graph.paths(**kw, include_callbacks=True)
43
+ assert withcb
44
+ assert withcb[0].symbols[-1].qname == "go:os/exec.Command"
45
+ assert "_root.handler" in [s.qname for s in withcb[0].symbols]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes