Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PassedParameters::hasParameters(): compatibility with the PHP 8 identifier name tokenization #211

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions PHPCSUtils/Utils/PassedParameters.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand All @@ -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
*
Expand All @@ -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.'
);
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
*
Expand Down
12 changes: 12 additions & 0 deletions Tests/Utils/PassedParameters/GetParameterCountTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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 );

Expand Down
42 changes: 35 additions & 7 deletions Tests/Utils/PassedParameters/GetParameterCountTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
namespace PHPCSUtils\Tests\Utils\PassedParameters;

use PHPCSUtils\TestUtils\UtilityMethodTestCase;
use PHPCSUtils\Tokens\Collections;
use PHPCSUtils\Utils\PassedParameters;

/**
Expand All @@ -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);
}
Expand All @@ -56,6 +62,8 @@ public function testGetParameterCount($testMarker, $expected)
*/
public function dataGetParameterCount()
{
$php8Names = parent::usesPhp8NameTokens();

return [
'function-call-0' => [
'/* testFunctionCall0 */',
Expand Down Expand Up @@ -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' => [
Expand Down
13 changes: 13 additions & 0 deletions Tests/Utils/PassedParameters/HasParametersTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
38 changes: 33 additions & 5 deletions Tests/Utils/PassedParameters/HasParametersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -115,6 +117,8 @@ public function testHasParameters($testMarker, $targetType, $expected)
*/
public function dataHasParameters()
{
$php8Names = parent::usesPhp8NameTokens();

return [
// Function calls.
'no-params-function-call-1' => [
Expand Down Expand Up @@ -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' => [
Expand Down