Problem/Motivation
In #3024341: Improve deprecation listing with filtering @jhodgdon noted that even though core coding standards (at https://www.drupal.org/core/deprecation) list a specific text structure with exact words for deprecation messages, this is not true of the overall coding standards at https://www.drupal.org/docs/develop/standards/api-documentation-and-comm... so does not apply to every Drupal project.
On the other hand we'd like to build tools on api.drupal.org (#3024341: Improve deprecation listing with filtering), testbot (#3024347: Add a mechanism to selectively enable deprecation testing per configuration) and in-site (#3024296: Add option to log deprecation errors). All of these require know-how about the deprecation version and the removal version, which is only retrievable from the code if a standard deprecation format is used. Therefore general coding standards should adopt the core coding standards to facilitate contrib updates for deprecated APIs.
@deprecated docblock format
@deprecated in %deprecation-version% and is removed from %removal-version%. %extra-info%.
@see %cr-link%
For example:
* @deprecated in drupal:8.7.0 and is removed from drupal:9.0.0. Use
* date('c', $date) instead.
*
* @see https://www.drupal.org/node/2999991
@trigger_error() format
When the trigger_error() call is associated with a matching @deprecated doc tag, the format of the text is the same as the @deprecated tag:
%thing% is deprecated in %deprecation-version% and is removed from %removal-version%. %extra-info%. See %cr-link%
Where there is no associated @deprecated doc tag, the format is more relaxed to allow flexibilty in wording:
%thing% is deprecated in %deprecation-version% (free text describing what will happen) %removal-version%. %extra-info%(optional). See %cr-link%
Deprecation example (which uses the stricter format):
@trigger_error('addDescription configuration key is deprecated in paragraphs:8.x-1.0 and is removed from paragraphs:9.x-1.0. Use add_description instead. See https://www.drupal.org/project/paragraphs/issues/2911242', E_USER_DEPRECATED);
Addition example (which uses the relaxed format):
@trigger_error('Calling Foo::__construct() without the $entity_repository argument is deprecated in drupal:8.7.0 and the $entity_repository argument will be required in drupal:9.0.0. See https://www.drupal.org/node/2549139', E_USER_DEPRECATED);
Definitions
- %thing%
- What is being deprecated - for example, the class name, method name, function name, service name or the use or optional status of a parameter
- %deprecation-version%
- The version string representing when the change occurred. For semver projects such as Drupal core - project:major.minor.patch-modifier. For contrib projects - project:drupal-major.x-minor.patch-modifier
- %removal-version%
- The version string representing when the deprecated code path will be removed. See %deprecation-version% for format
- %extra-info%
- This is free text. Useful things to include are what version the code will break in, hints on how to correct the code, or what replacement to use, etc.
- %cr-link%
- The link to the change record on drupal.org
Remaining tasks
Agree and implement #2908391: Add a rule for expected format of @deprecated and @trigger_error() textUpdate Drupal core deprecation policy https://www.drupal.org/core/deprecationFix core @deprecated via #3048498: [≈Nov. 11] Fix Drupal.Commenting.Deprecated coding standard and #3094454: Fix remaining @deprecated manually and enable the coding standard- Fix core @trigger_error via #3048495: Fix Drupal.Semantics.FunctionTriggerError coding standard
Update API documentation and comment standards https://www.drupal.org/docs/develop/standards/api-documentation-and-comm...</li>
Comments
Comment #2
gábor hojtsyComment #3
jhodgdonAdopting this standard formally would help the API module parse deprecation messages, to allow filtering on pages like
https://api.drupal.org/api/drupal/deprecated/8.6.x
so that we could filter to stuff slated to be removed in D9 vs. D10, for instance. This would be a good thing.
Also, Core has already adopted this standard.
Also, it is in line with the standard we currently have, which says what information needs to be provided, but doesn't provide a standard wording -- having a standard wording makes it easier for both humans and machines (such as the API module) to read.
All in all -- +1 from me.
Comment #4
mikelutzI fully support and endorse standardising the format of @deprecation annotations in the coding standards. Clearly our standards originate from the Symfony deprecation rules but that doesn’t explicitly formalize the message or annotation, just the use of annotations and trigger_error. Even our core deprecation documentation simply gives an example, rather than formalizing it. I would like to see explicitly something documented like:
in the coding standards so that contrib could make use of it as well.
Comment #5
gábor hojtsyWell, for contrib it would be:
Contrib does not have semver and for it to apply to both core and contrib it needs to be less strict about the version format to specify IMHO.
Comment #6
jhodgdonIs
<project>supposed to be the project short name here or the Human Readable Name? Because if it contains spaces, that makes it more difficult to parse out<project> <version>, I think?EDIT: put things that looked like HTML codes in code blocks so you can see them. Oops.
Comment #7
nickdickinsonwilde++ That'd certainly be cleaner feeling than having the same boiler plate text many many many times.
Comment #8
jhodgdonI don't understand comment #7? I think we're talking about making the same boiler-plate text appear many times...
Comment #9
mikelutzMaybe #7 was referring to #3024555: Create a static Utility method wrapper for generating deprecation messages for @trigger_error calls
Comment #10
jhodgdonPossibly, but this issue needs to keep on track for what it is about: the coding standards for the @deprecation tag message that goes into doc blocks.
Comment #11
gábor hojtsyAdding "needs announcement for final discussion" as per the process description at https://www.drupal.org/project/coding_standards
Comment #12
alexpott+1 to this proposal. I think
<project>should be the shortname. Also the think the version should be separated from the project with a colon for exampledrupal:8.7.xorparagraphs:8.x-3.xThe colon is inspired by how you required a specific version in composer - ie.
$ composer require refinery29/test-util:0.10.2Comment #13
drunken monkeyFor final discussion, this should really have an actual proposal in the IS. Do we go with #5? And is
<project>the short name, to make parsing easier? Do we want Composer syntax as per #12?But all in all, I’m +1 on this – and would defer to jhodgdon’s opinion on specifics, as it should be as reliable to parse as possible.
Since colon vs. space shouldn’t matter, I’d vote for a space, as that’s how Core is already doing it, and is better to read for humans.
Comment #14
alexpott@drunken monkey what do mean
- it the messages already? We're not using shortnames so the point is a bit moot. Also the only place version info is listed in a string like this are composer files or .info.yml files. The more future thinking solution is using the composer notation.
There's another problem. Using the docblock annotations is not really that great. There can be multiple deprecations in the a code block - ie. different arguments deprecated at different times. The thing we need a standard format for is the message in
@trigger_errorbecause these are the things we have to handle in the deprecation listener - not the doc block. Atm in the the current standard is something like:So I think we can agree that this message should be split into three parts:
So I proposed that this becomes:
So the format is (for core):
%thing% is deprecated in project:major.minor.patch-modifier and will be removed before project:major.minor.patch-modifier. %what-to-do%. See %CR link%So the format is (for contrib):
%thing% is deprecated in project:drupal-major.x-minor.patch-modifier and will be removed before project:drupal-major.x-minor.patch-modifier. %what-to-do%. See %CR link%Points to note:
%thing%can be a class name / method / function / constant / interface name / service / hook and maybe other things - we have to check they can all be followed byis%what-to-do%.can be anything - the format ofUse blah instead.is not always possible.and will be removed before project:major.minor.patch-modifierto be omitted when it is the next major version. Less boilerplate and I think if something is deprecated in 8.7.x then the fact it will not be there in 9.0.0 is not surprising.Comment #15
gábor hojtsyIf we are to modify and not just adopt the core standard then indeed we need more discussion. Why not adopt #3024555: Create a static Utility method wrapper for generating deprecation messages for @trigger_error calls right away (once it lands)? Would that be a concern of forcing a new core version for contrib that wants to follow the standard?
Comment #16
alexpottHere are examples from the standard:
@trigger_error('The concept of container scopes is deprecated since version 8.0.0 and will be removed in 9.0.0. Omit the third parameter. See https://www.drupal.org/node/2549395.', E_USER_DEPRECATED);The standard was not written with machine parsing these messages in mind. We have an aim to allow machines to parse these messages. So in order to achieve the aims of this issue we need to fix the core standard before moving it to the contrib standard - because we don't want it to change much once it is there.
As the issue summary says
Comment #17
jhodgdonIs it possible to have a dedicated function call instead of the generic trigger_error(), something like trigger_deprecation_error()?
The reason I ask is that if this was adopted, then on api.drupal.org you could look at the function calls to trigger_deprecation_error() rather than trying to parse the @deprecation tag. Or api.drupal.org could even parse out the arguments to trigger_deprecation_error() and save them somewhere -- we are already parsing out various function calls (such as to theme()) and saving parts of them, and during parsing, we have information about function arguments. But I think trigger_error() is being used for other things... or is it?
Comment #18
jhodgdonOh sorry, looks like that is the proposal in #15?
Comment #19
alexpottre #17 we can't have a method trigger the error. Because that would change where the deprecation is triggered from and the call chain is important. But we can have a method that creates the message in whatever format we agree for the @trigger_error call.
W.r.t to api.d.o parsing the annotations - one problem is the annotation allows for one deprecation message whereas there can be multiple deprecations per block of code. And different things deprecated at different times. But api.d.o could look for
@trigger_error('the message', E_USER_DEPRECATION);because that is how all deprecations are triggered.Comment #20
jhodgdonThe problem with looking for @trigger_error instead of @deprecated in the API module is that we probably have contrib modules and/or D7 and/or ??? that is using @deprecated without trigger_error. Switching to only parsing on trigger_error would probably mean we miss some?
Comment #21
alexpott@jhodgdon not only contrib - there is tonnes of @deprecated without @trigger_error in core. I think api.d.o might need to scan both :(
Comment #22
gábor hojtsy@jhodgdon: I think we should parse for more information when/if it is available, but fall back on general information if more specific is not available so:
1. look for @trigger_error() in the expected format => gather info
2. If (1) failed, look for @deprecated and fill in the missing data points with "N/A" or somesuch
Comment #23
gábor hojtsyChanging title now that we are not strictly talking about spreading core practice but changing it.
Comment #24
xjmThis issue title confused me, because I said "We've got one already". Trying to make it clearer that we're looking to improve our existing core standard to a standard that both core and contrib can use.
Comment #25
xjmJust a note that we can't always say
Use Object::method() instead.for the replacements. E.g. a recent Layout Builder fix introduced a deprecation that said:...because there was no 1:1 replacement for the thing being deprecated; you had to change your implementation beyond that in order to get the same result. The CR (linked immediately afterward) explained how.
For any standard we pick here, we should write a quick script to scan core and find examples of non-compliant deprecation messages, to validate the standard and find any usecases we're missing.
Comment #26
xjmComment #27
larowlanWe also have deprecation messages for new constructor arguments of the form
The entity_display.repository service must be passed to EntityViewBuilder::__construct(), it is required before Drupal 9.0.0.i.e no mention of 'and will be removed by'
Comment #28
alexpottComment #29
alexpottComment #30
alexpottComment #31
alexpott@larowlan brought up the issue of constructor additions in slack and the fact this format does not deal with them. I think actually this format does not generally deal with additions so we should have a format for them too. Something like:
%thing% is added in %added-version% and is required before %required-version%. %what-to-do%. See %cr-link%So for example:
I think %what-to-do% can be omitted in this instance.
[Edit: thanks @jhodgdon]
Comment #32
jhodgdonGood point, and good catch @larowlan!
Just pointing out that the format suggested in #31 still says "and will be removed" and doesn't match the example. Probably copy/pasted and then not modified from the original format?
Comment #33
alexpottNoticed an inconsistency in the summary examples too.
Comment #34
alexpottUpdating issue summary for addition standard.
Comment #35
alexpottComment #36
alexpottComment #37
alexpottComment #38
alexpott@Gábor Hojtsy pointed out in slack that:
I think 0.x is not a valid branch at least I don't think you can set that up on d.o and in semver 0.x.y has a special meaning so I've changed the example.
Yeah
E_USER_DEPRECATIONis odd for additions but it feels the best way we have to do this. In effect we are adding a deprecated code path with the addition - i.e. calling the method with a null.Thinking about this, could we handle this case with the deprecation format? Ie. instead the format could be:
@trigger_error('Calling __construct() without the $entity_repository argument is deprecated in drupal:8.7.0. See https://www.drupal.org/node/2549139', E_USER_DEPRECATED);Comment #39
mikelutzCan we just add some flexibility in the verbs? In terms of Regex, something like:
/(.*) is (deprecated|supported) in ([^:\s])+:([0-9]+\.[0-9]+\.[0-9]+) and will be (removed|required) before ([^:\s])+:([0-9]+\.0\.0)\. (.*). See (https?:\/\/.*)\./U
So
@trigger_error('Calling __construct() without the $entity_repository argument is deprecated in drupal:8.7.0. See https://www.drupal.org/node/2549139', E_USER_DEPRECATED);becomes
@trigger_error('Calling Foo::__construct() with the $entity_repository argument is supported in drupal:8.7.0 and will be required before drupal:9.0.0. Pass an implementation of /Drupal/Core/Entity/EntityRepositoryInterface as the xth argument in the Foo Constructor. See https://www.drupal.org/node/2549139', E_USER_DEPRECATED);Comment #40
alexpott@mikelutz I like the idea.
Pass an implementation of /Drupal/Core/Entity/EntityRepositoryInterface as the xth argument in the Foo Constructorfor me this repeats the first bit - ieCalling Foo::__construct() with the $entity_repository argumentand unnecessarily verbose.Comment #41
mikelutzWell, then maybe the %what to do% block is optional at committer discretion if the %thing% being deprecated/added makes %what to do% self-evident. I'm not generally opposed to verbosity in documentation, but I don't like redundancy. EntityManager stuff adds an extra layer of trickery in that it references a generic CR. Most deprecations have a dedicated CR where things can be made very clear for that explicit piece of code.
Comment #42
alexpott@mikelutz the one thing that gives me a bit of pause is that the
@deprecatedshould NOT be included for additions. So we need to extend the standard to say something like:deprecatedthe@deprecateddocblock is required.supportedthe@deprecateddocblock must be omitted.Comment #43
alexpott@mikelutz also note
(^[:\s])+:([0-9]+\.[0-9]+\.[0-9]+)only copes with the core project - it doesn't cope with contrib - ie paragraphs:8.x-1.0Comment #44
alexpottComment #45
alexpottUpdated the issue summary with the latest change to the proposal from @mikelutz
Comment #46
berdirStarting to use this for constructor additions in #3023981: Add @trigger_error() to deprecated EntityManager->EntityRepository methods, hoping it won't change too much anymore :)
This is a case that fits neither additional nor removal:
I used "must provide .. since drupal:8.7.0". Something like that might also be an option for the addition format, "is supported" sounds too weak/optional to me, but no strong feelings on that..
Comment #47
jonathan1055 commentedFixed a typo in IS introduced in #33 when "prior to" was changed to "before to"
Comment #48
mikelutzHow about:
That would support the following, according to online regex testers..
@trigger_error('Classes that use EntityTranslationRenderTrait should provide an getEntityRepository() method in drupal:8.7.0 and must do so before drupal:9.0.0. This implementation will be abstract in Drupal 9. See https://www.drupal.org/node/2549139.', E_USER_DEPRECATED);@trigger_error('Calling Foo::__construct() with the $entity_repository argument is supported in drupal:8.7.0 and will be required before drupal:9.0.0. See https://www.drupal.org/node/2549139', E_USER_DEPRECATED);@trigger_error('Foo is deprecated in paragraphs:8.x-2.3-beta4 and will be removed before paragraphs:8.x-2.4. See https://drupal.org/node/9999999.', E_USER_DEPRECATED);Comment #49
xjmI don't quite understand the intent of the use of "supported" instead of "deprecated" in these examples above. It seems confusing and magical. I don't get the binary.
Instead of :
I would have said:
I don't think we should be too strict with the regex. We want to throw a coding standards error if they omit required info (like the version, what's deprecated, the change record, what to do instead). I really think we should loosen it up to the template to allow for human words that explain things:
Comment #50
xjmAlso, it seems like maybe this "supported" stuff should be split off into its own discussion?
Comment #51
jonathan1055 commented+1 for the better message alternative in #49, it is positive and clear. Having "is supported in ... and will be required by ..." is unnecessarily confusing. By definition, when the deprecated message is seen by anyone at a specific release then the alternative will already be available at that release. So the message is redundant, and we can use the better and consistent format as suggetsed in the second code block of #49.
However, the template suggested in quotes at the end is not necessarily the best though: "will no longer be supported in" ? What was wrong with the original "will be removed before". If the thing is being removed then that is very clear that something else has to be used. "no longer supported" could be interpreted as "but use it at your own risk" as is the case with other non-supported things in software.
Comment #52
alexpottSo the bits of information we need to extract from the this string are:
We need this information so that modules can say I'm update to with drupal:8.5.0 and paragraphs:8.x-2.0 and then the test system can behave as expected
We need the version the deprecation will be removed so we can build tools to remove deprecations automatically.
The rest of the standard being proposed here is for humans so that the messages are easy to scan for the important information.
I'm +1 on using the deprecation language for additions as detailed in #49 - I proposed something similar in #38. However the latest proposal for additions splits up the
%in-version%and%before-version%which makes parsing harder and we need both.Perhaps we can use more generic language to get around this.
@trigger_error()
%thing% is deprecated in %in-version% and will not be supported in %before-version%. %what-to-do%. See %cr-link%Deprecation example:
Addition example:
Berdir's example from #46
Comment #53
jhodgdonThere is one point from #51 that is kind of important though: "will not be supported" isn't really strong enough to get across the point of "your code will not work any more because the ability to do this is going away". The examples in #52 all use the "will not be supported" phrase. Can we think of something else? Maybe "will not work" or "will break" or ... I don't really like either of those, but "support" is weak.
Comment #54
alexpottSo I'm a bit dubious about the need to parse the version that something is removed in. I think the automatic removal of deprecations is a bit of a pipe dream. So maybe thinking that way allows is to change things all around and make parsers life easier.
@trigger_error()
%thing% is deprecated in %in-version%. %extra-info%. See %cr-link%Deprecation example:
Addition example:
Berdir's example from #46
Comment #55
gábor hojtsyI certainly never dreamed about automated removal of deprecated things. It certainly makes it much easier to grep for things that you should be removing in a certain release (or testing that you did remove them) if the information is in the trigger_error(). But it was certainly not my intention to support automated removal.
The intention with that bit of information was to help focus people on working on the right things. For example, at this time it is not clear when we'll start adding deprecations with the intention to remove in Drupal 10, but acting on those for contrib is certainly not a priority to make stuff Drupal 9 compatible. We want to help contrib be Drupal 9 compatible (and contribs be compatible with new versions of other contribs as well to a lesser extent).
Being able to tell apart up to which version is your contrib compatible is only possible if we know the fails you are experiencing are not yet relevant. What are other means we can achieve the same if not information embedded in the messages?
Comment #56
alexpottFor this the key bit of information is when the deprecation occurred. I think if we do deprecated things in Drupal 8 for Drupal 10 then the deprecation message should be something like
I.e. it is a future deprecation because that reflects the reality.
And similarly for contrib pargraphs could do this in paragraphs 8.x if it wanted too...
So your contrib module could say I'm up to date with drupal:8.9.0 and paragraphs:8.x-2.0 and then these messages will not trigger a warning in tests.
Adding deprecation code for something in Drupal 8 for Drupal 10 should also be a rare occurrence too. Because it introduces more risk - we have to maintain the deprecation path in both Drupal 8 and 9.
Comment #57
gábor hojtsyBut your module is also compatible with Drupal 9.0.0, would that not trigger a warning either?
Comment #58
alexpottSaying you're update to date with deprecations is not the same as declaring compatibility. If you want to trigger Drupal 9 deprecations then you need to declare that you are up-to-date with drupal:9.0.0 and then this deprecation will be triggered for you if you use the code that triggers it.
This is the case for JSON_API - it was compatible with Drupal 8.7.x it also triggered new deprecations. So in the future it would be able to add something somewhere to say I'm up to date with drupal:8.6.0 and then the 8.7.0 deprecations would ignored when testing. Once it has handled those deprecations it could raise this to drupal:8.7.0. At that point drupal 8.9.0 might be out and JSON API would be compatible but it is likely it will be triggering deprecations for 8.8.0, 8.9.0 and maybe 9.0.0 (if those come to pass).
Comment #59
gábor hojtsyProcessing deprecations up to Drupal 8.9.0 should ideally mean that you are compatible with Drupal 8.9.0 and Drupal 9.0.0 at the same time according to our plans. What is the tool that proves that running deprecation testing with your code running on Drupal 8.9.0 and Drupal 9.0.0 will both pass? If we cannot filter out the deprecations to be removed in Drupal 10 then how will the tests pass on either branch?
How will any of the other tools (eg. a runtime deprecation logger) figure out the issues being found are irrelevant?
Comment #60
berdirAs discussed with @alexpott in slack, what he defines as "compatibility" is the same as the minimally supported core version, which is typically defined as a version dependency on the system.module (since you can't depend on drupal aka core in info.yml at the moment):
From pathauto.info.yml:
That means pathauto is "allowed" to update all things that were deprecated in drupal:8.5.0 and earlier. And it can not do anything about things deprecated in 8.6 or any later version, including drupal 9. So we should not show those deprecation messages. It will still *run* in 8.6, 8.7 (hopefully..) but it will use deprecated code and will trigger hidden deprecation messages.
At some point, pathauto will update that information say I'm compatible with ">= 8.8 || >= 9.0". that means it will not work at all on 8.7 and anything longer. And we can show all D8 deprecation messages. But if 9.0 (more likely, 9.1) will add new deprecation messages, then pathauto will need to use the deprecated code as long as it supports Drupal 8. At some point it will then update that again, for example ">= 9.2", meaning it will no longer support Drupal 8 at all and can use new API's and non-deprecated things from 9.1 and 9.2.
Whether or not pathauto *works* on Drupal 9/10/8.8 doesn't need any deprecation-message at all, either the tests pass or not. So once Drupal 9 is actually available in some version and removed the deprecated code, I can just run the tests against that because our deprecation messages will not cover every single thing anyway (e.g. deprecated constants, which only static inspection tools like phpstorm/phpstan can point out automatically). And then as we continue to release minor version for D9, deprecation messages will become more interesting again.
Wit the exception of our technical dept of things that we are only now properly deprecating and removing our own usages (entity manager, entity_* functions, db_* functions, ..), "fixing" deprecation messages has a cost (beside having to do the work, obviously): you have to increase your required core version and if you forget to do that, you will get bug reports from angry users (happened to me quite often).
Comment #61
mile23This kind of thing is the reason that we should have min/max tests, and why we should have different test targets (release vs. issue, etc) #2951375: Allow for build targets
That way you would be equipped to have a special release test that verifies your declared minimum. The workaround is to have a patch to drupalci.yml that does all the things and then run it manually, but that's still too inconvenient.
Moving forward, having a consistent deprecation format is a good idea, and the ways offered here are reasonable. But if we have a coder rule, then it will fail many years'-worth of deprecations, and it would be a lot of effort to fix those. That effort would be better spent making sure each @deprecated has a @trigger_error().
If there were a way to only ever sniff changed files, then that would be reasonable. In fact, that's what the testbot does for patches, but it always sniffs the whole project if there isn't a patch. We could probably come up with a way to alter the phpcs testbot plugin so it behaves this way.
Comment #62
gábor hojtsyI posted mocks to #3024296-18: Add option to log deprecation errors so one use case of what we are to use this data (when a deprecation is introduced and when it will be removed) is better explained. Another case where both the from and to versions would be useful is #3024341: Improve deprecation listing with filtering on api.drupal.org where you could filter the "to" version especially so you have a somewhat useful list of things deprecated for removal in Drupal 9 let's say with their docs.
Comment #63
xjm@Mile23, it's been the intent to add a coder rule for deprecation messages for years, and yes, we'll need to update existing code. But this is a good sprint task and many of them may be scriptable.
I think saying something is deprecated in Drupal 9 if we deprecated it in Drupal 8.8 is wrong. You should still kill your simpletests even if core isn't quite ready to kill it in a year. I don't see why our tooling couldn't filter the messages by the removal major version; that's the point of having a parseable format, after all. Humans will filter the message by major version, so tooling can too. It's no more difficult than parsing the version it was deprecated in -- it is, in fact, almost exactly the same.
Comment #64
drunken monkeyIf
trigger_error()calls (orDeprecationError::generate()) will be parsed in the future, would it be possible to remove@deprecatedtags in those cases where not the whole function/method is deprecated?This is currently a bit annoying, when the IDE screams “This is deprecated!” but in fact only one parameter you’re not even using is.
Comment #65
gábor hojtsyAs we have a (to me unexpected) hard time to agree on a format, I started fixing at least the current format issues that were clearly wrong according to current standards. Having them on the same standard will help a huge deal to grep and replace them with whatever new standard is to be decided. See #3033332: [META] Fix language and consistency of deprecation messages and annotations. We have so many inconsistencies now that I stopped after I reached 100k and I think it will easily go up to 200k so maybe needs to be done in chunks.
Comment #66
gábor hojtsyOk @xjm tells me I should not work on fixing any of the deprecation messages before this issue is resolved and we build a phpcs rules based on it. So since the proposed format covers the use cases people raised and is only slightly different from the core format used, let's move on with this now.
Adding "needs announcement for final discussion" as per the process description at https://www.drupal.org/project/coding_standards
Comment #67
gábor hojtsyComment #68
pfrenssenThanks everybody! This issue is in great shape for final discussion and is included in today's announcement: https://groups.drupal.org/node/534895
Depending on additional feedback from the community this will be evaluated again on or around March 20 for approval by the TWG, and if all goes well it will then be marked RTBC so it can be approved by a core maintainer.
Comment #69
jonathan1055 commentedFrom #38, #52 and #54 we appear to have broad agreement that the addition style of message should say "foo is deprecated" not the confusing "foo is supported ... and will be required in ..."
So should the issue summary proposal be updated to this? It still has the old style of message.
Comment #70
pfrenssen@jonathan1055 yes it does appear there is agreement on this, so the proposal can be updated to reflect it.
Comment #71
jonathan1055 commentedI have updated the issue summary based on the more flexible version proposed by alexpott in #54 which was
There was some subsequent discussion about the need for parsing the version that the code will break in, but there was no clear outcome on that. If that is required then the proposal would be:
For the docblock text I have changed it from
removed before %before-version%toremoved from %removal-version%. This has the benefits that (a) it tells developers that the code will break in that version (b) it is clearer than "before" because that could mean any time and any version after the in-version, which is confusing, (c) it is better grammar to remove something from a thing.Comment #72
jonathan1055 commentedRationalised the Notes into the Dedfinitions.
Comment #73
pfrenssenThe period for final discussion has concluded. Since there have been no objections this issue can now be considered to be reviewed and accepted by the community. However since this is a change that affects Drupal core this needs to be signed off by a core committer.
I am moving this to the core queue so it can be approved by the core team. If no more changes are needed this can be tagged with "Core Committer Approved" and moved back to the coding standards queue.
After this is done we can update the respective pages to publish the changed deprecation format.
Comment #74
claudiu.cristeaIn the examples provided in IS, some @trigger_error() cases are ending with dot, some not. The template
%thing% is deprecated in %in-version%. %extra-info%. See %cr-link%doesn't require a dot after%cr-link%. I think it should end with a dot because is not a docblock@seebut a human-readable phrase.Comment #75
pfrenssenIt's consistent in fact, the one example that deviates from the template is the "Doing the wrong thing example" which shows how it should _not_ be done.
Comment #76
catchOK this already has plenty of input from multiple core committers, works for me too so tagging and moving back.
Comment #77
jonathan1055 commentedHowever claudiu.cristea's observation in #74 has not be answered or fixed. The @trigger_error() template and two of the examples do not end with a dot. The third example does end with a dot. Because we know the last part of the message is a url then we do not need a dot after it. I have ammeded the 3rd example in the IS to be consistent with the others.
Comment #78
andypostDot is valid char for url path, so better remove it or use space after url https://www.w3.org/Addressing/URL/url-spec.txt
PS raised this many times, very often text editor opens a page with dot at the end of url in browser
That will affect d.org when it will went to 8.x where
node/123.leads to 404Comment #79
mile23Might want to check out how hooks are deprecated.
See: https://cgit.drupalcode.org/drupal/tree/core/lib/Drupal/Core/Extension/M...
Comment #80
pfrenssenThanks everyone for the interest and suggestions but please try to refrain from changing the proposed wording at this time. According to our procedure the text was finalized at the moment the deadline for final public discussion has expired and the ticket changed status to RTBC.
The standard has already gone through extensive discussion, and is formally approved by a core committer. If there are any important changes needed in the standard then this will need to go through the entire procedure again which will set us back by several weeks. The goal is to get this in by the time Drupalcon starts so this can be worked on at the sprints.
The standard is now considered final and will be included in its current form, except if a core committer steps in and removes the "Core Committer Approved" tag.
Comment #81
jonathan1055 commentedJust to be clear, the proposed wording has not changed since 14 March (before RTBC). Comments #77 and #78 were just making the example match the standard format.
Comment #82
gábor hojtsy@pfrenssen neither the procedure at https://www.drupal.org/project/coding_standards nor the comments above explain *who* is going to do the documentation updates to the coding standards. Based on the steps in https://www.drupal.org/project/coding_standards that seems to be the next step so it can be announced right after?
Comment #83
xjmThis can't be core-committer approved until the rule is done.
Comment #84
gábor hojtsyIf that tag is to be removed, then this does not need documentation updates. So mostly back to before #73 a week ago. Keeping RTBC since other than the coder rule this is agreed. The coder rule is apparently a pre-requisite to committer approval, which I took to update the project page process description at https://www.drupal.org/project/coding_standards. Hopefully its clear where we are in the process now, currently blocked on coder rule.
Let's get it done at #2908391: Add a rule for expected format of @deprecated and @trigger_error() text.
Comment #85
claudiu.cristeaThis is related: #2997100: Introduce a way to deprecate config schemas.
Comment #86
voleger#2908391: Add a rule for expected format of @deprecated and @trigger_error() text is committed.
Comment #87
jonathan1055 commentedThese issues are now open to fix core for the standards:
#3048495: Fix Drupal.Semantics.FunctionTriggerError coding standard
#3048498: [≈Nov. 11] Fix Drupal.Commenting.Deprecated coding standard
Comment #88
pfrenssenThe rule is implemented in Coder and has been released! We don't need to wait for core adoption to get the new standard published. @xjm, can we get the "Core committer approved" tag back?
I'll take care of updating the standard.
Comment #89
gábor hojtsy@xjm pointed out to me that somehow the trigger_error() case for where there is a matching @deprecated got different in the process. There are cases when only trigger_error() can be used, but for the case when both @deprecated and trigger_error() are to be placed, prescribing a slightly different text format for the two is painful. You cannot copy paste the text and make it pass coder.
These two:
and
The difference is
. It will be removedvs.and will be removed.I *think* this is what @xjm meant when she mentioned this in passing to me. It looks to me we better fix this because having copy-pastable messages is better than none. For this specific use case I think prescribing the exact words is better than not, since that avoids bikeshedding on each patch whether it would be
. It will be removedorand will be deletedor. Should not be used anymore startingor whatnot.Comment #90
jonathan1055 commentedHaving the text consistent is a good idea, and I raised the difference in #71. Finding a set of words which make sense regardless of whether the %thing% is a noun or a verb was the sticking point. Saying 'removed' does not work in all cases. So maybe "will not work in" or "will break in" is a general phrase that might be acceptable?
I'm happy to re-work the coder sniffs when there is agreement on the standard, that's not a problem :-)
Comment #91
gábor hojtsyWell the implied meaning of @deprecated is removed, no? Eg. IDEs will cross over the call to whatever is deprecated and tell you not to use it. So for the case where there is a @deprecated, the wording could say "removed" as the @deprecated pattern already prescribes. It is just some different English language syntax now.
Comment #92
jonathan1055 commentedOK so we seem to be heading back to requiring the %removal-version% in the @trigger_error standard text, not relying on it to be added in the %extra-info% section. It was there before, then we relaxed the wording, but I'm fine with adding it back in, and making the text copy/pasteable where a @deprecated tag and @trigger_error call are both used.
However, to allow for readable grammar when the %thing% being deprecated is an 'activity' not an 'object', such as calling a function without a parameter, we should let the @trigger_error text use "is not allowed" or "is disallowed" as an alternative to "will be removed from"
So the @deprecated standard stays exactly the same as we have now, i.e.
The @trigger_error standard would become:
%thing% is deprecated in %in-version% and will be (removed|disallowed) from %removal-version%. %extra-info%. See %cr-link%This brings up one other quesion - when we say "will be removed" this is a future-looking statement which is only factually accurate fot a short finite period of time. As soon as the %removal-version% exists the statement is inaccurate. If we used the general "is removed from" then this reads OK before the time of removal, and will remain accurate from a certain point in time forward for ever.
So my suggestions for the @deprecated tag standard is:
and the @trigger_error standard would become:
%thing% is deprecated in %in-version% and is (removed|disallowed) from %removal-version%. %extra-info%. See %cr-link%Comment #93
gábor hojtsy@jonathan1055: Why do we need to allow different text in the trigger_error() and @deprecated when they are used to signify the same thing (just for different tools: tests/runtime and static analyses)? Why do we need the trigger_error() to be (possibly) different in that case? Why do we not need that same flexibility in @deprecated then?
Comment #94
xjmYeah I have the same question as #93.
I think "is removed from" is fine.
Comment #95
alexpottWe can not always say
is removed fromin the @trigger_error() text. This has been shown in #56. Whatever standard we come up with needs to cope with all the @trigger_error use cases which are not just straight up deprecation.Comment #96
gábor hojtsyWe can prescribe the removed use case separate from the rest. The original coder issue did compare the trigger_error() and the @deprecated cases and ensured they both existed on something. One way we can bring back testing the removed use case for trigger_error() is when we find a @deprecated we match it up. Or if we cannot find a way to test that specific format (given that we need to allow for other formats), at least we can define that as the standard.
Comment #97
jonathan1055 commentedThanks alexpott, it was your comments from way back that I was catering for.
So as I suggested, if we have
is removedoris disallowedin the trigger_error standard, that would cope with all cases.[edit: cross-posted before seeing comment #96 above]
Comment #98
alexpottIt is highly likely that matching @trigger_error with @deprecated will prove very tricky as it is possible for a method to have multiple @trigger_error and 1 @deprecated - hopefully this is super rare but over time this is a very likely scenario.
@jonathan1055 I'm not a huge fan of the word
disallowed. For instance a case like:doesn't really work. I worry that we are being overly prescriptive for little to no gain. We should always value clearly written docs and instruction over a standard that makes it easier for computers to extract strings. The message for the above trigger error is clear and correct. The the argument becomes required in Drupal 9 - saying anything else means that the developer reading that has to learn new terminology.
Comment #99
gábor hojtsyWe may be able to match a @deprecated to have a trigger_error() pair with the same text though. We don't need to pair all trigger_error()s with @deprecated as per definition there will be trigger_error()s without @deprecated. The examples given in the issue summary are definitely different for the wording of trigger_error() and @deprecated for the exact same case which is wrong. We should not standardise to have different wording. If we standardise on a wording for @deprecated, we should suggest the same wording for trigger_error() for the exact same case and ideally check for it. We should not suggest and definitely not standardise on different wording for trigger_error() and @deprecated for the exact same case.
I am totally aware that trigger_error() has other use cases, all I am saying is when they are paired with a @deprecated, allowing for a different format for the two is confusing and will bound to bikeshedding the wording, when a simple copy-paste should suffice and be document by the standard even if not enforceable programatically.
Comment #100
alexpott@Gábor Hojtsy I think your comment in #99 points towards a resolution. I think what we need now a standards proposals that we can test against the requirements which seem to be something like...
The @deprecated format is:
If an @deprecated tag is present there must be a corresponding @trigger_error. The
@trigger_error()has the format%thing% is deprecated in %in-version% and will be removed from %removal-version%. %extra-info%. See %cr-link%For
@trigger_error()'s without a corresponding @deprecated tag the format is:%thing% is deprecated in %in-version% and will be VERB ADVERB %removal-version%. %extra-info%. See %cr-link%OR
%thing% is deprecated in %in-version%. %extra-info%. See %cr-link%So the above satisfies the requirement of matching text for @deprecated and @trigger_error and can possibly be enforced in the the @deprecated PHPCS check (note I don't think we can check anything about the @deprecated tag in the @trigger_error rule). The one thing to be decided is what to do about the
@trigger_error()'s without a corresponding @deprecated tag case - which is why I keep bringing it up. I'm not sure what is best because the situations where is can be use are manyfold - hence the loose%thing% is deprecated in %in-version%. %extra-info%. See %cr-link%suggestion originally arrived at.Comment #101
alexpottJust found
in web/core/lib/Drupal/Core/Entity/Sql/DefaultTableMapping.php
Unfortunately the current standard makes doing that hard.
Comment #102
gábor hojtsyYeah I meant to use the same words for when both exist :)
There is also ongoing work to display Drupal 9 compatibility information on project pages, so the more messages we can get to include machine-processable
%removal-version%the better. Then the less false positives there will be where we piss users and module maintainers off displaying there are actionable deprecations when there are none. If a sizable number of messages have no indication of when they are actionable we need to run our (static) analyses against multiple codebases which raises costs and could lead to other unintended side effects (such as where we make up our mind about deprecating something and the older set of deprecations is not a subset of the newer ones). So if we can doand will be VERB ADVERB %removal-version%that is best. We will be doing this across 8000 projects, so we need a reliable format that we can depend on since manually looking at them will not be possible on this scale.Comment #103
jonathan1055 commented@alexpott Thanks for summarising in #100 where we seem to have got to. However, you said:
I don't know if this is correct or not, but it appears to contradict @Gabor in #17 on #2908391-17: Add a rule for expected format of @deprecated and @trigger_error() text
and in #19 also from @Gabor
I'm not trying to say which is correct, just pointing out that I think I'll hold off doing any relationship checking until we get this discussed and agreed.
Comment #104
alexpott@jonathan1055 good point. Given the just-now discussions on #2847678-33: Deprecate WebTestBase and its required classes in favour of BrowserTestBase I think you and @Gábor Hojtsy are correct. So given #102 and #103 the standard could be...
The @deprecated format is:
For @trigger_error()'s the format is:
%thing% is deprecated in %in-version% and will be VERB ADVERB %removal-version%. %extra-info%. See %cr-link%If there is a corresponding @deprecated tag the
VERB ADVERBis expected to beremoved fromSo that leaves us with how to address #101. I guess one question is - Is #101 is a reasonable usage of an @deprecated tag? I can see both sides of that - on one hand the function is not deprecated - only it's scope is changing - on the other hand how to do this if you don't use @deprecated. Actually I think that helps answer the question. Since an @deprecated tag cannot differentiate how a method is called we should remove this and replace it with an @trigger_error that looks at the caller OR we create a new protected method now and do a proper deprecation.
I still think it might be worth being less prescriptive in the standard for @trigger_error and making it something like
%thing% is deprecated in %in-version% SOME TEXT %removal-version%. %extra-info%. See %cr-link%because I think we're in danger of trying to over prescribe and will end up with a standard that forces bad choices on us. I also think%extra_infoshould be optional.[Edit: to correctly attribute correctness and a word on optionality.]
Comment #105
jonathan1055 commentedI have updated the proposed standards in the issue summary to reflect the comments from #89 onwards.
Specifically where a trigger_error can be associated with a @deprecated doc tag this implies that there really is a "removal" and the more strict format is required, which will make it the same as the @deprecated text. Where no associated @deprecated tag is found, a more relaxed standard is used which allows free text to describe the nature of removal but still requires the removal version.
Secondly, as per the suggestion in #92 I have changed the future-looking 'will be removed from' to 'is removed from'. xjm and alexpott have both used this phrase in comments above.
Even if the wording is not yet finalised, it seems we have agreement on the need to have both strict and relaxed trigger_error versions depending on whether an associated @deprecated tag can be found. I have started work on this and will update #2908391: Add a rule for expected format of @deprecated and @trigger_error() text with a patch in due course, so that technical discussions can continue on that issue, so that this issue can remain focussed on agreeing the standards.
Comment #106
jonathan1055 commentedThere is a patch for review and a pull request on
https://www.drupal.org/project/coder/issues/2908391#comment-13094468
@klausi has proposed the next steps forward for this, but it would be good to get final approval on the changed standard for trigger_error which aligns it with deprecated tag for the strict cases. What is the process for getting this approved? Can we just get confirmation from key people involved here such as @gabor, @alexpott, @xjm, @pfrenssen?
Comment #107
catchComment #108
jonathan1055 commentedThanks @catch, that's good. We also now have Core using the latest coder 8.3.4 so the modified sniffs can be used on
#3048495: Fix Drupal.Semantics.FunctionTriggerError coding standard and
#3048498: [≈Nov. 11] Fix Drupal.Commenting.Deprecated coding standard
I have made the preliminary updates to the deprecation policy page https://www.drupal.org/core/deprecation so that the examples match the new agreed standard. It needs to be expanded to explain the strict vs relaxed trigger_error layout, which I can do but have not got round to that yet.
Comment #109
jonathan1055 commentedAdded remaining tasks to the I.S.
Comment #110
bojanz commentedAs a non-native speaker I found this to be puzzling, since "is removed from" tells me that the removal already occurred, but in reality we're referencing a future unreleased branch (which might not even be called the way we're documenting it, since it's not a given that the 9.x prefix will be used, but that's a different story). The "will be removed" version sounded more logical. Just my two cents.
Comment #111
jonathan1055 commentedHi bojanz, thanks for your interest, and I will try to explain.
You are right that some of the deprecation texts refer to future events, but many of the existing ones refer to past events where the deprecation has already happened. Often the most critical time for developers, when we need to know about these deprecations, is when the deprecation has just occurred (because we did not see it in advance) and something needs to be fixed. At that point, the event is already in the past.
Secondly, if the code branch referenced in the message already exists then it is not a future event, that branch is useable and the function/feature has already been removed from it.
Thirdly, any future event will become a past event in due course, hence any specific deprecation will eventually become a past event.
So we took the decision to use a form of language that is neither forward-looking nor backward-looking but just states the situation from a neutral point.
Comment #112
berdirAlso not a native speaker, and the last thing I want to do is change the message again but I also don't really understand it, also not after that explanation :)
Arguably past/present/future is relative in this context. If you are reading this message then this means that *your* present is Drupal 8 and Drupal 9 is *your* future, whether or not that has technically already been released/done. So to me, that made more sense.
But again, I care 10x more about just getting our deprecations cleaned up and ready for D9 than grammar ;)
Comment #113
jonathan1055 commentedFrom #107 Issue tags: +Core Committer Approved
From #108
I have updated https://www.drupal.org/core/deprecation#how with the details taken from the top of this issue.
#3094454: Fix remaining @deprecated manually and enable the coding standard is RTBC, then we can work on #3122186: Fix @deprecated versions and enable Commenting.Deprecated.DeprecatedVersionFormat sniff
Comment #114
atul4drupal commentedThis future looking, present looking, past looking it is getting so confusing the more I think on this...
One suggestion:
"DEPRECATION MESSAGE WILL ALWAYS MAKE SENSE FOR OLDER VERSIONS"
The deprecation message are always going to be for the old versions only (we will never have a deprecation message for a yet to release version) where in the deprecated functionality will surely be removed from some future version, whether that future version is released or not... and that future version obviously is not released when deprecation was decided!
hence to me it always make sense to say "will be removed" instead of "is removed". Even if that future version releases, it still makes sense for that old version to say 'will be removed' from some future release/version...
for this deprecation message will never be there in the version where deprecation was to be removed.
From this standpoint of the older version where deprecation happened, it is always going to be a future thing for the deprecation to be removed, so I believe and profess that:
"WILL BE REMOVED" makes more sense than using "IS REMOVED"
#110 ++
This I believe certainly needs another perspective to look at
Comment #115
atul4drupal commentedwe may have something like
OR
OR
sharing for thoughts.
Comment #116
quietone commentedI have updated the API documentation, @deprecated: Indicating deprecated functionality so it will now need a review.
Comment #117
borisson_The api documentation updates are now clear, I think this issue is done now?
Comment #118
quietone commented@borisson_, thank you!
I have updated the IS to show that all but one of the remaining tasks is complete. As per practice, I am marking this fixed because there is only one task left. That issue needs to be rerolled for 10.0.x, if anyone is looking for something to do.
Thanks everyone!
Comment #119
quietone commented@jonathan1055 let me know that I didn't update credit. I am assigning this to myself as a reminded to do that this week.
Comment #121
quietone commentedFinally got back to this. Adding credit. Let me know if it needs further changes.
Comment #122
quietone commentedOops, too late. All that work lost. I'll get some help.
Comment #123
effulgentsia commentedReopening this issue per request from @quietone.
Comment #124
quietone commentedAdding credit per How is credit granted for Drupal core issues.
Comment #125
quietone commentedCame back and I see the credit is still not granted. :-(
Comment #126
quietone commentedRight, I am not able to add credit!
I am setting this is NW only sorting out how to add credit.
Comment #127
indrapatil commentedComment #128
gábor hojtsyA coding standards maintainer like @effulgentsia could give credit :)
Comment #129
quietone commentedAssigning back to myself as a reminder to continue to work on getting the credit fixed on this issue.
Comment #130
quietone commentedLet's see if I can add credit now.
Comment #131
quietone commentedIt seems to have worked this time. I followed the How is credit granted for Drupal core issues policy.
I am restoring the Fixed status and un-assigning.
Comment #132
xjmFor posterity, we temporarily granted @quietone "maintain issues" on the coding standards project since none of the maintainers were available ensure credits. (This seemed like a reasonable compromise given the role the release managers have in helping facilitate the discussion and implementing standards like these.) Belated thanks to everyone who helped make this a reality!
Comment #133
jonathan1055 commented@quietone is doing a lot of very good work overseeing and managing coding standards both here and on slack meetings, so I'd like to recommend that they be given the "maintain issues" permission permanently.