Skip to content

Implement rstest helper call-site collection (8.2.2)#235

Open
leynos wants to merge 24 commits into
mainfrom
8-2-2-call-site-collection-in-rstest-tests
Open

Implement rstest helper call-site collection (8.2.2)#235
leynos wants to merge 24 commits into
mainfrom
8-2-2-call-site-collection-in-rstest-tests

Conversation

@leynos

@leynos leynos commented May 28, 2026

Copy link
Copy Markdown
Owner

Summary

This branch implements roadmap task (8.2.2) for rstest_helper_should_be_fixture: passive helper call-site collection inside strict #[rstest] tests, fixture-local and constant-aware argument fingerprinting, deterministic per-callee storage, and diagnostic-silent crate-post observability.

Review feedback now addressed:

  • Method-call fingerprints include the receiver expression before explicit arguments.
  • #[case]/#[values] provider markers are read from the HIR parameter node.
  • Collection drop paths log debug-only observability without user diagnostics.
  • Collector deduplication avoids the second callee-key allocation.
  • The collection fixture runs through a Cargo-backed Dylint example harness.

Roadmap task: (8.2.2)
Execplan: docs/execplans/8-2-2-call-site-collection-in-rstest-tests.md

Review walkthrough

Validation

  • cargo check -p rstest_helper_should_be_fixture --all-targets --all-features: passed.
  • cargo nextest run -p rstest_helper_should_be_fixture --all-targets --all-features: passed, 28 tests.
  • RUSTFLAGS="-C prefer-dynamic -Z force-unstable-if-unmarked -D warnings" cargo nextest run -p rstest_helper_should_be_fixture --all-features example_compiles_without_diagnostics: passed, 2 tests.
  • make check-fmt: passed.
  • make lint: passed.
  • make typecheck: passed.
  • make test: passed, 1464 tests, 3 skipped.
  • make markdownlint: passed before this review-fix commit; no Markdown files changed in this commit.
  • make nixie: passed before this review-fix commit; no Mermaid files changed in this commit.
  • coderabbit review --agent --dir crates/rstest_helper_should_be_fixture: completed with 0 findings after earlier fixes.
  • coderabbit review --agent --dir src: completed with 0 findings.

Notes

The lint remains diagnostic-silent in this branch. Threshold aggregation and user-facing diagnostics remain assigned to roadmap items 8.2.3 and 8.2.4.

Full-scope CodeRabbit reviews repeatedly stalled after sandbox preparation or tool completion in CLI v0.5.3. Each stalled process was checked against this worktree before termination. Scoped reviews for the changed implementation areas completed cleanly; a docs-scoped review also stalled before producing stored findings.

References

@coderabbitai

coderabbitai Bot commented May 28, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Implemented passive call-site collection for rstest_helper_should_be_fixture in line with the new 8.2.2 exec plan.

  • Added a collector model for helper invocations, including deterministic per-callee storage, deduplication by callee/span location, and argument fingerprinting for fixture-local values, literals, consts, statics, and unsupported/unrecoverable cases.
  • Updated the lint driver to walk strict #[rstest] tests, gather call-site evidence without emitting diagnostics, and report crate-post collection summaries when enabled.
  • Added unit, BDD, UI, and example coverage for deduplication, ordering, span recovery, macro-only spans, and zero-diagnostic behaviour.
  • Introduced a new example-harness lock and Windows-specific environment handling to keep UI/example runs stable in CI.
  • Updated the related documentation and roadmap to describe the collector-based implementation and the new execution plan.

Walkthrough

Add passive call-site collection to rstest_helper_should_be_fixture, wire it through lint execution, expand validation coverage, adjust Windows test isolation, and update related roadmap and design docs.

Changes

Call-site collection for rstest_helper_should_be_fixture

Layer / File(s) Summary
Crate wiring and test support
crates/rstest_helper_should_be_fixture/Cargo.toml, crates/rstest_helper_should_be_fixture/src/lib.rs, common/src/test_support/mod.rs, src/testing/ui/mod.rs, src/testing/ui/tests.rs, .gitignore
Adds driver-only rustc dependencies, exposes the internal collector module, introduces scoped environment-variable guards, updates UI runner Windows environment handling and tests, and ignores .memdb/.
Collector model and lowering
crates/rstest_helper_should_be_fixture/src/collector.rs, src/hir/tests.rs, crates/rstest_helper_should_be_fixture/src/collector_tests.rs
Introduces call-site records and deduplicated storage, conservative HIR-to-fingerprint lowering, local callee resolution, and tests for span recovery, ordering, and deduplication.
Lint traversal and reporting
crates/rstest_helper_should_be_fixture/src/driver.rs
Adds collector state to the lint pass, records call-site evidence from strict #[rstest] bodies, and writes per-crate logs and optional summaries.
Validation harness and examples
crates/rstest_helper_should_be_fixture/src/collector_behaviour.rs, crates/rstest_helper_should_be_fixture/tests/features/collection.feature, crates/rstest_helper_should_be_fixture/examples/*, crates/rstest_helper_should_be_fixture/tests/ui.rs, crates/rstest_helper_should_be_fixture/tests/ui/collection_zero_diagnostic.rs, crates/rstest_helper_should_be_fixture/examples/bootstrap_zero_diagnostic.rs
Adds BDD scenarios, zero-diagnostic examples, collection-summary UI coverage, and Windows runner checks around example execution and lock recovery.
Docs
docs/roadmap.md, docs/users-guide.md, docs/developers-guide.md, docs/lints-for-rstest-fixtures-and-test-hygiene.md, docs/execplans/8-2-2-call-site-collection-in-rstest-tests.md, docs/whitaker-dylint-suite-design.md
Updates the roadmap and guide text for the collector milestone, adds the exec plan, and reformats the suite-design diagram.

Possibly related PRs

  • leynos/whitaker#224: Shares the ArgAtom/ArgFingerprint model used by the new argument-lowering logic.
  • leynos/whitaker#231: Extends the same lint crate with the collector-backed execution path and feature wiring.

Poem

A quiet lint begins to roam,
It gathers call-sites, heads for home.
With spans and keys in tidy rows,
It logs the facts as the compiler goes.
No thunder now, just careful trace,
And docs to keep the whole thing in place.

🚥 Pre-merge checks | ✅ 18 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Performance And Resource Use ⚠️ Warning FAIL: visit_expr manually visits closure bodies and still calls walk_expr, which likely walks the same nested body again, doubling work on closure-heavy tests. Return early after the manual closure-body visit, or drop it if walk_expr already descends into closures; add a regression test covering a closure-only helper call.
Concurrency And State ⚠️ Warning Poisoned shared locks are still unrecovered: windows_env_guard_test_lock and env_test_guard both unwrap lock poisoning and there is no poison-path test. Recover PoisonError with into_inner() (or equivalent) for shared test locks, and add a test that panics inside the serialised section then verifies later acquisitions still succeed.
✅ Passed checks (18 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the PR scope and includes the roadmap item reference 8.2.2.
Description check ✅ Passed The description directly describes the call-site collection work and related validation for roadmap task 8.2.2.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Testing (Overall) ✅ Passed The new collector, UI, BDD, property, example, and Windows env tests exercise the changed behaviour end-to-end and would fail on plausible regressions.
User-Facing Documentation ✅ Passed docs/users-guide.md now documents the experimental rstest_helper_should_be_fixture lint, its passive collection behaviour, config, allowed/denied cases, and fix guidance.
Developer Documentation ✅ Passed PASS: Developer guide documents EnvVarGuard and the collector boundary; design docs record 8.2.2 decisions; roadmap 8.2.2 is checked, and the execplan marks the work complete.
Module-Level Documentation ✅ Passed PASS: every touched Rust module begins with //! docs, and the docs explain purpose plus how each module fits the lint/UI harness/test support flow.
Testing (Unit And Behavioural) ✅ Passed Unit tests cover ordering, deduplication, span/error edges and invariants; behavioural scenarios hit the collector API; UI tests run the example harness end-to-end.
Testing (Property / Proof) ✅ Passed Property tests already cover the new invariants: collector insertion-order independence and config normalisation idempotence; no proof obligation is introduced.
Testing (Compile-Time / Ui) ✅ Passed Trybuild pass() coverage exists for both UI examples, and the text summary is checked with narrow redacted assertions rather than a brittle blanket snapshot.
Unit Architecture ✅ Passed PASS: env/fs/time/process dependencies are quarantined in small edge helpers and tests, while the collector and harness expose explicit Option/Result boundaries.
Domain Architecture ✅ Passed Keep the core collector domain-free; env/filesystem work stays in driver and test harness adapter code.
Observability ✅ Passed PASS: debug logs mark skip, collect and write-failure boundaries, with callee, DefId, span and fingerprint-shape context; no metrics or tracing were needed.
Security And Privacy ✅ Passed No secrets, auth gaps, or unsafe sinks appeared; env-var and summary paths are test-only, and logs/files redact payloads to shapes and counts.
Architectural Complexity And Maintainability ✅ Passed CallSiteCollector and EnvVarGuard each have a clear seam, real consumers, and docs stating their reuse boundaries; no gratuitous layer or hidden lifecycle emerged.
Rust Compiler Lint Integrity ✅ Passed PASS: The patch adds no broad lint suppressions or fake usage anchors; the only #[expect(dead_code)] is item-scoped on the non-driver stub, and the String clone is an owned dedup key.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 8-2-2-call-site-collection-in-rstest-tests

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai

sourcery-ai Bot commented May 28, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a detailed execution plan document for roadmap item 8.2.2, describing how the rstest_helper_should_be_fixture lint will collect and classify call sites in #[rstest] tests, including adapter placement, argument lowering, deduplication rules, risks, validation steps, and acceptance criteria, without changing any Rust code yet.

File-Level Changes

Change Details Files
Introduce a comprehensive ExecPlan for implementing call-site collection and argument fingerprinting for #[rstest] tests in the rstest helper lint, defining architecture, adapter placement, classification rules, deduplication policy, testing strategy, and validation gates while keeping the lint diagnostic-silent.
  • Create docs/execplans/8-2-2-call-site-collection-in-rstest-tests.md with status DRAFT and a living-document structure (constraints, tolerances, risks, progress, decision log, outcomes).
  • Specify that call-site collection will be implemented inside the rstest_helper_should_be_fixture lint crate, including a HIR-to-ArgAtom adapter, a CallSiteCollector, and LateLintPass hooks for rstest tests.
  • Define precise rules for lowering HIR expressions to ArgAtom variants (FixtureLocal, ConstLit, ConstPath, Unsupported) and for resolving local callees via LateContext using qpath_res and type_dependent_def_id.
  • Establish deduplication semantics for #[case]-generated companions using a key composed of callee DefId plus user-editable span (file and byte positions) recovered via recover_user_editable_hir_span.
  • Document constraints on scope (no diagnostics or thresholds yet), limits on API changes and dependencies, and explicit tolerances for scope, failing tests, property-test instability, and span-recovery edge cases.
  • Lay out a multi-stage implementation and validation plan covering adapter implementation, wiring into the late pass, behavioural and property tests (including rstest-bdd scenarios), documentation updates, and CI / make targets, plus acceptance criteria for marking roadmap item 8.2.2 complete.
docs/execplans/8-2-2-call-site-collection-in-rstest-tests.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@lodyai lodyai Bot changed the title Plan rstest helper call-site collection (8.2.2) Implement rstest helper call-site collection (8.2.2) Jun 4, 2026
lodyai Bot pushed a commit that referenced this pull request Jun 4, 2026
Mark the 8.2.2 execplan PR step complete after pushing the branch
and updating draft PR #235.
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 5, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response.

Code Duplication

crates/rstest_helper_should_be_fixture/src/collector_tests.rs: The module contains 2 functions with similar structure: collector_deduplicates_identical_callee_and_source_span,collector_keeps_distinct_source_spans_for_same_callee
crates/rstest_helper_should_be_fixture/src/collector_behaviour.rs: The module contains 2 functions with similar structure: given_distinct_source_calls,given_same_source_call

Why does this problem occur?

Duplicated code often leads to code that's harder to change since the same logical change has to be done in multiple functions. More duplication gives lower code health.

How to fix it?

A certain degree of duplicated code might be acceptable. The problems start when it is the same behavior that is duplicated across the functions in the module, ie. a violation of the Don't Repeat Yourself (DRY) principle. DRY violations lead to code that is changed together in predictable patterns, which is both expensive and risky. DRY violations can be identified using CodeScene's X-Ray analysis to detect clusters of change coupled functions with high code similarity. Read More
Once you have identified the similarities across functions, look to extract and encapsulate the concept that varies into its own function(s). These shared abstractions can then be re-used, which minimizes the amount of duplication and simplifies change.

Excess Number of Function Arguments

crates/rstest_helper_should_be_fixture/src/driver.rs: LateLintPass.check_fn

What lead to degradation?

LateLintPass.check_fn has 7 arguments, max arguments = 4

Why does this problem occur?

Functions with many arguments indicate either a) low cohesion where the function has too many responsibilities, or b) a missing abstraction that encapsulates those arguments.
The threshold for the Rust language is 4 function arguments.

How to fix it?

Start by investigating the responsibilities of the function. Make sure it doesn't do too many things, in which case it should be split into smaller and more cohesive functions. Consider the refactoring INTRODUCE PARAMETER OBJECT to encapsulate arguments that refer to the same logical concept.

@coderabbitai

This comment was marked as resolved.

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 15, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

Excess Number of Function Arguments

crates/rstest_helper_should_be_fixture/src/driver.rs: LateLintPass.check_fn

What lead to degradation?

LateLintPass.check_fn has 7 arguments, max arguments = 4

Why does this problem occur?

Functions with many arguments indicate either a) low cohesion where the function has too many responsibilities, or b) a missing abstraction that encapsulates those arguments.
The threshold for the Rust language is 4 function arguments.

How to fix it?

Start by investigating the responsibilities of the function. Make sure it doesn't do too many things, in which case it should be split into smaller and more cohesive functions. Consider the refactoring INTRODUCE PARAMETER OBJECT to encapsulate arguments that refer to the same logical concept.

Repository owner deleted a comment from coderabbitai Bot Jun 16, 2026
@coderabbitai

This comment was marked as resolved.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos leynos marked this pull request as ready for review June 19, 2026 18:32

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @leynos, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

leynos added a commit that referenced this pull request Jun 19, 2026
Mark the 8.2.2 execplan PR step complete after pushing the branch
and updating draft PR #235.
@leynos leynos force-pushed the 8-2-2-call-site-collection-in-rstest-tests branch from e4830a2 to a6ad47c Compare June 19, 2026 18:32
codescene-delta-analysis[bot]

This comment was marked as outdated.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6ad47c184

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/rstest_helper_should_be_fixture/src/driver.rs Outdated
Comment thread crates/rstest_helper_should_be_fixture/src/driver.rs Outdated
@coderabbitai coderabbitai Bot added the Roadmap label Jun 19, 2026
codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos

leynos commented Jun 23, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

crates/rstest_helper_should_be_fixture/src/collector.rs

Comment on lines +85 to +97

    pub(crate) const fn new(
        callee_key: String,
        file_name: FileName,
        lo: BytePos,
        hi: BytePos,
    ) -> Self {
        Self {
            callee_key,
            file_name,
            lo,
            hi,
        }
    }

❌ New issue: Code Duplication
The module contains 2 functions with similar structure: CallSiteLocation.new,DedupKey.new

@leynos

leynos commented Jun 23, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix. Include the file and symbol names indicated in the issue at the head of your response. Ensure that this is validated against the current version of the codegraph.

If further refinement to address this finding would be deleterious, please supply a clear explanatory one to two paragraph markdown message I can paste into the CodeScene web ui's diagnostic suppression function so this diagnostic can be silenced.

crates/rstest_helper_should_be_fixture/src/driver.rs

Comment on lines +193 to +203

    fn check_fn(
        &mut self,
        cx: &LateContext<'tcx>,
        _kind: hir::intravisit::FnKind<'tcx>,
        _decl: &'tcx hir::FnDecl<'tcx>,
        body: &'tcx hir::Body<'tcx>,
        _span: Span,
        def_id: LocalDefId,
    ) {
        self.collect_call_sites(cx, body, def_id);
    }

❌ New issue: Excess Number of Function Arguments
RstestHelperShouldBeFixture.check_fn has 7 arguments, max arguments = 4

@coderabbitai

This comment was marked as resolved.

codescene-delta-analysis[bot]

This comment was marked as outdated.

@coderabbitai

This comment was marked as resolved.

leynos and others added 22 commits July 5, 2026 02:33
Add a passive call-site collector for local helper invocations inside
strict `#[rstest]` tests. Lower positional arguments into the shared
argument fingerprint model, deduplicate recovered source spans, and log
collected evidence at crate-post time without emitting diagnostics.

Keep the implementation scoped to the lint crate and record the first
milestone validation and CodeRabbit review outcome in the ExecPlan.
Add behavioural, property, and trybuild pass coverage for the
rstest helper call-site collector. Record the CodeRabbit fixes and
validation results in the 8.2.2 execplan.
Add an explicit regression proving macro-only HIR spans do not
recover to user-editable source. Record the validation and
CodeRabbit review outcome in the 8.2.2 execplan.
Update user, developer, design, roadmap, and execplan docs for
the diagnostic-silent rstest helper call-site collection phase.
Record the validation and review outcomes for 8.2.2.
Mark the 8.2.2 execplan PR step complete after pushing the branch
and updating draft PR #235.
Extract shared duplicate call setup in the collector tests and
behaviour scenarios while preserving the existing assertions. Move the
`check_fn` call-site collection body into a private helper so the lint
pass method delegates cleanly.
Flatten wrapped node labels in the consumer adoption flow so `nixie`
can parse the Mermaid flowchart while preserving the documented decision
path.
Record the completed 8.2.2 collector behaviour, the follow-on test and
driver refactor, and the validation gates that now cover the current
implementation state.
Mark the 8.2.2 ExecPlan complete and record the final refactor,
validation, roadmap update, and retrospective notes so the plan matches
the implemented branch state.
Include method receivers in helper-call fingerprints and read provider attributes from rustc parameter nodes so case inputs are not mistaken for fixture locals.

Add debug logging for collection drop paths, remove redundant callee-key allocation during deduplication, expand collector test-module documentation, and move the collection fixture into a Cargo-backed Dylint example harness.
Use CallSiteLocation as the collector deduplication key instead of a separate DedupKey wrapper. This keeps the duplicate check deterministic while avoiding an extra callee-key allocation on each record insertion.
Clear `RUSTC_WRAPPER` in the Windows CI test step and in the shared
UI harness when running on Windows. `dylint_testing::Test::example`
expects bare `rustc` invocations in Cargo's JSON build output, so a
wrapper such as `sccache` prevents it from discovering the example
compiler command.

Fold the wrapper cleanup into the existing vcpkg environment guard so
both Windows-only mutations share one `env_test_guard()` lock and avoid
re-entering the process-wide environment mutex.
Keep the Windows UI-test environment adjustments active while the runner
executes, but release `env_test_guard()` before invoking the callback. This
prevents nested runner setup from deadlocking on the non-re-entrant environment
mutex while preserving the `RUSTC_WRAPPER` workaround needed by
`dylint_testing::Test::example`.
Remove the Windows CI-wide `RUSTC_WRAPPER` override so sccache remains
active for normal test work. Keep bare `rustc` handling scoped to the UI
harness, where `dylint_testing::Test::example` needs it.

Use `camino::Utf8Path` for the Windows vcpkg probe and convert it with
`as_std_path()` at the environment boundary.
Ignore `.memdb/` so local daemon state and pid files do not appear as
untracked repository changes after tool runs.
Move the `RUSTC_WRAPPER` inspection in `windows_env_guard` under
`env_test_guard` so the early no-op path observes serialized environment
state. Keep the mutex scoped to setup inspection and mutation so it is not
held across the UI runner callback.
Drive `rstest_helper_should_be_fixture` through the Dylint example harness
and assert the pass-owned collector records real call-site evidence. Treat
rstest companion functions discovered from macro-expanded HIR as eligible
collection roots so the boundary test exercises the actual driver path.

Restore trybuild compile-time smoke coverage for the rstest fixtures and add
a Windows-only harness test for scoped `RUSTC_WRAPPER` clearing. Document the
internal collection-summary hook as test-only so it is not mistaken for a
supported user-facing interface.
Redact call-site fingerprint values from normal driver debug output while
keeping shape-only summaries for test harness assertions.

Share the environment variable guard across UI tests, make collection
summary paths unique per call, and restore Windows wrapper state for both
previously set and absent `RUSTC_WRAPPER` values.

Keep companion HIR exclusion explicit while preserving macro-aware rstest
collection roots for generated test bodies.
Remove the fixed retry budget from `ExampleHarnessLock::acquire` so peer
nextest processes wait for the cross-process directory lock instead of
failing during long Windows CI example runs.

Keep the existing directory-lock design and continue releasing the lock from
`Drop` with `std::fs::remove_dir`.
Add a compile-checked `EnvVarGuard::set` example so the public test helper
shows both usage and observable effect.

Leave `RUSTC_WRAPPER` untouched when the Windows UI environment guard only
performed VCPKG setup and did not clear a wrapper value itself.
Add focused collector coverage for literal argument lowering and
unrecoverable-span handling without constructing a full rustc lint
context.

Recover abandoned example-harness lock directories after a
conservative stale threshold so crashed test processes cannot block
future runs indefinitely while legitimate Windows CI waits still
succeed.

Add shared env-var removal support and a Windows-only regression
test for the VCPKG setup path with no `RUSTC_WRAPPER`.
Make helper-call collection walk closure bodies instead of returning early,
while keeping closure call spans recoverable from the surrounding closure span.

Return I/O errors from the example harness lock path, recover stale lock races,
and bound stuck-lock waits with explicit timeout errors. Move Windows env guard
assertions into the runner callback and document the shared UI harness env and
lock conventions for future tests.
@lodyai lodyai Bot force-pushed the 8-2-2-call-site-collection-in-rstest-tests branch from b81b889 to a37bc88 Compare July 5, 2026 00:38
codescene-access[bot]

This comment was marked as outdated.

@pandalump

Copy link
Copy Markdown
Collaborator

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

Update the stale `CallSiteCollector::record` documentation example to use
`CallSiteLocation`, collapse duplicate stale-lock policy tests into a single
parameterized case, and serialize Windows environment guard tests across their
full bodies.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/rstest_helper_should_be_fixture/src/driver.rs (1)

1-462: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Split driver.rs — it looks like it exceeds the 400-line-per-file limit.

Last annotated line number in the diff context is 462, which is over the workspace's own limit ("Files must not exceed 400 lines in length — Large modules must be decomposed"). CallSiteVisitor plus the rstest-parameter/attribute conversion helpers (Lines 316-462) are a self-contained unit and a natural candidate to extract into a sibling module (e.g. visitor.rs), leaving driver.rs focused on lint-pass wiring and reporting.

As per path instructions for **/*.rs: "Files must not exceed 400 lines in length - Large modules must be decomposed."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rstest_helper_should_be_fixture/src/driver.rs` around lines 1 - 462,
`driver.rs` is over the 400-line module limit, so split out the self-contained
call-site collection and rstest helper logic into a sibling Rust module. Move
`CallSiteVisitor` and the related helpers (`rstest_parameters`,
`parameter_binding`, `parameter_attributes`, `attribute_from_hir`,
`attribute_path`, `attribute_kind`, `attribute_style`, and `redacted_*` if they
stay coupled) into a new module such as `visitor.rs`, then update
`RstestHelperShouldBeFixture` to import and use them so `driver.rs` only handles
lint wiring, config, and reporting.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/rstest_helper_should_be_fixture/src/collector.rs`:
- Around line 100-129: The doctest on CallSiteCollector::record is stale because
it still passes four arguments even though record now accepts a CallSiteRecord
and a CallSiteLocation. Update the example to construct a CallSiteLocation and
pass it as the second argument to CallSiteCollector::record, keeping the ignored
doctest aligned with the current API and using the existing CallSiteCollector,
CallSiteRecord, and CallSiteLocation symbols.

In `@crates/rstest_helper_should_be_fixture/src/driver.rs`:
- Around line 174-213: The dead companion-test guard in collect_call_sites is
never exercised because rstest_companion_tests is never populated, so remove
that early return or populate the set in check_crate and keep the existing
rstest_collection_roots gating as the source of truth. Also split driver.rs into
smaller modules to satisfy the 400-line limit, keeping collect_call_sites,
CallSiteVisitor, and related helper logic grouped by responsibility so the
module stays under the cap.

---

Outside diff comments:
In `@crates/rstest_helper_should_be_fixture/src/driver.rs`:
- Around line 1-462: `driver.rs` is over the 400-line module limit, so split out
the self-contained call-site collection and rstest helper logic into a sibling
Rust module. Move `CallSiteVisitor` and the related helpers
(`rstest_parameters`, `parameter_binding`, `parameter_attributes`,
`attribute_from_hir`, `attribute_path`, `attribute_kind`, `attribute_style`, and
`redacted_*` if they stay coupled) into a new module such as `visitor.rs`, then
update `RstestHelperShouldBeFixture` to import and use them so `driver.rs` only
handles lint wiring, config, and reporting.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4b7b9e7f-8ce0-4b23-abb6-2b07f5ce31cf

📥 Commits

Reviewing files that changed from the base of the PR and between 902d262 and a37bc88.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (22)
  • .gitignore
  • common/src/test_support/mod.rs
  • crates/rstest_helper_should_be_fixture/Cargo.toml
  • crates/rstest_helper_should_be_fixture/examples/bootstrap_zero_diagnostic.rs
  • crates/rstest_helper_should_be_fixture/examples/collection_zero_diagnostic.rs
  • crates/rstest_helper_should_be_fixture/src/collector.rs
  • crates/rstest_helper_should_be_fixture/src/collector_behaviour.rs
  • crates/rstest_helper_should_be_fixture/src/collector_tests.rs
  • crates/rstest_helper_should_be_fixture/src/driver.rs
  • crates/rstest_helper_should_be_fixture/src/lib.rs
  • crates/rstest_helper_should_be_fixture/tests/features/collection.feature
  • crates/rstest_helper_should_be_fixture/tests/ui.rs
  • crates/rstest_helper_should_be_fixture/tests/ui/collection_zero_diagnostic.rs
  • docs/developers-guide.md
  • docs/execplans/8-2-2-call-site-collection-in-rstest-tests.md
  • docs/lints-for-rstest-fixtures-and-test-hygiene.md
  • docs/roadmap.md
  • docs/users-guide.md
  • docs/whitaker-dylint-suite-design.md
  • src/hir/tests.rs
  • src/testing/ui/mod.rs
  • src/testing/ui/tests.rs

Comment thread crates/rstest_helper_should_be_fixture/src/collector.rs
Comment on lines +174 to 213
fn collect_call_sites<'tcx>(
&mut self,
cx: &LateContext<'tcx>,
body: &'tcx hir::Body<'tcx>,
def_id: LocalDefId,
) {
let hir_id = cx.tcx.local_def_id_to_hir_id(def_id);
if self.rstest_companion_tests.contains(&hir_id) {
debug!(
target: LINT_NAME,
"skipping helper call-site collection for non-rstest function: def_id={:?}",
def_id,
);
return;
}

let attrs = cx
.tcx
.hir_attrs(hir_id)
.iter()
.filter_map(attribute_from_hir)
.collect::<Vec<_>>();
if !is_rstest_test_with(&attrs, None, &self.detection_options)
&& !self.rstest_collection_roots.contains(&hir_id)
{
debug!(
target: LINT_NAME,
"skipping helper call-site collection for non-rstest function: def_id={:?}",
def_id,
);
return;
}

let parameters = rstest_parameters(cx, body);
let fixture_locals = fixture_local_names(&parameters, &self.detection_options);
let mut visitor =
CallSiteVisitor::new(cx, &mut self.collector, def_id.to_def_id(), &fixture_locals);
visitor.visit_expr(body.value);
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== all references to rstest_companion_tests =="
rg -n --type=rust 'rstest_companion_tests' crates/rstest_helper_should_be_fixture

echo
echo "== does a harness-companion collector for SYNTHESIZED functions exist? =="
rg -n --type=rust 'fn collect_harness_test_functions|fn collect_rstest_companion_test_functions' src

echo
echo "== driver.rs total line count (400-line policy check) =="
wc -l crates/rstest_helper_should_be_fixture/src/driver.rs

Repository: leynos/whitaker

Length of output: 1040


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== driver.rs around the set and the call-site collection =="
sed -n '90,230p' crates/rstest_helper_should_be_fixture/src/driver.rs

echo
echo "== src/hir/mod.rs around both collectors =="
sed -n '140,240p' src/hir/mod.rs

echo
echo "== all write sites for the companion-test set across the repo =="
rg -n --type=rust 'rstest_companion_tests\s*[.=]' .

Repository: leynos/whitaker

Length of output: 8938


Remove the dead companion-test guard and split this module

  • Populate rstest_companion_tests in check_crate or delete the field and early
    return; nothing writes to the set, so the branch never runs and the existing
    rstest_collection_roots check already excludes the same inputs.
  • Split crates/rstest_helper_should_be_fixture/src/driver.rs; it is 522 lines,
    which breaks the 400-line module limit.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rstest_helper_should_be_fixture/src/driver.rs` around lines 174 - 213,
The dead companion-test guard in collect_call_sites is never exercised because
rstest_companion_tests is never populated, so remove that early return or
populate the set in check_crate and keep the existing rstest_collection_roots
gating as the source of truth. Also split driver.rs into smaller modules to
satisfy the 400-line limit, keeping collect_call_sites, CallSiteVisitor, and
related helper logic grouped by responsibility so the module stays under the
cap.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/rstest_helper_should_be_fixture/src/collector.rs`:
- Around line 108-114: The doctest example in collector.rs is using a
non-existent CallSiteRecord field, since record.callee_key is not available on
the record type. Update the example around CallSiteLocation::new and
collector.record to use a plain callee key string/value instead of pulling
callee_key from record, so the snippet matches the actual CallSiteRecord fields
(callee_def_id, fingerprint, test_source_def_id, span) and stays consistent with
CallSiteLocation.

In `@src/testing/ui/tests.rs`:
- Around line 124-132: The Windows test serialization lock in
windows_env_guard_test_lock currently panics on poison, which causes later tests
to fail after the first panic. Update the lock acquisition in this helper to
recover from a poisoned Mutex by using poisoned.into_inner() instead of
unwrap_or_else panic, so the test suite can continue and surface the original
failure in the serial UI tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: da69928b-8e3d-4a0b-aafa-f5c0baa4189b

📥 Commits

Reviewing files that changed from the base of the PR and between a37bc88 and 1140259.

📒 Files selected for processing (3)
  • crates/rstest_helper_should_be_fixture/src/collector.rs
  • crates/rstest_helper_should_be_fixture/tests/ui.rs
  • src/testing/ui/tests.rs

Comment on lines +108 to +114
/// let location = CallSiteLocation::new(
/// record.callee_key.clone(),
/// rustc_span::FileName::Custom("src/lib.rs".to_string()),
/// rustc_span::BytePos(0),
/// rustc_span::BytePos(4),
/// );
/// let inserted = collector.record(record, location);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the doctest — record.callee_key does not exist.

The updated example reads record.callee_key.clone(), but CallSiteRecord carries only callee_def_id, fingerprint, test_source_def_id, and span. callee_key lives on CallSiteLocation, not on the record. Because the doctest is ignored, this drift compiles cleanly and slips past cargo test, just like the argument-count issue before it. Use a plain callee key string instead.

📝 Proposed fix
     /// let location = CallSiteLocation::new(
-    ///     record.callee_key.clone(),
+    ///     "crate::helper".to_string(),
     ///     rustc_span::FileName::Custom("src/lib.rs".to_string()),
     ///     rustc_span::BytePos(0),
     ///     rustc_span::BytePos(4),
     /// );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/// let location = CallSiteLocation::new(
/// record.callee_key.clone(),
/// rustc_span::FileName::Custom("src/lib.rs".to_string()),
/// rustc_span::BytePos(0),
/// rustc_span::BytePos(4),
/// );
/// let inserted = collector.record(record, location);
/// let location = CallSiteLocation::new(
/// "crate::helper".to_string(),
/// rustc_span::FileName::Custom("src/lib.rs".to_string()),
/// rustc_span::BytePos(0),
/// rustc_span::BytePos(4),
/// );
/// let inserted = collector.record(record, location);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/rstest_helper_should_be_fixture/src/collector.rs` around lines 108 -
114, The doctest example in collector.rs is using a non-existent CallSiteRecord
field, since record.callee_key is not available on the record type. Update the
example around CallSiteLocation::new and collector.record to use a plain callee
key string/value instead of pulling callee_key from record, so the snippet
matches the actual CallSiteRecord fields (callee_def_id, fingerprint,
test_source_def_id, span) and stays consistent with CallSiteLocation.

Comment thread src/testing/ui/tests.rs
Comment on lines +124 to +132
#[cfg(windows)]
fn windows_env_guard_test_lock() -> MutexGuard<'static, ()> {
// These tests inspect process-global environment state after callbacks,
// so their whole bodies must run serially rather than only each mutation.
static LOCK: OnceLock<Mutex<()>> = OnceLock::new();
LOCK.get_or_init(|| Mutex::new(()))
.lock()
.unwrap_or_else(|error| panic!("expected Windows env guard test lock: {error}"))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Inspecting the Windows test lock helper and nearby test harness code...\n'
git ls-files 'src/testing/ui/tests.rs' 'src/testing/ui/*' 'docs/*' | sed -n '1,120p'

printf '\n--- src/testing/ui/tests.rs (around the helper) ---\n'
sed -n '100,170p' src/testing/ui/tests.rs

printf '\n--- Search for similar serialisation / poison handling patterns ---\n'
rg -n "into_inner\\(|poison|Mutex<\\(\\)>|OnceLock<Mutex" src/testing -S

Repository: leynos/whitaker

Length of output: 5361


Recover the poisoned lock in src/testing/ui/tests.rs. A panic in one serial test poisons this mutex and makes later acquisitions fail in a cascade that hides the first breakage; return poisoned.into_inner() instead of panicking.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/testing/ui/tests.rs` around lines 124 - 132, The Windows test
serialization lock in windows_env_guard_test_lock currently panics on poison,
which causes later tests to fail after the first panic. Update the lock
acquisition in this helper to recover from a poisoned Mutex by using
poisoned.into_inner() instead of unwrap_or_else panic, so the test suite can
continue and surface the original failure in the serial UI tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants