diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/TodoCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/TodoCommentSniff.php new file mode 100644 index 00000000..41193b68 --- /dev/null +++ b/coder_sniffer/Drupal/Sniffs/Commenting/TodoCommentSniff.php @@ -0,0 +1,100 @@ + + */ + public function register() + { + return [ + T_COMMENT, + T_DOC_COMMENT_TAG, + T_DOC_COMMENT_STRING, + ]; + + }//end register() + + + /** + * Processes this test, when one of its tokens is encountered. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * + * @return void + */ + public function process(File $phpcsFile, $stackPtr) + { + $tokens = $phpcsFile->getTokens(); + // Standard comments and multi-line comments where the "@" is missing so + // it does not register as a T_DOC_COMMENT_TAG. + if ($tokens[$stackPtr]['code'] === T_COMMENT || $tokens[$stackPtr]['code'] === T_DOC_COMMENT_STRING) { + $comment = $tokens[$stackPtr]['content']; + $this->checkTodoFormat($phpcsFile, $stackPtr, $comment); + } else if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_TAG) { + // Document comment tag (i.e. comments that begin with "@"). + // Determine if this is related at all and build the full comment line + // from the various segments that the line is parsed into. + $expression = '/^@to/i'; + if ((bool) preg_match($expression, $tokens[$stackPtr]['content']) === true) { + $index = $stackPtr; + $comment = ''; + while ($tokens[$index]['line'] === $tokens[$stackPtr]['line']) { + $comment .= $tokens[$index]['content']; + $index++; + } + + $this->checkTodoFormat($phpcsFile, $stackPtr, $comment); + }//end if + } + + }//end process() + + + /** + * Checks a comment string for the correct syntax. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. + * @param int $stackPtr The position of the current token + * in the stack passed in $tokens. + * @param string $comment The comment text. + * + * @return void + */ + private function checkTodoFormat(File $phpcsFile, $stackPtr, string $comment) + { + $expression = '/^(\/\/|\*)*\s*(?i)(?=(@*to(-|\s|)+do))(?-i)(?!@todo\s(?!-|:)\S)/m'; + if ((bool) preg_match($expression, $comment) === true) { + $comment = trim($comment, " /\r\n"); + $phpcsFile->addError("'%s' should match the format '@todo Some task'", $stackPtr, 'TodoFormat', [$comment]); + } + + }//end checkTodoFormat() + + +}//end class diff --git a/tests/Drupal/Commenting/TodoCommentUnitTest.inc.php b/tests/Drupal/Commenting/TodoCommentUnitTest.inc.php new file mode 100644 index 00000000..39f16694 --- /dev/null +++ b/tests/Drupal/Commenting/TodoCommentUnitTest.inc.php @@ -0,0 +1,320 @@ + + */ + protected function getErrorList(string $testFile): array + { + $errorList = array_fill_keys(range(19, 37), 1); + for ($i = 102; $i < 320; $i += 14) { + $errorList[$i] = 1; + } + + return $errorList; + + }//end getErrorList() + + + /** + * Returns the lines where warnings should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of warnings that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array + */ + protected function getWarningList(string $testFile): array + { + return []; + + }//end getWarningList() + + +}//end class diff --git a/tests/Drupal/good/good.php b/tests/Drupal/good/good.php index 0efcf91c..2f36e561 100644 --- a/tests/Drupal/good/good.php +++ b/tests/Drupal/good/good.php @@ -1185,10 +1185,10 @@ function test6(array $names) { /** * Some short description. * - * @todo TODOs are allowed here. - * * @param string $x * Some parameter. + * + * @todo These are allowed here. */ function test7($x) { @@ -1205,8 +1205,8 @@ class ListContainsTest extends RulesIntegrationTestBase {} /** * Provides a 'Delete any path alias' action. * - * @todo: Add access callback information from Drupal 7. - * @todo: Add group information from Drupal 7. + * @todo Add access callback information from Drupal 7. + * @todo Add group information from Drupal 7. * * @Action( * id = "rules_path_alias_delete",