Skip to content

4.0.0beta1

Pre-release
Pre-release
Compare
Choose a tag to compare
@jrfnl jrfnl released this 11 May 04:53
· 76 commits to 4.x since this release
4.0.0beta1
b370661

Added

  • Files without extension can now be scanned if the path is passed in directly. #2916
    • Previously, files without extension would always be ignored.
    • Now, files with no extension are checked if explicitly passed on the command line or specified in a ruleset.
    • Files without extension will still be ignored when scanning directories recursively.
  • Support for extending a default value for an array property on a sniff from an XML ruleset file. #15
    • Previously, using extend="true" on an property tag for setting an array value could already extend a property value set elsewhere in an (inluded) ruleset.
    • Now, you can also add to (extend) a default value as set on the sniff itself.
    • Note: the property default value and the values set via the ruleset will be merged.
      • This also means that for associative arrays, you can redefine the value for a particular array key.
      • For numerically indexed arrays, this means the array will be renumbered. Keep this in mind if the numeric indexes hold meaning.
  • Added support for PHP 8.4 properties in interfaces to File::getMemberProperties(). #2455
    • Note: properties in interfaces is not fully supported yet, it is just this one method which handles them correctly at this moment.
  • Tokens::NAME_TOKENS containing an array with the tokens used for identifier names. #3041
  • New sniff Generic.WhiteSpace.GotoTargetSpacing to enforce no space between the label of a goto target and the colon following it. #1026
  • An error message is now displayed if no files were checked during a run. #1595
    • This occurs when all of the specified files matched exclusion rules, or none matched filtering rules.
  • An error will be shown when attempting to change an unchangable PHP ini setting using -d option[=value] or via the ruleset with <ini name=...>. #416
    • Previously, this was silently ignored.
    • Attempting to change non-existent ini settings (typo, extension not loaded) will continue to be silently ignored.

Changed

  • The minimum required PHP version has changed from 5.4.0 to 7.2.0.
  • The default coding standard has changed from PEAR to PSR12.
  • Both phpcs as well as phpcbf will now exit with exit code 0 if no issues were found/remain after fixing. #184
    • Non auto-fixable issues can be ignored for the exit code determination by setting the new ignore_non_auto_fixable_on_exit config flag to 1.
    • For full details on the new exit codes, please refer to the Uncyclo "Advanced Usage" page.
  • Composer installs no longer include any test files. #1908
    • The test framework files will still be included to allow for use by external standards.
  • All status, debug, and progress output is now sent to STDERR instead of STDOUT. #1612
    • Only report output now goes through STDOUT. As a result of this, piping output to a file will now only include report output.
      • Pipe both STDERR and STDOUT to the same file to capture the entire output of the run.
    • The --report-file functionality remains untouched.
    • With this change in place, timing and memory consumption stats will now be displayed more often as this will no longer interfere with reports.
  • The --extensions command line argument no longer accepts the tokenizer along with the extension. #2448
    • Previously, you would check .module files as PHP files using --extensions=module/php.
    • Now, you use --extensions=module.
  • When processing rulesets, <config> directives will be applied based on the nesting level of the ruleset. #2197
    • Previously, it was not possible to overrule a <config> directive set in an included ruleset from the "root" ruleset.
    • Now, <config> directives set in the "root" ruleset will always "win" over directives in included rulesets.
    • When two included rulesets at the same nesting level both set the same directive, the value from the last included ruleset "wins" (= same as before).
  • When processing rulesets, <arg> directives will be applied based on the nesting level of the ruleset. #2395, #2597, #2602
    • Previously, it was not possible to overrule a <arg> directive set in an included ruleset from the "root" ruleset.
    • Now, <arg> directives set in the "root" ruleset will always "win" over directives in included rulesets.
    • When two included rulesets at the same nesting level both set the same directive, the value from the first included ruleset "wins" (= same as before).
  • Internal errors will no longer be suppressed when the --sniffs CLI argument is used. #98
  • The File::getDeclarationName() method will no longer accept T_ANON_CLASS or T_CLOSURE tokens. #3766
    • A RuntimeException will be thrown if these tokens are passed.
  • The File::getDeclarationName() method will now always return a string (or throw an Exception). #1007
    • Previously, the method would return null if the name could not be determined, like during live coding.
      Now it will return an empty string in those situations.
  • The File::getMemberProperties() method will no longer add warnings about possible parse errors. #2455
    • This means the Internal.ParseError.InterfaceHasMemberVar and the Internal.ParseError.EnumHasMemberVar error codes have been removed.
    • The method will now throw a "$stackPtr is not a class member var" RuntimeException for properties declared in enums (parse error).
    • Properties declared in interfaces will be analyzed like all other properties, as these are allowed since PHP 8.4.
  • None of the included sniffs will warn about possible parse errors any more. #2455
    • This improves the experience when the file is being checked inside an editor during live coding.
    • If you want to detect parse errors, use the Generic.PHP.Syntax sniff or a dedicated linter instead.
  • The PEAR + PSR2 FunctionCallSignature sniffs will now also examine anonymous class instantiations with parameters. #47
  • The error code Squiz.Classes.ValidClassName.NotCamelCaps has been changed to Squiz.Classes.ValidClassName.NotPascalCase. #2046
    • This reflects that the sniff is actually checking for ClassName and not className.
  • The error code Squiz.PHP.Heredoc.NotAllowed has been replaced by Squiz.PHP.Heredoc.HeredocNotAllowed and Squiz.PHP.Heredoc.NowdocNotAllowed. #2318
    • This allows for forbidding either heredocs or nowdocs without forbidding both.
  • The PSR12.Files.FileHeader sniff now has more modular error codes to allow for more selectively applying the rules. #2729 #3453
    • The PSR12.Files.FileHeader.SpacingAfterBlock error code is replaced by:
      • PSR12.Files.FileHeader.SpacingAfterTagBlock
      • PSR12.Files.FileHeader.SpacingAfterDocblockBlock
      • PSR12.Files.FileHeader.SpacingAfterDeclareBlock
      • PSR12.Files.FileHeader.SpacingAfterNamespaceBlock
      • PSR12.Files.FileHeader.SpacingAfterUseBlock
      • PSR12.Files.FileHeader.SpacingAfterUseFunctionBlock
      • PSR12.Files.FileHeader.SpacingAfterUseConstBlock
    • The PSR12.Files.FileHeader.SpacingInsideBlock error code is replaced by:
      • PSR12.Files.FileHeader.SpacingInsideUseBlock
      • PSR12.Files.FileHeader.SpacingInsideUseFunctionBlock
      • PSR12.Files.FileHeader.SpacingInsideUseConstBlock
  • The error code Squiz.Commenting.VariableComment.TagNotAllowed has been replaced by a dynamic Squiz.Commenting.VariableComment.[TagName]TagNotAllowed error code. #1039
    • This allows for selectively allowing specific tags by excluding the error code for that tag.
    • Example: to allow @link tags in property docblocks, exclude the Squiz.Commenting.VariableComment.LinkTagNotAllowed error code.
  • The following sniffs have received performance related improvements:
    • PEAR.NamingConventions.ValidVariableName
    • PSR2.Classes.PropertyDeclaration
    • Squiz.Commenting.VariableComment
    • Squiz.Scope.MemberVarScope
    • Squiz.WhiteSpace.MemberVarSpacing
    • These sniffs will no longer listen to non-variable tokens, nor for variables tokens outside of OO context. #374
      External sniffs which extend one of these sniffs may need adjustment if they want to retain the old behaviour.
  • PHPCS now uses the PHP >= 8.0 native method for tokenizing (namespaced) identifier names. #3041
    • Before PHP 8.0, PHP would tokenize namespaced names using T_STRING and T_NS_SEPARATOR.
    • From PHP 8.0, PHP uses the tokens T_NAME_FULLY_QUALIFIED, T_NAME_RELATIVE, and T_NAME_QUALIFIED instead.
    • PHPCS now uses these new PHP 8.0 tokens no matter what version of PHP is being used to run PHPCS.
    • Custom sniffs that use T_STRING and T_NS_SEPARATOR tokens to look for namespaced names will need to be modified.
    • The Tokens::FUNCTION_NAME_TOKENS/Tokens::$functionNameTokens array now includes the identifier name tokens.
  • Closure T_USE tokens, T_ISSET, T_UNSET, T_EMPTY, T_EVAL and T_EXIT tokens now contain parenthesis information. #23, #2593
    • Previously, you had to find the opening and closing parenthesis by looking forward through the token stack.
    • Now, you can use the parenthesis_owner, parenthesis_opener and parenthesis_closer array indexes.
  • The static keyword when preceded by instanceof will now be tokenized (again) as T_STATIC. #22
    • Previously, the token was (re-)tokenized to T_STRING.
  • T_OPEN_TAG tokens will no longer contain any whitespace. #593
    • Previously, "long" open tags could include either a single space or a new line character.
    • This whitespace will now be tokenized as a T_WHITESPACE token.
  • T_GOTO_LABEL tokens will no longer include the colon following it. #185
    • The colon belonging with a goto label will now be tokenized separately as T_GOTO_COLON.
  • Context sensitive keywords used as a label in a goto statement will now be tokenized as T_STRING to prevent confusing sniffs. #185
  • All T_DOC_COMMENT_* tokens now have the comment_opener and comment_closer indexes set. #484
  • The Tokens::FUNCTION_NAME_TOKENS/Tokens::$functionNameTokens array now includes the T_ANON_CLASS token. #47
  • Type casting for sniff property values set from within a ruleset has been made more consistent. #708
    • true and false will now always be set to a boolean value, independently of the case in which the value was provided.
    • null will now be set to an actual null value. Previously, the sniff property would have been set to string 'null'.
    • Array element values will now also get the type casting treatment. Previously, array values would always be strings.
  • The PHP_CodeSniffer\Config::setConfigData() method is no longer static. #2675
    • The associated (private) Config::$overriddenDefaults property is also no longer static.
  • The PHP_CodeSniffer\Config::setSettings() method is now a void method. #1001
  • The signature of the DummyFile::setErrorCounts() method has changed and now expects the following parameters: $errorCount, $warningCount, $fixableErrorCount, $fixableWarningCount, $fixedErrorCount, $fixedWarningCount. #1079
  • The Generator classes will now throw a PHP_CodeSniffer\Exceptions\GeneratorException when encountering errors in the documentation XML. #1072
  • The PHP_CodeSniffer\Generators\HTML::STYLESHEET, PHP_CodeSniffer\Util\Timing::MINUTE_IN_MS and PHP_CodeSniffer\Util\Timing::SECOND_IN_MS class constants are no longer public. #1051
  • The PHP_CodeSniffer\Util\Timing class is now final and marked as an internal class. #1074
  • The Ruleset class no longer has special behaviour when used in a test context. #996
  • The minimum required PHPUnit version for the test framework has changed from 4.0 to 8.0. #994, #997
    • The test framework is now compatible with PHPUnit 8.x - 11.x (ignoring PHPUnit deprecations related to PHPUnit 12).
  • The test framework has been refactored and no longer creates a custom test suite. #25
    • If tests for an external standard extend the PHPCS native test suite, be sure to read the upgrade guide for more detail.
  • The two abstract base test cases have been renamed. #25
    • Replace PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest with PHP_CodeSniffer\Tests\Standards\AbstractSniffTestCase.
    • Replace PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest with PHP_CodeSniffer\Tests\Core\AbstractMethodTestCase.
  • Tests which extend the AbstractSniffTestCase for which no test case files (.inc files) can be found, will now be marked as "incomplete". #998
    • Previously, those tests would silently pass.
  • All test case files (inc) which would be changed by the sniff under test if running the fixer, are now required to be accompanied by a *.fixed file. #300

Deprecated

  • The static token array properties in the Tokens class. Use the corresponding class constants on the Tokens class instead. #500
  • PHP_CodeSniffer\Util\Common::$allowedTypes. Use PHP_CodeSniffer\Util\Common::ALLOWED_TYPES instead. #1043
  • PHP_CodeSniffer\Tokenizers\PHP::$tstringContexts. Use PHP_CodeSniffer\Tokenizers\PHP::T_STRING_CONTEXTS instead. #1043
  • PHP_CodeSniffer\Sniffs\AbstractVariableSniff::$phpReservedVars. Use PHP_CodeSniffer\Sniffs\AbstractVariableSniff::PHP_RESERVED_VARS instead. #1043
  • PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::$magicMethods. Use PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::MAGIC_METHODS instead. #1043
    • This also affects the PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff class which extends the CamelCapsFunctionNameSniff.
  • PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::$methodsDoubleUnderscore. Use PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::DOUBLE_UNDERSCORE_METHODS instead. #1043
    • This also affects the PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff class which extends the CamelCapsFunctionNameSniff.
  • PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::$magicFunctions. Use PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff::MAGIC_FUNCTIONS instead. #1043
    • This also affects the PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff class which extends the CamelCapsFunctionNameSniff.
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Files\ByteOrderMarkSniff::$bomDefinitions. Use PHP_CodeSniffer\Standards\Generic\Sniffs\Files\ByteOrderMarkSniff::BOM_DEFINITIONS instead. #1043
  • PHP_CodeSniffer\Standards\Generic\Sniffs\Files\InlineHTMLSniff::$bomDefinitions. Use PHP_CodeSniffer\Standards\Generic\Sniffs\Files\InlineHTMLSniff::BOM_DEFINITIONS instead. #1043
  • PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\CharacterBeforePHPOpeningTagSniff::$bomDefinitions. Use PHP_CodeSniffer\Standards\Generic\Sniffs\PHP\CharacterBeforePHPOpeningTagSniff::BOM_DEFINITIONS instead. #1043
  • PHP_CodeSniffer\Standards\Generic\Sniffs\VersionControl\SubversionPropertiesSniff::$properties. Use PHP_CodeSniffer\Standards\Generic\Sniffs\VersionControl\SubversionPropertiesSniff::REQUIRED_PROPERTIES instead. #1043
  • PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FileCommentSniff::$tags. Use PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\FileCommentSniff::EXPECTED_TAGS instead. #1043
    • This also affects the PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting\ClassCommentSniff class which extends the FileCommentSniff.
  • PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff::$magicMethods. Use PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff::MAGIC_METHODS instead. #1043
    • This also affects the PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions\ValidFunctionNameSniff class which extends the PEAR ValidFunctionNameSniff.
  • PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff::$magicFunctions. Use PHP_CodeSniffer\Standards\PEAR\Sniffs\NamingConventions\ValidFunctionNameSniff::MAGIC_FUNCTIONS instead. #1043
    • This also affects the PHP_CodeSniffer\Standards\Squiz\Sniffs\NamingConventions\ValidFunctionNameSniff class which extends the PEAR ValidFunctionNameSniff.
  • PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DisallowSizeFunctionsInLoopsSniff::$forbiddenFunctions. Use PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\DisallowSizeFunctionsInLoopsSniff::FORBIDDEN_FUNCTIONS instead. #1043
  • PHP_CodeSniffer\Util\Standards::printInstalledStandards(). Use echo PHP_CodeSniffer\Util\Standards::prepareInstalledStandardsForDisplay() instead. #1054
  • PHP_CodeSniffer\Config::printConfigData(). Use echo PHP_CodeSniffer\Config::prepareConfigDataForDisplay() instead. #1055
  • The Reporter::$totalFixable and Reporter::$totalFixed properties. #1079
    • Use respectively (Reporter::$totalFixableErrors + Reporter::$totalFixableWarnings) and (Reporter::$totalFixedErrors + Reporter::$totalFixedWarnings) instead.

Removed

  • Support for checking the coding standards of CSS and JS files has been removed. #2448
    • Sniffs which are specifically aimed at CSS/JS files will no longer run.
    • All other sniffs will now treat all files under scan as PHP files.
    • The JS/CSS tokenizers and all tokens which were specifically for CSS/JS have also been removed.
  • Support for sniffs not implementing the PHP_CodeSniffer\Sniffs\Sniff interface. See #694.
  • Support for sniffs not following the naming conventions. See #689.
  • Support for external standards called "Internal". See #799.
  • Support for the deprecated @codingStandard annotation syntax has been removed. #1954
    • Use the phpcs: or @phpcs: syntax instead
      • Replace @codingStandardsIgnoreFile with phpcs:ignoreFile
      • Replace @codingStandardsIgnoreStart with phpcs:disable
      • Replace @codingStandardsIgnoreEnd with phpcs:enable
      • Replace @codingStandardsIgnoreLine with phpcs:ignore
      • Replace @codingStandardsChangeSetting with phpcs:set
  • Support for the deprecated ruleset.xml array property string-based syntax has been removed. #1983
    • Previously, an array value could be set using a comma-delimited string print=>echo,create_function=>null
    • Now, individual array elements are specified using an element tag with key and value attributes
      • For example, <element key="print" value="echo">
  • The unused T_ARRAY_HINT token. #1997
  • The unused T_RETURN_TYPE token. #1997
  • The Generic.Debug.ClosureLinter sniff. #2448
  • The Generic.Debug.CSSLint sniff. #2448
  • The Generic.Debug.ESLint sniff. #2448
  • The Generic.Debug.JSHint sniff. #2448
  • The Generic.Formatting.NoSpaceAfterCast sniff. #2234
    • Use the Generic.Formatting.SpaceAfterCast sniff instead with the $spacing property set to 0.
  • The Generic.Functions.CallTimePassByReference sniff. #921
  • The entire MySource standard, and all sniffs within. #2471
  • The Squiz.Classes.DuplicateProperty sniff. #2448
  • The entire Squiz.CSS category, and all sniffs within. #2448
  • The Squiz.Debug.JavaScriptLint sniff. #2448
  • The Squiz.Debug.JSLint sniff. #2448
  • The Squiz.Objects.DisallowObjectStringIndex sniff. #2448
  • The Squiz.Objects.ObjectMemberComment sniff. #2448
  • The Squiz.WhiteSpace.LanguageConstructSpacing sniff. #1953
    • Use the Generic.WhiteSpace.LanguageConstructSpacing sniff instead.
  • The Squiz.WhiteSpace.PropertyLabelSpacing sniff. #2448
  • The Zend.Debug.CodeAnalyzer sniff. #58
  • The error property of sniff Generic.Strings.UnnecessaryStringConcat. See #2823
    • This sniff now always produces errors
    • To make this sniff produce warnings, include the following in a ruleset.xml or [.]phpcs.xml[.dist] file:
      <rule ref="Generic.Strings.UnnecessaryStringConcat">
          <type>warning</type>
      </rule>
  • The error property of sniff Generic.Formatting.MultipleStatementAlignment. See #2823
    • This sniff now always produces warnings
    • The Generic.Formatting.MultipleStatementAlignment.IncorrectWarning error code has been removed.
      • Refer to the Generic.Formatting.MultipleStatementAlignment.Incorrect error code instead.
    • The Generic.Formatting.MultipleStatementAlignment.NotSameWarning error code has been removed.
      • Refer to the Generic.Formatting.MultipleStatementAlignment.NotSame error code instead.
    • To make this sniff produce errors, include the following in a ruleset.xml or [.]phpcs.xml[.dist] file:
      <rule ref="Generic.Formatting.MultipleStatementAlignment">
          <type>error</type>
      </rule>
  • The $ignoreComments parameter for the AbstractPatternSniff::__construct() method.
  • Ruleset::setSniffProperty(): support for the old $settings parameter format. #3629
  • Use of the deprecated auto_detect_line_endings ini setting. #3394
    • This removes support for files with \r line endings.
  • The abstract PHP_CodeSniffer\Filters\ExactMatch::getBlacklist() and PHP_CodeSniffer\Filters\ExactMatch::getWhitelist() methods. See #199.
    • These have been replaced by the ExactMatch::getDisallowedFiles() and ExactMatch::getAllowedFiles() methods.
  • The deprecated PHP_CodeSniffer\Generators\[HTML|Markdown|Text]::print*() methods. See #755.
  • Unused static PHP_CodeSniffer\Reporter::$startTime property. #1064

Fixed

  • Fixed bug #185 : goto labels were incorrectly tokenized as T_STRING if there was whitespace and/or comments between the label and colon.
  • Fixed bug #1012 : in edge cases, the tokenizer could create some stray parenthesis_* keys.
  • Fixed bug #1020 : File::findExtendedClassName() will no longer break on namespace relative class names.
  • Fixed bug #1020 : File::findImplementedInterfaceNames() will no longer break on namespace relative interface names.
  • Fixed bug #1020 : Various sniffs now have better support for ignoring/examining qualified function calls.

Other

Calling all testers!

Please help by testing the beta release and reporting any issues you run into.
Upgrade guides for both ruleset maintainers/end-users, as well as for sniff developers and integrators, have been published to the Uncyclo to help smooth the transition.


All patches courtesy of Greg Sherwood (@gsherwood) and Juliette Reinders Folmer (@jrfnl).

Special thanks go out to Dan Wallis (@fredden) and Rodrigo Primo (@rodrigoprimo) for their reviews and feedback.

Statistics

Closed: 51 issues
Merged: 95 pull requests

Follow @phpcs on Mastodon or @PHP_CodeSniffer on X to stay informed.

Please consider funding the PHP_CodeSniffer project. If you already do so: thank you!