Skip to content

Adds HaveTrait and NotHaveTrait rules#555

Open
fain182 wants to merge 9 commits intomainfrom
claude/create-rules-issue-424-2jMAP
Open

Adds HaveTrait and NotHaveTrait rules#555
fain182 wants to merge 9 commits intomainfrom
claude/create-rules-issue-424-2jMAP

Conversation

@fain182
Copy link
Collaborator

@fain182 fain182 commented Dec 27, 2025

Fixes #424

@codecov
Copy link

codecov bot commented Dec 27, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.87%. Comparing base (b8749c1) to head (817c6bf).

Additional details and impacted files
@@             Coverage Diff              @@
##               main     #555      +/-   ##
============================================
+ Coverage     97.80%   97.87%   +0.06%     
- Complexity      627      646      +19     
============================================
  Files            81       83       +2     
  Lines          1824     1884      +60     
============================================
+ Hits           1784     1844      +60     
  Misses           40       40              

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@fain182 fain182 marked this pull request as ready for review January 1, 2026 17:17
@fain182 fain182 requested a review from micheleorselli January 1, 2026 17:17
This commit implements the feature requested in issue #424, enabling
enforcement of trait usage policies across classes.

Changes:
- Extended ClassDescription to track traits used by classes
- Added getTraits() and hasTrait() methods to ClassDescription
- Updated ClassDescriptionBuilder with addTrait() method and trait tracking
- Modified FileVisitor to parse trait usage statements (TraitUse nodes)
- Implemented HaveTrait rule to require specific traits on classes
- Implemented NotHaveTrait rule to prohibit specific traits on classes
- Added comprehensive test coverage for both new rules

The implementation follows existing patterns for attribute and interface
checking, providing consistent API and behavior.

Example usage:
```php
// Require DatabaseTransactions trait on all Feature tests
Rule::allClasses()
    ->that(new ResideInOneOfTheseNamespaces('Tests\\Feature'))
    ->should(new HaveTrait(DatabaseTransactions::class))
    ->because('All Feature tests should run transactions');

// Prohibit RefreshDatabase trait for performance
Rule::allClasses()
    ->that(new ResideInOneOfTheseNamespaces('Tests\\Feature'))
    ->should(new NotHaveTrait(RefreshDatabase::class))
    ->because('Feature tests should never refresh the database');
```

All existing tests continue to pass, ensuring backward compatibility.

Fixes #424
…criptionBuilder

This commit adds comprehensive test coverage for the new trait tracking
functionality introduced in the previous commit.

Changes:
- Added test_it_should_add_traits() in ClassDescriptionBuilderTest to verify
  the addTrait() method correctly stores and retrieves traits
- Added test_should_return_true_if_has_trait() in ClassDescriptionTest to
  verify hasTrait() method with exact and wildcard pattern matching
- Added test_should_return_false_if_not_has_trait() in ClassDescriptionTest
  to verify hasTrait() returns false for non-matching traits

All tests pass (337 tests, 563 assertions). Coverage now includes:
- ClassDescriptionBuilder::addTrait()
- ClassDescription::getTraits()
- ClassDescription::hasTrait()
This commit adds comprehensive integration tests that verify the complete
workflow from parsing PHP files to validating trait usage rules.

Integration tests added:
- test_feature_tests_should_use_database_transactions_trait(): Verifies
  that classes in Tests\Feature namespace are required to use the
  DatabaseTransactions trait
- test_feature_tests_should_not_use_refresh_database_trait(): Verifies
  that classes in Tests\Feature namespace are prohibited from using the
  RefreshDatabase trait
- test_classes_with_uuid_should_have_uuid_trait(): Verifies that all
  classes in App\Models namespace use the HasUuid trait

These tests use vfsStream to create virtual PHP files and TestRunner to
execute the complete parsing and validation pipeline, ensuring that:
1. FileVisitor correctly parses trait usage from PHP code
2. ClassDescription correctly stores and retrieves traits
3. HaveTrait and NotHaveTrait rules correctly validate violations
4. The entire system works end-to-end

All tests pass (340 tests, 571 assertions).
The PHPDoc parameter annotations were not in the same order as the actual
constructor parameters. This fixes the type checking issue reported by
Scrutinizer.

Changed the order in PHPDoc from:
- , , , , ,

To match the actual constructor order:
- , , , , ,
This commit adds comprehensive documentation for the new trait rules
in the "Available rules" section of the README.

Documentation added:
- "Use a trait" section explaining the HaveTrait rule with a Laravel
  DatabaseTransactions example
- "Not use a trait" section explaining the NotHaveTrait rule with a
  Laravel RefreshDatabase example

The examples demonstrate the real-world use case from issue #424:
enforcing trait usage policies in test classes for performance and
consistency reasons.
@fain182 fain182 force-pushed the claude/create-rules-issue-424-2jMAP branch from 9ac4ff5 to 1b3da0d Compare February 8, 2026 20:12
- Remove redundant parentheses in instanceof check
- Use static function for closure in NotHaveTrait
Following the pattern from PR #561, add comprehensive tests that explicitly verify the appliesTo() method behavior for both HaveTrait and NotHaveTrait expressions:

- Add tests verifying appliesTo() returns true for regular classes
- Add tests verifying appliesTo() returns false for interfaces
- Add tests verifying appliesTo() returns false for traits
- Add tests verifying evaluate() respects appliesTo() behavior

Also fix coding standards (trailing commas) in various files.

This ensures proper test coverage and prevents the issues fixed in PR #561.
Remove trailing commas from function parameters which are only supported
in PHP 8.0+. The project supports PHP 7.4 as minimum version.

Changes:
- src/Analyzer/ClassDescription.php
- src/Analyzer/FileParser.php
- src/CLI/Runner.php
- src/Rules/ArchRule.php
- src/PHPUnit/ArchRuleCheckerConstraintAdapter.php
- tests/E2E/Cli/CheckCommandTest.php
Following the pattern from PR #561, fix the appliesTo() logic:
- Traits CAN use other traits in PHP
- Only interfaces cannot use traits
- Both HaveTrait and NotHaveTrait now apply to traits (consistent logic)

Changes:
- Update appliesTo() to only exclude interfaces
- Update evaluate() to only skip interfaces
- Update tests to verify traits are properly evaluated
- Add tests for traits using/not using other traits

This ensures the rules work correctly for all PHP class types.
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.

Add new HasTrait/NotHasTrait Rules

2 participants