Skip to content

Commit

Permalink
Merge pull request #368 from PHPCSStandards/php-8.2/add-support-true-…
Browse files Browse the repository at this point in the history
…type

PHP 8.2: add support for `true` type
  • Loading branch information
jrfnl committed Oct 15, 2022
2 parents bdc9d70 + aef1a01 commit c2a08c5
Show file tree
Hide file tree
Showing 12 changed files with 311 additions and 10 deletions.
9 changes: 9 additions & 0 deletions PHPCSUtils/Tokens/Collections.php
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ class Collections
* @since 1.0.0-alpha1
* @since 1.0.0-alpha4 Added the T_TYPE_UNION, T_FALSE, T_NULL tokens for PHP 8.0 union type support.
* @since 1.0.0-alpha4 Added the T_TYPE_INTERSECTION token for PHP 8.1 intersection type support.
* @since 1.0.0-alpha4 Added the T_TRUE token for PHP 8.2 true type support.
*
* @deprecated 1.0.0-alpha4 Use the {@see Collections::parameterTypeTokens()} method instead.
*
Expand All @@ -486,6 +487,7 @@ class Collections
\T_SELF => \T_SELF,
\T_PARENT => \T_PARENT,
\T_FALSE => \T_FALSE,
\T_TRUE => \T_TRUE,
\T_NULL => \T_NULL,
\T_STRING => \T_STRING,
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
Expand Down Expand Up @@ -530,6 +532,7 @@ class Collections
* @since 1.0.0-alpha1
* @since 1.0.0-alpha4 Added the T_TYPE_UNION, T_FALSE, T_NULL tokens for PHP 8.0 union type support.
* @since 1.0.0-alpha4 Added the T_TYPE_INTERSECTION token for PHP 8.1 intersection type support.
* @since 1.0.0-alpha4 Added the T_TRUE token for PHP 8.2 true type support.
*
* @deprecated 1.0.0-alpha4 Use the {@see Collections::propertyTypeTokens()} method instead.
*
Expand All @@ -540,6 +543,7 @@ class Collections
\T_SELF => \T_SELF,
\T_PARENT => \T_PARENT,
\T_FALSE => \T_FALSE,
\T_TRUE => \T_TRUE,
\T_NULL => \T_NULL,
\T_STRING => \T_STRING,
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
Expand All @@ -553,6 +557,7 @@ class Collections
* @since 1.0.0-alpha1
* @since 1.0.0-alpha4 Added the T_TYPE_UNION, T_FALSE, T_NULL tokens for PHP 8.0 union type support.
* @since 1.0.0-alpha4 Added the T_TYPE_INTERSECTION token for PHP 8.1 intersection type support.
* @since 1.0.0-alpha4 Added the T_TRUE token for PHP 8.2 true type support.
*
* @deprecated 1.0.0-alpha4 Use the {@see Collections::returnTypeTokens()} method instead.
*
Expand All @@ -564,6 +569,7 @@ class Collections
\T_PARENT => \T_PARENT,
\T_STATIC => \T_STATIC,
\T_FALSE => \T_FALSE,
\T_TRUE => \T_TRUE,
\T_NULL => \T_NULL,
\T_STRING => \T_STRING,
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
Expand Down Expand Up @@ -922,6 +928,7 @@ public static function parameterPassingTokens()
* @since 1.0.0-alpha4 Added the T_TYPE_UNION, T_FALSE, T_NULL tokens for PHP 8.0 union type support.
* @since 1.0.0-alpha4 Added support for PHP 8.0 identifier name tokens.
* @since 1.0.0-alpha4 Added the T_TYPE_INTERSECTION token for PHP 8.1 intersection type support.
* @since 1.0.0-alpha4 Added the T_TRUE token for PHP 8.2 true type support.
*
* @return array <int|string> => <int|string>
*/
Expand Down Expand Up @@ -962,6 +969,7 @@ public static function parameterTypeTokensBC()
* @since 1.0.0-alpha4 Added the T_TYPE_UNION, T_FALSE, T_NULL tokens for PHP 8.0 union type support.
* @since 1.0.0-alpha4 Added support for PHP 8.0 identifier name tokens.
* @since 1.0.0-alpha4 Added the T_TYPE_INTERSECTION token for PHP 8.1 intersection type support.
* @since 1.0.0-alpha4 Added the T_TRUE token for PHP 8.2 true type support.
*
* @return array <int|string> => <int|string>
*/
Expand Down Expand Up @@ -1002,6 +1010,7 @@ public static function propertyTypeTokensBC()
* @since 1.0.0-alpha4 Added the T_TYPE_UNION, T_FALSE, T_NULL tokens for PHP 8.0 union type support.
* @since 1.0.0-alpha4 Added support for PHP 8.0 identifier name tokens.
* @since 1.0.0-alpha4 Added the T_TYPE_INTERSECTION token for PHP 8.1 intersection type support.
* @since 1.0.0-alpha4 Added the T_TRUE token for PHP 8.2 true type support.
*
* @return array <int|string> => <int|string>
*/
Expand Down
20 changes: 19 additions & 1 deletion PHPCSUtils/Utils/FunctionDeclarations.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ public static function getName(File $phpcsFile, $stackPtr)
* - Defensive coding against incorrect calls to this method.
* - More efficient checking whether a function has a body.
* - Support for PHP 8.0 identifier name tokens in return types, cross-version PHP & PHPCS.
* - Support for the PHP 8.2 `true` type.
*
* @see \PHP_CodeSniffer\Files\File::getMethodProperties() Original source.
* @see \PHPCSUtils\BackCompat\BCFile::getMethodProperties() Cross-version compatible version of the original.
Expand All @@ -157,6 +158,7 @@ public static function getName(File $phpcsFile, $stackPtr)
* @since 1.0.0-alpha3 Added support for PHP 8.0 static return type.
* @since 1.0.0-alpha4 Added support for PHP 8.0 union types.
* @since 1.0.0-alpha4 Added support for PHP 8.1 intersection types.
* @since 1.0.0-alpha4 Added support for PHP 8.2 true type.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position in the stack of the function token to
Expand Down Expand Up @@ -246,6 +248,12 @@ public static function getProperties(File $phpcsFile, $stackPtr)
$hasBody = false;
$returnTypeTokens = Collections::returnTypeTokens();

/*
* BC PHPCS < 3.x.x: The union type separator is not (yet) retokenized correctly
* for union types containing the `true` type.
*/
$returnTypeTokens[\T_BITWISE_OR] = \T_BITWISE_OR;

$parenthesisCloser = null;
if (isset($tokens[$stackPtr]['parenthesis_closer']) === true) {
$parenthesisCloser = $tokens[$stackPtr]['parenthesis_closer'];
Expand Down Expand Up @@ -354,6 +362,7 @@ public static function getProperties(File $phpcsFile, $stackPtr)
* - More efficient and more stable looping of the default value.
* - Clearer exception message when a non-closure use token was passed to the function.
* - Support for PHP 8.0 identifier name tokens in parameter types, cross-version PHP & PHPCS.
* - Support for the PHP 8.2 `true` type.
*
* @see \PHP_CodeSniffer\Files\File::getMethodParameters() Original source.
* @see \PHPCSUtils\BackCompat\BCFile::getMethodParameters() Cross-version compatible version of the original.
Expand All @@ -366,6 +375,7 @@ public static function getProperties(File $phpcsFile, $stackPtr)
* @since 1.0.0-alpha4 Added support for PHP 8.0 parameter attributes.
* @since 1.0.0-alpha4 Added support for PHP 8.1 readonly keyword for constructor property promotion.
* @since 1.0.0-alpha4 Added support for PHP 8.1 intersection types.
* @since 1.0.0-alpha4 Added support for PHP 8.2 true type.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position in the stack of the function token
Expand Down Expand Up @@ -433,8 +443,16 @@ public static function getParameters(File $phpcsFile, $stackPtr)
$visibilityToken = null;
$readonlyToken = null;

$parameterTypeTokens = Collections::parameterTypeTokens();

/*
* BC PHPCS < 3.x.x: The union type separator is not (yet) retokenized correctly
* for union types containing the `true` type.
*/
$parameterTypeTokens[\T_BITWISE_OR] = \T_BITWISE_OR;

for ($i = $paramStart; $i <= $closer; $i++) {
if (isset(Collections::parameterTypeTokens()[$tokens[$i]['code']]) === true
if (isset($parameterTypeTokens[$tokens[$i]['code']]) === true
// Self and parent are valid, static invalid, but was probably intended as type declaration.
|| $tokens[$i]['code'] === \T_STATIC
) {
Expand Down
8 changes: 8 additions & 0 deletions PHPCSUtils/Utils/Variables.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class Variables
* other non-property variables passed to the method.
* - Defensive coding against incorrect calls to this method.
* - Support PHP 8.0 identifier name tokens in property types, cross-version PHP & PHPCS.
* - Support for the PHP 8.2 `true` type.
*
* @see \PHP_CodeSniffer\Files\File::getMemberProperties() Original source.
* @see \PHPCSUtils\BackCompat\BCFile::getMemberProperties() Cross-version compatible version of the original.
Expand All @@ -91,6 +92,7 @@ class Variables
* @since 1.0.0-alpha4 No longer gets confused by PHP 8.0 property attributes.
* @since 1.0.0-alpha4 Added support for PHP 8.1 readonly properties.
* @since 1.0.0-alpha4 Added support for PHP 8.1 intersection types.
* @since 1.0.0-alpha4 Added support for PHP 8.2 true type.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position in the stack of the `T_VARIABLE` token
Expand Down Expand Up @@ -181,6 +183,12 @@ public static function getMemberProperties(File $phpcsFile, $stackPtr)
$nullableType = false;
$propertyTypeTokens = Collections::propertyTypeTokens();

/*
* BC PHPCS < 3.x.x: The union type separator is not (yet) retokenized correctly
* for union types containing the `true` type.
*/
$propertyTypeTokens[\T_BITWISE_OR] = \T_BITWISE_OR;

if ($i < $stackPtr) {
// We've found a type.
for ($i; $i < $stackPtr; $i++) {
Expand Down
1 change: 1 addition & 0 deletions Tests/Tokens/Collections/ParameterTypeTokensTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public function testParameterTypeTokens()
\T_SELF => \T_SELF,
\T_PARENT => \T_PARENT,
\T_FALSE => \T_FALSE,
\T_TRUE => \T_TRUE,
\T_NULL => \T_NULL,
\T_STRING => \T_STRING,
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
Expand Down
1 change: 1 addition & 0 deletions Tests/Tokens/Collections/PropertyTypeTokensTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public function testPropertyTypeTokens()
\T_SELF => \T_SELF,
\T_PARENT => \T_PARENT,
\T_FALSE => \T_FALSE,
\T_TRUE => \T_TRUE,
\T_NULL => \T_NULL,
\T_STRING => \T_STRING,
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
Expand Down
1 change: 1 addition & 0 deletions Tests/Tokens/Collections/ReturnTypeTokensTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function testReturnTypeTokens()
\T_PARENT => \T_PARENT,
\T_STATIC => \T_STATIC,
\T_FALSE => \T_FALSE,
\T_TRUE => \T_TRUE,
\T_NULL => \T_NULL,
\T_STRING => \T_STRING,
\T_NS_SEPARATOR => \T_NS_SEPARATOR,
Expand Down
8 changes: 8 additions & 0 deletions Tests/Utils/FunctionDeclarations/GetParametersDiffTest.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

/* testPHP82PseudoTypeTrue */
function pseudoTypeTrue(?true $var = true) {}

/* testPHP82PseudoTypeFalseAndTrue */
// Intentional fatal error - Type contains both true and false, bool should be used instead, but that's not the concern of the method.
function pseudoTypeFalseAndTrue(true|false $var = true) {}
115 changes: 106 additions & 9 deletions Tests/Utils/FunctionDeclarations/GetParametersDiffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,124 @@ class GetParametersDiffTest extends UtilityMethodTestCase
{

/**
* Initialize PHPCS & tokenize the test case file.
* Test passing a non-existent token pointer.
*
* @beforeClass
* @return void
*/
public function testNonExistentToken()
{
$this->expectPhpcsException('$stackPtr must be of type T_FUNCTION, T_CLOSURE or T_USE or an arrow function');

FunctionDeclarations::getParameters(self::$phpcsFile, 10000);
}

/**
* Verify recognition of PHP 8.2 stand-alone `true` type.
*
* @return void
*/
public static function setUpTestFile()
public function testPHP82PseudoTypeTrue()
{
self::$caseFile = \dirname(\dirname(__DIR__)) . '/DummyFile.inc';
parent::setUpTestFile();
$expected = [];
$expected[0] = [
'token' => 7, // Offset from the T_FUNCTION token.
'name' => '$var',
'content' => '?true $var = true',
'default' => 'true',
'default_token' => 11, // Offset from the T_FUNCTION token.
'default_equal_token' => 9, // Offset from the T_FUNCTION token.
'has_attributes' => false,
'pass_by_reference' => false,
'reference_token' => false,
'variable_length' => false,
'variadic_token' => false,
'type_hint' => '?true',
'type_hint_token' => 5, // Offset from the T_FUNCTION token.
'type_hint_end_token' => 5, // Offset from the T_FUNCTION token.
'nullable_type' => true,
'comma_token' => false,
];

$this->getMethodParametersTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
}

/**
* Test passing a non-existent token pointer.
* Verify recognition of PHP 8.2 type declaration with (illegal) type false combined with type true.
*
* @return void
*/
public function testNonExistentToken()
public function testPHP82PseudoTypeFalseAndTrue()
{
$this->expectPhpcsException('$stackPtr must be of type T_FUNCTION, T_CLOSURE or T_USE or an arrow function');
$expected = [];
$expected[0] = [
'token' => 8, // Offset from the T_FUNCTION token.
'name' => '$var',
'content' => 'true|false $var = true',
'default' => 'true',
'default_token' => 12, // Offset from the T_FUNCTION token.
'default_equal_token' => 10, // Offset from the T_FUNCTION token.
'has_attributes' => false,
'pass_by_reference' => false,
'reference_token' => false,
'variable_length' => false,
'variadic_token' => false,
'type_hint' => 'true|false',
'type_hint_token' => 4, // Offset from the T_FUNCTION token.
'type_hint_end_token' => 6, // Offset from the T_FUNCTION token.
'nullable_type' => false,
'comma_token' => false,
];

FunctionDeclarations::getParameters(self::$phpcsFile, 10000);
$this->getMethodParametersTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
}

/**
* Test helper.
*
* @param string $marker The comment which preceeds the test.
* @param array $expected The expected function output.
* @param array $targetType Optional. The token type to search for after $marker.
* Defaults to the function/closure/arrow tokens.
*
* @return void
*/
protected function getMethodParametersTestHelper($marker, $expected, $targetType = [\T_FUNCTION, \T_CLOSURE, \T_FN])
{
$target = $this->getTargetToken($marker, $targetType);
$found = FunctionDeclarations::getParameters(self::$phpcsFile, $target);

foreach ($expected as $key => $param) {
$expected[$key]['token'] += $target;

if ($param['reference_token'] !== false) {
$expected[$key]['reference_token'] += $target;
}
if ($param['variadic_token'] !== false) {
$expected[$key]['variadic_token'] += $target;
}
if ($param['type_hint_token'] !== false) {
$expected[$key]['type_hint_token'] += $target;
}
if ($param['type_hint_end_token'] !== false) {
$expected[$key]['type_hint_end_token'] += $target;
}
if ($param['comma_token'] !== false) {
$expected[$key]['comma_token'] += $target;
}
if (isset($param['default_token'])) {
$expected[$key]['default_token'] += $target;
}
if (isset($param['default_equal_token'])) {
$expected[$key]['default_equal_token'] += $target;
}
if (isset($param['visibility_token'])) {
$expected[$key]['visibility_token'] += $target;
}
if (isset($param['readonly_token'])) {
$expected[$key]['readonly_token'] += $target;
}
}

$this->assertSame($expected, $found);
}
}
7 changes: 7 additions & 0 deletions Tests/Utils/FunctionDeclarations/GetPropertiesDiffTest.inc
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,10 @@ trait FooTrait {
$func();
}
}

/* testPHP82PseudoTypeTrue */
function pseudoTypeTrue(): ?true {}

/* testPHP82PseudoTypeFalseAndTrue */
// Intentional fatal error - Type contains both true and false, bool should be used instead, but that's not the concern of the method.
function pseudoTypeFalseAndTrue(): true|false {}
46 changes: 46 additions & 0 deletions Tests/Utils/FunctionDeclarations/GetPropertiesDiffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,52 @@ public function testMessyPhpcsAnnotationsStaticClosure()
$this->getPropertiesTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
}

/**
* Verify recognition of PHP 8.2 stand-alone `true` type.
*
* @return void
*/
public function testPHP82PseudoTypeTrue()
{
$expected = [
'scope' => 'public',
'scope_specified' => false,
'return_type' => '?true',
'return_type_token' => 8, // Offset from the T_FUNCTION token.
'return_type_end_token' => 8, // Offset from the T_FUNCTION token.
'nullable_return_type' => true,
'is_abstract' => false,
'is_final' => false,
'is_static' => false,
'has_body' => true,
];

$this->getPropertiesTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
}

/**
* Verify recognition of PHP 8.2 type declaration with (illegal) type false combined with type true.
*
* @return void
*/
public function testPHP82PseudoTypeFalseAndTrue()
{
$expected = [
'scope' => 'public',
'scope_specified' => false,
'return_type' => 'true|false',
'return_type_token' => 7, // Offset from the T_FUNCTION token.
'return_type_end_token' => 9, // Offset from the T_FUNCTION token.
'nullable_return_type' => false,
'is_abstract' => false,
'is_final' => false,
'is_static' => false,
'has_body' => true,
];

$this->getPropertiesTestHelper('/* ' . __FUNCTION__ . ' */', $expected);
}

/**
* Test helper.
*
Expand Down
Loading

0 comments on commit c2a08c5

Please sign in to comment.