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.
- {entrygraph-0.1.20 → entrygraph-0.1.22}/PKG-INFO +1 -1
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/_version.py +2 -2
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/csharp.py +26 -1
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/golang.py +25 -1
- entrygraph-0.1.22/tests/fixtures/csharp/minimalapi_app/Program.cs +15 -0
- entrygraph-0.1.22/tests/fixtures/csharp/minimalapi_app/app.csproj +5 -0
- entrygraph-0.1.22/tests/fixtures/go/nethttp_app/go.mod +3 -0
- entrygraph-0.1.22/tests/fixtures/go/nethttp_app/main.go +15 -0
- entrygraph-0.1.22/tests/test_csharp_callbacks.py +46 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_csharp.py +21 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_go.py +23 -0
- entrygraph-0.1.22/tests/test_go_callbacks.py +45 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/.github/workflows/ci.yml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/.github/workflows/release.yml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/.gitignore +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/LICENSE +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/README.md +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/RELEASING.md +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/pyproject.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/__main__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/api.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/cli/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/cli/main.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/cli/render.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/csharp.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/go.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/java.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/javascript.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/lib_javascript.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/lib_python.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/php.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/python.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/ruby.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/data/sinks/rust.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/engine.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/meta.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/models.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/db/queries.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/base.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/configs.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/csharp.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/golang.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/java.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/javascript.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/php.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/python.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/ruby.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/entrypoints/rust.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/frameworks.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/manifests.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/detect/taint.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/errors.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/base.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/ir.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/java.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/javascript.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/php.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/python.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/registry.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/ruby.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/extract/rust.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/fs/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/fs/hashing.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/fs/lang.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/fs/walker.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/graph/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/graph/adjacency.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/graph/cte.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/graph/scoring.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/kinds.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/parsing/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/parsing/parsers.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/parsing/queries.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/pipeline/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/pipeline/scanner.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/pipeline/worker.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/pipeline/writer.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/py.typed +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/csharp/calls.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/csharp/definitions.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/csharp/imports.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/go/calls.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/go/definitions.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/go/imports.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/java/calls.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/java/definitions.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/java/imports.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/javascript/calls.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/javascript/definitions.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/javascript/imports.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/php/calls.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/php/definitions.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/php/imports.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/python/calls.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/python/definitions.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/python/imports.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/ruby/calls.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/ruby/definitions.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/ruby/imports.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/rust/calls.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/rust/definitions.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/queries/rust/imports.scm +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/externals.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/hierarchy.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/resolver.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/resolve/symbol_table.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/src/entrygraph/results.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/conftest.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/csharp/aspnet_app/Controllers/ReportsController.cs +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/csharp/aspnet_app/Program.cs +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/csharp/aspnet_app/Services/ReportService.cs +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/csharp/aspnet_app/app.csproj +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/go/gin_app/go.mod +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/go/gin_app/main.go +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/go/gin_app/service.go +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/pom.xml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/src/main/java/com/example/Application.java +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/src/main/java/com/example/ReportRunner.java +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/src/main/java/com/example/ReportService.java +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/java/spring_app/src/main/java/com/example/UserController.java +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/javascript/commonjs_app/server.js +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/javascript/express_app/package.json +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/javascript/express_app/src/routes.js +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/javascript/express_app/src/services.js +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/php/laravel_app/app/Http/Controllers/ReportController.php +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/php/laravel_app/artisan +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/php/laravel_app/composer.json +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/php/laravel_app/routes/web.php +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/chained_sinks/app.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/app/__init__.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/app/db.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/app/routes.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/app/services.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/cli.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/flask_app/requirements.txt +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/fuzzy_sink/app.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/heal_fidelity/caller.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/heal_fidelity/worker.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/may_continue/app.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/sanitizer/app.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/python/taint_source/handler.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/ruby/sinatra_app/Gemfile +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/ruby/sinatra_app/app.rb +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/ruby/sinatra_app/services/runner.rb +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/rust/axum_app/Cargo.toml +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/rust/axum_app/src/handlers.rs +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/rust/axum_app/src/main.rs +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_api.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_cli.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_commonjs.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_cte_bounds.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_engine_pragmas.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_entrypoint_expansion.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_entrypoints.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_java.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_javascript.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_php.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_python.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_ruby.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_extract_rust.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_frameworks.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_fuzzy_sink.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_hardening.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_heal_fidelity.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_incremental.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_indexer.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_lang.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_manifests.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_may_continue.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_models.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_pool.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_reachability.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_registry_cache.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_render.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_resolver.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_scoring.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_sink_catalog.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_taint.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_taint_sanitizers.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_taint_sources.py +0 -0
- {entrygraph-0.1.20 → entrygraph-0.1.22}/tests/test_walker.py +0 -0
- {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.
|
|
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.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
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=
|
|
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=
|
|
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
|
+
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/csharp/aspnet_app/Services/ReportService.cs
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{entrygraph-0.1.20 → entrygraph-0.1.22}/tests/fixtures/javascript/express_app/src/services.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|