Skip to content

refactor(quality): Rector wave 4 β€” collection, dead-code, readonly gate (AID-532) - #191

Merged
abkrim merged 1 commit into
mainfrom
abdelkarim/aid-532-rector-wave-collection-deadcode
Jul 17, 2026
Merged

refactor(quality): Rector wave 4 β€” collection, dead-code, readonly gate (AID-532)#191
abkrim merged 1 commit into
mainfrom
abdelkarim/aid-532-rector-wave-collection-deadcode

Conversation

@abkrim

@abkrim abkrim commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Fourth and final wave of the original plan. 6 app/ files, 6 insertions, 20 deletions. Resized with --clear-cache first: 4 + 3 files, overlap 1, combined 6.

Collection β€” equivalence verified per site

The three toArray() β†’ all() rewrites all operate on collections of strings or plain arrays (table rows, filenames, multiselect options) β€” never Arrayable objects, where the two methods genuinely differ (toArray() recurses, all() does not). The filter(!empty) β†’ reject(empty) rewrite moves the negation into the method choice without touching the predicate.

Dead-code β€” manual review, as the ticket required

  • 2Γ— SimplifyUselessVariable: trivial $marked = ...; return $marked β†’ return ....
  • 1Γ— RemoveUnusedPrivateProperty on FirewallService: verified dead repo-wide β€” case-insensitive grep across app/, tests/, routes/, config/, database/ found zero callers of setModSecurityOutput() and the property is write-only. (A first case-sensitive grep missed the method name entirely β€” the re-check with -i is what makes the claim solid.)
  • Hand finish: Rector only empties the orphan public setter, leaving public function setModSecurityOutput(string $output): void {} β€” a silent no-op promising to store state. Its docblock says "for testing", but no test calls it. The whole method was removed in the same wave. Suite stayed green, consistent with the zero-caller finding.

The two rules deferred from PR 0 both enter the gate β€” proven on both sides

Rule Bites (probe) Safe (contra-probe)
ReadOnlyClassRector all-readonly app class β†’ rc=2 Livewire component with only readonly props β†’ rc=0 β€” a readonly class cannot extend a non-readonly parent and the rule honours it. The Filament/Livewire risk recorded at PR 0 is empirically refuted, not assumed away.
LARAVEL_TYPE_DECLARATIONS Eloquent closure without hint β†’ rc=2 (EloquentWhereTypeHintClosureParameterRector) zero-diff on the current tree; its Builder hints are the ones that help larastan

Gates

Diff shape-verified (every changed line classified, none unexplained) Β· idempotent (second pass byte-level no-op) Β· composer check-full β†’ exit 0, 1442 passed / 16 skipped, coverage 89.8% Β· refactor:dry (cleared cache) exit 0.

…te (AID-532)

Enable LARAVEL_COLLECTION, LARAVEL_TYPE_DECLARATIONS, dead-code level 50
and ReadOnlyClassRector; apply via rector with cleared cache: 6 app/
files, 6 insertions, 20 deletions.

Collection (4 sites, equivalence verified per site): the three
toArray()->all() rewrites operate on collections of strings or plain
arrays (table rows, filenames, multiselect options) β€” never Arrayable
objects, where the two methods genuinely differ. The
filter(!empty)->reject(empty) rewrite moves the negation into the method
choice without touching the predicate.

Dead-code (manual review, as the ticket required): the two
SimplifyUselessVariable hits are trivial intermediate variables. The
RemoveUnusedPrivateProperty hit on FirewallService was verified dead
repo-wide β€” case-insensitive grep across app/, tests/, routes/, config/
and database/ found zero callers of setModSecurityOutput() and the
property is write-only. Rector only empties the orphan public setter,
which would leave a silent no-op promising to store state; the empty
shell (docblock claims "for testing", but no test calls it) was removed
by hand in the same wave. The suite stayed green, consistent with the
zero-caller finding.

The two rules deferred from PR 0 both enter the gate, each proven on
both sides:
- ReadOnlyClassRector bites on an all-readonly app class (probe ->
  exit 2) and leaves a Livewire component untouched even when all its
  properties are readonly β€” a readonly class cannot extend a
  non-readonly parent and the rule honours that. The Filament/Livewire
  risk recorded at PR 0 is empirically refuted, not just assumed away.
- LARAVEL_TYPE_DECLARATIONS bites via
  EloquentWhereTypeHintClosureParameterRector (probe -> exit 2); the
  Builder hints it inserts are the ones that help larastan.

Wave checklist:
- resized with --clear-cache first: 4 + 3, overlap 1, combined 6
- diff shape-verified: every changed line classified, none unexplained
- idempotence: second rector+pint pass is a byte-level no-op
- gates: check-full green, 1442 passed / 16 skipped, coverage 89.8%,
  refactor:dry (cleared cache) exit 0

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@abkrim
abkrim merged commit fca9d22 into main Jul 17, 2026
2 checks passed
@abkrim
abkrim deleted the abdelkarim/aid-532-rector-wave-collection-deadcode branch July 17, 2026 17:31
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.

1 participant