Installs rector/rector ^2.0 (v2.4.2) + driftingly/rector-laravel ^2.0 as dev-dependencies. Configures PHP 8.2 language sets + safe quality rule sets (CODE_QUALITY, DEAD_CODE, EARLY_RETURN, TYPE_DECLARATION, PRIVATIZATION) + Laravel-specific sets (LARAVEL_CODE_QUALITY, LARAVEL_COLLECTION). Dry-run baseline: 487 rule-applications across 357 files. NO changes applied in this commit — adoption is incremental via per- set sprints documented in BACKLOG.md. Top rules by volume: 103 AddClosureVoidReturnTypeWhereNoReturnRector 71 AddArrowFunctionReturnTypeRector 51 AppToResolveRector 34 ConvertStaticToSelfRector 27 ReadOnlyClassRector 18 NullToStrictStringFuncCallArgRector 16 ReturnBinaryOrToEarlyReturnRector 16 MakeModelAttributesAndScopesProtectedRector 13 RemoveUnusedVariableAssignRector 13 OptionalToNullsafeOperatorRector 13 FlipTypeControlToUseExclusiveTypeRector Composer scripts: - composer rector — DRY-RUN (default) - composer rector:apply — apply changes - composer rector:clear-cache — clear Rector cache Dry-run exits with code 2 when suggestions exist (Rector convention, not an error state). Apply-mode exits 0 on clean runs. Documentation: /dev-docs/RECTOR.md added; CLAUDE.md updated. Backlog: per-set application sprints seeded (TECH-RECTOR-01..05 + TECH-RECTOR-CI). DEAD_CODE (smallest scope) and TYPE_DECLARATION (biggest volume, will help reduce Larastan baseline) are the natural first two. Disruptive sets deliberately deferred: - LaravelLevelSetList::UP_TO_LARAVEL_* — broad bulk upgrades - SetList::NAMING — high-churn variable renames - SetList::INSTANCEOF — substantial logic changes Memory limit 2G (dry-run completed within it). No production behavior change. No code modified — Rector ran dry-run only. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3.0 KiB
Rector (automated refactoring)
Modernisation tool for the Crewli backend. Provides automated refactoring against PHP-version and Laravel-version rule sets.
Running locally
composer rector— DRY-RUN. Lists proposed changes, modifies nothing. Default mode for safety. Exit code is 2 when suggestions exist, 0 when the codebase is clean — this is Rector's convention and NOT an error state.composer rector:apply— APPLIES changes. Use only inside a scoped reduction sprint with a planned set of rule-applications.composer rector:clear-cache— clear Rector cache.
Memory: 2G default. Bump to 4G if OOM.
The dry-run-then-apply model
Rector configuration in rector.php defines the rule sets that
SHOULD apply. composer rector reports what WOULD change without
modifying code. composer rector:apply actually performs the
changes.
Rules
- Default workflow is dry-run. Never run
composer rector:applyoutside a scoped reduction sprint. Mass-applying produces unreviewable PRs. - One rule-set per sprint. Pick
SetList::DEAD_CODE(or similar) for one PR. Apply, review, regenerate baselines, commit. Then move to the next set. - Run all tests + Larastan after each apply. Rector is
deterministic but rule-set interactions can produce surprises
(e.g.,
TYPE_DECLARATIONmay surface new Larastan errors that were previously hidden by dynamic typing).
Currently configured rule sets
PHP language:
withPhpSets(php82: true)— language features up to PHP 8.2
Quality:
SetList::CODE_QUALITYSetList::DEAD_CODESetList::EARLY_RETURNSetList::TYPE_DECLARATIONSetList::PRIVATIZATION
Laravel:
LaravelSetList::LARAVEL_CODE_QUALITYLaravelSetList::LARAVEL_COLLECTION
Not yet enabled (deferred to specific reduction sprints):
LaravelLevelSetList::UP_TO_LARAVEL_*— disruptive bulk upgradesSetList::NAMING— reformats variable names; high churnSetList::INSTANCEOF— substantial logic changes
Add a set during a reduction sprint by editing rector.php and
running composer rector (dry-run) before applying.
Adding skip-rules
If a specific rule produces incorrect changes for the project, add
to withSkip([...]) in rector.php:
->withSkip([
SomeSpecificRule::class => [
__DIR__ . '/app/path/to/file.php',
],
])
Document the skip with a code comment in rector.php explaining
why the rule is bypassed for that path.
Relationship to Larastan
Different concerns:
- Larastan: "this code is wrong" (types, null-safety, missing methods)
- Rector: "this code can be modernised" (PHP version idioms, Laravel idioms, dead code, early-return patterns)
Both run on the same codebase. After a Rector apply-sprint, regenerate the Larastan baseline — Rector changes often resolve Larastan errors automatically.
CI integration
Not enabled yet. When added, composer rector (dry-run) becomes
a non-blocking PR comment that surfaces suggested modernisations.
Apply happens manually, never automatically in CI.