diff --git a/phpcs/autoload.php b/phpcs/autoload.php index fae35978..1691d7e8 100644 --- a/phpcs/autoload.php +++ b/phpcs/autoload.php @@ -160,20 +160,47 @@ public static function loadFile($path) return self::$loadedClasses[$path]; } - $classes = get_declared_classes(); - $interfaces = get_declared_interfaces(); - $traits = get_declared_traits(); + $classesBeforeLoad = [ + 'classes' => get_declared_classes(), + 'interfaces' => get_declared_interfaces(), + 'traits' => get_declared_traits(), + ]; include $path; - $className = null; - $newClasses = array_reverse(array_diff(get_declared_classes(), $classes)); - // Since PHP 7.4 get_declared_classes() does not guarantee any order. That - // implies that parent classes aren't the first any more, rendering the - // array_reverse() technique futile for the loop & break code that follows. - // So, additionally, let's try to reduce the list of candidates by removing all - // the classes known to be "parents". That way, at the end, only the "main" - // class just included with remain. + $classesAfterLoad = [ + 'classes' => get_declared_classes(), + 'interfaces' => get_declared_interfaces(), + 'traits' => get_declared_traits(), + ]; + + $className = self::determineLoadedClass($classesBeforeLoad, $classesAfterLoad); + + self::$loadedClasses[$path] = $className; + self::$loadedFiles[$className] = $path; + return self::$loadedClasses[$path]; + + }//end loadFile() + + + /** + * Determine which class was loaded based on the before and after lists of loaded classes. + * + * @param array $classesBeforeLoad The classes/interfaces/traits before the file was included. + * @param array $classesAfterLoad The classes/interfaces/traits after the file was included. + * + * @return string The fully qualified name of the class in the loaded file. + */ + public static function determineLoadedClass($classesBeforeLoad, $classesAfterLoad) + { + $className = null; + + $newClasses = array_diff($classesAfterLoad['classes'], $classesBeforeLoad['classes']); + + // Since PHP 7.4 get_declared_classes() does not guarantee any order, making + // it impossible to use order to determine which is the parent an which is the child. + // Let's reduce the list of candidates by removing all the classes known to be "parents". + // That way, at the end, only the "main" class just included will remain. $newClasses = array_reduce( $newClasses, function ($remaining, $current) { @@ -181,9 +208,7 @@ function ($remaining, $current) { }, $newClasses ); - $newClasses = array_reduce($newClasses, function($remaining, $current) { - return array_diff($remaining, class_parents($current)); - }, $newClasses); + foreach ($newClasses as $name) { if (isset(self::$loadedFiles[$name]) === false) { $className = $name; @@ -192,7 +217,7 @@ function ($remaining, $current) { } if ($className === null) { - $newClasses = array_reverse(array_diff(get_declared_interfaces(), $interfaces)); + $newClasses = array_reverse(array_diff($classesAfterLoad['interfaces'], $classesBeforeLoad['interfaces'])); foreach ($newClasses as $name) { if (isset(self::$loadedFiles[$name]) === false) { $className = $name; @@ -202,7 +227,7 @@ function ($remaining, $current) { } if ($className === null) { - $newClasses = array_reverse(array_diff(get_declared_traits(), $traits)); + $newClasses = array_reverse(array_diff($classesAfterLoad['traits'], $classesBeforeLoad['traits'])); foreach ($newClasses as $name) { if (isset(self::$loadedFiles[$name]) === false) { $className = $name; @@ -211,11 +236,9 @@ function ($remaining, $current) { } } - self::$loadedClasses[$path] = $className; - self::$loadedFiles[$className] = $path; - return self::$loadedClasses[$path]; + return $className; - }//end loadFile() + }//end determineLoadedClass() /** diff --git a/phpcs/package.xml b/phpcs/package.xml index f95be96a..3249ae8a 100644 --- a/phpcs/package.xml +++ b/phpcs/package.xml @@ -14,11 +14,11 @@ http://pear.php.net/dtd/package-2.0.xsd"> gsherwood@squiz.net yes - 2020-08-10 - + 2020-10-23 + - 3.5.7 - 3.5.7 + 3.5.8 + 3.5.8 stable @@ -26,44 +26,8 @@ http://pear.php.net/dtd/package-2.0.xsd"> BSD 3-Clause License - - The PHP 8.0 T_NULLSAFE_OBJECT_OPERATOR token has been made available for older versions - -- Existing sniffs that check for T_OBJECT_OPERATOR have been modified to apply the same rules for the nullsafe object operator - -- Thanks to Juliette Reinders Folmer for the patch - - The new method of PHP 8.0 tokenizing for namespaced names has been revert to thr pre 8.0 method - -- This maintains backwards compatible for existing sniffs on PHP 8.0 - -- This change will be removed in PHPCS 4.0 as the PHP 8.0 tokenizing method will be backported for pre 8.0 versions - -- Thanks to Juliette Reinders Folmer for the patch - - Added support for changes to the way PHP 8.0 tokenizes hash comments - -- The existing PHP 5-7 behaviour has been replicated for version 8, so no sniff changes are required - -- Thanks to Juliette Reinders Folmer for the patch - - Running the unit tests now includes warnings in the found and fixable error code counts - -- Thanks to Juliette Reinders Folmer for the patch - - PSR12.Functions.NullableTypeDeclaration now supports the PHP8 static return type - -- Thanks to Juliette Reinders Folmer for the patch - - Fixed Squiz.Formatting.OperatorBracket false positive when exiting with a negative number - - Fixed Squiz.PHP.DisallowComparisonAssignment false positive for methods called on an object - - Fixed bug #2882 : Generic.Arrays.ArrayIndent can request close brace indent to be less than the statement indent level - - Fixed bug #2883 : Generic.WhiteSpace.ScopeIndent.Incorrect issue after NOWDOC - - Fixed bug #2975 : Undefined offset in PSR12.Functions.ReturnTypeDeclaration when checking function return type inside ternary - - Fixed bug #2988 : Undefined offset in Squiz.Strings.ConcatenationSpacing during live coding - -- Thanks to Thiemo Kreuz for the patch - - Fixed bug #2989 : Incorrect auto-fixing in Generic.ControlStructures.InlineControlStructure during live coding - -- Thanks to Thiemo Kreuz for the patch - - Fixed bug #3007 : Directory exclude pattern improperly excludes directories with names that start the same - -- Thanks to Steve Talbot for the patch - - Fixed bug #3053 : PSR2 incorrect fix when multiple use statements on same line do not have whitespace between them - - Fixed bug #3058 : Progress gets unaligned when 100% happens at the end of the available dots - - Fixed bug #3059 : Squiz.Arrays.ArrayDeclaration false positive when using type casting - -- Thanks to Sergei Morozov for the patch - - Fixed bug #3060 : Squiz.Arrays.ArrayDeclaration false positive for static functions - -- Thanks to Sergei Morozov for the patch - - Fixed bug #3065 : Should not fix Squiz.Arrays.ArrayDeclaration.SpaceBeforeComma if comment between element and comma - -- Thanks to Sergei Morozov for the patch - - Fixed bug #3066 : No support for namespace operator used in type declarations - -- Thanks to Juliette Reinders Folmer for the patch - - Fixed bug #3099 : Squiz.WhiteSpace.OperatorSpacing false positive when exiting with negative number - -- Thanks to Sergei Morozov for the patch - - Fixed bug #3124 : PSR-12 not reporting error for empty lines with only whitespace + - Reverted a change to the way include/exclude patterns are processed for STDIN content + -- This change is not backwards compatible and will be re-introduced in version 3.6.0 @@ -95,6 +59,17 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + + + + + + + + @@ -1986,6 +1961,11 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + + @@ -2051,6 +2031,11 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + + + @@ -2102,6 +2087,87 @@ http://pear.php.net/dtd/package-2.0.xsd"> + + + 3.5.8 + 3.5.8 + + + stable + stable + + 2020-10-23 + BSD License + + - Reverted a change to the way include/exclude patterns are processed for STDIN content + -- This change is not backwards compatible and will be re-introduced in version 3.6.0 + + + + + 3.5.7 + 3.5.7 + + + stable + stable + + 2020-10-23 + BSD License + + - The PHP 8.0 T_NULLSAFE_OBJECT_OPERATOR token has been made available for older versions + -- Existing sniffs that check for T_OBJECT_OPERATOR have been modified to apply the same rules for the nullsafe object operator + -- Thanks to Juliette Reinders Folmer for the patch + - The new method of PHP 8.0 tokenizing for namespaced names has been revert to thr pre 8.0 method + -- This maintains backwards compatible for existing sniffs on PHP 8.0 + -- This change will be removed in PHPCS 4.0 as the PHP 8.0 tokenizing method will be backported for pre 8.0 versions + -- Thanks to Juliette Reinders Folmer for the patch + - Added support for changes to the way PHP 8.0 tokenizes hash comments + -- The existing PHP 5-7 behaviour has been replicated for version 8, so no sniff changes are required + -- Thanks to Juliette Reinders Folmer for the patch + - The autoloader has been changed to fix sniff class name detection issues that may occur when running on PHP 7.4+ + -- Thanks to Eloy Lafuente for the patch + - Running the unit tests now includes warnings in the found and fixable error code counts + -- Thanks to Juliette Reinders Folmer for the patch + - PSR12.ControlStructures.BooleanOperatorPlacement.FoundMixed error message is now more accurate when using the allowOnly setting + -- Thanks to Vincent Langlet for the patch + - PSR12.Functions.NullableTypeDeclaration now supports the PHP8 static return type + -- Thanks to Juliette Reinders Folmer for the patch + - Fixed Squiz.Formatting.OperatorBracket false positive when exiting with a negative number + - Fixed Squiz.PHP.DisallowComparisonAssignment false positive for methods called on an object + - Fixed bug #2882 : Generic.Arrays.ArrayIndent can request close brace indent to be less than the statement indent level + - Fixed bug #2883 : Generic.WhiteSpace.ScopeIndent.Incorrect issue after NOWDOC + - Fixed bug #2975 : Undefined offset in PSR12.Functions.ReturnTypeDeclaration when checking function return type inside ternary + - Fixed bug #2988 : Undefined offset in Squiz.Strings.ConcatenationSpacing during live coding + -- Thanks to Thiemo Kreuz for the patch + - Fixed bug #2989 : Incorrect auto-fixing in Generic.ControlStructures.InlineControlStructure during live coding + -- Thanks to Thiemo Kreuz for the patch + - Fixed bug #3007 : Directory exclude pattern improperly excludes directories with names that start the same + -- Thanks to Steve Talbot for the patch + - Fixed bug #3043 : Squiz.WhiteSpace.OperatorSpacing false positive for negation in arrow function + -- Thanks to Juliette Reinders Folmer for the patch + - Fixed bug #3049 : Incorrect error with arrow function and parameter passed as reference + -- Thanks to Juliette Reinders Folmer for the patch + - Fixed bug #3053 : PSR2 incorrect fix when multiple use statements on same line do not have whitespace between them + - Fixed bug #3058 : Progress gets unaligned when 100% happens at the end of the available dots + - Fixed bug #3059 : Squiz.Arrays.ArrayDeclaration false positive when using type casting + -- Thanks to Sergei Morozov for the patch + - Fixed bug #3060 : Squiz.Arrays.ArrayDeclaration false positive for static functions + -- Thanks to Sergei Morozov for the patch + - Fixed bug #3065 : Should not fix Squiz.Arrays.ArrayDeclaration.SpaceBeforeComma if comment between element and comma + -- Thanks to Sergei Morozov for the patch + - Fixed bug #3066 : No support for namespace operator used in type declarations + -- Thanks to Juliette Reinders Folmer for the patch + - Fixed bug #3075 : PSR12.ControlStructures.BooleanOperatorPlacement false positive when operator is the only content on line + - Fixed bug #3099 : Squiz.WhiteSpace.OperatorSpacing false positive when exiting with negative number + -- Thanks to Sergei Morozov for the patch + - Fixed bug #3102 : PSR12.Squiz.OperatorSpacing false positive for default values of arrow functions + -- Thanks to Juliette Reinders Folmer for the patch + - Fixed bug #3124 : PSR-12 not reporting error for empty lines with only whitespace + - Fixed bug #3135 : Ignore annotations are broken on PHP 8.0 + -- Thanks to Juliette Reinders Folmer for the patch + + 3.5.6 diff --git a/phpcs/src/Config.php b/phpcs/src/Config.php index f77eaef4..be451ff5 100644 --- a/phpcs/src/Config.php +++ b/phpcs/src/Config.php @@ -79,7 +79,7 @@ class Config * * @var string */ - const VERSION = '3.5.7'; + const VERSION = '3.5.8'; /** * Package stability; either stable, beta or alpha. diff --git a/phpcs/src/Files/File.php b/phpcs/src/Files/File.php index d1e9a4da..8f50d6d3 100644 --- a/phpcs/src/Files/File.php +++ b/phpcs/src/Files/File.php @@ -1981,6 +1981,7 @@ public function isReference($stackPtr) $owner = $this->tokens[$this->tokens[$lastBracket]['parenthesis_owner']]; if ($owner['code'] === T_FUNCTION || $owner['code'] === T_CLOSURE + || $owner['code'] === T_FN ) { $params = $this->getMethodParameters($this->tokens[$lastBracket]['parenthesis_owner']); foreach ($params as $param) { @@ -2094,12 +2095,12 @@ public function getTokensAsString($start, $length, $origContent=false) * @param int|string|array $types The type(s) of tokens to search for. * @param int $start The position to start searching from in the * token stack. - * @param int $end The end position to fail if no token is found. + * @param int|null $end The end position to fail if no token is found. * if not specified or null, end will default to * the start of the token stack. * @param bool $exclude If true, find the previous token that is NOT of * the types specified in $types. - * @param string $value The value that the token(s) must be equal to. + * @param string|null $value The value that the token(s) must be equal to. * If value is omitted, tokens with any value will * be returned. * @param bool $local If true, tokens outside the current statement @@ -2175,12 +2176,12 @@ public function findPrevious( * @param int|string|array $types The type(s) of tokens to search for. * @param int $start The position to start searching from in the * token stack. - * @param int $end The end position to fail if no token is found. + * @param int|null $end The end position to fail if no token is found. * if not specified or null, end will default to * the end of the token stack. * @param bool $exclude If true, find the next token that is NOT of * a type specified in $types. - * @param string $value The value that the token(s) must be equal to. + * @param string|null $value The value that the token(s) must be equal to. * If value is omitted, tokens with any value will * be returned. * @param bool $local If true, tokens outside the current statement @@ -2487,7 +2488,7 @@ public function hasCondition($stackPtr, $types) * @param int $stackPtr The position of the token we are checking. * @param int|string $type The type of token to search for. * @param bool $first If TRUE, will return the matched condition - * furtherest away from the passed token. + * furthest away from the passed token. * If FALSE, will return the matched condition * closest to the passed token. * diff --git a/phpcs/src/Fixer.php b/phpcs/src/Fixer.php index 897e1477..1e1f2561 100644 --- a/phpcs/src/Fixer.php +++ b/phpcs/src/Fixer.php @@ -743,7 +743,7 @@ public function addContentBefore($stackPtr, $content) * @param int $change The number of spaces to adjust the indent by * (positive or negative). * - * @return bool If the change was accepted. + * @return void */ public function changeCodeBlockIndent($start, $end, $change) { diff --git a/phpcs/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php b/phpcs/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php index 94eab1f9..cc9958c5 100644 --- a/phpcs/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php +++ b/phpcs/src/Standards/Generic/Sniffs/CodeAnalysis/UnconditionalIfStatementSniff.php @@ -63,7 +63,7 @@ public function process(File $phpcsFile, $stackPtr) $tokens = $phpcsFile->getTokens(); $token = $tokens[$stackPtr]; - // Skip for-loop without body. + // Skip if statement without body. if (isset($token['parenthesis_opener']) === false) { return; } diff --git a/phpcs/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php b/phpcs/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php index ad663db9..98f7f849 100644 --- a/phpcs/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php +++ b/phpcs/src/Standards/PSR12/Sniffs/ControlStructures/BooleanOperatorPlacementSniff.php @@ -90,35 +90,56 @@ public function process(File $phpcsFile, $stackPtr) break; } - $operators[] = $operator; - $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($operator - 1), $parenOpener, true); if ($prev === false) { // Parse error. return; } + $next = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), $parenCloser, true); + if ($next === false) { + // Parse error. + return; + } + + $firstOnLine = false; + $lastOnLine = false; + if ($tokens[$prev]['line'] < $tokens[$operator]['line']) { // The boolean operator is the first content on the line. - if ($position === null) { - $position = 'first'; - } + $firstOnLine = true; + } - if ($position !== 'first') { - $error = true; - } + if ($tokens[$next]['line'] > $tokens[$operator]['line']) { + // The boolean operator is the last content on the line. + $lastOnLine = true; + } + if ($firstOnLine === true && $lastOnLine === true) { + // The operator is the only content on the line. + // Don't record it because we can't determine + // placement information from looking at it. continue; } - $next = $phpcsFile->findNext(T_WHITESPACE, ($operator + 1), $parenCloser, true); - if ($next === false) { - // Parse error. - return; + $operators[] = $operator; + + if ($firstOnLine === false && $lastOnLine === false) { + // It's in the middle of content, so we can't determine + // placement information from looking at it, but we may + // still need to process it. + continue; } - if ($tokens[$next]['line'] > $tokens[$operator]['line']) { - // The boolean operator is the last content on the line. + if ($firstOnLine === true) { + if ($position === null) { + $position = 'first'; + } + + if ($position !== 'first') { + $error = true; + } + } else { if ($position === null) { $position = 'last'; } @@ -126,8 +147,6 @@ public function process(File $phpcsFile, $stackPtr) if ($position !== 'last') { $error = true; } - - continue; } } while ($operator !== false); @@ -135,8 +154,18 @@ public function process(File $phpcsFile, $stackPtr) return; } - $error = 'Boolean operators between conditions must be at the beginning or end of the line, but not both'; - $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundMixed'); + switch ($this->allowOnly) { + case 'first': + $error = 'Boolean operators between conditions must be at the beginning of the line'; + break; + case 'last': + $error = 'Boolean operators between conditions must be at the end of the line'; + break; + default: + $error = 'Boolean operators between conditions must be at the beginning or end of the line, but not both'; + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'FoundMixed'); if ($fix === false) { return; } diff --git a/phpcs/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc b/phpcs/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc index 3289f7ee..cc2ae92d 100644 --- a/phpcs/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc +++ b/phpcs/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc @@ -108,3 +108,13 @@ if ( ) { // elseif body } + +if ( + ($value == 1 || + $value == 2) + && + ($value == 3 || + $value == 4) +) { + return 5; +} diff --git a/phpcs/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed b/phpcs/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed index 5e8f0c3f..19792a76 100644 --- a/phpcs/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed +++ b/phpcs/src/Standards/PSR12/Tests/ControlStructures/BooleanOperatorPlacementUnitTest.inc.fixed @@ -118,3 +118,13 @@ if ( ) { // elseif body } + +if ( + ($value == 1 || + $value == 2) + && + ($value == 3 || + $value == 4) +) { + return 5; +} diff --git a/phpcs/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc b/phpcs/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc index 82c68f25..6cc482af 100644 --- a/phpcs/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc +++ b/phpcs/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc @@ -56,3 +56,8 @@ function name($a = -1) {} $a =& $ref; $a = [ 'a' => &$something ]; + +$fn = fn(array &$one) => 1; +$fn = fn(array & $one) => 1; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); diff --git a/phpcs/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed b/phpcs/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed index abab6027..c90fb9a7 100644 --- a/phpcs/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed +++ b/phpcs/src/Standards/PSR12/Tests/Operators/OperatorSpacingUnitTest.inc.fixed @@ -56,3 +56,8 @@ function name($a = -1) {} $a =& $ref; $a = [ 'a' => &$something ]; + +$fn = fn(array &$one) => 1; +$fn = fn(array & $one) => 1; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); diff --git a/phpcs/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php b/phpcs/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php index fd4bf44f..ee44545a 100644 --- a/phpcs/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php +++ b/phpcs/src/Standards/Squiz/Sniffs/WhiteSpace/OperatorSpacingSniff.php @@ -77,11 +77,12 @@ public function register() // Returning/printing a negative value; eg. (return -1). $this->nonOperandTokens += [ - T_RETURN => T_RETURN, - T_ECHO => T_ECHO, - T_EXIT => T_EXIT, - T_PRINT => T_PRINT, - T_YIELD => T_YIELD, + T_RETURN => T_RETURN, + T_ECHO => T_ECHO, + T_EXIT => T_EXIT, + T_PRINT => T_PRINT, + T_YIELD => T_YIELD, + T_FN_ARROW => T_FN_ARROW, ]; // Trying to use a negative value; eg. myFunction($var, -2). @@ -90,7 +91,6 @@ public function register() T_OPEN_PARENTHESIS => T_OPEN_PARENTHESIS, T_OPEN_SQUARE_BRACKET => T_OPEN_SQUARE_BRACKET, T_OPEN_SHORT_ARRAY => T_OPEN_SHORT_ARRAY, - T_DOUBLE_ARROW => T_DOUBLE_ARROW, T_COLON => T_COLON, T_INLINE_THEN => T_INLINE_THEN, T_INLINE_ELSE => T_INLINE_ELSE, @@ -99,15 +99,7 @@ public function register() ]; // Casting a negative value; eg. (array) -$a. - $this->nonOperandTokens += [ - T_ARRAY_CAST => T_ARRAY_CAST, - T_BOOL_CAST => T_BOOL_CAST, - T_DOUBLE_CAST => T_DOUBLE_CAST, - T_INT_CAST => T_INT_CAST, - T_OBJECT_CAST => T_OBJECT_CAST, - T_STRING_CAST => T_STRING_CAST, - T_UNSET_CAST => T_UNSET_CAST, - ]; + $this->nonOperandTokens += Tokens::$castTokens; /* These are the tokens the sniff is looking for. @@ -345,6 +337,7 @@ protected function isOperator(File $phpcsFile, $stackPtr) $function = $tokens[$bracket]['parenthesis_owner']; if ($tokens[$function]['code'] === T_FUNCTION || $tokens[$function]['code'] === T_CLOSURE + || $tokens[$function]['code'] === T_FN || $tokens[$function]['code'] === T_DECLARE ) { return false; diff --git a/phpcs/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc b/phpcs/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc index dead3068..82d4af15 100644 --- a/phpcs/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc +++ b/phpcs/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc @@ -465,5 +465,12 @@ $a = $a ? - $b : - $b; exit -1; +$cl = function ($boo =-1) {}; +$cl = function ($boo =+1) {}; +$fn = fn ($boo =-1) => $boo; +$fn = fn ($boo =+1) => $boo; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + /* Intentional parse error. This has to be the last test in the file. */ $a = 10 + diff --git a/phpcs/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed b/phpcs/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed index 1179b4e3..ee4060bc 100644 --- a/phpcs/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed +++ b/phpcs/src/Standards/Squiz/Tests/WhiteSpace/OperatorSpacingUnitTest.inc.fixed @@ -459,5 +459,12 @@ $a = $a ? - $b : - $b; exit -1; +$cl = function ($boo =-1) {}; +$cl = function ($boo =+1) {}; +$fn = fn ($boo =-1) => $boo; +$fn = fn ($boo =+1) => $boo; + +$fn = static fn(DateTime $a, DateTime $b): int => -($a->getTimestamp() <=> $b->getTimestamp()); + /* Intentional parse error. This has to be the last test in the file. */ $a = 10 + diff --git a/phpcs/src/Tokenizers/PHP.php b/phpcs/src/Tokenizers/PHP.php index cae054c1..1aaf2224 100644 --- a/phpcs/src/Tokenizers/PHP.php +++ b/phpcs/src/Tokenizers/PHP.php @@ -908,7 +908,7 @@ protected function tokenize($string) && $tokens[($stackPtr + 2)][0] === T_STRING && strtolower($tokens[($stackPtr + 2)][1]) === 'from' ) { - // Could be multi-line, so just the token stack. + // Could be multi-line, so adjust the token stack. $token[0] = T_YIELD_FROM; $token[1] .= $tokens[($stackPtr + 1)][1].$tokens[($stackPtr + 2)][1]; @@ -1040,7 +1040,7 @@ protected function tokenize($string) /* Before PHP 7, the ??= operator was tokenized as T_INLINE_THEN, T_INLINE_THEN, T_EQUAL. - Between PHP 7.0 and 7.2, the ??= operator was tokenized as + Between PHP 7.0 and 7.3, the ??= operator was tokenized as T_COALESCE, T_EQUAL. So look for and combine these tokens in earlier versions. */ @@ -1493,7 +1493,7 @@ function return types. We want to keep the parenthesis map clean, if (is_array($tokens[$x]) === false && $tokens[$x] === '?') { // Found a nullable operator, so skip it. - // But also covert the token to save the tokenizer + // But also convert the token to save the tokenizer // a bit of time later on. $tokens[$x] = [ T_NULLABLE, diff --git a/phpcs/src/Tokenizers/Tokenizer.php b/phpcs/src/Tokenizers/Tokenizer.php index e0bf22fb..ac9aa202 100644 --- a/phpcs/src/Tokenizers/Tokenizer.php +++ b/phpcs/src/Tokenizers/Tokenizer.php @@ -424,10 +424,10 @@ private function createPositionMap() $disabledSniffs = []; $additionalText = substr($commentText, 14); - if ($additionalText === false) { + if (empty($additionalText) === true) { $ignoring = ['.all' => true]; } else { - $parts = explode(',', substr($commentText, 13)); + $parts = explode(',', $additionalText); foreach ($parts as $sniffCode) { $sniffCode = trim($sniffCode); $disabledSniffs[$sniffCode] = true; @@ -459,10 +459,10 @@ private function createPositionMap() $enabledSniffs = []; $additionalText = substr($commentText, 13); - if ($additionalText === false) { + if (empty($additionalText) === true) { $ignoring = null; } else { - $parts = explode(',', substr($commentText, 13)); + $parts = explode(',', $additionalText); foreach ($parts as $sniffCode) { $sniffCode = trim($sniffCode); $enabledSniffs[$sniffCode] = true; @@ -520,10 +520,10 @@ private function createPositionMap() $ignoreRules = []; $additionalText = substr($commentText, 13); - if ($additionalText === false) { + if (empty($additionalText) === true) { $ignoreRules = ['.all' => true]; } else { - $parts = explode(',', substr($commentText, 13)); + $parts = explode(',', $additionalText); foreach ($parts as $sniffCode) { $ignoreRules[trim($sniffCode)] = true; } diff --git a/readme_moodle.txt b/readme_moodle.txt index 4ef833bb..3536425b 100644 --- a/readme_moodle.txt +++ b/readme_moodle.txt @@ -11,11 +11,11 @@ Instructions to upgrade the phpcs bundled version: Current checkout: - 3.5.6+ (7c1df7d2c) - + 3.5.8 (9d583721a) + Local modifications (only allowed if there is a PR upstream backing it): - - PHP 7.4 fix: https://github.com/squizlabs/PHP_CodeSniffer/pull/3130 + - None, right now. ===== ===== ===== ===== ===== ===== =====