How the Graph Query Tool Handles Patterns like callers_of and tests_for in Code-Review-Graph
The graph query tool routes requests through the _QUERY_PATTERNS registry and executes specialized traversal algorithms for each query type, such as traversing CALLS edges for callers_of and combining transitive lookups with naming conventions for tests_for.
The graph query tool in the tirth8205/code-review-graph repository provides a Model-Code-Protocol (MCP) interface for running predefined queries against the code knowledge graph. It validates inputs against a central registry, resolves targets to concrete nodes using multiple resolution strategies, and dispatches to pattern-specific traversal logic. Understanding how it handles distinct patterns reveals how the system performs impact analysis and test discovery across Python, Java, and C++ codebases.
Pattern Registry and Validation
All supported query patterns are centrally defined in the _QUERY_PATTERNS dictionary located at lines 25–42 of code_review_graph/tools/query.py. This registry maps pattern names (such as callers_of and tests_for) to human-readable descriptions, driving both validation and documentation for the tool.
The public entry point query_graph_tool registered in code_review_graph/main.py at line 246 forwards client requests to the internal query_graph implementation. Before executing any traversal, query_graph validates that the requested pattern exists in _QUERY_PATTERNS (lines 56–64). If the pattern is unrecognized, the tool returns an error response listing all valid patterns.
Target Resolution Strategy
For most patterns, the tool attempts to resolve the target parameter to a concrete graph node through a multi-stage process implemented at lines 100–118:
- Direct lookup via
store.get_node - Path-based resolution for absolute file paths
- Java FQN disambiguation using
_java_fqn_candidates - General name search via
store.search_nodes
If resolution fails—and the pattern is not consumers_of or file_summary—the tool returns a "not_found" status immediately.
Pattern-Specific Traversal Logic
Once the target resolves to a qualified name or node, an if … elif chain selects the specific traversal algorithm. These algorithms utilize the GraphStore API provided by code_review_graph/graph.py to navigate relationships.
Callers of Pattern
The callers_of pattern identifies all functions that invoke the target symbol. The implementation at lines 62–70 performs the following steps:
- Iterates over edges where the target is the destination using
store.iter_edges_by_target(qn) - Filters for edges of kind
"CALLS"and deduplicates by the caller's qualified name - Adds each resolved caller node to the results
- C++ overload handling: For C++ targets, an additional pass scans edges indexed by the bare function name to handle ambiguous overloads
Tests for Pattern
The tests_for pattern locates test nodes verifying the target through a two-phase approach (lines 25–41):
- Transitive test lookup: Calls
store.get_transitive_tests(qn)to retrieve tests linked via explicitTESTSedges, marking indirect relationships withindirect: true - Naming-convention fallback: If the target is not a C++ overload set, searches for common test prefixes (
test_<name>,Test<name>). Matches found via this heuristic includeinferred_by: "naming_convention"in the result metadata
Result Processing and Output
The tool applies result limiting and formatting before returning data to the client.
Capping and Detail Levels
The max_results parameter restricts the total number of logical results, while detail_level controls presentation (lines 65–73). When set to "minimal", the output truncates the visible results list to five items and reports the count of omitted entries in results_omitted.
Response Structure
The function returns a standardized dictionary containing:
status:"ok"or error codespattern,target, and human-readabledescriptionfrom_QUERY_PATTERNSsummary: A concise textual description of the query outcomeresult_count,results_omitted, and theresultslistedges: Included only whendetail_levelis"standard"
Usage Examples
The following examples demonstrate how to invoke the graph query tool for the patterns discussed:
# Find all callers of a Python function
await mcp.run_tool(
"query_graph_tool",
pattern="callers_of",
target="my_module.my_function",
detail_level="standard",
)
# Retrieve tests for a Java class using FQN
await mcp.run_tool(
"query_graph_tool",
pattern="tests_for",
target="com.example.service.UserService",
detail_level="minimal",
)
These calls return JSON structures matching the format described above, with results containing caller or test node dictionaries.
Summary
- The graph query tool validates all requests against the
_QUERY_PATTERNSregistry incode_review_graph/tools/query.pybefore execution. - Target resolution uses a four-stage strategy including direct lookup, path resolution, Java FQN disambiguation, and name search.
- The
callers_ofpattern traverses"CALLS"edges fromstore.iter_edges_by_target()with special handling for C++ overloads. - The
tests_forpattern combinesstore.get_transitive_tests()with naming-convention heuristics to locate both explicit and inferred tests. - Results are capped by
max_resultsand filtered bydetail_level, returning standardized dictionaries with counts, summaries, and optional edge details.
Frequently Asked Questions
How does the graph query tool validate query patterns?
The tool checks the requested pattern against the _QUERY_PATTERNS dictionary defined at lines 25–42 of code_review_graph/tools/query.py. If the pattern is not found in this registry, the function returns an error listing all valid patterns (lines 56–64).
What happens if the target symbol cannot be resolved?
If the target resolution fails after attempting direct lookup, path-based search, Java FQN disambiguation, and general name search, the tool returns a "not_found" status. This applies to most patterns except consumers_of and file_summary, which may operate on unresolved targets.
How does callers_of handle C++ function overloading?
For C++ targets, the implementation performs an additional pass that scans edges indexed by the bare function name. It filters out ambiguous or unresolved overloads to ensure the returned callers actually match the specific target signature, as implemented in the pattern-specific logic at lines 62–70.
What is the difference between transitive tests and naming-convention tests in tests_for?
Transitive tests are discovered via explicit TESTS edges in the graph using store.get_transitive_tests(qn), and are marked with indirect: true when not directly connected. Naming-convention tests are found by searching for prefixes like test_<name> or Test<name> and include inferred_by: "naming_convention" metadata, indicating they were identified by heuristic rather than explicit relationship edges.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →