Problem/Motivation
Splitting #1539712: [policy, no patch] Coding standards for breaking function calls and language constructs across lines as suggested #1539712-92: [policy, no patch] Coding standards for breaking function calls and language constructs across lines and agreed at a #3282227: Coding Standards Meeting 2022-06-07 2100 UTC
Option A (from PSR-12)
When declaring functions, argument lists MAY be split across multiple lines, where each subsequent line is indented once. When doing so, the first item in the list MUST be on the next line, and there MUST be only one argument per line.
When the argument list is split across multiple lines, the closing parenthesis and opening brace MUST be placed together on their own line with one space between them. When you have a return type declaration present, there MUST be one space after the colon followed by the type declaration. The colon and declaration MUST be on the same line as the argument list closing parenthesis with no spaces between the two characters.
When the argument list is split across multiple lines, the last argument in the list SHOULD use a trailing comma. Trailing commas are supported since PHP 8.0.
Option A is viewed as an improvement over status quo (Option B) for several reasons:
- improved code readability.
- cleaner, simpler diffs, patches, and git blame history.
- consistency with other non Drupal PHP projects.
- ease of adding attributes for auto-injection later.
Here is a code sample from PSR-12 (linked above) that has been adapted for Drupal's coding conventions (including the 2-space indentation and placing opening bracket on the same line as class declaration) and adds the trailing comma best practice to the last argument:
// A simple function example.
function a_very_long_function_name(
ClassTypeHint $arg1,
&$arg2,
array $arg3 = [],
) {
// function body
}
// A simple class method example.
class ClassName {
public function aVeryLongMethodName(
ClassTypeHint $arg1,
&$arg2,
array $arg3 = [],
) {
// method body
}
}
// A simple function example with return types.
function a_very_long_function_name_with_return_type(
string $foo,
string $bar,
int $baz,
): string {
return 'foo';
}
// A class method example with return types.
class ReturnTypeVariations {
public function aFunctionWithReturnType(
string $foo,
string $bar,
int $baz,
): string {
return 'foo';
}
}
Option B from #1539712-4: [policy, no patch] Coding standards for breaking function calls and language constructs across lines
Function declarations MUST be written on a single line; they should never wrap multiple lines.
Benefits
If we adopted this change, the Drupal Project would benefit by ...
Three supporters required
- jwilson3
- alex.skrypnyk
- steinmb
Proposed changes
Provide all proposed changes to the Drupal Coding standards. Give a link to each section that will be changed, and show the current text and proposed text as in the following layout:
1. Function Declarations
Current text
function funstuff_system($field) { $system["description"] = t("This module inserts funny text into posts randomly."); return $system[$field]; }Arguments with default values go at the end of the argument list. Always attempt to return a meaningful value from a function if one is appropriate.
Proposed text
function funstuff_system( string $foo, string $bar, int $baz, ) { // body }Argument lists may be split across multiple lines, where each subsequent line is indented once.
When the argument list is split across multiple lines
- The first item in the list must be on the next line.
- There must be only one argument per line.
- The last argument in the list must use a trailing comma.
- The closing parenthesis and opening brace must be placed together on their own line with one space between them.
Remaining tasks
Decide on option A or B
Option A has overwhelming support from community members in comments #5 #6 #8 #9 #10 #11 #12 #13 #14 #16.
Create this issue in the Coding Standards queue, using the defined templateList three supportersCreate a Change RecordReview by the Coding Standards CommitteeCoding Standards Committee takes action as requiredTagged with 'Needs documentation updates' if Core is not affectedDiscussed by the Core Committer Committee, if it impacts Drupal CoreDocumentation updates- Edit all pages
- Publish change record
- Remove 'Needs documentation updates' tag
If applicable, create follow-up issues for PHPCS rules/sniffs changes#3440075: Add rule for multi-line function declarations
For a fuller explanation of these steps see the Coding Standards project page
Comments
Comment #2
quietone commented#1539712-88: [policy, no patch] Coding standards for breaking function calls and language constructs across lines provides an example showing the benefits of option A in regard to __constuct() and create() functions.
Comment #3
quietone commentedComment #4
joachim commentedHow are the closing parenthesis and opening brace indented?
Could we have an example? I think that would help with understanding the proposal.
Comment #5
jwilson3+1 for option A.
The PSR-12 linked on Option A in issue summary points to several examples, and we do need to adapt these to Drupal's 2-char indentation style instead of 4-char from those examples, so here goes:
Comment #6
joachim commentedThanks!
I am very much +1 for this.
Adds to readability, and makes diff and history much easier to understand with functions with lots of parameters.
Comment #7
ressaFixing typo :-)
Comment #8
borisson_#6 also covers my feelings on this, +1 on option A
Comment #9
rivimeyI would go for option A as well... but I do find the 'just one level indent' of the args a pain. It results in the code becoming less easy to parse the function signature from the body. I much prefer a much larger indent - not necesarily as much as "to the same column as the opening (" as some formats suggest, but something like 8..12 spaces.
Option A:
Modified:
Comment #10
mondrake+1 for Option A - especially for promoted properties (PHP 8+) this greatly increases readibility of constructors.
Comment #11
longwaveAlso +1 to option A, same reasoning in my comments over in #3278431: Use PHP 8 constructor property promotion for existing code
Comment #12
steinmb commented+1. BTW are we also planning on allowing using a trailing comma?
Comment #13
joachim commented+1 to trailing commas -- though require, rather than allow.
We require them in multi-line arrays, so it would be consistent to require them here too.
Comment #14
larowlanFWIW, +1 from me on this for all of these reasons:
* readability
* consistency with other non Drupal PHP projects
* ease of adding attributes for auto-injection later
Comment #15
andypostTrailing comma is available since PHP 8.0 https://php.watch/versions/8.0/trailing-comma-parameter-use-list
Comment #16
penyaskito+1 to A+trailing comma
I'm not a fan of how it looks like, but I'll get used to it (as if you care :-P) and adopting PSR is always worth it.
Comment #17
dwwIt looks like this has overwhelming support for option A. We need to update the summary with examples, including proposed changes to docs.
Otherwise, I think this is ready for public announcement and to finalize the steps to get it adopted.
Comment #18
jwilson3How about this for an update. I took the code examples from #5 and added trailing comma to last arg.
Comment #19
jwilson3Added #14 to issue summary.
Comment #20
jwilson3Comment #21
jwilson3whitespace fix in code sample.
Comment #22
arkener commented+1 to option A with required trailing commas.
Comment #23
jwilson3I removed the "Needs issue summary update" but forgot to set the status back to NR.
Comment #24
longwaveThe issue summary looks good to me, and the issue has been open for 9 months with no disagreement so I think this is ready to move to RTBC.
Comment #25
steinmb commented2.0.0 is out from https://github.com/php-fig/per-coding-style/releases/tag/2.0.0
Comment #26
dwwIndeed, and https://github.com/php-fig/per-coding-style/blob/2.0.0/spec.md#45-method... includes:
🎉 We do a few things differently (e.g. 2 spaces for indent, the
{on class declarations, etc), but otherwise, this is exactly what we're proposing. Ship it! 😉Comment #27
jwilson3I added this blurb to the IS. I noticed it before but thanks for catching this to be more explicit.
Comment #28
jwilson3mention Drupal's coding conventions that explicitly differ from PSR-12 in IS
Comment #29
jwilson3🤦♂️
Comment #30
alex.skrypnyk+1 on Option A
Comment #31
larowlanDraft CR
Comment #32
quietone commentedAdding new template as best I can.
Comment #33
quietone commentedAs I reviewed this I realized that there are outstanding issues for two of the changes here. There are #1795750: Revise coding standards to use IETF RFC 2119 standards and #2928856: Adopt the PSR-12 standard for PHP return types. Because of the I have removed those changes and am tagging for a change record update.
I also removed repeated text and used a list format. That is what I see in the existing standards.
Comment #34
quietone commentedSetting to Needs Review so the doc changes can be reviewed and then the CR updated.
Comment #35
larowlanLooks good, I'll update the CR
Comment #36
murzI created a similar improvement to allow multi-line conditions: #3392321: Relax the "Conditions should not be wrapped into multiple lines" rule for more code readability - please support it too ;)
Comment #37
andypostRTBC++
Comment #38
catch+1 from me, and the CR looks good (and easier to read than the version in the issue summary).
Comment #39
aaronmchale+1, agree with everything here, supporting Option A.
Comment #40
larowlanThis was discussed at the coding standards committee meeting and @dww, @bbrala, @AaronMcHale and myself were +1.
I think this needs to go out in an announcement now.
Comment #41
quietone commentedThis is tagged for change record updates which I think should be done before the announcement. Have they been done?
Comment #42
catchLooks to me like they were done? https://www.drupal.org/node/3396762/revisions/view/13284559/13286250 but I'm not 100% confident those were the same changes you tagged for, so leaving the tag on...
Comment #43
jonathan1055 commentedI made a minor change to proposed text, to swap the last two bullet points around. Logically it makes sense to talk about the final item in the list before talking about the closing parenthesis and opening brace.
I also notice that the following text has been dropped from the existing standard
Was this by accident? Is the order of arguments still important? I think it is, and that first sentence should be added back.
I know this is RTBC and these changes should not impact the upcoming blog post. Its just the details of the wording, we all agree that the new standard will go ahead.
Comment #44
catchI think this is already enforced somewhere - maybe phpstan? I'm not sure it is really coding style as such, feels like an actual bug if optional arguments aren't at the end.
Comment #45
darvanenPretty sure it's a 500 error in PHP 8.1
Comment #46
mondrakeIt’s deprecated since 8.0.0, https://3v4l.org/JPtv7
Comment #47
larowlanThis was discussed at core committers meeting on Wed December 5th (UTC)
There were no objections
Completing steps 6 and 7.
Next step is the documentation edits and core issue for phpcs rule (which may be a case of relaxing a rule in this instance).
Comment #48
nigelcunningham commentedI know it's too late now but trailing commas are ugly, unnecessary extra work for the parser and only useful when you're adding another arg later on. They should be removed from the array requirement, not added elsewhere!
Comment #49
jonathan1055 commentedHi Nigel Cunningham,
Yes you are right that it is a bit late, we have completed step 7 out of 9 and we have 29 followers on the issue and no disagreement on the standard as proposed. Thank you for making the suggestion, everyone's input is appreciated and hopefully you will take part in other Coding Standards issues, there are plenty more that need discussion and agreements. But this one is pretty much done and dusted :-)
Jonathan
Comment #50
quietone commentedThere are already instance of this in core, for example, mstrelan pointed out in Slack, \Drupal\Core\Extension\DatabaseDriver::__construct
Comment #51
dwwThat (and many like it) don't adhere to the standard we're laying out:
Current:
Per above "must" statements (3rd and 4th bullets), this should become:
Don't we want a sniff about that? If this is our standard, we should adopt it core-wide and have our tooling enforce it. I presume a sniff that would flag this could be configured to ignore single line function declarations, right?
Comment #52
jonathan1055 commentedThanks @dww, that's useful info. But writing sniffs, or finding existing ones to include, will be covered in step 9 of the process. That does not hinder the progress of getting the standard updated. Is that right?
[edit: core/phpcs.xml.dist has
Squiz.Functions.MultiLineFunctionDeclaration11.x/core/phpcs.xml.dist?ref_type=heads#L393-409 but checking and testing of these options will be done in a separate issue]
Currently we are at step 8 "Needs documentation updates". I can see there was a Slack thread on this at the meeting. If everything is agreed, can we proceed to update the docs?
Comment #53
quietone commentedI have made the edit to the doc page and published the CR
Comment #54
quietone commentedForgot to remove the tag.
Who can followup with issues for Code etc.
Comment #55
cmlaraShould this be marked as Fixed per the step 8 procedures or left open because step 9 work is needed?
Comment #56
dwwYeah, we need to open the follow-up now to:
Only once that exists and is linked here can we fully close this one out.
Thanks,
-Derek
Comment #57
quietone commentedThe sniff is
Squiz.Functions.MultiLineFunctionDeclarationbut I can find no documentation for it.Core is using that sniff
I tested by changing \Drupal\Core\DrupalKernel::handleException to
I then ran the commit-code-checks and there were no errors. So, Coder is not preventing using this new standard.
I changed to incorrect indentation as shown.
And tested again and this passes phpcs.
I then remove this rule
And tested again. This time the indentation error was found. However, phpcs reports heaps of other errors in core. The ones I checked had correct indentation. Plus it was reporting errors from
sniffSquiz.Functions.MultiLineFunctionDeclaration.BraceOnSameLinewhich was not changed. That seems wrong.Comment #58
quietone commentedCreated Coder issue, #3440075: Add rule for multi-line function declarations
Comment #59
quietone commentedComment #60
klausiThis was implemented in Coder, only the trailing comma rule is missing for now. Opened #3440603: Validate trailing comma in multi-line function declaration for that.
Comment #61
jonathan1055 commentedKlausi has released coder 8.3.24
https://www.drupal.org/project/coder/releases/8.3.24
This includes both the initial #3440075: Add rule for multi-line function declarations and the follow-up #3440603: Validate trailing comma in multi-line function declaration
For contrib gitlab pipelines, the Coder 8.3.24 will be used immediately. So be prepared for some failing contrib phpcs jobs and the need for support. What would be the mechanism by which we give maintainers notice that this is going to happen? This issue is still RTBC, but looks like all the 9 steps are done.
Comment #62
longwaveThe change in Coder seems to work well, we upgraded to this on a work project yesterday and
phpcbfcorrectly fixed both spacing and trailing commas on all our badly formatted multiline constructors - we use property promotion a lot but our formatting was not consistent before.Comment #63
klausiHappy to hear it is working - we have also deployed it over our work codebases and are quite happy with the auto fixes.
Comment #64
bbralaMade an issue for core, needs quite a few fixes :)
#3443117: Fix Drupal.Functions.MultiLineFunctionDeclaration coding standard
Comment #65
jonathan1055 commentedJust reporting here for info, and to help others, that the change to add a trailing comma is not compatible with PHPUnit 9.6.19 in Drupal 9.5 PHP 7.4 (which is what you get when using
OPT_IN_TEST_PREVIOUS_MAJORon gitlab pipelines). The phpunit test complains of a syntax error and givesSo if you want to fix the PHPCS rule and still maintain the ability to test at 'Previous Major' you can ignore the rule on the next line:
Comment #66
bbralaTHis is all done. Followup is posted, cr also.