Tier A/B api polish: enclosing-scope context, caller_of/callee_of, filters - #46
Merged
Merged
Conversation
Two tiers of API enhancements from the friction notes after using the
tool through a full stsom + absblobstore code-trace session. All changes
are AST-side or daemon-side; no schema changes, no re-index required.
TIER A -- workflow / output polish
* ``body`` promoted to ``query_codebase``: returns the full source of
every matching declaration across the codebase in one call, instead
of forcing the agent through three round-trips (find declarations ->
find implementor types -> body per file). Same compact ASCII header
format that ``query_single_file body`` already used. Other languages
silently skip when they don't implement ``body``.
* Enclosing-scope prefix on every pattern-mode hit
(``calls`` / ``uses`` / ``casts`` / ``accesses_of`` / ``accesses_on``):
each result row now starts with ``[in TypeName.MemberName] ``
(or ``[in TypeName] `` at type-level). Collapses the common
"wait, which class/method is this in?" follow-up that previously
needed a separate ``at LINE:COL`` query.
* ``head_lines`` argument on ``body`` and
``declarations include_body=True``: truncates each emitted body to
the first N source lines, with a ``... +K more lines`` tail marker.
Cheap token-saver when scanning many bodies.
* Compact tier-3 follow-up suggestions: the verbose per-file
``query_single_file("X", "Y", file="path") # N total hits`` lines
collapsed to ``[+K capped] path`` form, with one shared reminder at
the top of the suggestion block. ~80 chars saved per capped file.
TIER B -- new modes and filters
* ``var_type`` promoted to ``query_codebase``: report resolved type of
every occurrence of NAME across the codebase, not just one file.
* New ``caller_of METHOD`` mode: like ``calls``, but groups call sites
by the enclosing caller (``[in TypeName.MemberName] (N call sites)``).
Collapses 53 call-site hits into ~18 unique-caller rows.
* New ``callee_of METHOD`` mode: walk the body of the named method
and return one row per distinct callee with invocation counts.
Constructor calls (``new T()``) are reported as
``T (N invocations, ctor)``. Useful for "what does this method
depend on" analysis without reading the full body.
* ``enclosing_method=`` and ``enclosing_class=`` filters on every
pattern mode (``calls``/``uses``/``casts``/``accesses_of``/
``accesses_on``/``all_refs``). Compose as logical AND. Lets the agent
ask "find calls to Save inside methods named WriteBack of class
OrderProcessor" in one query instead of post-filtering.
DAEMON
* ``_run_query`` now catches ``ValueError`` from per-file AST dispatch
so codebase-wide queries with mixed-language file sets don't crash
when one of the files' languages doesn't implement the mode.
TESTS: +44 new cases. All 1131 tests pass; 10x full-suite stability
sweep clean.
DOCS: CLAUDE.md mode table updated with the new ``body`` semantics,
``caller_of``/``callee_of`` rows, ``var_type`` codebase-wide note,
and a new enclosing-scope-filter section. MCP tool docstrings updated
with the new modes and arguments.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three small cleanups in query/cs.py, no behavior change. All 469 query tests pass. * Extract _iter_call_sites: shared by q_calls and q_caller_of so both modes have identical matching semantics. q_caller_of previously re-parsed q_calls' "[in TypeName.MemberName] " text prefix to recover the caller key -- now it walks the AST directly via the shared iterator and pulls the caller name straight from _enclosing_type_name / _enclosing_member_name. No format coupling between the two modes. * Extract _member_decl_name_node: the field_declaration / event_field_declaration unwrap (name lives inside a nested variable_declarator) was duplicated in _enclosing_member_name and the now-removed _filter_by_enclosing. One helper, one rule. * Inline enclosing-scope filtering in each q_uses sub-helper instead of the _filter_by_enclosing line-map post-pass. _q_field_type / _q_param_type / _q_return_type / _q_local_type / _q_base_uses now take enclosing_method / enclosing_class kwargs and skip non-matching nodes during their own walk. Removes the second AST pass that built line -> (type, member) maps for every call. Docstring on q_uses notes that declaration-level kinds (field/param/return/ base) drop every row when enclosing_method is set -- the decl node has no enclosing method by definition. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
API enhancements driven by friction notes from a full stsom + absblobstore code-trace session. All changes are AST-side or daemon-side; no schema changes, no re-index required.
Tier A -- workflow / output polish
bodypromoted toquery_codebase: returns full source of every matching declaration across the codebase in one call (was 3 round-trips).calls/uses/casts/accesses_of/accesses_on): each row starts with[in TypeName.MemberName]-- collapses the common "wait, which class/method is this in?" follow-up.head_linesargument onbodyanddeclarations include_body=True: truncate each body to first N lines with a... +K more linestail.Tier B -- new modes and filters
var_typepromoted toquery_codebase: resolved type of every occurrence of NAME across the codebase.caller_of METHODmode: groups call sites by enclosing caller ([in TypeName.MemberName] (N call sites)). 53 hits -> ~18 unique-caller rows in the sample run.callee_of METHODmode: walks the named method's body and emits one row per distinct callee with invocation counts. Constructor calls reported asT (N invocations, ctor).enclosing_method=/enclosing_class=filters on every pattern mode (calls/uses/casts/accesses_of/accesses_on/all_refs). Compose as logical AND.Daemon
_run_querycatchesValueErrorfrom per-file AST dispatch so mixed-language codebase queries don't crash when one file's language doesn't implement the mode.Refactor (second commit)
_iter_call_sitesshared byq_calls/q_caller_of-- removes the text-prefix re-parsing that previously coupled the two modes._member_decl_name_node-- the field/event_field unwrap was duplicated._filter_by_enclosingline-map post-pass with nativeenclosing_method/enclosing_classkwargs on eachq_usessub-helper. One AST walk instead of two.Tests: +44 new cases. Full suite (1131 tests) green; 10x stability sweep clean.
Docs: CLAUDE.md mode table updated with new
bodysemantics,caller_of/callee_ofrows,var_typecodebase-wide note, and the enclosing-scope-filter section. MCP tool docstrings updated.Test plan
pytest tests/ query/tests/ -v-- 1131 passedcaller_ofandcallee_ofagainst real stsom files via MCPbodycodebase-wide withhead_linestruncationcallsanduses