From 39dd4b701f5f429c3d7b3130c445b5dcfc4a81b4 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Fri, 23 Jul 2021 15:38:24 +0200 Subject: [PATCH] Squiz/BlockComment: prevent false positives with attributes PHP 8.0+ attributes can be placed between a docblock and the function/class declaration it applies to. The `Squiz.Commenting.BlockComment` sniff did not yet take this into account when determining whether a comment was a docblock or an block comment incorrectly using the docblock syntax. This would result in false positive `Block comments must be started with /*` errors. Fixed now. --- .../Sniffs/Commenting/BlockCommentSniff.php | 14 ++++++++++++-- .../Tests/Commenting/BlockCommentUnitTest.inc | 16 ++++++++++++++++ .../Commenting/BlockCommentUnitTest.inc.fixed | 16 ++++++++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php b/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php index 93b60adaad..6a12bb7368 100644 --- a/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php +++ b/src/Standards/Squiz/Sniffs/Commenting/BlockCommentSniff.php @@ -69,8 +69,18 @@ public function process(File $phpcsFile, $stackPtr) // If this is a function/class/interface doc block comment, skip it. // We are only interested in inline doc block comments. if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_OPEN_TAG) { - $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); - $ignore = [ + $nextToken = $stackPtr; + do { + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($nextToken + 1), null, true); + if ($tokens[$nextToken]['code'] === T_ATTRIBUTE) { + $nextToken = $tokens[$nextToken]['attribute_closer']; + continue; + } + + break; + } while (true); + + $ignore = [ T_CLASS => true, T_INTERFACE => true, T_TRAIT => true, diff --git a/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc b/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc index daf50fa382..eed554b3f3 100644 --- a/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc +++ b/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc @@ -272,3 +272,19 @@ $contentToEcho * No blank line allowed above the comment if it's the first non-empty token after a PHP open tag. */ $contentToEcho + +/** + * Comment should be ignored, even though there is an attribute between the docblock and the class declaration. + */ + +#[AttributeA] + +final class MyClass +{ + /** + * Comment should be ignored, even though there is an attribute between the docblock and the function declaration + */ + #[AttributeA] + #[AttributeB] + final public function test() {} +} diff --git a/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc.fixed b/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc.fixed index e402160f02..7471b582a9 100644 --- a/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc.fixed +++ b/src/Standards/Squiz/Tests/Commenting/BlockCommentUnitTest.inc.fixed @@ -274,3 +274,19 @@ $contentToEcho * No blank line allowed above the comment if it's the first non-empty token after a PHP open tag. */ $contentToEcho + +/** + * Comment should be ignored, even though there is an attribute between the docblock and the class declaration. + */ + +#[AttributeA] + +final class MyClass +{ + /** + * Comment should be ignored, even though there is an attribute between the docblock and the function declaration + */ + #[AttributeA] + #[AttributeB] + final public function test() {} +}