diff --git a/PHPCSUtils/Tokens/Collections.php b/PHPCSUtils/Tokens/Collections.php index 7b743dee..1b843144 100644 --- a/PHPCSUtils/Tokens/Collections.php +++ b/PHPCSUtils/Tokens/Collections.php @@ -164,6 +164,7 @@ class Collections * DEPRECATED: Modifier keywords which can be used for a class declaration. * * @since 1.0.0-alpha1 + * @since 1.0.0-alpha4 Added the T_READONLY token for PHP 8.2 readonly classes. * * @deprecated 1.0.0-alpha4 Use the {@see Collections::classModifierKeywords()} method instead. * @@ -172,6 +173,7 @@ class Collections public static $classModifierKeywords = [ \T_FINAL => \T_FINAL, \T_ABSTRACT => \T_ABSTRACT, + \T_READONLY => \T_READONLY, ]; /** diff --git a/PHPCSUtils/Utils/ObjectDeclarations.php b/PHPCSUtils/Utils/ObjectDeclarations.php index 956ab1cb..61dc2fd9 100644 --- a/PHPCSUtils/Utils/ObjectDeclarations.php +++ b/PHPCSUtils/Utils/ObjectDeclarations.php @@ -138,11 +138,13 @@ public static function getName(File $phpcsFile, $stackPtr) * - Handling of PHPCS annotations. * - Handling of unorthodox docblock placement. * - Defensive coding against incorrect calls to this method. + * - Support for PHP 8.2 readonly classes. * * @see \PHP_CodeSniffer\Files\File::getClassProperties() Original source. * @see \PHPCSUtils\BackCompat\BCFile::getClassProperties() Cross-version compatible version of the original. * * @since 1.0.0 + * @since 1.0.0-alpha4 Added support for the PHP 8.2 readonly keyword. * * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. * @param int $stackPtr The position in the stack of the `T_CLASS` @@ -154,6 +156,7 @@ public static function getName(File $phpcsFile, $stackPtr) * array( * 'is_abstract' => false, // TRUE if the abstract keyword was found. * 'is_final' => false, // TRUE if the final keyword was found. + * 'is_readonly' => false, // TRUE if the readonly keyword was found. * ); * ``` * @@ -172,6 +175,7 @@ public static function getClassProperties(File $phpcsFile, $stackPtr) $properties = [ 'is_abstract' => false, 'is_final' => false, + 'is_readonly' => false, ]; for ($i = ($stackPtr - 1); $i > 0; $i--) { @@ -187,6 +191,10 @@ public static function getClassProperties(File $phpcsFile, $stackPtr) case \T_FINAL: $properties['is_final'] = true; break; + + case \T_READONLY: + $properties['is_readonly'] = true; + break; } } diff --git a/Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.inc b/Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.inc index ccd0ba5e..2abe6a38 100644 --- a/Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.inc +++ b/Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.inc @@ -16,3 +16,20 @@ final * @phpcs:disable Standard.Cat.SniffName -- Just because. */ class ClassWithModifierBeforeDocblock {} + +/* testReadonlyClass */ +readonly class ReadOnlyClass {} + +/* testFinalReadonlyClass */ +final readonly class FinalReadOnlyClass extends Foo {} + +/* testReadonlyFinalClass */ +readonly /*comment*/ final class ReadOnlyFinalClass {} + +/* testAbstractReadonlyClass */ +abstract readonly class AbstractReadOnlyClass {} + +/* testReadonlyAbstractClass */ +readonly +abstract +class ReadOnlyAbstractClass {} diff --git a/Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.php b/Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.php index 98060957..688da07f 100644 --- a/Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.php +++ b/Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.php @@ -72,6 +72,7 @@ public function dataGetClassProperties() 'expected' => [ 'is_abstract' => false, 'is_final' => true, + 'is_readonly' => false, ], ], 'unorthodox-docblock-placement' => [ @@ -79,6 +80,47 @@ public function dataGetClassProperties() 'expected' => [ 'is_abstract' => false, 'is_final' => true, + 'is_readonly' => false, + ], + ], + 'readonly' => [ + '/* testReadonlyClass */', + [ + 'is_abstract' => false, + 'is_final' => false, + 'is_readonly' => true, + ], + ], + 'final-readonly' => [ + '/* testFinalReadonlyClass */', + [ + 'is_abstract' => false, + 'is_final' => true, + 'is_readonly' => true, + ], + ], + 'readonly-final' => [ + '/* testReadonlyFinalClass */', + [ + 'is_abstract' => false, + 'is_final' => true, + 'is_readonly' => true, + ], + ], + 'abstract-readonly' => [ + '/* testAbstractReadonlyClass */', + [ + 'is_abstract' => true, + 'is_final' => false, + 'is_readonly' => true, + ], + ], + 'readonly-abstract' => [ + '/* testReadonlyAbstractClass */', + [ + 'is_abstract' => true, + 'is_final' => false, + 'is_readonly' => true, ], ], ]; diff --git a/Tests/Utils/ObjectDeclarations/GetClassPropertiesTest.php b/Tests/Utils/ObjectDeclarations/GetClassPropertiesTest.php index 05f271f5..43464339 100644 --- a/Tests/Utils/ObjectDeclarations/GetClassPropertiesTest.php +++ b/Tests/Utils/ObjectDeclarations/GetClassPropertiesTest.php @@ -55,4 +55,21 @@ public static function setUpTestFile() self::$caseFile = \dirname(\dirname(__DIR__)) . '/BackCompat/BCFile/GetClassPropertiesTest.inc'; parent::setUpTestFile(); } + + /** + * Data provider. + * + * @see testGetClassProperties() For the array format. + * + * @return array + */ + public function dataGetClassProperties() + { + $data = parent::dataGetClassProperties(); + foreach ($data as $name => $dataset) { + $data[$name][1]['is_readonly'] = false; + } + + return $data; + } }