diff --git a/PHPCSUtils/Utils/PassedParameters.php b/PHPCSUtils/Utils/PassedParameters.php index c813f6df..2dddcb16 100644 --- a/PHPCSUtils/Utils/PassedParameters.php +++ b/PHPCSUtils/Utils/PassedParameters.php @@ -13,6 +13,7 @@ use PHP_CodeSniffer\Exceptions\RuntimeException; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Util\Tokens; +use PHPCSUtils\Tokens\Collections; use PHPCSUtils\Utils\Arrays; use PHPCSUtils\Utils\GetTokensAsString; @@ -64,7 +65,8 @@ class PassedParameters /** * Checks if any parameters have been passed. * - * - If passed a `T_STRING` or `T_VARIABLE` stack pointer, it will treat it as a function call. + * - If passed a `T_STRING`, `T_NAME_FULLY_QUALIFIED`, `T_NAME_RELATIVE`, `T_NAME_QUALIFIED` + * or `T_VARIABLE` stack pointer, it will treat it as a function call. * If a `T_STRING` or `T_VARIABLE` which is *not* a function call is passed, the behaviour is * undetermined. * - If passed a `T_SELF` or `T_STATIC` stack pointer, it will accept it as a @@ -75,10 +77,12 @@ class PassedParameters * language constructs have "parameters". * * @since 1.0.0 + * @since 1.0.0-alpha4 Added support for PHP 8.0 identifier name tokenization. * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. - * @param int $stackPtr The position of the `T_STRING`, `T_VARIABLE`, `T_ARRAY`, - * `T_OPEN_SHORT_ARRAY`, `T_ISSET`, or `T_UNSET` token. + * @param int $stackPtr The position of the `T_STRING`, PHP 8.0 identifier + * name token, `T_VARIABLE`, `T_ARRAY`, `T_OPEN_SHORT_ARRAY`, + * `T_ISSET`, or `T_UNSET` token. * * @return bool * @@ -89,7 +93,11 @@ public static function hasParameters(File $phpcsFile, $stackPtr) { $tokens = $phpcsFile->getTokens(); - if (isset($tokens[$stackPtr], self::$allowedConstructs[$tokens[$stackPtr]['code']]) === false) { + if (isset($tokens[$stackPtr]) === false + || (isset(self::$allowedConstructs[$tokens[$stackPtr]['code']]) === false + // Allow for the PHP 8.0 identifier name tokens. + && isset(Collections::nameTokens()[$tokens[$stackPtr]['code']]) === false) + ) { throw new RuntimeException( 'The hasParameters() method expects a function call, array, isset or unset token to be passed.' ); @@ -159,8 +167,9 @@ public static function hasParameters(File $phpcsFile, $stackPtr) * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. - * @param int $stackPtr The position of the `T_STRING`, `T_VARIABLE`, `T_ARRAY`, - * `T_OPEN_SHORT_ARRAY`, `T_ISSET`, or `T_UNSET` token. + * @param int $stackPtr The position of the `T_STRING`, PHP 8.0 identifier + * name token, `T_VARIABLE`, `T_ARRAY`, `T_OPEN_SHORT_ARRAY`, + * `T_ISSET`, or `T_UNSET` token. * * @return array A multi-dimentional array information on each parameter/array item. * The information gathered about each parameter/array item is in the following format: @@ -281,8 +290,9 @@ public static function getParameters(File $phpcsFile, $stackPtr) * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. - * @param int $stackPtr The position of the `T_STRING`, `T_VARIABLE`, `T_ARRAY`, - * `T_OPEN_SHORT_ARRAY`, `T_ISSET` or `T_UNSET` token. + * @param int $stackPtr The position of the `T_STRING`, PHP 8.0 identifier + * name token, `T_VARIABLE`, `T_ARRAY`, `T_OPEN_SHORT_ARRAY`, + * `T_ISSET`, or `T_UNSET` token. * @param int $paramOffset The 1-based index position of the parameter to retrieve. * * @return array|false Array with information on the parameter/array item at the specified offset. @@ -319,8 +329,9 @@ public static function getParameter(File $phpcsFile, $stackPtr, $paramOffset) * @since 1.0.0 * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. - * @param int $stackPtr The position of the `T_STRING`, `T_VARIABLE`, `T_ARRAY`, - * `T_OPEN_SHORT_ARRAY`, `T_ISSET` or `T_UNSET` token. + * @param int $stackPtr The position of the `T_STRING`, PHP 8.0 identifier + * name token, `T_VARIABLE`, `T_ARRAY`, `T_OPEN_SHORT_ARRAY`, + * `T_ISSET`, or `T_UNSET` token. * * @return int * diff --git a/Tests/Utils/PassedParameters/GetParameterCountTest.inc b/Tests/Utils/PassedParameters/GetParameterCountTest.inc index 63c66a72..b605ce01 100644 --- a/Tests/Utils/PassedParameters/GetParameterCountTest.inc +++ b/Tests/Utils/PassedParameters/GetParameterCountTest.inc @@ -150,6 +150,18 @@ json_encode(['a' => $a, 'b' => $b, 'c' => $c]); /* testFunctionCall47 */ json_encode(['a' => $a, 'b' => $b, 'c' => $c,] + ['c' => $c, 'd' => $d,]); +/* testFunctionCallFullyQualified */ +\myfunction( $a ); + +/* testFunctionCallFullyQualifiedWithNamespace */ +\My\Named\myfunction( $a ); + +/* testFunctionCallPartiallyQualified */ +Partially\Qualified\myfunction( $a ); + +/* testFunctionCallNamespaceOperator */ +namespace\myfunction( $a ); + /* testLongArray1 */ $foo = array( 1, 2, 3, 4, 5, 6, true ); diff --git a/Tests/Utils/PassedParameters/GetParameterCountTest.php b/Tests/Utils/PassedParameters/GetParameterCountTest.php index 82d57ed2..38364be5 100644 --- a/Tests/Utils/PassedParameters/GetParameterCountTest.php +++ b/Tests/Utils/PassedParameters/GetParameterCountTest.php @@ -11,6 +11,7 @@ namespace PHPCSUtils\Tests\Utils\PassedParameters; use PHPCSUtils\TestUtils\UtilityMethodTestCase; +use PHPCSUtils\Tokens\Collections; use PHPCSUtils\Utils\PassedParameters; /** @@ -32,17 +33,22 @@ class GetParameterCountTest extends UtilityMethodTestCase * * @dataProvider dataGetParameterCount * - * @param string $testMarker The comment which prefaces the target token in the test file. - * @param int $expected The expected parameter count. + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int $expected The expected parameter count. + * @param string $targetContent Optional. The content of the target token to find. + * Defaults to null (ignore content). * * @return void */ - public function testGetParameterCount($testMarker, $expected) + public function testGetParameterCount($testMarker, $expected, $targetContent = null) { - $stackPtr = $this->getTargetToken( - $testMarker, - [\T_STRING, \T_ARRAY, \T_OPEN_SHORT_ARRAY, \T_ISSET, \T_UNSET] - ); + $targetTypes = Collections::nameTokens(); + $targetTypes[\T_ARRAY] = \T_ARRAY; + $targetTypes[\T_OPEN_SHORT_ARRAY] = \T_OPEN_SHORT_ARRAY; + $targetTypes[\T_ISSET] = \T_ISSET; + $targetTypes[\T_UNSET] = \T_UNSET; + + $stackPtr = $this->getTargetToken($testMarker, $targetTypes, $targetContent); $result = PassedParameters::getParameterCount(self::$phpcsFile, $stackPtr); $this->assertSame($expected, $result); } @@ -56,6 +62,8 @@ public function testGetParameterCount($testMarker, $expected) */ public function dataGetParameterCount() { + $php8Names = parent::usesPhp8NameTokens(); + return [ 'function-call-0' => [ '/* testFunctionCall0 */', @@ -249,6 +257,26 @@ public function dataGetParameterCount() '/* testFunctionCall47 */', 1, ], + 'function-call-fully-qualified' => [ + '/* testFunctionCallFullyQualified */', + 1, + ($php8Names === true) ? null : 'myfunction', + ], + 'function-call-fully-qualified-with-namespace' => [ + '/* testFunctionCallFullyQualifiedWithNamespace */', + 1, + ($php8Names === true) ? null : 'myfunction', + ], + 'function-call-partially-qualified' => [ + '/* testFunctionCallPartiallyQualified */', + 1, + ($php8Names === true) ? null : 'myfunction', + ], + 'function-call-namespace-operator' => [ + '/* testFunctionCallNamespaceOperator */', + 1, + ($php8Names === true) ? null : 'myfunction', + ], // Long arrays. 'long-array-1' => [ diff --git a/Tests/Utils/PassedParameters/HasParametersTest.inc b/Tests/Utils/PassedParameters/HasParametersTest.inc index 3c05a5c7..f814705c 100644 --- a/Tests/Utils/PassedParameters/HasParametersTest.inc +++ b/Tests/Utils/PassedParameters/HasParametersTest.inc @@ -42,6 +42,19 @@ class Bar { } } +/* testNoParamsFunctionCallFullyQualified */ +\myfunction( ); + +/* testHasParamsFunctionCallFullyQualifiedWithNamespace */ +\My\Named\myfunction( $a ); + +/* testNoParamsFunctionCallPartiallyQualified */ +Partially\Qualified\myfunction(); + +/* testHasParamsFunctionCallNamespaceOperator */ +namespace\myfunction( $a ); + + // Arrays: no parameters. /* testNoParamsLongArray1 */ diff --git a/Tests/Utils/PassedParameters/HasParametersTest.php b/Tests/Utils/PassedParameters/HasParametersTest.php index 36290a5e..0e74837b 100644 --- a/Tests/Utils/PassedParameters/HasParametersTest.php +++ b/Tests/Utils/PassedParameters/HasParametersTest.php @@ -93,15 +93,17 @@ public function testNotAShortArray() * * @dataProvider dataHasParameters * - * @param string $testMarker The comment which prefaces the target token in the test file. - * @param int|string $targetType The type of token to look for. - * @param bool $expected Whether or not the function/array has parameters/values. + * @param string $testMarker The comment which prefaces the target token in the test file. + * @param int|string $targetType The type of token to look for. + * @param bool $expected Whether or not the function/array has parameters/values. + * @param string $targetContent Optional. The content of the target token to find. + * Defaults to null (ignore content). * * @return void */ - public function testHasParameters($testMarker, $targetType, $expected) + public function testHasParameters($testMarker, $targetType, $expected, $targetContent = null) { - $stackPtr = $this->getTargetToken($testMarker, $targetType); + $stackPtr = $this->getTargetToken($testMarker, $targetType, $targetContent); $result = PassedParameters::hasParameters(self::$phpcsFile, $stackPtr); $this->assertSame($expected, $result); } @@ -115,6 +117,8 @@ public function testHasParameters($testMarker, $targetType, $expected) */ public function dataHasParameters() { + $php8Names = parent::usesPhp8NameTokens(); + return [ // Function calls. 'no-params-function-call-1' => [ @@ -153,6 +157,30 @@ public function dataHasParameters() [\T_SELF, \T_STRING], true, ], + 'no-params-function-call-fully-qualified' => [ + '/* testNoParamsFunctionCallFullyQualified */', + ($php8Names === true) ? \T_NAME_FULLY_QUALIFIED : \T_STRING, + false, + ($php8Names === true) ? null : 'myfunction', + ], + 'has-params-function-call-fully-qualified-with-namespace' => [ + '/* testHasParamsFunctionCallFullyQualifiedWithNamespace */', + ($php8Names === true) ? \T_NAME_FULLY_QUALIFIED : \T_STRING, + true, + ($php8Names === true) ? null : 'myfunction', + ], + 'no-params-function-call-partially-qualified' => [ + '/* testNoParamsFunctionCallPartiallyQualified */', + ($php8Names === true) ? \T_NAME_QUALIFIED : \T_STRING, + false, + ($php8Names === true) ? null : 'myfunction', + ], + 'has-params-function-call-namespace-operator-relative' => [ + '/* testHasParamsFunctionCallNamespaceOperator */', + ($php8Names === true) ? \T_NAME_RELATIVE : \T_STRING, + true, + ($php8Names === true) ? null : 'myfunction', + ], // Arrays. 'no-params-long-array-1' => [