Is your feature request related to a problem? Please describe.
The facade exposes mostly one-at-a-time, fully-reconstructed reads. On the read-only Neo4j backend these become N+1 round-trips (per module → per class → per callable, recursing), and even in-process they over-fetch: enumerating an application rebuilds call-sites, inner callables, locals, etc. that the caller throws away. #180 / #181 fixed this for four Python callable accessors, but that covers only 2 of ~5 optimization shapes, and only the callable entity, and only Python. TypeScript and Java have none.
The optimizable shapes:
| Shape |
Fixes |
Done (Python) |
| A. Projected enumeration |
enumerate an entity-set without reconstructing each |
get_callables_overview() ✅ |
| B. Batch-by-signature field fetch |
N bodies/fields in one round-trip |
get_method_bodies() ✅ |
| C. Filtered enumeration (predicate pushdown) |
filter in Cypher, return projections |
get_decorated_callables() ✅ |
| D. Batch relationship walk |
one query for N entities' edges |
get_callsites_for() ✅ |
| E. Projected graph |
build the graph from a flat edge+node projection |
— |
Applying A–E across {callables, classes, modules, fields, hierarchy, call-graph} yields ~10–12 accessors per language. Python has 4; TS and Java have 0.
Describe the solution you'd like
Add bulk / field-projected accessors across all three facades + backends (in-process and Neo4j), with per-language overview models, mirroring the #181 pattern (ABC + both backends + facade + parity tests). Each is a single projected Cypher RETURN on Neo4j and one in-memory walk in-process.
Cross-language accessors
| Proposed accessor |
Python |
TypeScript |
Java |
get_callables_overview() |
✅ |
new TSCallableOverview (+kind,is_exported,is_async) |
new JCallableOverview (+modifiers,annotations,is_constructor,is_entrypoint) |
get_classes_overview() |
new |
new (spans interfaces/enums via kind) |
new |
get_modules_overview() |
new |
new (modules) |
new (compilation units) |
get_fields_overview() / get_fields_for(sigs) |
new |
new |
new |
get_method_bodies(sigs) |
✅ |
new (TSCallable.code) |
new (JCallable.code) |
get_files_for(sigs) |
new |
new (get_typescript_file) |
new (get_java_file) |
get_decorated_callables(markers) |
✅ |
new (TS decorators) |
→ get_annotated_callables(annotations) |
get_decorated_classes / get_annotated_types |
new |
new (get_classes_with_decorators today is full-fetch) |
new (get_methods_with_annotations today is full-fetch) |
get_entrypoints_overview() |
new |
new (TSCallable.entrypoints) |
new (is_entrypoint; pairs with existing get_service_entry_point_*) |
get_callers_for(sigs) / get_callees_for(sigs) |
new |
new |
new |
get_subclasses_for / get_supertypes_for / get_implemented_interfaces_for |
new |
new |
new |
get_call_edges() (projected graph) |
new |
new |
new |
Language-specific accessors (- = not applicable)
| Proposed accessor |
Python |
TypeScript |
Java |
get_interfaces_overview() / get_enums_overview() / get_type_aliases_overview() |
- |
new |
- |
get_exports_overview() / get_variables_overview() |
- |
new |
- |
get_exported_callables() (off is_exported) |
- |
new |
- |
get_crud_overview() (+ create/read/update/delete) |
- |
- |
new |
get_comments_for(sigs) / get_docstrings (batch) |
- |
- |
new (scans every callable today) |
TypeScript's get_interfaces() / get_enums() / get_type_aliases() / get_exports() / get_variables() all enumerate-by-reconstruction → each wants an *_overview(). Java's get_all_crud_operations() (+ create/read/update/delete) and the comment/docstring family (get_all_comments, get_all_docstrings, get_comments_in_a_method) scan every callable. CRUD lives on JCallSite, so it also rides along in a Java get_callsites_for().
Describe alternatives you've considered
- Hand-written Cypher in consumers — leaks graph schema into callers, isn't backend-agnostic; the whole point is SDK-owned projections.
- Only speed up the existing reconstruction (session reuse, batching the fan-out) — helps but doesn't fix over-fetch: enumeration still rebuilds fields the caller discards.
- Blind-port the 4 Python methods — wrong: the analogs are language-specific. Java has no decorators →
get_annotated_callables(annotations); TS adds entity kinds (interfaces/enums/type-aliases) and is_exported; Java adds CRUD/comments and is_entrypoint/modifiers.
Additional context
Is your feature request related to a problem? Please describe.
The facade exposes mostly one-at-a-time, fully-reconstructed reads. On the read-only Neo4j backend these become N+1 round-trips (per module → per class → per callable, recursing), and even in-process they over-fetch: enumerating an application rebuilds call-sites, inner callables, locals, etc. that the caller throws away. #180 / #181 fixed this for four Python callable accessors, but that covers only 2 of ~5 optimization shapes, and only the callable entity, and only Python. TypeScript and Java have none.
The optimizable shapes:
get_callables_overview()✅get_method_bodies()✅get_decorated_callables()✅get_callsites_for()✅Applying A–E across
{callables, classes, modules, fields, hierarchy, call-graph}yields ~10–12 accessors per language. Python has 4; TS and Java have 0.Describe the solution you'd like
Add bulk / field-projected accessors across all three facades + backends (in-process and Neo4j), with per-language overview models, mirroring the #181 pattern (ABC + both backends + facade + parity tests). Each is a single projected Cypher
RETURNon Neo4j and one in-memory walk in-process.Cross-language accessors
get_callables_overview()TSCallableOverview(+kind,is_exported,is_async)JCallableOverview(+modifiers,annotations,is_constructor,is_entrypoint)get_classes_overview()kind)get_modules_overview()get_fields_overview()/get_fields_for(sigs)get_method_bodies(sigs)TSCallable.code)JCallable.code)get_files_for(sigs)get_typescript_file)get_java_file)get_decorated_callables(markers)get_annotated_callables(annotations)get_decorated_classes/get_annotated_typesget_classes_with_decoratorstoday is full-fetch)get_methods_with_annotationstoday is full-fetch)get_entrypoints_overview()TSCallable.entrypoints)is_entrypoint; pairs with existingget_service_entry_point_*)get_callers_for(sigs)/get_callees_for(sigs)get_subclasses_for/get_supertypes_for/get_implemented_interfaces_forget_call_edges()(projected graph)Language-specific accessors (
-= not applicable)get_interfaces_overview()/get_enums_overview()/get_type_aliases_overview()get_exports_overview()/get_variables_overview()get_exported_callables()(offis_exported)get_crud_overview()(+ create/read/update/delete)get_comments_for(sigs)/get_docstrings(batch)TypeScript's
get_interfaces()/get_enums()/get_type_aliases()/get_exports()/get_variables()all enumerate-by-reconstruction → each wants an*_overview(). Java'sget_all_crud_operations()(+ create/read/update/delete) and the comment/docstring family (get_all_comments,get_all_docstrings,get_comments_in_a_method) scan every callable. CRUD lives onJCallSite, so it also rides along in a Javaget_callsites_for().Describe alternatives you've considered
get_annotated_callables(annotations); TS adds entity kinds (interfaces/enums/type-aliases) andis_exported; Java adds CRUD/comments andis_entrypoint/modifiers.Additional context
PyCallableOverview).*AnalysisBackendABC, both backends (in-process + Neo4j), and the facade, with offline + Neo4j-parity tests.get_methods_with_decorators()is still aNotImplementedErrorstub on Python — supersede it viaget_decorated_callablesrather than implementing the stub.