Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Import advanced PHP 7.1 sniffs #9

Merged
merged 1 commit into from
Dec 26, 2017

Conversation

Majkl578
Copy link
Contributor

@Majkl578 Majkl578 commented Sep 5, 2017

Hi,
here's a bunch of great sniffs, most of them requiring PHP 7.1+.

These awesome sniffs are provided under MIT license by Slevomat guys (czech company) at slevomat/coding-standard. Note that I have no affiliation to them, besides some pull requests.
Full list of all available sniffs, their descriptions and options is available in README of the abovementioned repository.

All referenced sniffs are imported explicitly instead of importing whole standard, to avoid unwanted sniffs to appear in newer versions.
Every sniff is accompanied with a comment of its intention.
Note that these sniffs are pretty damn strict. :)

Initial version is mostly based what we're using as internal CS in our company, slightly adjusted for Doctrine.
Some of them may be pretty harsh initially so please let's discuss here what would be applicable and what not.

This will break a lot of things currently since most of the code is still 5.6-like, thus is not applicable to stable branches as is due to BC (some sniffs may be eligible to be backported though). Thus this would target 2.0 milestone here and only be used and applied to develop branches targetting next major (i.e. ORM 3.0).

Follow-up of discussion with @lcobucci in doctrine/common#817.

<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php"/>

<!-- Forbid useless annotations -->
<!--<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenAnnotationsSniff.php">-->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've explicitly disabled this sniff, but I think it should eventually be enabled and useless annotations be removed. This includes i.e.:

  • @author: Git provides more accurate information.
  • @package: Redundant to namespaces.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can enable it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And it should be SlevomatCodingStandard.Commenting.ForbiddenAnnotations

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enabled for @author, @created, @copyright, @license, @package, @since, @version. All these are provided by Git or LICENCE file.

<!-- Require ? when default value is null -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/NullableTypeForNullDefaultValueSniff.php"/>

<!-- Require one space between typehint and variable, require no space between nullability sign and typehint -->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires function foo(?Bar $bar) format.

<!-- Require presence of constant visibility -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Classes/ClassConstantVisibilitySniff.php"/>

<!-- Require ? when default value is null -->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires function foo(?Bar $bar = null) format instead of function foo(Bar $bar = null).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what is the point of this one...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To force presence of ? when parameter is supposed to be nullable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That I understood, but what's the benefit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please read the discussion here: doctrine/common#805 (comment), I explained the reasons there. 😊

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The LSP argument is very convincing!

<!-- Require using Throwable instead of Exception -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Exceptions/ReferenceThrowableOnlySniff.php"/>

<!-- Require presence of declare(strict_types=1) -->
Copy link
Contributor Author

@Majkl578 Majkl578 Sep 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires file to begin with:

<?php

declare(strict_types=1) 

<anything else>

<!-- Require types to be written as natively if possible;
require iterable types to specify phpDoc with their contnet;
forbid useless/duplicated information in php doc -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/TypeHintDeclarationSniff.php">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sniff is pretty advanced:

  • Requires native types be expressed natively (i.e. scalar types).
  • Requires iterable types (array/iterable/custom) have specified what they contain, i.e. @return Foo[].
  • Forbids duplication of type information - all @param and @return are forbidden unless they're mixed, traversable or explicit description is given.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That last one looks awesome

</rule>

<!-- Require types to be written as natively if possible;
require iterable types to specify phpDoc with their contnet;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

content?

</rule>

<!-- Forbid assignments in conditions -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/AssignmentInConditionSniff.php"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's the price to pay to avoid Yoda, 👍
I wrote about this lately, BTW

<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Arrays/TrailingArrayCommaSniff.php"/>

<!-- Forbid fancy yoda conditions -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/ControlStructures/YodaComparisonSniff.php"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn right!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be SlevomatCodingStandard.ControlStructures.YodaComparison

@Majkl578 Majkl578 force-pushed the advanced-sniffs branch 3 times, most recently from 7fff2c1 to 72dfd0f Compare September 5, 2017 22:49
@@ -57,7 +40,11 @@ public function register()
];
}

public function process(File $phpcsFile, $stackPtr)
/**
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Majkl578 I usually add a comment explaining, why the sniff is suppressed

Copy link
Contributor Author

@Majkl578 Majkl578 Sep 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but I think the name is pretty self-explaining in this case: Type Hint Declaration - Missing Parameter Type Hint

@Majkl578
Copy link
Contributor Author

Majkl578 commented Dec 8, 2017

ping @lcobucci

@alcaeus
Copy link
Member

alcaeus commented Dec 9, 2017

Ping @Ocramius @malarzm

Copy link
Member

@lcobucci lcobucci left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like this idea and I didn't know of slevomat/coding-standard, quite cool!

I wonder if would be nice to add FullyQualifiedGlobalConstantsSniff and FullyQualifiedGlobalFunctionsSniff to the list.

composer.json Outdated
@@ -17,7 +17,8 @@
"require": {
"php": "^7.1",
"squizlabs/php_codesniffer": "~3.0",
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.2"
"dealerdirect/phpcodesniffer-composer-installer": "^0.4.2",
"slevomat/coding-standard": "3.3.*"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we require ^4.0 instead? They have changed the composer project type, then dealerdirect/phpcodesniffer-composer-installer will be able to install it automatically for us (and we don't need to use file paths)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I'll update it and the way how we reference sniff. There was no 4.0 release back when I created this PR. 👍

@@ -30,4 +30,149 @@
<property name="ignoreNewlines" value="true"/>
</properties>
</rule>

<!-- Forbid using absolute class name references (except global ones) -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/ReferenceUsedNamesOnlySniff.php">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly

</rule>

<!-- Forbid empty lines around type declarations -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Types/EmptyLinesAroundTypeBracesSniff.php">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be SlevomatCodingStandard.Types.EmptyLinesAroundTypeBraces

</rule>

<!-- Require space around colon in return types -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/ReturnTypeHintSpacingSniff.php">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be SlevomatCodingStandard.TypeHints.ReturnTypeHintSpacing

<!-- Require types to be written as natively if possible;
require iterable types to specify phpDoc with their content;
forbid useless/duplicated information in phpDoc -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/TypeHints/TypeHintDeclarationSniff.php">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be SlevomatCodingStandard.TypeHints.TypeHintDeclaration

<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php"/>

<!-- Forbid useless annotations -->
<!--<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenAnnotationsSniff.php">-->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can enable it

<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Namespaces/UseDoesNotStartWithBackslashSniff.php"/>

<!-- Forbid useless annotations -->
<!--<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/ForbiddenAnnotationsSniff.php">-->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And it should be SlevomatCodingStandard.Commenting.ForbiddenAnnotations

<!--</rule>-->

<!-- report invalid format of inline phpDocs with @var -->
<rule ref="vendor/slevomat/coding-standard/SlevomatCodingStandard/Sniffs/Commenting/InlineDocCommentDeclarationSniff.php"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration

@@ -1,61 +0,0 @@
<?php

function () : void {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we removing this? The idea of these tests was to provide examples and ensure that, regardless if we're providing the sniffs or using sniffs from a package, things are working properly (in Travis)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Afaik these are already provided via rules from Slevomat CS (SlevomatCodingStandard.TypeHints.ReturnTypeHintSpacing) and seemed redundant to their tests, but can check again. The tests otherwise don't look like a full representation of this PR so it didn't make much sense to me to keep it.
If we want to test full CS, we can add more specific tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests were added in cdce50d to cover SpaceOnReturnTypeSniff defined by this CS. It's now replaced by external sniff.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I added the tests to validate the configuration of the ruleset and not individual sniffs (regardless of what package provides the sniffs). But sure this is up for discussion 😄

My concern was to ensure that we're setting everything the way we want and we don't have any side effect.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I've reverted the removal, updated it and added extra example class. 😎

@@ -25,6 +8,9 @@

trait EnsureSpaces
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can move these methods to Doctrine\Sniffs\Spacing\SpaceOnNotSniff, which is the only class that uses it

@Majkl578 Majkl578 force-pushed the advanced-sniffs branch 3 times, most recently from c434d3e to 3e7e982 Compare December 17, 2017 16:54
<rule ref="SlevomatCodingStandard.Arrays.TrailingArrayComma"/>

<!-- Forbid fancy yoda conditions -->
<rule ref="SlevomatCodingStandard.ControlStructures.DisallowYodaComparison"/>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on doctrine/orm#6888, disallowing Yoda conditions should be discussed. I've already expressed my negative feelings in the PR, what do others think?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm all for not using Yoda conditions. The last time I made a typo like if ($foo = 'bar') was longer than 10 years ago. Mutation testing is much better in finding untested conditions.

@Majkl578
Copy link
Contributor Author

Upgraded to version 4.0, changed the way we reference external sniffs.

I wonder if would be nice to add FullyQualifiedGlobalConstantsSniff and FullyQualifiedGlobalFunctionsSniff to the list.

See doctrine/orm#6807, @Ocramius suggested using use function foo; to import them, that idea seems neat and doesn't pollute code with \.

{
return [\T_BOOLEAN_NOT];
}

public function process(File $phpcsFile, $stackPtr)
/**
* @phpcsSuppress SlevomatCodingStandard.TypeHints.TypeHintDeclaration.MissingParameterTypeHint
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish there was a way to not pollute code with standard-specific annotations and have exceptions described in an external file (like PHPStan does).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this exact one (with no typehint) should be also suppressable by adding @param annotation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

phpcsSuppress should be the exception - especially for this one. MissingParameterTypeHint requires either a type declaration on the parameter or a @param docblock, so there should be @param, not @phpcsSuppress.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There isn't actually much cases where you would need that annotation, its use is mostly exceptional (like design errors i.e. write-only property).
Otherwise in this case @param is provided by parent declaration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried removing it, but realized it must be kept, because otherwise CS will report int not being used natively - but it can't be, parent forces mixed. Unfortunately CS has no way to know, it only has single file scope. :(

<properties>
<property
name="newlinesCountBetweenOpenTagAndDeclare"
value="2"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I find this formatting better:

<?php declare(strict_types=1);

It kind of makes the declare part of the file header.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's stick to the (upcoming) PSR-12 as much as possible please. See https://github.com/php-fig/fig-standards/blob/master/proposed/extended-coding-style-guide.md#3-declare-statements-namespace-and-import-statements

It kind of makes the declare part of the file header.

Which is exactly the problem. declare is a statement like many others and strict_types may not be the only statement:

<?php declare(strict_types=1);

declare(ticks = 1);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed with @alcaeus, declare could be anywhere in the file, it's only strict_types that must be first statement. Also in future it's possible there will be more similar declare statements.
Personally I don't see a reason to follow PSR-12, it's not a standard, is unfinished and Doctrine is not part of FIG group.
Btw we already use strict types in ORM (doctrine/orm#6524) and format was discussed by @Ocramius.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I don't see a reason to follow PSR-12, it's not a standard, is unfinished

Correct - it's currently still in a draft phase.

and Doctrine is not part of FIG group.

Which means we are not involved in the creation and adoption of new PSRs. By the same logic, we might as well drop PSR-2, start using tabs and roll our own autoloading standard because we dislike PSR-0 and PSR-4 and we're not part of PHP-FIG.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I meant is that Doctrine is not part of FIG and is then not obliged to follow PSR. On the other hand, it's not reason to not follow PSRs that are compatible with Doctrine's vision, like currently PSR-2.

Copy link
Member

@morozov morozov Dec 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's stick to the (upcoming) PSR-12 as much as possible please.

Didn't know it's a thing. Let's stick to the standard.

<rule ref="SlevomatCodingStandard.Namespaces.UseDoesNotStartWithBackslash"/>

<!-- Forbid useless annotations -->
<!--<rule ref="SlevomatCodingStandard.Commenting.ForbiddenAnnotations">-->
Copy link
Member

@morozov morozov Dec 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a sniff which forbids committing commented out code? :-)

This one makes sense to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course: Squiz.PHP.CommentedOutCode

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, but why is this block commented out?

Copy link
Contributor Author

@Majkl578 Majkl578 Dec 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally copied out this part from our company's coding standard, probably commented it out because ORM still uses @author, @since etc. I'm all for enabing it and removing redundant annotations, Git's history/blame provide more accurate information.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Let's get this rule enabled.

Copy link
Member

@alcaeus alcaeus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, I'm still not happy with the return type declaration. PSR-12 specifies (in https://github.com/php-fig/fig-standards/blob/master/proposed/extended-coding-style-guide.md#45-method-and-function-arguments):

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 parentheses with no spaces between the two characters. The declaration keyword (e.g. string) MUST be lowercase.

Most code I've seen so far (with the notable exception of anything written by @Ocramius) also follows that notation, so it would make sense for us to not do it differently: there's no advantage to the space before the colon and we don't use it in other places either (e.g. switch):

switch ($foo) {
    case 'something' :
        break;
    // ...
}

@Majkl578 Majkl578 mentioned this pull request Dec 26, 2017
Copy link
Member

@Ocramius Ocramius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Majkl578 due to #11, this patch needs another rebase

@Majkl578
Copy link
Contributor Author

Rebased. And sniffs reordered alphabetically.

Copy link
Member

@Ocramius Ocramius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚢

@Ocramius Ocramius self-assigned this Dec 26, 2017
@Ocramius Ocramius added this to the 1.0.0 milestone Dec 26, 2017
@Ocramius Ocramius merged commit 5b65b75 into doctrine:master Dec 26, 2017
@Majkl578 Majkl578 deleted the advanced-sniffs branch December 27, 2017 01:08
@Slamdunk Slamdunk mentioned this pull request Dec 29, 2017
2 tasks
@alcaeus
Copy link
Member

alcaeus commented Dec 29, 2017

@Majkl578 not sure if the result of the votes is already factored in. Except for the "spaces around colon" vote they are pretty one-sides. As for that one that isn't, counting doctrine team members results in favor of "spaces around colon", so I suggest we use that for now and possibly revisit this if PSR-12 ever becomes a thing (and makes sense; see spaces around equal sign within declare).

@Majkl578
Copy link
Contributor Author

Majkl578 commented Dec 29, 2017

@alcaeus As far as I checked the proposed ruleset matches the results so no change was needed. As for the rules proposed by @carusogabriel - we currently have no sniff implementing them. ! spacing was handled in #11. Did I miss something?
For the return spacing, feel free to override the rule on project-level.

@Majkl578 Majkl578 modified the milestones: 1.0.0, 1.1.0 Dec 29, 2017
@carusogabriel
Copy link
Contributor

@Majkl578 Should I PR my proposed rules? 😄

carusogabriel added a commit that referenced this pull request Mar 19, 2020
[PSR-12](https://www.php-fig.org/psr/psr-12) is an extension of the PSR-2 set of rules
that aims to standardize the code style.

Doctrine, so far, hasn't adopted 100% off it, and this PR proposes to start to migrate our rules
to PSR-12.

The first one is the return types. As described under the section [4.5](https://www.php-fig.org/psr/psr-12/#45-method-and-function-arguments),
they SHOULD NOT be a blank space between the return type and colon (`:`).

For context on why this was voted in the past, see #9.# Please enter the commit message for your changes. Lines starting
carusogabriel added a commit that referenced this pull request Mar 19, 2020
[PSR-12](https://www.php-fig.org/psr/psr-12) is an extension of the PSR-2 set of rules
that aims to standardize the code style.

Doctrine, so far, hasn't adopted 100% off it, and this PR proposes to start to migrate our rules
to PSR-12.

The first one is the return types. As described under the section [4.5](https://www.php-fig.org/psr/psr-12/#45-method-and-function-arguments),
they SHOULD NOT be a blank space between the return type and colon (`:`).

For context on why this was voted in the past, see #9.# Please enter the commit message for your changes. Lines starting
carusogabriel added a commit that referenced this pull request Mar 20, 2020
[PSR-12](https://www.php-fig.org/psr/psr-12) is an extension of the PSR-2 set of rules
that aims to standardize the code style.

As per PSR-12, under the [item 3](https://www.php-fig.org/psr/psr-12/#3-declare-statements-namespace-and-import-statements):

The header of a PHP file may consist of a number of different blocks. If present,
each of the blocks below MUST be separated by a single blank line, and MUST NOT
contain a blank line. Each block MUST be in the order listed below, although
blocks that are not relevant may be omitted.

For context on why this was voted in the past, see #9.
carusogabriel added a commit that referenced this pull request Mar 20, 2020
[PSR-12](https://www.php-fig.org/psr/psr-12) is an extension of the PSR-2 set of rules
that aims to standardize the code style.

As per PSR-12, under the [item 3](https://www.php-fig.org/psr/psr-12/#3-declare-statements-namespace-and-import-statements):

The header of a PHP file may consist of a number of different blocks. If present,
each of the blocks below MUST be separated by a single blank line, and MUST NOT
contain a blank line. Each block MUST be in the order listed below, although
blocks that are not relevant may be omitted.

For context on why this was voted in the past, see #9.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet