-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Added new sniff Generic.PHP.DeclareStrictTypes #1771
Added new sniff Generic.PHP.DeclareStrictTypes #1771
Conversation
Just wondering whether it would be better to have two sniffs:
The reason would be that some standards may require a strict statement, but haven't got a strict guideline on how it should be formatted. Of course, the other errorcodes could be silenced or - if using PHPCS 3.x - the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just had a look in detail at the code of the sniff and have found a couple of additional situations which you may want to account for.
Hope it helps!
Example 1
<?php
declare(ticks=1) {}
declare(strict_types=1);
will generate the following report:
----------------------------------------------------------------------------------------------------
FOUND 2 ERRORS AFFECTING 1 LINE
----------------------------------------------------------------------------------------------------
2 | ERROR | [x] Invalid number of blank lines before declare statement; expected 1, but found 0
| | (Generic.PHP.DeclareStrictTypes.LinesBefore)
2 | ERROR | [x] Invalid format of declaration; expected "declare(strict_types=1);", but found
| | "declare(ticks=1) {}
| |
| | declare(strict_types=1);"
| | (Generic.PHP.DeclareStrictTypes.InvalidFormat)
----------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------------------------------------
I would expect a NotFirst
kind of error instead, i.e. "Strict type declaration has to be the first statement in a file".
Examining the ticks
declaration as if it is the strict
declaration feels wrong.
More painful, the auto-fixer fixes this to:
<?php
declare(strict_types=1);
In other words: the whole ticks
statement is removed by the fixer.
Example 2
<html>
<head>
<title>
<?php
declare(strict_types=1);
echo 'Title';
?>
</title>
</head>
<?php echo $content; ?>
</html>
will generate the following report:
----------------------------------------------------------------------------------------------------
FOUND 2 ERRORS AFFECTING 1 LINE
----------------------------------------------------------------------------------------------------
5 | ERROR | [x] Invalid number of blank lines before declare statement; expected 1, but found 0
| | (Generic.PHP.DeclareStrictTypes.LinesBefore)
5 | ERROR | [x] Invalid number of blank lines after declare statement; expected 1, but found 0
| | (Generic.PHP.DeclareStrictTypes.LinesAfter)
----------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------------------------------------
I would an expect an error for the declare
statement not being the first content of the file and the auto-fixer to move the statment to above the HTML or for this error not to be auto-fixable.
Example 3
<?php /* Must be first. */ declare(strict_types=1); /* Comment after. */ ?>
This is not seen as a one-line statement and would be auto-fixed to:
<?php /* Must be first. */
declare(strict_types=1);
/* Comment after. */ ?>
Is this what you intended ?
Example 4
<?php
// Comment
declare(strict_types=1); ?>
<html>
<?php echo $content; ?>
</html>
will generate the following report:
----------------------------------------------------------------------------------------------------
FOUND 2 ERRORS AFFECTING 1 LINE
----------------------------------------------------------------------------------------------------
3 | ERROR | [x] Invalid number of blank lines before declare statement; expected 1, but found 0
| | (Generic.PHP.DeclareStrictTypes.LinesBefore)
3 | ERROR | [x] Invalid number of blank lines after declare statement; expected 0, but found -1
| | (Generic.PHP.DeclareStrictTypes.LinesAfter)
----------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 2 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------------------------------------
The -1
in the Generic.PHP.DeclareStrictTypes.LinesAfter
error message looks incorrect.
This also results in the auto-fixer not adding enough blank lines:
<?php
// Comment
declare(strict_types=1);
?>
<html>
<?php echo $content; ?>
</html>
Take note of the additional whitespace in front of the PHP closing tag in the fixed code.
Example 5
<?php
declare(strict_types=1) /* comment */;
will generate the following report (as expected):
----------------------------------------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------------------------------------
3 | ERROR | [x] Invalid format of declaration; expected "declare(strict_types=1);", but found
| | "declare(strict_types=1) /* comment */;"
| | (Generic.PHP.DeclareStrictTypes.InvalidFormat)
----------------------------------------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------------------------------------
The fixer will however remove the comment, resulting in:
<?php
declare(strict_types=1);
IMHO, comments should never be removed by the auto-fixer. Maybe moved to after the declaration, but not removed. If this is difficult to account for, the error should in that case maybe not be auto-fixable.
&& $tokens[$after]['code'] === T_CLOSE_TAG | ||
) { | ||
if ($tokens[$prev]['line'] !== $tokens[$next]['line']) { | ||
$error = 'PHP open tag must be in the same line as declaration.'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in
=> on
as declaration
=> either as strict type declaration
or as the declaration
} | ||
|
||
if ($tokens[$after]['line'] !== $tokens[$eos]['line']) { | ||
$error = 'PHP close tag must be in the same line as declaration.'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same spelling/grammar remarks as above for the open tag
message.
$after = false; | ||
}//end if | ||
|
||
// Check how many blank lines is before declare statement. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is
=> there are
I could have sworn strict types declaration was required to be the first statement in the file. Apparently other |
@jrfnl Thanks for your great feedback. I've addressed almost all of your suggestion in my last update. I need to check on more case: <?php
// comment
declare(strict_types=1); I think in that case, also declaration should be moved before the comment. Could you have a look please on my changes and let me know what do you think? Thanks! |
Sorry, I've just got to this on my todo list. I actually don't like the idea of either the If I was writing a strict types sniff, I'd write one to enforce the format outlined in PSR-12 because I imagine that will be the way developers will write these statements when they don't have any strong opinion about how to format them or where to place them. So to be merged in, I think this sniff should only be checking the format of the declare statement, to ensure it looks exactly like PSR-12 should be able to make use of this sniff, and then ensure other rules (like the fact this must come after a file comment) are followed using new sniffs. I'm going to remove this from the 3.3.0 roadmap, but will re-add if we can agree on a new version of the sniff before that release. |
8330b5e
to
0053c65
Compare
- linesBefore -> spacingBefore - linesAfter -> spacingAfter
@gsherwood I've updated this PR:
I didn't add Is there any chance to bring it back to 3.3.0 release? |
@@ -310,7 +310,7 @@ public function process(File $phpcsFile, $stackPtr) | |||
|
|||
$this->checkOtherDeclarations($phpcsFile, $next); | |||
|
|||
return (count($tokens) + 1); | |||
return $phpcsFile->numTokens; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I remember correctly, elsewhere return ($phpcsFile->numTokens + 1)
is used. Shouldn't really make a difference, but just thought I'd mention it for consistency sake.
@gsherwood any chance to re-add it into 3.3.0 release? |
@webimpress how challenging would it be to back-port this to 2.9? |
Is there any progress on this? I would like to include this in our ruleset |
@WarriorXK You can use SlevomatCodingStandard.TypeHints.DeclareStrictTypes from https://github.com/slevomat/coding-standard. There are many useful sniffs. |
How can i try the |
@floverdevel To test, you'll need to merge this PR, then create a <?xml version="1.0"?>
<ruleset name="MyStandard">
<rule ref="PSR2">
<exclude name="Generic.Files.LineLength"/>
</rule>
<rule ref="Generic.PHP.DeclareStrictTypes"/>
</ruleset> Then run PHPCS like this: |
@gsherwood thank you very much !!! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you like to add a test case where the declare is in this format: declare( strict_types=1 );
This sniff still has a public sniff property called Maybe we need a setting for how many spaces there are inside the parenthesis. Maybe another for spaces around the equals sign? Or maybe we release it to enforce the most common format first and add settings later if they are requested. Edit: did not mean to close - pressed wrong button |
@gsherwood just a quick question : what prevents us from merging this pull-request? |
The changes relate to public sniff properties. Changes to these would be BC breaks that can only be made in a major version, so this needs to be right before it is released. |
We don't want this configuration option to be available - per @gsherwood
Any news on this PR ? |
No changed has been made to remove the I also don't think this sniff should be inserting the declare statement if it doesn't exit. The PHPCS fixers don't modify the behaviour of code - only the formatting of the code. |
@gsherwood Changes has been made in this PR very long time ago. Property Anyway, I am closing this PR as I can't see any interest of including it in that library. Everyone who is interested in using sniff like that can use my library: |
You no need configure format property.
|
Configuration option:
omitCommentWithTags
- tags names, comment with one of these tags will be omitted and declaration will be added below the comment (default:['@author', '@copyright', '@license']
,format
- how declaration should look like (defaultdeclare(strict_types=1);
).linesBefore
spacesBefore
- number of blank lines before the declaration (default1
)linesAfter
spacesAfter
- number of lines after the declaration and before the script (default1
)Resolves #911
/cc @Xerkus