diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/ClassCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/ClassCommentSniff.php index 8245f7b0efb1536ea238f24aecfdf480edbaa9a8..53f86e06b23f87b25489ae4cd8733a1469948d0e 100644 --- a/coder_sniffer/Drupal/Sniffs/Commenting/ClassCommentSniff.php +++ b/coder_sniffer/Drupal/Sniffs/Commenting/ClassCommentSniff.php @@ -58,17 +58,37 @@ class ClassCommentSniff implements Sniff { $tokens = $phpcsFile->getTokens(); $find = Tokens::$methodPrefixes; - $find[] = T_WHITESPACE; - $find[] = T_READONLY; - $name = $tokens[$stackPtr]['content']; + $find[T_WHITESPACE] = T_WHITESPACE; + $find[T_READONLY] = T_READONLY; + $name = $tokens[$stackPtr]['content']; + $classCodeStart = $stackPtr; + + $previousContent = null; + for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) { + if (isset($find[$tokens[$commentEnd]['code']]) === true) { + continue; + } + + if ($previousContent === null) { + $previousContent = $commentEnd; + } + + if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END + && isset($tokens[$commentEnd]['attribute_opener']) === true + ) { + $commentEnd = $classCodeStart = $tokens[$commentEnd]['attribute_opener']; + continue; + } + + break; + } - $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG && $tokens[$commentEnd]['code'] !== T_COMMENT ) { - $fix = $phpcsFile->addFixableError('Missing %s doc comment', $stackPtr, 'Missing', [$name]); + $fix = $phpcsFile->addFixableError('Missing %s doc comment', $classCodeStart, 'Missing', [$name]); if ($fix === true) { - $phpcsFile->fixer->addContent($commentEnd, "\n/**\n *\n */"); + $phpcsFile->fixer->addContent($commentEnd, "\n\n/**\n *\n */"); } return; @@ -84,7 +104,7 @@ class ClassCommentSniff implements Sniff $fileTag = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($start + 1), $commentEnd, false, '@file'); if ($fileTag !== false) { // This is a file comment. - $fix = $phpcsFile->addFixableError('Missing %s doc comment', $stackPtr, 'Missing', [$name]); + $fix = $phpcsFile->addFixableError('Missing %s doc comment', $classCodeStart, 'Missing', [$name]); if ($fix === true) { $phpcsFile->fixer->addContent($commentEnd, "\n/**\n *\n */"); } @@ -93,7 +113,7 @@ class ClassCommentSniff implements Sniff } if ($tokens[$commentEnd]['code'] === T_COMMENT) { - $fix = $phpcsFile->addFixableError('You must use "/**" style comments for a %s comment', $stackPtr, 'WrongStyle', [$name]); + $fix = $phpcsFile->addFixableError('You must use "/**" style comments for a %s comment', $classCodeStart, 'WrongStyle', [$name]); if ($fix === true) { // Convert the comment into a doc comment. $phpcsFile->fixer->beginChangeset(); @@ -110,12 +130,12 @@ class ClassCommentSniff implements Sniff return; } - if ($tokens[$commentEnd]['line'] !== ($tokens[$stackPtr]['line'] - 1)) { + if ($tokens[$commentEnd]['line'] !== ($tokens[$classCodeStart]['line'] - 1)) { $error = 'There must be exactly one newline after the %s comment'; $fix = $phpcsFile->addFixableError($error, $commentEnd, 'SpacingAfter', [$name]); if ($fix === true) { $phpcsFile->fixer->beginChangeset(); - for ($i = ($commentEnd + 1); $tokens[$i]['code'] === T_WHITESPACE && $i < $stackPtr; $i++) { + for ($i = ($commentEnd + 1); $tokens[$i]['code'] === T_WHITESPACE && $i < $classCodeStart; $i++) { $phpcsFile->fixer->replaceToken($i, ''); } diff --git a/tests/Drupal/Commenting/ClassCommentUnitTest.inc b/tests/Drupal/Commenting/ClassCommentUnitTest.inc index c6bcecc3ec97507753d99cd5b955738b9c0a7856..6b3fe874d0281f686df3bf85642323bfa11f7b6f 100644 --- a/tests/Drupal/Commenting/ClassCommentUnitTest.inc +++ b/tests/Drupal/Commenting/ClassCommentUnitTest.inc @@ -29,3 +29,25 @@ trait Bango { final readonly class Example { } + +/** + * My class comment. + */ +#[\Attribute] +class AllGood { + +} + +#[\Attribute] +class NotGood { + +} + +/** + * There should be no empty line after this. + */ + +#[\Attribute] +class WrongSpacing { + +} diff --git a/tests/Drupal/Commenting/ClassCommentUnitTest.inc.fixed b/tests/Drupal/Commenting/ClassCommentUnitTest.inc.fixed index d74c5a295ea29a69886d1d9614bc725b0cc19d89..4c6436311261fdfb84a204f50e6fa087796a38c6 100644 --- a/tests/Drupal/Commenting/ClassCommentUnitTest.inc.fixed +++ b/tests/Drupal/Commenting/ClassCommentUnitTest.inc.fixed @@ -32,3 +32,27 @@ trait Bango { final readonly class Example { } + +/** + * My class comment. + */ +#[\Attribute] +class AllGood { + +} + +/** + * + */ +#[\Attribute] +class NotGood { + +} + +/** + * There should be no empty line after this. + */ +#[\Attribute] +class WrongSpacing { + +} diff --git a/tests/Drupal/Commenting/ClassCommentUnitTest.php b/tests/Drupal/Commenting/ClassCommentUnitTest.php index 19c854347f8c5440c56f0dc10ff143e241adc455..b866322413eff087d741b8429c6a46173ddf1077 100644 --- a/tests/Drupal/Commenting/ClassCommentUnitTest.php +++ b/tests/Drupal/Commenting/ClassCommentUnitTest.php @@ -20,7 +20,11 @@ class ClassCommentUnitTest extends CoderSniffUnitTest */ protected function getErrorList(string $testFile): array { - return [8 => 1]; + return [ + 8 => 1, + 41 => 1, + 48 => 1, + ]; }//end getErrorList() diff --git a/tests/Drupal/bad/bad.php.fixed b/tests/Drupal/bad/bad.php.fixed index bb85c0506578f50d58335da6cae54f4df68c6084..798dd04d709f88325153e02c7aabdd426c779c75 100644 --- a/tests/Drupal/bad/bad.php.fixed +++ b/tests/Drupal/bad/bad.php.fixed @@ -447,10 +447,12 @@ class FunctionTest { } } + /** * */ interface startsLowerInterface {} + /** * */ @@ -849,6 +851,7 @@ preg_match('@.+@e', 'subject'); preg_match('@.+@iemesuexADSUeXJ', 'subject'); preg_filter('@.+@imsuexADSUXJ', 'replacement', 'subject'); preg_replace('@.+@imsuxADSUeXJ', 'replacement', 'subject'); + /** * */