From 4966b545db497e038b3ba01fd21c0899be9365a9 Mon Sep 17 00:00:00 2001 From: Greg Sherwood Date: Wed, 13 Jan 2016 10:22:08 +1100 Subject: [PATCH] PEAR and Squiz FunctionComment sniffs now support variadic functions (request #841) --- CodeSniffer/File.php | 6 +++++ .../Commenting/FunctionCommentSniff.php | 10 +++++++- .../Commenting/FunctionCommentUnitTest.inc | 23 +++++++++++++++++++ .../Commenting/FunctionCommentUnitTest.php | 2 ++ .../Commenting/FunctionCommentSniff.php | 10 +++++++- .../Commenting/FunctionCommentUnitTest.inc | 23 +++++++++++++++++++ .../Commenting/FunctionCommentUnitTest.php | 4 ++++ package.xml | 1 + tests/Core/File/GetMethodParametersTest.php | 9 +++++++- 9 files changed, 85 insertions(+), 3 deletions(-) diff --git a/CodeSniffer/File.php b/CodeSniffer/File.php index f57a208173..4f1a29758e 100644 --- a/CodeSniffer/File.php +++ b/CodeSniffer/File.php @@ -2729,6 +2729,7 @@ public function getMethodParameters($stackPtr) $defaultStart = null; $paramCount = 0; $passByReference = false; + $variableLength = false; $typeHint = ''; for ($i = ($opener + 1); $i <= $closer; $i++) { @@ -2757,6 +2758,9 @@ public function getMethodParameters($stackPtr) case T_VARIABLE: $currVar = $i; break; + case T_ELLIPSIS: + $variableLength = true; + break; case T_ARRAY_HINT: case T_CALLABLE: $typeHint = $this->_tokens[$i]['content']; @@ -2816,11 +2820,13 @@ public function getMethodParameters($stackPtr) } $vars[$paramCount]['pass_by_reference'] = $passByReference; + $vars[$paramCount]['variable_length'] = $variableLength; $vars[$paramCount]['type_hint'] = $typeHint; // Reset the vars, as we are about to process the next parameter. $defaultStart = null; $passByReference = false; + $variableLength = false; $typeHint = ''; $paramCount++; diff --git a/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php b/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php index 7ae5d02d25..25466668a4 100644 --- a/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php +++ b/CodeSniffer/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php @@ -225,7 +225,7 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $comment = ''; if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { $matches = array(); - preg_match('/([^$&]+)(?:((?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); + preg_match('/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); $typeLen = strlen($matches[1]); $type = trim($matches[1]); @@ -284,6 +284,14 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $realParams = $phpcsFile->getMethodParameters($stackPtr); $foundParams = array(); + // We want to use ... for all variable length arguments, so added + // this prefix to the variable name so comparisons are easier. + foreach ($realParams as $pos => $param) { + if ($param['variable_length'] === true) { + $realParams[$pos]['name'] = '...'.$realParams[$pos]['name']; + } + } + foreach ($params as $pos => $param) { if ($param['var'] === '') { continue; diff --git a/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc b/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc index 77e68175d6..83f99b9e23 100644 --- a/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc +++ b/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.inc @@ -297,3 +297,26 @@ class Baz { public function completeStep($status, array $array = [Class1::class, 'test'], $note = '') { echo 'foo'; } + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} diff --git a/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php b/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php index cd7286449c..5332f9108a 100644 --- a/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php +++ b/CodeSniffer/Standards/PEAR/Tests/Commenting/FunctionCommentUnitTest.php @@ -69,6 +69,8 @@ public function getErrorList() 206 => 1, 234 => 1, 272 => 1, + 313 => 1, + 317 => 1, ); }//end getErrorList() diff --git a/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php b/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php index 1d2fbe7b77..0cc2376e75 100644 --- a/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php +++ b/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentSniff.php @@ -251,7 +251,7 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $commentLines = array(); if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { $matches = array(); - preg_match('/([^$&]+)(?:((?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); + preg_match('/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); $typeLen = strlen($matches[1]); $type = trim($matches[1]); @@ -327,6 +327,14 @@ protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $co $realParams = $phpcsFile->getMethodParameters($stackPtr); $foundParams = array(); + // We want to use ... for all variable length arguments, so added + // this prefix to the variable name so comparisons are easier. + foreach ($realParams as $pos => $param) { + if ($param['variable_length'] === true) { + $realParams[$pos]['name'] = '...'.$realParams[$pos]['name']; + } + } + foreach ($params as $pos => $param) { // If the type is empty, the whole line is empty. if ($param['type'] === '') { diff --git a/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc b/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc index f315012a0e..683e3172e1 100644 --- a/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc +++ b/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.inc @@ -728,3 +728,26 @@ public function callableCallback(callable $cb) { */ public function myFunction (string $name1, int $name2, float $name3, bool $name4) { } + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string ...$name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} + + +/** + * Variadic function. + * + * @param string $name1 Comment. + * @param string $name2 Comment. + * + * @return void + */ +public function myFunction(string $name1, string ...$name2) { +} diff --git a/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php b/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php index d4d183df65..5f6d79a2fa 100644 --- a/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php +++ b/CodeSniffer/Standards/Squiz/Tests/Commenting/FunctionCommentUnitTest.php @@ -109,6 +109,8 @@ public function getErrorList() 548 => 1, 641 => 1, 669 => 1, + 744 => 1, + 748 => 1, ); // The yield tests will only work in PHP versions where yield exists and @@ -131,6 +133,8 @@ public function getErrorList() $errors[627] = 1; } else { $errors[729] = 4; + $errors[740] = 2; + $errors[752] = 2; } return $errors; diff --git a/package.xml b/package.xml index 4688119436..d743448823 100644 --- a/package.xml +++ b/package.xml @@ -34,6 +34,7 @@ http://pear.php.net/dtd/package-2.0.xsd"> - Squiz ComparisonOperatorUsageSniff no longer hangs on JS FOR loops that don't use semicolons - PHP_CodesSniffer now includes the composer autoload.php file, if there is one -- Thanks to Klaus Purer for the patch + - PEAR and Squiz FunctionComment sniffs now support variadic functions (request #841) - Fixed bug #622 : Wrong detection of Squiz.CSS.DuplicateStyleDefinition with media queries - Fixed bug #752 : The missing exception error is reported in first found DocBlock - Fixed bug #794 : PSR2 MultiLineFunctionDeclaration forbids comments after opening parenthesis of a multiline call diff --git a/tests/Core/File/GetMethodParametersTest.php b/tests/Core/File/GetMethodParametersTest.php index c8d96aa1a0..7524556bd3 100644 --- a/tests/Core/File/GetMethodParametersTest.php +++ b/tests/Core/File/GetMethodParametersTest.php @@ -85,6 +85,7 @@ public function testPassByReference() $expected[0] = array( 'name' => '$var', 'pass_by_reference' => true, + 'variable_length' => false, 'type_hint' => '', ); @@ -114,6 +115,7 @@ public function testArrayHint() $expected[0] = array( 'name' => '$var', 'pass_by_reference' => false, + 'variable_length' => false, 'type_hint' => 'array', ); @@ -143,12 +145,14 @@ public function testTypeHint() $expected[0] = array( 'name' => '$var1', 'pass_by_reference' => false, + 'variable_length' => false, 'type_hint' => 'foo', ); $expected[1] = array( 'name' => '$var2', 'pass_by_reference' => false, + 'variable_length' => false, 'type_hint' => 'bar', ); @@ -178,6 +182,7 @@ public function testVariable() $expected[0] = array( 'name' => '$var', 'pass_by_reference' => false, + 'variable_length' => false, 'type_hint' => '', ); @@ -208,6 +213,7 @@ public function testSingleDefaultValue() 'name' => '$var1', 'default' => 'self::CONSTANT', 'pass_by_reference' => false, + 'variable_length' => false, 'type_hint' => '', ); @@ -238,12 +244,14 @@ public function testDefaultValues() 'name' => '$var1', 'default' => '1', 'pass_by_reference' => false, + 'variable_length' => false, 'type_hint' => '', ); $expected[1] = array( 'name' => '$var2', 'default' => "'value'", 'pass_by_reference' => false, + 'variable_length' => false, 'type_hint' => '', ); @@ -274,4 +282,3 @@ public function testDefaultValues() // @codingStandardsIgnoreEnd ?> -