Skip to content

feat: add PHP_CodeSniffer 4.x support - #724

Open
MickaelN wants to merge 1 commit into
nunomaduro:masterfrom
MickaelN:feat/phpcs-4-support
Open

feat: add PHP_CodeSniffer 4.x support#724
MickaelN wants to merge 1 commit into
nunomaduro:masterfrom
MickaelN:feat/phpcs-4-support

Conversation

@MickaelN

@MickaelN MickaelN commented Apr 15, 2026

Copy link
Copy Markdown

Summary

Adds support for squizlabs/php_codesniffer 4.x, bumping it from ^3.13.5 to ^4.0 and slevomat/coding-standard from ^8.22.1 to ^8.23.

Closes #723

Rebased on master, so the composer.json diff is limited to those two packages — every other constraint is left as it is on master.

Changes

Core:

  • File.php: addMessage() now declares native parameter types to match the new parent signature, and fixableCount — removed in PHPCS 4 — is replaced by fixableErrorCount / fixableWarningCount, incremented according to $isError
  • SniffDecorator.php: native int type on the process() $stackPtr parameter, dropping the now-unnecessary @phpcsSuppress annotation
  • ForbiddenSetterSniff.php: same native type on process(), error code changed to the dotted form PhpInsights.Sniffs.ForbiddenSetter to satisfy PHPCS 4 code validation, and the getDeclarationName() null check replaced by an empty-string check — the method's return type went from ?string to string in PHPCS 4, returning '' when the name cannot be determined during live coding

Removed sniffs (dropped in PHPCS 4):

  • Zend\Debug\CodeAnalyzerSniff — removed upstream without replacement. It shelled out to zend_code_analyzer, a binary that has not shipped for years, and its role is already covered by SyntaxCheck via parallel-lint
  • Generic\Functions\CallTimePassByReferenceSniff — removed upstream without replacement. Call-time pass-by-reference has been a fatal error since PHP 5.4, so the sniff cannot fire on any version this package supports

Moved sniff:

  • Squiz\WhiteSpace\LanguageConstructSpacingSniffGeneric\WhiteSpace\LanguageConstructSpacingSniff

Tests:

  • TestCase::prepareFixtureWithSniff(): registers the sniff instance manually. PHPCS 4 validates sniff namespaces in populateTokenListeners() against the Standard\Sniffs\Category\SniffName convention, which this package's custom sniffs do not follow
  • Two fixtures (ParamTypeHint, UnorderedUse) updated to stay consistent with what the fixers now produce

Verification

Full CI suite green locally on PHP 8.4.17, with PHPCS 4.0.4 and slevomat 8.31.1:

Step Result
phpstan 0 errors
php-cs-fixer --dry-run 0 of 125 files to fix
phpunit 100 tests, 97 passed, 3 skipped, 0 failures
insights (self-analysis) exit 0 — Code 90.9 / Complexity 87.2 / Architecture 94.1 / Style 97.6

Also run against a large Symfony codebase (~1900 files): Code, Complexity and Architecture scores are identical to the PHPCS 3 baseline, Style is within 1.2 points.

Upgrade squizlabs/php_codesniffer from ^3.13.5 to ^4.0 and
slevomat/coding-standard from ^8.22.1 to ^8.23.

Changes:
- File.php: typed addMessage() signature, fixableCount replaced by
  fixableErrorCount/fixableWarningCount
- SniffDecorator.php: typed process() parameter
- ForbiddenSetterSniff.php: typed process() parameter, dotted error
  code to comply with PHPCS 4 naming validation, getDeclarationName
  empty string check
- Metrics: removed CodeAnalyzerSniff (dropped from Zend in PHPCS 4,
  redundant with SyntaxCheck), removed CallTimePassByReferenceSniff
  (dropped, irrelevant since PHP 5.4), moved LanguageConstructSpacingSniff
  from Squiz to Generic namespace
- TestCase: manual sniff registration to bypass PHPCS 4 namespace
  convention validation for custom sniffs

Closes nunomaduro#723
@MickaelN
MickaelN force-pushed the feat/phpcs-4-support branch from bf35750 to 5aaef9c Compare August 25, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow "squizlabs/php_codesniffer": "^4"

2 participants