From 6108d2af361d26ce1c355f723c7df3fae91be7b2 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Fri, 5 Sep 2025 03:38:26 +0200 Subject: [PATCH 1/2] Composer: raise the minimum supported PHPCS + PHPCSUtils versions PHP_CodeSniffer 3.13.3 + 3.13.4 and PHPCSUtils 1.1.2 have been released. This commit raises the minimum supported PHPCS/Utils versions for improved PHP 8.4 support. Note: while raising to 3.13.4 is not necessary from a functional point of view, 3.13.3 contains an issue which blocks the ability to run the tests, so we need 3.13.4 to safeguard the functionality of this external standard correctly. Ref: * https://github.com/PHPCSStandards/PHPCSUtils/releases/tag/1.1.2 * https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/tag/3.13.3 * https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/tag/3.13.4 --- README.md | 8 ++++---- composer.json | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8b6b42b..904691d 100644 --- a/README.md +++ b/README.md @@ -43,8 +43,8 @@ PHPCSExtra is a collection of sniffs and standards for use with [PHP_CodeSniffer ## Minimum Requirements * PHP 5.4 or higher. -* [PHP_CodeSniffer][phpcs-gh] version **3.13.0** or higher. -* [PHPCSUtils][phpcsutils-gh] version **1.1.0** or higher. +* [PHP_CodeSniffer][phpcs-gh] version **3.13.4** or higher. +* [PHPCSUtils][phpcsutils-gh] version **1.1.2** or higher. ## Installation @@ -58,7 +58,7 @@ Installing via Composer is highly recommended. Run the following from the root of your project: ```bash composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true -composer require --dev phpcsstandards/phpcsextra:"^1.2.0" +composer require --dev phpcsstandards/phpcsextra:"^1.3.0" ``` ### Composer Global Installation @@ -66,7 +66,7 @@ composer require --dev phpcsstandards/phpcsextra:"^1.2.0" Alternatively, you may want to install this standard globally: ```bash composer global config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true -composer global require --dev phpcsstandards/phpcsextra:"^1.2.0" +composer global require --dev phpcsstandards/phpcsextra:"^1.3.0" ``` ### Updating to a newer version diff --git a/composer.json b/composer.json index 4b986cb..599d827 100644 --- a/composer.json +++ b/composer.json @@ -22,8 +22,8 @@ }, "require" : { "php" : ">=5.4", - "squizlabs/php_codesniffer" : "^3.13.0 || ^4.0", - "phpcsstandards/phpcsutils" : "^1.1.0" + "squizlabs/php_codesniffer" : "^3.13.4 || ^4.0", + "phpcsstandards/phpcsutils" : "^1.1.2" }, "require-dev" : { "php-parallel-lint/php-parallel-lint": "^1.4.0", From f6441ad10139da062d4fe43b2da1155f67880b56 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Fri, 5 Sep 2025 03:56:58 +0200 Subject: [PATCH 2/2] Universal/NoFQNTrueFalseNull: fix for changed tokenization in PHPCS 3.13.3 and 4.0 The tokenization of fully qualified `true`/`false`/`null` has been changed for both PHPCS 3.x (as of 3.13.3) as well as PHPCS 4.0. The new tokenization means we don't need to take these tokens being tokenized as `T_STRING` or `T_NAME_FULLY_QUALIFIED` into account anymore, as long as the minimum supported PHPCS version will be PHPCS 3.13.3. However, we now do need to verify that `T_TRUE`/`T_FALSE`/`T_NULL` tokens don't have a namespace separator included in their contents. This commit updates the sniff for these changes. Ref: * PHPCSStandards/PHP_CodeSniffer 1201 * PHPCSStandards/PHP_CodeSniffer 1206 --- .../Sniffs/PHP/NoFQNTrueFalseNullSniff.php | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/Universal/Sniffs/PHP/NoFQNTrueFalseNullSniff.php b/Universal/Sniffs/PHP/NoFQNTrueFalseNullSniff.php index e9354b8..e46c903 100644 --- a/Universal/Sniffs/PHP/NoFQNTrueFalseNullSniff.php +++ b/Universal/Sniffs/PHP/NoFQNTrueFalseNullSniff.php @@ -10,6 +10,7 @@ namespace PHPCSExtra\Universal\Sniffs\PHP; +use PHP_CodeSniffer\Config; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; @@ -31,18 +32,17 @@ final class NoFQNTrueFalseNullSniff implements Sniff */ public function register() { - return [ - // PHPCS 3.x on PHP < 8.0. + $targets = [ \T_TRUE, \T_FALSE, \T_NULL, + ]; - // PHPCS 3.x on PHP >= 8.0. - \T_STRING, + if (\version_compare(Config::VERSION, '4.0.0', '>=') === true) { + $targets[] = \T_NS_SEPARATOR; + } - // PHPCS 4.x. - \T_NAME_FULLY_QUALIFIED, - ]; + return $targets; } /** @@ -62,17 +62,21 @@ public function process(File $phpcsFile, $stackPtr) $content = $tokens[$stackPtr]['content']; $contentLC = \strtolower($content); - if ($tokens[$stackPtr]['code'] === \T_NAME_FULLY_QUALIFIED) { + if ($contentLC === '\true' || $contentLC === '\false' || $contentLC === '\null') { // PHPCS 4.x. - if ($contentLC !== '\true' && $contentLC !== '\false' && $contentLC !== '\null') { + } elseif ($tokens[$stackPtr]['code'] === \T_NS_SEPARATOR) { + // PHPCS 4.x for code which is a parse error on PHP 8.0+. + $next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] !== \T_STRING) { return; } - } else { - // PHPCS 3.x. - if ($contentLC !== 'true' && $contentLC !== 'false' && $contentLC !== 'null') { + + $nextContentLC = \strtolower($tokens[$next]['content']); + if ($nextContentLC !== 'true' && $nextContentLC !== 'false' && $nextContentLC !== 'null') { return; } - + } else { + // PHPCS 3.x. $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true); if ($tokens[$prev]['code'] !== \T_NS_SEPARATOR) { return; @@ -97,9 +101,12 @@ public function process(File $phpcsFile, $stackPtr) ); if ($fix === true) { - if ($tokens[$stackPtr]['code'] === \T_NAME_FULLY_QUALIFIED) { + if ($contentLC === '\true' || $contentLC === '\false' || $contentLC === '\null') { // PHPCS 4.x. $phpcsFile->fixer->replaceToken($stackPtr, \ltrim($tokens[$stackPtr]['content'], '\\')); + } elseif ($tokens[$stackPtr]['code'] === \T_NS_SEPARATOR) { + // PHPCS 4.x for code which is a parse error on PHP 8.0+. + $phpcsFile->fixer->replaceToken($stackPtr, ''); } else { // PHPCS 3.x. $phpcsFile->fixer->replaceToken($prev, '');