diff --git a/coder_sniffer/Drupal/Sniffs/Commenting/InlineVariableCommentSniff.php b/coder_sniffer/Drupal/Sniffs/Commenting/InlineVariableCommentSniff.php new file mode 100644 index 0000000000000000000000000000000000000000..82c5b5c417c0181d349dfa41d1a5c6083ad7b089 --- /dev/null +++ b/coder_sniffer/Drupal/Sniffs/Commenting/InlineVariableCommentSniff.php @@ -0,0 +1,139 @@ +<?php + +/** + * \Drupal\Sniffs\Commenting\InlineVariableCommentSniff + * + * @category PHP + * @package PHP_CodeSniffer + * @link http://pear.php.net/package/PHP_CodeSniffer + */ + +namespace Drupal\Sniffs\Commenting; + +use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Sniffs\Sniff; +use PHP_CodeSniffer\Util\Tokens; + +/** + * Checks for the correct usage of inline variable type declarations. + * + * @category PHP + * @package PHP_CodeSniffer + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class InlineVariableCommentSniff implements Sniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array<int|string> + */ + public function register() + { + return [ + T_COMMENT, + T_DOC_COMMENT_TAG, + ]; + + }//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(); + $ignore = [ + T_CLASS, + T_INTERFACE, + T_TRAIT, + T_FUNCTION, + T_CLOSURE, + T_PUBLIC, + T_PRIVATE, + T_PROTECTED, + T_FINAL, + T_STATIC, + T_ABSTRACT, + T_CONST, + T_PROPERTY, + T_INCLUDE, + T_INCLUDE_ONCE, + T_REQUIRE, + T_REQUIRE_ONCE, + T_VAR, + ]; + + // If this is a function/class/interface doc block comment, skip it. + $nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if (in_array($tokens[$nextToken]['code'], $ignore, true) === true) { + return; + } + + if ($tokens[$stackPtr]['code'] === T_COMMENT) { + if (strpos($tokens[$stackPtr]['content'], '@var') !== false) { + $warning = 'Inline @var declarations should use the /** */ delimiters'; + + if ($phpcsFile->addFixableWarning($warning, $stackPtr, 'VarInline') === true) { + if (strpos($tokens[$stackPtr]['content'], '#') === 0) { + $varComment = substr_replace(rtrim($tokens[$stackPtr]['content']), '/**', 0, 1)." */\n"; + } else if (strpos($tokens[$stackPtr]['content'], '//') === 0) { + $varComment = substr_replace(rtrim($tokens[$stackPtr]['content']), '/**', 0, 2)." */\n"; + } else { + $varComment = substr_replace($tokens[$stackPtr]['content'], '/**', 0, 2); + } + + $phpcsFile->fixer->replaceToken($stackPtr, $varComment); + } + } + + return; + }//end if + + // Skip if it's not a variable declaration. + if ($tokens[$stackPtr]['content'] !== '@var') { + return; + } + + // Get the content of the @var tag to determine the order. + $varContent = ''; + $varContentPtr = $phpcsFile->findNext(T_DOC_COMMENT_STRING, ($stackPtr + 1)); + if ($varContentPtr !== false) { + $varContent = $tokens[$varContentPtr]['content']; + } + + if (strpos($varContent, '$') === 0) { + $warning = 'The variable name should be defined after the type'; + + $parts = explode(' ', $varContent, 3); + if (isset($parts[1]) === true) { + if ($phpcsFile->addFixableWarning($warning, $varContentPtr, 'VarInlineOrder') === true) { + // Switch type and variable name. + $replace = [ + $parts[1], + $parts[0], + ]; + if (isset($parts[2]) === true) { + $replace[] = $parts[2]; + } + + $phpcsFile->fixer->replaceToken($varContentPtr, implode(' ', $replace)); + } + } else { + $phpcsFile->addWarning($warning, $varContentPtr, 'VarInlineOrder'); + } + }//end if + + }//end process() + + +}//end class diff --git a/tests/Drupal/Commenting/InlineCommentUnitTest.inc b/tests/Drupal/Commenting/InlineCommentUnitTest.inc index 758cb4f77bb8beff862e31d95e6d8b45ae025515..1ed73360d8948aa51f08cc409acdc167647a5107 100644 --- a/tests/Drupal/Commenting/InlineCommentUnitTest.inc +++ b/tests/Drupal/Commenting/InlineCommentUnitTest.inc @@ -102,11 +102,11 @@ function test2() { // Date formats cannot be loaded during install or update. if (!defined('MAINTENANCE_MODE')) { if ($date_format_entity = DateFormat::load('html_date')) { - /** @var $date_format_entity \Drupal\Core\Datetime\DateFormatInterface */ + /** @var \Drupal\Core\Datetime\DateFormatInterface $date_format_entity */ $date_format = $date_format_entity->getPattern(); } if ($time_format_entity = DateFormat::load('html_time')) { - /** @var $time_format_entity \Drupal\Core\Datetime\DateFormatInterface */ + /** @var \Drupal\Core\Datetime\DateFormatInterface $time_format_entity */ $time_format = $time_format_entity->getPattern(); } } diff --git a/tests/Drupal/Commenting/InlineCommentUnitTest.inc.fixed b/tests/Drupal/Commenting/InlineCommentUnitTest.inc.fixed index 23f410d43997a8f3b07e00a1bc59d28fce814132..4dd627a87a41ccf267c65f149c8aada320e2b2b5 100644 --- a/tests/Drupal/Commenting/InlineCommentUnitTest.inc.fixed +++ b/tests/Drupal/Commenting/InlineCommentUnitTest.inc.fixed @@ -101,11 +101,11 @@ function test2() { // Date formats cannot be loaded during install or update. if (!defined('MAINTENANCE_MODE')) { if ($date_format_entity = DateFormat::load('html_date')) { - /** @var $date_format_entity \Drupal\Core\Datetime\DateFormatInterface */ + /** @var \Drupal\Core\Datetime\DateFormatInterface $date_format_entity */ $date_format = $date_format_entity->getPattern(); } if ($time_format_entity = DateFormat::load('html_time')) { - /** @var $time_format_entity \Drupal\Core\Datetime\DateFormatInterface */ + /** @var \Drupal\Core\Datetime\DateFormatInterface $time_format_entity */ $time_format = $time_format_entity->getPattern(); } } diff --git a/tests/Drupal/Commenting/InlineVariableCommentUnitTest.inc b/tests/Drupal/Commenting/InlineVariableCommentUnitTest.inc new file mode 100644 index 0000000000000000000000000000000000000000..05831df5bbfa4e6e38fbb728af391404888e5ba8 --- /dev/null +++ b/tests/Drupal/Commenting/InlineVariableCommentUnitTest.inc @@ -0,0 +1,20 @@ +<?php + +/** + * @file + */ + +/** + * Ipsum. + */ +function lorem() { + /* @var \Drupal\node\NodeInterface $node */ + /* @var $node \Drupal\node\NodeInterface */ + /** @var $node \Drupal\node\NodeInterface */ + /** @var \Drupal\node\NodeInterface $node */ + // @var \Drupal\node\NodeInterface $node + // @var $node \Drupal\node\NodeInterface + # @var \Drupal\node\NodeInterface $node + # @var $node \Drupal\node\NodeInterface + $node = Node::load(1); +} diff --git a/tests/Drupal/Commenting/InlineVariableCommentUnitTest.inc.fixed b/tests/Drupal/Commenting/InlineVariableCommentUnitTest.inc.fixed new file mode 100644 index 0000000000000000000000000000000000000000..141270b39a2c620eec6bb545f1cf3c611e5d64ce --- /dev/null +++ b/tests/Drupal/Commenting/InlineVariableCommentUnitTest.inc.fixed @@ -0,0 +1,20 @@ +<?php + +/** + * @file + */ + +/** + * Ipsum. + */ +function lorem() { + /** @var \Drupal\node\NodeInterface $node */ + /** @var \Drupal\node\NodeInterface $node */ + /** @var \Drupal\node\NodeInterface $node */ + /** @var \Drupal\node\NodeInterface $node */ + /** @var \Drupal\node\NodeInterface $node */ + /** @var \Drupal\node\NodeInterface $node */ + /** @var \Drupal\node\NodeInterface $node */ + /** @var \Drupal\node\NodeInterface $node */ + $node = Node::load(1); +} diff --git a/tests/Drupal/Commenting/InlineVariableCommentUnitTest.php b/tests/Drupal/Commenting/InlineVariableCommentUnitTest.php new file mode 100644 index 0000000000000000000000000000000000000000..12e1987a7fa93d37198230b2ce60d0a372d1197c --- /dev/null +++ b/tests/Drupal/Commenting/InlineVariableCommentUnitTest.php @@ -0,0 +1,53 @@ +<?php + +namespace Drupal\Test\Commenting; + +use Drupal\Test\CoderSniffUnitTest; + +class InlineVariableCommentUnitTest extends CoderSniffUnitTest +{ + + + /** + * Returns the lines where errors should occur. + * + * The key of the array should represent the line number and the value + * should represent the number of errors that should occur on that line. + * + * @param string $testFile The name of the file being tested. + * + * @return array<int, int> + */ + protected function getErrorList(string $testFile): array + { + return []; + + }//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<int, int> + */ + protected function getWarningList(string $testFile): array + { + return [ + 11 => 1, + 12 => 1, + 13 => 1, + 15 => 1, + 16 => 1, + 17 => 1, + 18 => 1, + ]; + + }//end getWarningList() + + +}//end class