Skip to content

Commit 84fccb4

Browse files
authored
Merge pull request #950 from PHPCSStandards/feature/psr2-propertydeclaration-support-php84-final-properties
PHP 8.4 | PSR2/PropertyDeclaration: add support for final properties
2 parents 143a9ca + a4eccd3 commit 84fccb4

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed

src/Standards/PSR2/Sniffs/Classes/PropertyDeclarationSniff.php

+27-2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ protected function processMemberVar(File $phpcsFile, $stackPtr)
4343
$find[] = T_VARIABLE;
4444
$find[] = T_VAR;
4545
$find[] = T_READONLY;
46+
$find[] = T_FINAL;
4647
$find[] = T_SEMICOLON;
4748
$find[] = T_OPEN_CURLY_BRACKET;
4849

@@ -130,12 +131,36 @@ protected function processMemberVar(File $phpcsFile, $stackPtr)
130131
*
131132
* Ref: https://www.php-fig.org/per/coding-style/#46-modifier-keywords
132133
*
133-
* At this time (PHP 8.2), inheritance modifiers cannot be applied to properties and
134-
* the `static` and `readonly` modifiers are mutually exclusive and cannot be used together.
134+
* The `static` and `readonly` modifiers are mutually exclusive and cannot be used together.
135135
*
136136
* Based on that, the below modifier keyword order checks are sufficient (for now).
137137
*/
138138

139+
if ($propertyInfo['scope_specified'] === true && $propertyInfo['is_final'] === true) {
140+
$scopePtr = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($stackPtr - 1));
141+
$finalPtr = $phpcsFile->findPrevious(T_FINAL, ($stackPtr - 1));
142+
if ($finalPtr > $scopePtr) {
143+
$error = 'The final declaration must come before the visibility declaration';
144+
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'FinalAfterVisibility');
145+
if ($fix === true) {
146+
$phpcsFile->fixer->beginChangeset();
147+
148+
for ($i = ($finalPtr + 1); $finalPtr < $stackPtr; $i++) {
149+
if ($tokens[$i]['code'] !== T_WHITESPACE) {
150+
break;
151+
}
152+
153+
$phpcsFile->fixer->replaceToken($i, '');
154+
}
155+
156+
$phpcsFile->fixer->replaceToken($finalPtr, '');
157+
$phpcsFile->fixer->addContentBefore($scopePtr, $tokens[$finalPtr]['content'].' ');
158+
159+
$phpcsFile->fixer->endChangeset();
160+
}
161+
}
162+
}//end if
163+
139164
if ($propertyInfo['scope_specified'] === true && $propertyInfo['is_static'] === true) {
140165
$scopePtr = $phpcsFile->findPrevious(Tokens::$scopeModifiers, ($stackPtr - 1));
141166
$staticPtr = $phpcsFile->findPrevious(T_STATIC, ($stackPtr - 1));

src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc

+11
Original file line numberDiff line numberDiff line change
@@ -85,3 +85,14 @@ class ReadOnlyProp {
8585

8686
readonly protected ?string $wrongOrder2;
8787
}
88+
89+
class FinalProperties {
90+
final public int $foo,
91+
$bar,
92+
$var = null;
93+
94+
final protected (D|N)|false $foo;
95+
final array $foo;
96+
public FINAL ?int $wrongOrder1;
97+
static protected final ?string $wrongOrder2;
98+
}

src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.inc.fixed

+11
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,14 @@ class ReadOnlyProp {
8282

8383
protected readonly ?string $wrongOrder2;
8484
}
85+
86+
class FinalProperties {
87+
final public int $foo,
88+
$bar,
89+
$var = null;
90+
91+
final protected (D|N)|false $foo;
92+
final array $foo;
93+
FINAL public ?int $wrongOrder1;
94+
final protected static ?string $wrongOrder2;
95+
}

src/Standards/PSR2/Tests/Classes/PropertyDeclarationUnitTest.php

+5
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ public function getErrorList()
5656
82 => 1,
5757
84 => 1,
5858
86 => 1,
59+
90 => 1,
60+
94 => 1,
61+
95 => 1,
62+
96 => 1,
63+
97 => 2,
5964
];
6065

6166
}//end getErrorList()

0 commit comments

Comments
 (0)