Fix ClassMustBeFinal final insertion for #11460#11855
Open
HenkPoley wants to merge 1 commit into
Open
Conversation
ClassMustBeFinal used a text search over the class statement snippet and treated the relative match offset as a file offset. During --alter this could insert "final" near the start of the file, such as before <?php, before a namespace/use statement, or inside leading text. This keeps the fixes intended by PR vimeo#11542: - uses an absolute file offset instead of a relative snippet offset - inserts before readonly class, producing final readonly class - avoids adding manipulations for suppressed ClassMustBeFinal issues It also fixes remaining cases not covered by PR vimeo#11542: - preserves attribute placement by inserting after attributes and before class - avoids duplicate indentation by not preserving indentation for "final " - avoids matching "class" inside docblocks or other non-declaration text The insertion point is now derived from the actual class declaration token in the snippet, then translated back to the corresponding file offset before the file manipulation is added.
This was referenced May 19, 2026
Contributor
Author
|
Hmm, the CircleCI failure is inside src/Psalm/Type/Atomic/TLiteralFloat.php; which I did not patch. Am I supposed to base my patch on top of the last non-CircleCI-failing push? |
Contributor
Author
|
Just to show how annoying this bug is with a bog standard Laravel install: composer global require laravel/installer
# Just accept the defaults to create a new Laravel project folder
laravel new barebones-laravel
cd barebones-laravel
# Add laravel-psalm to make working with Laravel's magic less annoying
composer config minimum-stability dev && composer config prefer-stable true
composer require --dev psalm/plugin-laravel:^4.*
./vendor/bin/psalm-laravel init
# So we can track what Psalm butchers
git init
git add .
git commit -m 'Initial commit'
# optional
./vendor/bin/psalm-laravel analyze
# Now muck up the PHP code with `psalter` 👇
./vendor/bin/psalter --issues=all
# Search for 'final' by typing /final
git diffExcerpts where diff --git a/app/Models/User.php b/app/Models/User.php
index 68f3a66..cfc4480 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -1,4 +1,4 @@
-<?php
+final <?php
namespace App\Models;
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 452e6b6..925a894 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -1,4 +1,4 @@
-<?php
+final <?php
namespace App\Providers;
diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php
index c4ceb07..a89da1b 100644
--- a/database/factories/UserFactory.php
+++ b/database/factories/UserFactory.php
@@ -1,6 +1,6 @@
<?php
-namespace Database\Factories;
+namespace Database\Factoriefinal s;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index 6b901f8..3af438d 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -1,4 +1,4 @@
-<?php
+final <?php
namespace Database\Seeders;
|
Contributor
Author
|
I verified that my PR still places the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ClassMustBeFinal used a text search over the class statement snippet and treated the relative match offset as a file offset. During --alter this could insert "final" near the start of the file, such as before <?php, before a namespace/use statement, or inside leading text.
The fixes implemented:
It also fixes remaining cases not covered by PR #11542:
The insertion point is now derived from the actual class declaration token in the snippet, then translated back to the corresponding file offset before the file manipulation is added. This should fix Issue #11460.
This is LLM-assisted code, GPT-5.5 Low in Codex. I did review it, and looks like it does what it should do. I see
token-get-all()is also used to (re-)parse PHP in some other gnarly spots. Further fixes of the regex code from the original PR did not seem to be a viable approach.