Skip to content

fix(parser): detect Rust #[test] attribute and emit Test-kind nodes#503

Open
TimERTy wants to merge 1 commit into
tirth8205:mainfrom
TimERTy:fix/rust-test-attribute-detection
Open

fix(parser): detect Rust #[test] attribute and emit Test-kind nodes#503
TimERTy wants to merge 1 commit into
tirth8205:mainfrom
TimERTy:fix/rust-test-attribute-detection

Conversation

@TimERTy
Copy link
Copy Markdown

@TimERTy TimERTy commented May 20, 2026

Summary

Closes #502.

Rust #[test] functions were indexed as kind="Function" with is_test=False. tests_for(...) returned 0 edges for any Rust target, detect_changes flagged every test fn as untested, and test-gap counts were inflated by one per real test.

Root cause

Three compounding gaps in code_review_graph/parser.py:

  1. _extract_function doesn't read Rust attributes. Decorators are collected only for Java/Kotlin/C# (via modifiers child) and Python (via decorated_definition parent). In tree-sitter-rust, attributes are preceding siblings of function_item in the enclosing scope, not children — so decorators was always () for Rust.
  2. _TEST_ANNOTATIONS missing Rust entries. Only JUnit annotations were listed.
  3. Fixture had no #[test] fn. tests/fixtures/sample_rust.rs had zero #[test] functions and TestRustParsing never asserted on kind == "Test", so the bug shipped invisible to the suite.

Changes

  • code_review_graph/parser.py
    • In _extract_function, walk attribute_item preceding siblings when language == "rust", strip #[ ] / #![ ] wrapping, and append the inner text to deco_list.
    • Extend _TEST_ANNOTATIONS with test, tokio::test, async_std::test, rstest, rstest::rstest, proptest.
  • tests/fixtures/sample_rust.rs — add #[cfg(test)] mod tests { ... } with #[test] and #[tokio::test] functions.
  • tests/test_multilang.py::TestRustParsing — three new assertions:
    • test_detects_test_attribute#[test] fns produce kind="Test".
    • test_detects_tokio_test_attribute#[tokio::test] likewise.
    • test_non_test_functions_not_misclassified — non-annotated fns stay kind="Function", guarding against over-broad attribute matching.

Test plan

  • pytest tests/test_multilang.py::TestRustParsing -v — 8/8 pass (5 existing + 3 new).
  • pytest tests/test_multilang.py tests/test_parser.py — 406 passed, no regressions.
  • Verified on an external Rust crate (a small CLI with #[cfg(test)] mod tests in src/): before patch, 0 Test-kind nodes; after patch, every #[test] fn correctly tagged Test, every non-annotated fn (incl. a fn parse(...) helper inside the test module) stays Function.

Notes

  • Derive macros like #[derive(Debug, Clone)] get added to the decorator list too — they don't match any entry in _TEST_ANNOTATIONS, so no false positives.
  • #[cfg_attr(test, test)] and other conditional wrappers are out of scope; covered by the literal #[test] path that's overwhelmingly common.

Rust `#[test]` functions were indexed as `kind="Function"` with
`is_test=False`, so `tests_for(...)` returned 0 edges, `detect_changes`
flagged every test as untested code, and test-gap counts were inflated.

Three compounding gaps:

1. `_extract_function` only collected decorators for Java/Kotlin/C# (via
   `modifiers` child) and Python (via `decorated_definition` parent).
   Rust attributes are preceding siblings of `function_item`, not
   children, so `decorators` was always empty for Rust.
2. `_TEST_ANNOTATIONS` only contained JUnit annotations — no `test`,
   `tokio::test`, `async_std::test`, `rstest`, or `proptest`.
3. `tests/fixtures/sample_rust.rs` had zero `#[test]` functions and
   `TestRustParsing` never asserted on Test-kind nodes, so this shipped
   invisible to the test suite.

Fix:
- Walk `attribute_item` preceding siblings of `function_item`, strip
  `#[ ]` / `#![ ]`, append the inner text to `deco_list`.
- Extend `_TEST_ANNOTATIONS` with Rust built-in + common framework
  attributes.
- Add `#[test]`, `#[tokio::test]`, and a non-test fn to
  `sample_rust.rs`; assert Test-kind detection and that non-test fns
  stay Function-kind in `TestRustParsing`.

Closes tirth8205#502
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.

Rust #[test] functions indexed as Function not Test — every Rust test misclassified, no TESTED_BY edges

1 participant