Skip to content

feat(codegraph): extract call graph from Rust function bodies - #1025

Merged
TimeToBuildBob merged 2 commits into
masterfrom
codegraph-rust-call-extraction
May 30, 2026
Merged

TimeToBuildBob merged 2 commits into
masterfrom
codegraph-rust-call-extraction

Conversation

@TimeToBuildBob

Copy link
Copy Markdown
Member

Summary

  • _extract_symbols_rust built Symbol objects for function_item nodes but never populated Symbol.calls — the field was always []
  • The generic _extract_calls() already handles call_expression (the node type Rust tree-sitter uses for function calls), so the fix is adding two lines to the function_item branch
  • Adds two new tests: test_parse_rust_function_calls (verifies multiply → multiply_internal) and test_parse_rust_impl_method_calls (verifies impl methods also get calls extracted, and pure-arithmetic functions return [])

Closes

Part of #1024 (Rust call extraction). Rust import (use statement) extraction from the same issue is a follow-up.

Test plan

  • uv run --package gptme-codegraph --extra treesitter pytest packages/gptme-codegraph/tests/test_multilang.py -k rust — all 10 Rust tests pass
  • Verified multiply.calls contains "multiply_internal" after the fix

_extract_symbols_rust populated Symbol.calls as [] for every function.
The generic _extract_calls() already handles call_expression (Rust's
node type), so wiring it to the function body is a one-liner fix.

Adds tests: test_parse_rust_function_calls (multiply → multiply_internal)
and test_parse_rust_impl_method_calls (add body = no calls, with_max
has a non-empty but not-crashing calls list).

Closes part of #1024.
@greptile-apps

greptile-apps Bot commented May 30, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the long-standing gap where _extract_symbols_rust built Symbol objects for function_item nodes but always left Symbol.calls empty. The fix wires the existing _extract_calls helper into the Rust extractor by reading the function body node and passing deduped results to the Symbol constructor.

  • core.py — two lines added to the function_item branch: child_by_field_name(\"body\") retrieves the block, and _extract_calls traverses it for call_expression nodes; result is deduped with list(set(...)), mirroring the JS extraction pattern.
  • test_multilang.py — two new @_skip_no_rust tests using the next(..., None) guard pattern, one verifying \"multiply_internal\" in multiply.calls and one verifying empty calls for no-call bodies.
  • .pre-commit-config.yaml — gptme-codegraph added to the mypy exclusion list.

Confidence Score: 5/5

Safe to merge — the change is a two-line addition to an isolated Rust extractor function with no effect on Python or JS/TS extraction paths.

The fix reuses the battle-tested _extract_calls helper already used for Python and JS extractors, and the new tests properly guard against regressions. No existing behaviour is altered.

No files require special attention.

Important Files Changed

Filename Overview
packages/gptme-codegraph/src/gptme_codegraph/core.py Adds two lines to populate Symbol.calls for Rust function_item nodes via the existing _extract_calls helper; correct use of child_by_field_name("body") and deduplication with list(set(calls)).
packages/gptme-codegraph/tests/test_multilang.py Adds two new Rust call-extraction tests with proper next(..., None) guards. The impl-method test covers only the empty-calls case; a positive assertion for an impl method with actual calls is absent.
.pre-commit-config.yaml Adds gptme-codegraph to the mypy exclusion list alongside the other contrib packages that skip type checking.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["_extract_symbols_rust(root, filepath)"] --> B{node.type == function_item?}
    B -- Yes --> C["name = child_by_field_name('name')"]
    C --> D["body_node = child_by_field_name('body')"]
    D --> E{"body_node is not None?"}
    E -- Yes --> F["_extract_calls(body_node)"]
    F --> G["Walk body via cursor looking for call_expression nodes"]
    G --> H["calls.append(_text(func_node))"]
    E -- No --> I["calls = []"]
    H --> J["calls = list(set(calls))"]
    I --> J
    J --> K["Symbol(..., calls=calls)"]
    B -- No --> L["Recurse into children (impl_item passes parent_kind='impl')"]
    L --> B
Loading

Reviews (2): Last reviewed commit: "test(codegraph): improve Rust call-extra..." | Re-trigger Greptile

Comment thread packages/gptme-codegraph/tests/test_multilang.py Outdated
Comment thread packages/gptme-codegraph/tests/test_multilang.py
@codecov

codecov Bot commented May 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

- Replace bare next() with next(..., None) + assert for meaningful error
  messages when a symbol is missing
- Fix trivially-passing 'is not None' assertion on with_max to assert
  calls == [] (with_max body has no call_expression nodes)
- Exclude gptme-codegraph from mirrors-mypy hook (typecheck-packages
  already handles it; fresh pre-commit envs failed with import-not-found)

Addresses Greptile feedback on PR #1025.
@TimeToBuildBob

Copy link
Copy Markdown
Member Author

Thanks for the review!

Addressed in 112acfc:

  • bare next() → next(..., None) + assertion — both test_parse_rust_function_calls and test_parse_rust_impl_method_calls now give a clear AssertionError message (e.g. "multiply symbol not found in parse result") instead of a cryptic StopIteration
  • trivially-passing with_max.calls is not None — fixed to assert with_max.calls == []; the with_max body is self.max_value = max; self which has no call_expression nodes, so the correct assertion is an empty list
  • gptme-codegraph added to mirrors-mypy exclude list — the typecheck-packages local hook already runs mypy for the package with the correct env; the mirrors-mypy isolated venv doesn't have gptme-codegraph installed, which caused a fresh pre-commit failure when the test file was touched

@TimeToBuildBob

Copy link
Copy Markdown
Member Author

@greptileai review

@TimeToBuildBob
TimeToBuildBob merged commit 79960ad into master May 30, 2026
14 checks passed
@TimeToBuildBob
TimeToBuildBob deleted the codegraph-rust-call-extraction branch May 30, 2026 22:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant