Description
Is your feature request related to a problem?
There are times when a sniff gets superseded by another sniff or just isn't relevant anymore and needs to be deprecated.
In PHPCS itself, this was most recently done in PHPCS 3.3.0 for the Squiz.WhiteSpace.LanguageConstructSpacing
sniff and in PHPCS 3.4.0 for the Generic.Formatting.NoSpaceAfterCast
sniff.
It can also be said that the MySource standard + all CSS/JS sniffs are effectively deprecated as they will be removed in PHPCS 4.0.
However, deprecating sniffs is not something which is unique to PHPCS itself. External standards will also, at times, want to deprecate sniffs.
Current options for deprecating a sniff
At this moment, when deprecating a sniff, there are effectively two options:
- Soft deprecation, i.e. deprecation in name only via a mention in the changelog.
This will largely go unnoticed and end-users will be confronted with the removal in the next major. - Hard deprecation, i.e. deprecation by throwing a PHPCS warning from the sniff when the sniff is used.
This potentially breaks builds when CI is set to fail on warnings, which makes the impact of a deprecation too large for it to still be called a deprecation.
All in all, neither option is very satisfactory.
Describe the solution you'd like
Now to solve this conundrum, I'm thinking of introducing a new DeprecatedSniff
interface which extends the existing Sniff
interface and adds one additional method getDeprecationMessage()
.
interface DeprecatedSniff extends Sniff {
/**
* Retrieve an arbitrary deprecation notice.
* @return string
*/
public functon getDeprecationMessage();
}
When a sniff gets deprecated, the implements Sniff
would then be swopped out for an implements DeprecatedSniff
and the getDeprecationMessage()
method would need to be added.
final class MySniff implements DeprecatedSniff {
public function register() { ... }
public function process() { ... }
public function getDeprecationMessage() {
// Example for a sniff which is deprecated with replacement:
return 'This sniff is deprecated since [VERSION] and will be removed in [VERSION]. Use the [REPLACEMENT] sniff instead.';
// Example for a sniff which is deprecated without replacement:
return 'This sniff is deprecated since [VERSION] and will be removed in [VERSION].';
}
}
In the PHPCS framework, when the ruleset gets loaded, it could then be detected if a sniff is deprecated and all sniff deprecation messages could be collected and displayed above the report output. Similar to messages about the ruleset containing a reference to a non-existent sniff or to a property which doesn't exist.
These deprecation messages would not influence the exit code of a PHPCS run and would therefore be non-breaking.
When the -q
(quiet) option is used, these messages would also be silenced.
Opinions ?
Open questions:
- Should the
DeprecateSniff
interfaceextend Sniff
or should it be a stand-alone interface ?
A stand-alone interface would possibly allow it to be used more easily in combination with arbitrary abstract sniff classes. - Should there be just a
getDeprecationMessage()
method which allows for an arbitrary message or should the message be standardized more ?
If the message should be more standardized, this could be done by having multiple methods:getDeprecationVersion()
,getRemovalVersion()
,getReplacement()
; or by agetDeprecationInfo()
method which would expect an array with this info in three predefined keys.
/cc @kukulich @wimg @GaryJones @dingo-d @fredden @michalbundyra @stronk7
Additional Context
In a future iteration, I can imagine another interface which would allow for PHPCS natively handling the deprecation of one or more public properties in a sniff.
- I intend to create a pull request to implement this feature.