Skip to content

CoversClass does not transitively target traits used by enumerations#1147

Merged
sebastianbergmann merged 1 commit intosebastianbergmann:12.5from
no-simpler:fix/enum-trait-transitive-coverage-12.5
Apr 4, 2026
Merged

CoversClass does not transitively target traits used by enumerations#1147
sebastianbergmann merged 1 commit intosebastianbergmann:12.5from
no-simpler:fix/enum-trait-transitive-coverage-12.5

Conversation

@no-simpler
Copy link
Copy Markdown
Contributor

Problem

When a class uses a trait, #[CoversClass(TheClass::class)] transitively whitelists the trait's lines for coverage. When an enum uses the same trait, the trait's lines are not whitelisted — PHPUnit flags the test as risky:

This test executed code that is not listed as code to be covered or used: …

This forces authors to add #[UsesTrait] or #[CoversTrait] to enum tests, which is inconsistent with the class behavior and creates friction with static analysis tools that don't accept those attributes.

A minimal reproduction is available at https://github.com/no-simpler/phpunit-psalm-trit-catch22 (rows 1 vs 4 in its test matrix).

Root cause

CodeUnitFindingVisitor::leaveNode() resolves trait usages only for Class_ and Trait_ nodes. Enum_ extends ClassLike (not Class_), so it is excluded by the early-return gate. Enums are correctly discovered in enterNode() via processClass(), but their trait lists are never populated.

Changes

Three one-line fixes in CodeUnitFindingVisitor:

  1. leaveNode() — include Enum_ in the gate so enums proceed to trait resolution
  2. postProcessClassOrTrait() signature — widen the type union to accept Enum_
  3. postProcessClassOrTrait() body — route Enum_ into the class branch (enums are stored in $this->classes)

Plus a regression test (testHandlesEnumUsingTrait) and fixture file mirroring the existing testHandlesTraitUsingTrait pattern.

Note: This is a copy of !1145, re-created on branch 12.5 to be able to merge as bug fix.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.21%. Comparing base (f3a1f87) to head (f6c3b9b).
⚠️ Report is 1 commits behind head on 12.5.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff            @@
##               12.5    #1147   +/-   ##
=========================================
  Coverage     88.21%   88.21%           
- Complexity     1398     1400    +2     
=========================================
  Files           105      105           
  Lines          4718     4718           
=========================================
  Hits           4162     4162           
  Misses          556      556           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sebastianbergmann sebastianbergmann merged commit 4ffbc88 into sebastianbergmann:12.5 Apr 4, 2026
20 checks passed
@no-simpler no-simpler deleted the fix/enum-trait-transitive-coverage-12.5 branch April 4, 2026 10:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants