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

PSR12 standard #750

Closed
juliangut opened this issue Oct 26, 2015 · 61 comments
Closed

PSR12 standard #750

juliangut opened this issue Oct 26, 2015 · 61 comments

Comments

@juliangut
Copy link

I know this might be a bit too early as the Extended Coding Style Guide is still on Draft phase but IMO having early access to what could be the standard in the end could be helpful

What anyone else think about this?

@gsherwood
Copy link
Member

I've been following it, but I haven't got time to do anything about it.

@juliangut
Copy link
Author

There are a few points that will hardly change in the future and can most certainly be added as sniffs

The PHP reserved words int, true, object, float, false, mixed, bool, null, numeric, string and resource MUST be in lower case

All files MUST declare strict types.

Anonymous Classes MUST follow the same guidelines and principles as closures in the above section.
The opening bracket MAY be on the same line as the class keyword so long as the list of implements interfaces does not wrap. If the list of interfaces wraps, the bracket MUST be placed on the line immediately following the last interface.

Do you think is a good idea to create a PSR12 standard before it is established (starting with this points) and then go updating it, or wait until it is fully finished?

@gsherwood
Copy link
Member

Do you think is a good idea to create a PSR12 standard before it is established (starting with this points) and then go updating it, or wait until it is fully finished?

Most of the hard work is done, but some custom sniffs will need to be written. It should be possible for anyone to create a ruleset.xml file that checks almost all of PSR12 today. But I don't think I'd include it in PHPCS until it's done.

@gsherwood
Copy link
Member

Closing this. I'll re-evaluate if the PSR-12 fighting ever stops and something gets released.

@mrVrAlex
Copy link

@gsherwood
So, after 2 years, PSR-12 now in draft status - https://medium.com/php-fig/a-month-of-php-fig-1-october-2017-af253682ef5b

@stefan-endouble
Copy link

Now is in review https://www.php-fig.org/psr/#review . Anyone have some tips am how to enforce those recommendations until something official is released?

@jrfnl
Copy link
Contributor

jrfnl commented Feb 20, 2018

@gsherwood Maybe its time to re-open this issue as I suspect more questions will start coming about this ?

@heiglandreas
Copy link

As far as i'Ve seen the FIG is looking for a second example implementation. Wouldn't a sniff for codesniffer be a good way to prove the concept?

Or would an external sniff be more of interest?

@jrfnl
Copy link
Contributor

jrfnl commented Mar 16, 2018

@heiglandreas What does an "example implementation" constitute though ?
I don't expect the PHPCS library to change its native codestyle to match PSR-12, so a sniff would be able to enforce - an arbitrary part of - PSR-12, but would not implement it in the code of the sniff itself.

@heiglandreas
Copy link

The current Example-Implementation is https://github.com/KorvinSzanto/PHP-CS-Fixer/tree/feature/psr12 and from what I can read from it it's an implementation that enforces PRS-12 on a codebase. The same thing phpbcs does.

So AFAIK it's not about implementing PSR-12 inside the sniff but to create a sniff that finds violations of PSR-12.

@jrfnl
Copy link
Contributor

jrfnl commented Mar 16, 2018

@heiglandreas I've got a few sniffs which cover parts of PSR-12 ready already and I seem to recall @timoschinkel has a large part of PSR-12 covered already as well.

@gsherwood Would now be a good time maybe to start with a PSR-12 ruleset and allow people who have sniffs covering parts of PSR-12 which aren't already covered by sniffs in PHPCS, to start pulling them ?

Want me to have a go at making an initial ruleset with what can be covered by existing sniffs ?

@gsherwood
Copy link
Member

Would now be a good time maybe to start with a PSR-12 ruleset and allow people who have sniffs covering parts of PSR-12 which aren't already covered by sniffs in PHPCS, to start pulling them ?

Yes, I think so.

@gsherwood
Copy link
Member

Want me to have a go at making an initial ruleset with what can be covered by existing sniffs ?

Sorry, missed this. If you'd like to :) If you could comment it like I did for PSR2, it helps me maintain it going forward and makes sure we've covered everything: https://github.com/squizlabs/PHP_CodeSniffer/blob/master/src/Standards/PSR2/ruleset.xml

@jrfnl
Copy link
Contributor

jrfnl commented Mar 18, 2018

@gsherwood I'll try and get to it later this week. In the mean time, you may want to reopen this issue ?

@gsherwood
Copy link
Member

I've committed a ruleset for PSR-12, which pulls in a few current sniffs and includes a couple of new ones. Lots of work to go though.

@TomasVotruba
Copy link
Contributor

TomasVotruba commented Jun 8, 2018

@gsherwood
Copy link
Member

For my own reference:

The current working group for PSR-12 is as follows:

Editor:
Korvin Szanto

Sponsor:
Chris Tankersley

Members:
Alexander Makarov
Michael Cullum
Robert Deutz

@tag
Copy link

tag commented Jan 25, 2019

I know the ruleset is still being worked, but I see the following issue:

$foo .= $bar;

Generates the following (incorrectly, I presume, as .= should be treated as a single assignment operator?):

# | ERROR | [x] Expected at least 1 space after "."; 0 found

@gsherwood
Copy link
Member

@tag That code does not generate an error for me. Are you sure you don't have a syntax error in your file causing incorrect tokenizing? Can you share a code sample that replicates the error alone?

@jrfnl
Copy link
Contributor

jrfnl commented Jan 25, 2019

@tag I just tried to reproduce the issue and that code snippet does not produce any errors for me against the PSR12 ruleset. Can you please provide more information ?

gsherwood added a commit that referenced this issue Sep 5, 2019
… spacing and indents are correct inside control structure parenthesis (ref #750)
gsherwood added a commit that referenced this issue Sep 5, 2019
gsherwood added a commit that referenced this issue Sep 5, 2019
… of classes/interfaces/traits/functions are not followed by a comment or statement (ref #750)

Fixers were not added to this sniff as it is likely that comments would be found more than anything else, and simply moving them to the next line is probably not the right fix. More likely, the comment should be removed, which only the developer should do.
@gsherwood
Copy link
Member

gsherwood commented Sep 5, 2019

Another update: Only the checks for anon classes need to be done now. I think everything else has been taken care of.

First thing to do is figure out what "Anonymous Classes MUST follow the same guidelines and principles as closures in the above section" really means, then I'll add a sniff for it.

@gsherwood
Copy link
Member

gsherwood commented Sep 5, 2019

These are the anon class rules that I believe PSR-12 wants enforced:

Anon classes MUST be declared with a space after the class keyword, and a space before and after the extends and implements keywords.

If present, there MUST NOT be a space after the opening parenthesis of the argument list, and there MUST NOT be a space before the closing parenthesis of the argument list. In the argument list, there MUST NOT be a space before each comma, and there MUST be one space after each comma. 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 or variable per line.

The extends and implements keywords MUST be declared on the same line as the class name.

Lists of implements and, in the case of interfaces, extends 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 interface per line.

The opening brace MAY be on the same line as the class keyword so long as the list of implements interfaces does not wrap. If the list of interfaces wraps, the brace MUST be placed on the line immediately following the last interface.

The closing brace MUST go on the next line following the body and MUST NOT be preceded by a blank line.

@ncou
Copy link

ncou commented Sep 7, 2019

Do you have an idear when there will be a new release of phpcs with the full psr12 rules ? Thank you.

@gsherwood
Copy link
Member

Do you have an idear when there will be a new release of phpcs with the full psr12 rules ?
This issue is on the 3.5.0 milestone, which is the next release. The PSR-12 standard itself is nearly complete (see my updates above), and this is the last major change for that release, so it wont be too long now.

I've got a very busy week this week, so I might not complete the PSR-12 standard until next week. That would mean a release should be ready in the next 2 weeks.

@ncou
Copy link

ncou commented Sep 9, 2019

great news. keep up the good work.

@gsherwood
Copy link
Member

I've committed the anon class sniff, which makes heavy use of the main class declaration sniff, as well as rules from function declarations and closures for when arguments are passed into the constructor.

(I forgot to mention this issue on the commit, but it is here: b770ed3)

So that means a basic PSR12 standard is now complete in PHPCS. I'll leave this issue open in case anyone can provide some testing and feedback. I'll work on the remaining few 3.5.0 issues and then do a release either this week or next, depending on the feedback I get.

@gmponos
Copy link
Contributor

gmponos commented Sep 17, 2019

Hello,

I tested against my project.

I have a symfony project which has a file like this:

<?php

declare(strict_types=1);

namespace App\Controller;

use Whatever

/**
 * @Route(
 *     "/myroute",
 *     name="app.myroute",
 *     methods={"GET"}
 * )
 */
final class MyController extends AbstractController

I get the following two errors:

-------------------------------------------------------------------------------------------------------------------------------------
FOUND 2 ERRORS AFFECTING 2 LINES
-------------------------------------------------------------------------------------------------------------------------------------
 14 | ERROR | [ ] The file-level docblock must follow the opening PHP tag in the file header
    |       |     (PSR12.Files.FileHeader.IncorrectOrder)
 23 | ERROR | [x] Header blocks must be followed by a single blank line (PSR12.Files.FileHeader.SpacingAfterBlock)
-------------------------------------------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
-------------------------------------------------------------------------------------------------------------------------------------

does not feel right.

@gmponos
Copy link
Contributor

gmponos commented Sep 17, 2019

Furthermore on a file like this:

<?php

declare(strict_types=1);

namespace App\Validator;

use Psr\Log\LoggerInterface;
use function GuzzleHttp\Psr7\uri_for;

It does not add a blank line between use and use function

Not sure if it is one of the things you left for later.

@gsherwood
Copy link
Member

does not feel right.

Yeah, it's hard to tell if that docblock is a file-level docblock or a class docblock. What you've actually got is no file-level docblock, but it looks to the sniff like you've just put it in the wrong spot.

I think the solution is to do what some others sniffs do, which is to just assume the docblocks followed by a class/interface/trait just belong to that OO structure.

It does not add a blank line between use and use function

It does for me:

$ php bin/phpcs temp.php --standard=PSR12 --report=diff
--- temp.php
+++ PHP_CodeSniffer
@@ -5,4 +5,5 @@
 namespace App\Validator;

 use Psr\Log\LoggerInterface;
+
 use function GuzzleHttp\Psr7\uri_for;

What does it show you?

Also, thanks a lot for testing this out. I really appreciate it.

gsherwood added a commit that referenced this issue Sep 18, 2019
Code wasn't taking prefixes into account when determining if the docblock belong to a scope opener
@gsherwood
Copy link
Member

I think the solution is to do what some others sniffs do, which is to just assume the docblocks followed by a class/interface/trait just belong to that OO structure.

I actually already had code in there for the, but the class and method prefixes were not being taken into account. I've fixed that, and the sample code now produces no errors.

@u01jmg3
Copy link

u01jmg3 commented Sep 18, 2019

Thanks @gsherwood for all the hard work you've put in and continue to do so


Everything looks good apart from one aspect of PSR-12 which interferes with Laravel Blade view files. However, I'm not sure anything can be done.

A typical Blade file might start with the following:

@extends('layouts.app')
@section('comments')
<?php

/**
 *
 *
 * @author
 * @version
 * @copyright
 */

?>
@endsection

This will lead to the error: The file header must be the first content in the file (PSR12.Files.FileHeader.HeaderPosition).

One solution would be to replace the <?php ?> syntax with the Blade equivalent (@php @endphp) which CodeSniffer cannot read. I am open to other suggestions though if you spot anything?

@spaceemotion
Copy link

I am wondering why you would want to have a licence header in that place though. It seems like it being the first thing in the file would make more sense I guess?

@u01jmg3
Copy link

u01jmg3 commented Sep 18, 2019

@spaceemotion here is another example. It's less about the contents of the PHP and more about using Laravel Blade syntax (@extends, @section) alongside PSR-12 at the beginning of a file.

@extends('layouts.app')
@section('imports')
<?php

use App\Models\User;

?>
@endsection

@gsherwood
Copy link
Member

However, I'm not sure anything can be done.

I'm not sure what can be done either. PSR-12 probably didn't consider template files when the standard was written, and the header part of the standard is very clear.

It's a pain, but you could exclude that specific sniff from your template files using a custom ruleset, along with a path or regex that matches the template file names or extensions. Something like:

 <rule ref="PSR12.Files.FileHeader">
    <exclude-pattern>*/templates/*</exclude-pattern>
 </rule>

I'm not really sure beyond that.

@alexanderpas
Copy link

alexanderpas commented Sep 19, 2019

When a file contains a mix of HTML and PHP, any of the above sections may still be used. If so, they MUST be present at the top of the file, even if the remainder of the code consists of a closing PHP tag and then a mixture of HTML and PHP.

I personally believe that the can be treated as if the use statement in this case is part of the "rest of the code" part, as the use statement is not nessecarily part of the file.

<?php
/**
 * File Based Doc block etc...
 */
?>
@extends('layouts.app')
@section('imports')
<?php

// rest of code
use App\Models\User;

?>
@endsection

The equivalent of the original in full blade syntax would be

@extends('layouts.app')
@section('imports')
@php

use App\Models\User;

@endphp
@endsection

or

@extends('layouts.app')
@section('imports')
{{--*/ use App\Models\User; /*--}}
@endsection

or

@extends('layouts.app')
@section('imports')
@{ use App\Models\User; }}
@endsection

depending on which version you are using.

@gmponos
Copy link
Contributor

gmponos commented Sep 19, 2019

What does it show you?

Hello.. not sure if I did something wrong before but yes it works...

I've fixed that, and the sample code now produces no errors.

Yes.. checked and it works...

👍

@gsherwood
Copy link
Member

I personally believe that the can be treated as if the use statement in this case is part of the "rest of the code" part, as the use statement is not nessecarily part of the file.

This code passes PSR12, except for a few blank lines that are needed in the header section:

<?php

/**
 * File Based Doc block etc...
 */

?>
@extends('layouts.app')
@section('imports')
<?php

// rest of code
use App\Models\User;

?>
@endsection

@gsherwood
Copy link
Member

Marking as complete in preparation for a release. Any bugs in the PSR12 implementation should now be opened as seperate issues. Thanks to everyone who participated here.

PHPCS v3 Development automation moved this from Backlog to Ready for Release Sep 26, 2019
@hopeseekr
Copy link

I'm going to have to remove PSR12 sniffing, because apparently <?php declare(strict_types=1); is now verboten by our overlords. If you ask me, it's the only appropriate place.

@gmponos
Copy link
Contributor

gmponos commented Oct 5, 2019

You mentioned something similar on another issue as well.. TBH I can not understand what's the exact problem you are trying to solve..

@MasterOdin
Copy link
Contributor

MasterOdin commented Oct 5, 2019

@hopeseekr disable PSR12.Files.DeclareStatementSniff and add https://github.com/slevomat/coding-standard and enable SlevomatCodingStandard.TypeHints.DeclareStrictTypes.

You could also raise an issue on the PHP-Fig mailing list about how you disagree with #3 on PSR-12, namely:

If present, each of the blocks below MUST be separated by a single blank line, and MUST NOT contain a blank line.

LawnGnome added a commit to newrelic/newrelic-monolog-logenricher-php that referenced this issue Nov 13, 2019
We'll match the PHP minimum requirement exactly to Monolog 1, which is
5.3.0. The unit tests require 5.3.3 (because PHPUnit 4.8 requires
5.3.3), but technically the runtime requirement is just 5.3.0.

We'll also require PHP_CodeSniffer 3.5 or later specifically, as we need
the PSR-12 definition, and that was
[added in 3.5.0](squizlabs/PHP_CodeSniffer#750).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
PHPCS v3 Development
Ready for Release
Development

No branches or pull requests