Skip to content

Commit a5668d4

Browse files
committed
AbstractClassRestrictions: improve how anonymous classes are handled
Before this commit, `AbstractClassRestrictionsSniff::is_targetted_token()` would name an anonymous class as "\class" or "\readonly" (in the case of readonly anonymous classes). While this would not cause false positives as it is not possible for a class to be named "class" or "readonly", it is not the correct behavior. This commit improves how this method handles anonymous classes by returning `false` early as those classes don't have a name. Includes tests for readonly anonymous classes. It was not necessary to include more tests for normal anonymous classes as the existing tests are already enough.
1 parent 00e9af7 commit a5668d4

File tree

4 files changed

+29
-0
lines changed

4 files changed

+29
-0
lines changed

WordPress/AbstractClassRestrictionsSniff.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,15 @@ public function is_targetted_token( $stackPtr ) {
123123

124124
if ( \in_array( $token['code'], array( \T_NEW, \T_EXTENDS, \T_IMPLEMENTS ), true ) ) {
125125
if ( \T_NEW === $token['code'] ) {
126+
$nextNonEmpty = $this->phpcsFile->findNext( Tokens::$emptyTokens, ( $stackPtr + 1 ), null, true );
127+
128+
if ( false === $nextNonEmpty
129+
|| \in_array( $this->tokens[ $nextNonEmpty ]['code'], array( \T_READONLY, \T_ANON_CLASS, \T_ATTRIBUTE ), true )
130+
) {
131+
// Live coding or anonymous class (bow out for anonymous classes as they don't have a name).
132+
return false;
133+
}
134+
126135
$nameEnd = ( $this->phpcsFile->findNext( array( \T_OPEN_PARENTHESIS, \T_WHITESPACE, \T_SEMICOLON, \T_CLOSE_PARENTHESIS, \T_CLOSE_TAG ), ( $stackPtr + 2 ) ) - 1 );
127136
} else {
128137
$nameEnd = ( $this->phpcsFile->findNext( array( \T_CLOSE_CURLY_BRACKET, \T_WHITESPACE ), ( $stackPtr + 2 ) ) - 1 );

WordPress/Tests/DB/RestrictedClassesUnitTest.1.inc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,14 @@ $anon = new class extends PDOStatement {}; // Error.
104104

105105
// PHP 8.1: enums can implement.
106106
enum MysqliEnum implements mysqli {} // Error.
107+
108+
/*
109+
* Safeguard handling of PHP 8.3+ readonly anonymous classes.
110+
*/
111+
$anon = new readonly class {
112+
public function PDO() {} // OK.
113+
};
114+
115+
$anon = new readonly class extends PDOStatement {}; // Error.
116+
117+
$anon = new #[MyAttribute] readonly class {};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
/*
4+
* Intentional parse error (nothing after T_NEW).
5+
* This should be the only test in this file.
6+
*/
7+
8+
$annon = new

WordPress/Tests/DB/RestrictedClassesUnitTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ public function getErrorList( $testFile = '' ) {
106106
91 => 1,
107107
103 => 1,
108108
106 => 1,
109+
115 => 1,
109110
);
110111

111112
case 'RestrictedClassesUnitTest.2.inc':

0 commit comments

Comments
 (0)