Skip to content

Commit 40eb07e

Browse files
authored
Merge pull request #470 from PHPCSStandards/backcompat/bcfile-getclassproperties-add-support-readonly
BCFile::getClassProperties(): sync with upstream / add support for readonly classes
2 parents 2eecb13 + 45f4964 commit 40eb07e

File tree

6 files changed

+120
-81
lines changed

6 files changed

+120
-81
lines changed

PHPCSUtils/BackCompat/BCFile.php

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -527,19 +527,21 @@ public static function getMemberProperties(File $phpcsFile, $stackPtr)
527527
* array(
528528
* 'is_abstract' => boolean, // TRUE if the abstract keyword was found.
529529
* 'is_final' => boolean, // TRUE if the final keyword was found.
530+
* 'is_readonly' => false, // TRUE if the readonly keyword was found.
530531
* );
531532
* ```
532533
*
533534
* PHPCS cross-version compatible version of the `File::getClassProperties()` method.
534535
*
535536
* Changelog for the PHPCS native function:
536537
* - Introduced in PHPCS 1.3.0.
537-
* - The upstream method has received no significant updates since PHPCS 3.7.1.
538+
* - PHPCS 3.8.0: Added support for PHP 8.2 `readonly` classes.
538539
*
539540
* @see \PHP_CodeSniffer\Files\File::getClassProperties() Original source.
540541
* @see \PHPCSUtils\Utils\ObjectDeclarations::getClassProperties() PHPCSUtils native improved version.
541542
*
542543
* @since 1.0.0
544+
* @since 1.0.6 Sync with PHPCS 3.8.0, support for readonly classes. PHPCS#3686.
543545
*
544546
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
545547
* @param int $stackPtr The position in the stack of the `T_CLASS`
@@ -552,7 +554,50 @@ public static function getMemberProperties(File $phpcsFile, $stackPtr)
552554
*/
553555
public static function getClassProperties(File $phpcsFile, $stackPtr)
554556
{
555-
return $phpcsFile->getClassProperties($stackPtr);
557+
$tokens = $phpcsFile->getTokens();
558+
559+
if ($tokens[$stackPtr]['code'] !== T_CLASS) {
560+
throw new RuntimeException('$stackPtr must be of type T_CLASS');
561+
}
562+
563+
$valid = [
564+
T_FINAL => T_FINAL,
565+
T_ABSTRACT => T_ABSTRACT,
566+
T_READONLY => T_READONLY,
567+
T_WHITESPACE => T_WHITESPACE,
568+
T_COMMENT => T_COMMENT,
569+
T_DOC_COMMENT => T_DOC_COMMENT,
570+
];
571+
572+
$isAbstract = false;
573+
$isFinal = false;
574+
$isReadonly = false;
575+
576+
for ($i = ($stackPtr - 1); $i > 0; $i--) {
577+
if (isset($valid[$tokens[$i]['code']]) === false) {
578+
break;
579+
}
580+
581+
switch ($tokens[$i]['code']) {
582+
case T_ABSTRACT:
583+
$isAbstract = true;
584+
break;
585+
586+
case T_FINAL:
587+
$isFinal = true;
588+
break;
589+
590+
case T_READONLY:
591+
$isReadonly = true;
592+
break;
593+
}
594+
}
595+
596+
return [
597+
'is_abstract' => $isAbstract,
598+
'is_final' => $isFinal,
599+
'is_readonly' => $isReadonly,
600+
];
556601
}
557602

558603
/**

PHPCSUtils/Utils/ObjectDeclarations.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,6 @@ public static function getName(File $phpcsFile, $stackPtr)
136136
* - Handling of PHPCS annotations.
137137
* - Handling of unorthodox docblock placement.
138138
* - Defensive coding against incorrect calls to this method.
139-
* - Support for PHP 8.2 readonly classes.
140139
* - Additional `'abstract_token'`, `'final_token'`, and `'readonly_token'` indexes in the return array.
141140
*
142141
* @see \PHP_CodeSniffer\Files\File::getClassProperties() Original source.

Tests/BackCompat/BCFile/GetClassPropertiesTest.inc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,23 @@ abstract class AbstractClass {}
1818
/* testFinalClass */
1919
final class FinalClass {}
2020

21+
/* testReadonlyClass */
22+
readonly class ReadOnlyClass {}
23+
24+
/* testFinalReadonlyClass */
25+
final readonly class FinalReadOnlyClass extends Foo {}
26+
27+
/* testReadonlyFinalClass */
28+
readonly /*comment*/ final class ReadOnlyFinalClass {}
29+
30+
/* testAbstractReadonlyClass */
31+
abstract readonly class AbstractReadOnlyClass {}
32+
33+
/* testReadonlyAbstractClass */
34+
readonly
35+
abstract
36+
class ReadOnlyAbstractClass {}
37+
2138
/* testWithCommentsAndNewLines */
2239
abstract
2340
/* comment */

Tests/BackCompat/BCFile/GetClassPropertiesTest.php

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,7 @@ public function dataNotAClassException()
9292
public function testGetClassProperties($testMarker, $expected)
9393
{
9494
// Remove keys which will only exist in the PHPCSUtils version of this method.
95-
unset(
96-
$expected['abstract_token'],
97-
$expected['final_token'],
98-
$expected['is_readonly'],
99-
$expected['readonly_token']
100-
);
95+
unset($expected['abstract_token'], $expected['final_token'], $expected['readonly_token']);
10196

10297
$class = $this->getTargetToken($testMarker, \T_CLASS);
10398
$result = BCFile::getClassProperties(self::$phpcsFile, $class);
@@ -147,6 +142,61 @@ public function dataGetClassProperties()
147142
'readonly_token' => false,
148143
],
149144
],
145+
'readonly' => [
146+
'/* testReadonlyClass */',
147+
[
148+
'is_abstract' => false,
149+
'abstract_token' => false,
150+
'is_final' => false,
151+
'final_token' => false,
152+
'is_readonly' => true,
153+
'readonly_token' => -2,
154+
],
155+
],
156+
'final-readonly' => [
157+
'/* testFinalReadonlyClass */',
158+
[
159+
'is_abstract' => false,
160+
'abstract_token' => false,
161+
'is_final' => true,
162+
'final_token' => -4,
163+
'is_readonly' => true,
164+
'readonly_token' => -2,
165+
],
166+
],
167+
'readonly-final' => [
168+
'/* testReadonlyFinalClass */',
169+
[
170+
'is_abstract' => false,
171+
'abstract_token' => false,
172+
'is_final' => true,
173+
'final_token' => -2,
174+
'is_readonly' => true,
175+
'readonly_token' => -6,
176+
],
177+
],
178+
'abstract-readonly' => [
179+
'/* testAbstractReadonlyClass */',
180+
[
181+
'is_abstract' => true,
182+
'abstract_token' => -4,
183+
'is_final' => false,
184+
'final_token' => false,
185+
'is_readonly' => true,
186+
'readonly_token' => -2,
187+
],
188+
],
189+
'readonly-abstract' => [
190+
'/* testReadonlyAbstractClass */',
191+
[
192+
'is_abstract' => true,
193+
'abstract_token' => -2,
194+
'is_final' => false,
195+
'final_token' => false,
196+
'is_readonly' => true,
197+
'readonly_token' => -4,
198+
],
199+
],
150200
'comments-and-new-lines' => [
151201
'/* testWithCommentsAndNewLines */',
152202
[

Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.inc

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,3 @@ final
1616
* @phpcs:disable Standard.Cat.SniffName -- Just because.
1717
*/
1818
class ClassWithModifierBeforeDocblock {}
19-
20-
/* testReadonlyClass */
21-
readonly class ReadOnlyClass {}
22-
23-
/* testFinalReadonlyClass */
24-
final readonly class FinalReadOnlyClass extends Foo {}
25-
26-
/* testReadonlyFinalClass */
27-
readonly /*comment*/ final class ReadOnlyFinalClass {}
28-
29-
/* testAbstractReadonlyClass */
30-
abstract readonly class AbstractReadOnlyClass {}
31-
32-
/* testReadonlyAbstractClass */
33-
readonly
34-
abstract
35-
class ReadOnlyAbstractClass {}

Tests/Utils/ObjectDeclarations/GetClassPropertiesDiffTest.php

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -101,61 +101,6 @@ public function dataGetClassProperties()
101101
'readonly_token' => false,
102102
],
103103
],
104-
'readonly' => [
105-
'/* testReadonlyClass */',
106-
[
107-
'is_abstract' => false,
108-
'abstract_token' => false,
109-
'is_final' => false,
110-
'final_token' => false,
111-
'is_readonly' => true,
112-
'readonly_token' => -2,
113-
],
114-
],
115-
'final-readonly' => [
116-
'/* testFinalReadonlyClass */',
117-
[
118-
'is_abstract' => false,
119-
'abstract_token' => false,
120-
'is_final' => true,
121-
'final_token' => -4,
122-
'is_readonly' => true,
123-
'readonly_token' => -2,
124-
],
125-
],
126-
'readonly-final' => [
127-
'/* testReadonlyFinalClass */',
128-
[
129-
'is_abstract' => false,
130-
'abstract_token' => false,
131-
'is_final' => true,
132-
'final_token' => -2,
133-
'is_readonly' => true,
134-
'readonly_token' => -6,
135-
],
136-
],
137-
'abstract-readonly' => [
138-
'/* testAbstractReadonlyClass */',
139-
[
140-
'is_abstract' => true,
141-
'abstract_token' => -4,
142-
'is_final' => false,
143-
'final_token' => false,
144-
'is_readonly' => true,
145-
'readonly_token' => -2,
146-
],
147-
],
148-
'readonly-abstract' => [
149-
'/* testReadonlyAbstractClass */',
150-
[
151-
'is_abstract' => true,
152-
'abstract_token' => -2,
153-
'is_final' => false,
154-
'final_token' => false,
155-
'is_readonly' => true,
156-
'readonly_token' => -4,
157-
],
158-
],
159104
];
160105
}
161106
}

0 commit comments

Comments
 (0)