chore: install rector with accept-current-state baseline
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>
This commit is contained in:
@@ -19,6 +19,9 @@ Design document: `/dev-docs/design-document.md`
|
||||
- `composer analyse` — Larastan static analysis at level 6 with
|
||||
accept-all baseline. New errors beyond the baseline must be fixed
|
||||
before merge. See `/dev-docs/LARASTAN.md`.
|
||||
- `composer rector` — Rector dry-run for modernisation suggestions.
|
||||
See `/dev-docs/RECTOR.md`. Apply only in scoped sprints, never
|
||||
automatically.
|
||||
|
||||
## Repository layout
|
||||
|
||||
|
||||
1
api/.gitignore
vendored
1
api/.gitignore
vendored
@@ -18,6 +18,7 @@
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/storage/app/phpstan-tmp
|
||||
/storage/app/rector-cache
|
||||
/storage/pail
|
||||
/vendor
|
||||
Homestead.json
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"spatie/laravel-permission": "^7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"driftingly/rector-laravel": "^2.0",
|
||||
"fakerphp/faker": "^1.23",
|
||||
"larastan/larastan": "^3.0",
|
||||
"laravel/pail": "^1.2.2",
|
||||
@@ -25,7 +26,8 @@
|
||||
"laravel/sail": "^1.41",
|
||||
"mockery/mockery": "^1.6",
|
||||
"nunomaduro/collision": "^8.6",
|
||||
"phpunit/phpunit": "^11.5.3"
|
||||
"phpunit/phpunit": "^11.5.3",
|
||||
"rector/rector": "^2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
@@ -59,6 +61,9 @@
|
||||
"analyse": "vendor/bin/phpstan analyse --memory-limit=2G",
|
||||
"analyse:baseline": "vendor/bin/phpstan analyse --generate-baseline --memory-limit=2G",
|
||||
"analyse:clear-cache": "vendor/bin/phpstan clear-result-cache",
|
||||
"rector": "vendor/bin/rector process --dry-run --memory-limit=2G",
|
||||
"rector:apply": "vendor/bin/rector process --memory-limit=2G",
|
||||
"rector:clear-cache": "vendor/bin/rector --clear-cache",
|
||||
"post-autoload-dump": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||
"@php artisan package:discover --ansi"
|
||||
|
||||
160
api/composer.lock
generated
160
api/composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "4c61afc38c9aea624f684146a9b0719a",
|
||||
"content-hash": "0bf117afd2eabe5e7f1c5576276666cb",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -7580,6 +7580,42 @@
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "driftingly/rector-laravel",
|
||||
"version": "2.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/driftingly/rector-laravel.git",
|
||||
"reference": "3c1c13f335b3b4d1a1f944a8ea194020044871ed"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/driftingly/rector-laravel/zipball/3c1c13f335b3b4d1a1f944a8ea194020044871ed",
|
||||
"reference": "3c1c13f335b3b4d1a1f944a8ea194020044871ed",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"rector/rector": "^2.2.7",
|
||||
"webmozart/assert": "^1.11 || ^2.0"
|
||||
},
|
||||
"type": "rector-extension",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"RectorLaravel\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Rector upgrades rules for Laravel Framework",
|
||||
"support": {
|
||||
"issues": "https://github.com/driftingly/rector-laravel/issues",
|
||||
"source": "https://github.com/driftingly/rector-laravel/tree/2.3.0"
|
||||
},
|
||||
"time": "2026-04-08T10:52:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fakerphp/faker",
|
||||
"version": "v1.24.1",
|
||||
@@ -8975,6 +9011,66 @@
|
||||
],
|
||||
"time": "2026-02-18T12:37:06+00:00"
|
||||
},
|
||||
{
|
||||
"name": "rector/rector",
|
||||
"version": "2.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/rectorphp/rector.git",
|
||||
"reference": "e645b6463c6a88ea5b44b17d3387d35a912c7946"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/e645b6463c6a88ea5b44b17d3387d35a912c7946",
|
||||
"reference": "e645b6463c6a88ea5b44b17d3387d35a912c7946",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4|^8.0",
|
||||
"phpstan/phpstan": "^2.1.48"
|
||||
},
|
||||
"conflict": {
|
||||
"rector/rector-doctrine": "*",
|
||||
"rector/rector-downgrade-php": "*",
|
||||
"rector/rector-phpunit": "*",
|
||||
"rector/rector-symfony": "*"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "To manipulate phpunit.xml via the custom-rule command"
|
||||
},
|
||||
"bin": [
|
||||
"bin/rector"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Instant Upgrade and Automated Refactoring of any PHP code",
|
||||
"homepage": "https://getrector.com/",
|
||||
"keywords": [
|
||||
"automation",
|
||||
"dev",
|
||||
"migration",
|
||||
"refactoring"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/rectorphp/rector/issues",
|
||||
"source": "https://github.com/rectorphp/rector/tree/2.4.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/tomasvotruba",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-04-16T13:07:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sebastian/cli-parser",
|
||||
"version": "3.0.2",
|
||||
@@ -10138,6 +10234,68 @@
|
||||
}
|
||||
],
|
||||
"time": "2025-11-17T20:03:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "webmozart/assert",
|
||||
"version": "2.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/webmozarts/assert.git",
|
||||
"reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/webmozarts/assert/zipball/eb0d790f735ba6cff25c683a85a1da0eadeff9e4",
|
||||
"reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-ctype": "*",
|
||||
"ext-date": "*",
|
||||
"ext-filter": "*",
|
||||
"php": "^8.2"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "",
|
||||
"ext-simplexml": "",
|
||||
"ext-spl": ""
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-feature/2-0": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Webmozart\\Assert\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Bernhard Schussek",
|
||||
"email": "bschussek@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Woody Gilk",
|
||||
"email": "woody.gilk@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Assertions to validate method input/output with nice error messages.",
|
||||
"keywords": [
|
||||
"assert",
|
||||
"check",
|
||||
"validate"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/webmozarts/assert/issues",
|
||||
"source": "https://github.com/webmozarts/assert/tree/2.3.0"
|
||||
},
|
||||
"time": "2026-04-11T10:33:05+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
||||
40
api/rector.php
Normal file
40
api/rector.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Config\RectorConfig;
|
||||
use Rector\Set\ValueObject\SetList;
|
||||
use RectorLaravel\Set\LaravelSetList;
|
||||
|
||||
return RectorConfig::configure()
|
||||
->withPaths([
|
||||
__DIR__ . '/app',
|
||||
__DIR__ . '/database',
|
||||
__DIR__ . '/tests',
|
||||
])
|
||||
->withSkip([
|
||||
__DIR__ . '/bootstrap/cache',
|
||||
__DIR__ . '/storage',
|
||||
__DIR__ . '/vendor',
|
||||
])
|
||||
// PHP language-level upgrades up to current target
|
||||
->withPhpSets(php82: true)
|
||||
|
||||
// Quality + safety rule sets (low-risk for adoption)
|
||||
->withSets([
|
||||
SetList::CODE_QUALITY,
|
||||
SetList::DEAD_CODE,
|
||||
SetList::EARLY_RETURN,
|
||||
SetList::TYPE_DECLARATION,
|
||||
SetList::PRIVATIZATION,
|
||||
])
|
||||
|
||||
// Laravel-specific rule sets
|
||||
->withSets([
|
||||
LaravelSetList::LARAVEL_CODE_QUALITY,
|
||||
LaravelSetList::LARAVEL_COLLECTION,
|
||||
])
|
||||
|
||||
->withCache(
|
||||
cacheDirectory: __DIR__ . '/storage/app/rector-cache',
|
||||
);
|
||||
@@ -886,5 +886,86 @@ baseline; volledige test suite groen.
|
||||
|
||||
---
|
||||
|
||||
## Rector application sprints
|
||||
|
||||
Rector is geïnstalleerd en geconfigureerd op PHP 8.2 + safe quality
|
||||
+ Laravel code-quality rule sets. Dry-run rapporteert **487
|
||||
rule-applications over 357 files** verdeeld over ~35 distinct rules.
|
||||
Zie `/dev-docs/RECTOR.md` voor werkmodel. Per-ruleset sprints
|
||||
hieronder — elke sprint beperkt zich tot één scope, past toe,
|
||||
verifieert tests + Larastan, regenereert waar nodig.
|
||||
|
||||
### TECH-RECTOR-01 — DEAD_CODE sprint
|
||||
|
||||
**Priority:** Middel
|
||||
**Scope:** `SetList::DEAD_CODE` over app/, database/, tests/.
|
||||
**Estimate:** Top 13 unused-variable removals via
|
||||
`RemoveUnusedVariableAssignRector`, plus verwante dead-code rules.
|
||||
Exact totaal: ~30-50 changes.
|
||||
**Completion gate:** `composer rector:apply` clean voor deze set;
|
||||
test suite groen; Larastan baseline geregenereerd en kleiner (of
|
||||
gelijk). Commit per sub-directory indien >50 wijzigingen.
|
||||
|
||||
**Approach:**
|
||||
- Tijdelijk in rector.php alleen DEAD_CODE aanzetten, andere sets
|
||||
uitcommentariseren.
|
||||
- `composer rector` om diff te reviewen voor zekerheid.
|
||||
- `composer rector:apply`.
|
||||
- `composer test` + `composer analyse`.
|
||||
- Herstel rector.php naar volledige config.
|
||||
- Commit.
|
||||
|
||||
### TECH-RECTOR-02 — TYPE_DECLARATION sprint
|
||||
|
||||
**Priority:** Middel (hoogste volume — 174+ changes)
|
||||
**Scope:** `SetList::TYPE_DECLARATION`.
|
||||
**Estimate:** ~174+ changes — top drivers:
|
||||
`AddClosureVoidReturnTypeWhereNoReturnRector` (103),
|
||||
`AddArrowFunctionReturnTypeRector` (71), plus
|
||||
`AddArrayFunctionClosureParamTypeRector` en kleinere.
|
||||
**Completion gate:** zie TECH-RECTOR-01. **Extra**: deze set lost
|
||||
waarschijnlijk veel `missingType.*` errors in Larastan baseline op —
|
||||
regenereer en commit gereduceerde phpstan-baseline.neon mee.
|
||||
|
||||
### TECH-RECTOR-03 — LARAVEL_CODE_QUALITY + LARAVEL_COLLECTION sprint
|
||||
|
||||
**Priority:** Middel
|
||||
**Scope:** `LaravelSetList::LARAVEL_CODE_QUALITY` +
|
||||
`LaravelSetList::LARAVEL_COLLECTION`.
|
||||
**Estimate:** ~80 changes — `AppToResolveRector` (51),
|
||||
`DispatchToHelperFunctionsRector` (8),
|
||||
`EloquentOrderByToLatestOrOldestRector` (7),
|
||||
`CarbonToDateFacadeRector` (4), plus collection-idioms.
|
||||
**Completion gate:** zie TECH-RECTOR-01.
|
||||
|
||||
**Approach:**
|
||||
- Splits in twee commits (één per set) als het totaal te groot is
|
||||
om in één review te laten passen.
|
||||
|
||||
### TECH-RECTOR-04 — CODE_QUALITY + EARLY_RETURN + PRIVATIZATION
|
||||
|
||||
**Priority:** Laag
|
||||
**Scope:** resterende quality-sets (~80 changes).
|
||||
**Estimate:** `ConvertStaticToSelfRector` (34),
|
||||
`ReadOnlyClassRector` (27), `ReturnBinaryOrToEarlyReturnRector` (16),
|
||||
`ClosureToArrowFunctionRector` (9), etc.
|
||||
**Completion gate:** zie TECH-RECTOR-01.
|
||||
|
||||
### TECH-RECTOR-05 — Laravel modernisation sprint
|
||||
|
||||
**Priority:** Laag
|
||||
**Scope:** review en selectief enable van
|
||||
`LaravelLevelSetList::UP_TO_LARAVEL_*` in rector.php.
|
||||
**Estimate:** onbekend tot per-set dry-runs zijn bekeken.
|
||||
**Completion gate:** per-set applicatie als gescoopte commits.
|
||||
|
||||
### TECH-RECTOR-CI — CI integration
|
||||
|
||||
**Priority:** Laag
|
||||
**Scope:** `composer rector` (dry-run) als PR-comment-surface. Apply
|
||||
blijft handmatig.
|
||||
|
||||
---
|
||||
|
||||
_Laatste update: April 2026_
|
||||
_Voeg nieuwe items toe met prefix: ARCH-, COMM-, OPS-, VOL-, ART-, FORM-, SUP-, DIFF-, APPS-, TECH-, UX-_
|
||||
|
||||
94
dev-docs/RECTOR.md
Normal file
94
dev-docs/RECTOR.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# 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
|
||||
|
||||
1. **Default workflow is dry-run.** Never run `composer rector:apply`
|
||||
outside a scoped reduction sprint. Mass-applying produces
|
||||
unreviewable PRs.
|
||||
2. **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.
|
||||
3. **Run all tests + Larastan after each apply.** Rector is
|
||||
deterministic but rule-set interactions can produce surprises
|
||||
(e.g., `TYPE_DECLARATION` may 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_QUALITY`
|
||||
- `SetList::DEAD_CODE`
|
||||
- `SetList::EARLY_RETURN`
|
||||
- `SetList::TYPE_DECLARATION`
|
||||
- `SetList::PRIVATIZATION`
|
||||
|
||||
Laravel:
|
||||
- `LaravelSetList::LARAVEL_CODE_QUALITY`
|
||||
- `LaravelSetList::LARAVEL_COLLECTION`
|
||||
|
||||
**Not yet enabled** (deferred to specific reduction sprints):
|
||||
- `LaravelLevelSetList::UP_TO_LARAVEL_*` — disruptive bulk upgrades
|
||||
- `SetList::NAMING` — reformats variable names; high churn
|
||||
- `SetList::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`:
|
||||
|
||||
```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.
|
||||
Reference in New Issue
Block a user