Prevent ForbidMethodDeclaration sniff aborting on deprecated traits#36
Merged
alies-dev merged 1 commit intoJun 23, 2026
Merged
Conversation
9c652b9 to
64fbeee
Compare
is_subclass_of()/method_exists() autoload the analysed class. On PHP 8.5
the #[\Deprecated] attribute is honoured on traits, so loading a class that
uses a deprecated trait emits a deprecation ("Trait X used by Y is
deprecated"). PHP_CodeSniffer turns that into an exception, aborting the
whole file check with an Internal.Exception. Silence deprecations around the
reflection calls (they are a side effect of the analysed code, not of the
sniff) and add a regression test that fails on the leaked deprecation.
64fbeee to
4d06311
Compare
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.
Problem
On PHP 8.5 the
#[\Deprecated]attribute is now honoured on traits. Loading a class that uses a deprecated trait emits a runtime deprecation (e.g.Trait X used by Y is deprecated, ...). In PHP 8.4 the attribute on a trait was a no-op, so nothing fired.ForbidMethodDeclarationSniff::process()resolves the analysed class viais_subclass_of()/method_exists(), both of which autoload it. That autoload materialises the deprecated-trait usage, the deprecation fires, PHP_CodeSniffer turns it into an exception, and the whole file check aborts:Any class under analysis that uses a
#[\Deprecated]trait (or extends a deprecated class) hits this.Fix
The deprecation is a side effect of the analysed code, not an issue with the sniff, so the sniff must not let it abort the run. The two reflection calls are moved into a private helper that silences
E_DEPRECATED/E_USER_DEPRECATED(via a scopedset_error_handlerrestored in afinally) while resolving the class. Behaviour is otherwise identical.Tests
Added
ForbidMethodDeclarationSniffTestwith fixtures where the analysed class uses a#[\Deprecated]trait. The regression test installs its own deprecation-capturing handler around the run and asserts none leak, so it fails on the unpatched sniff (with the exact PHP 8.5 trait-deprecation message) and passes after the fix. Verified against the real IxDF-web codebase: a fullphpcsscan goes from 10Internal.Exceptionfailures to a clean run.