From d58dd44ce20d85b307d5fe6c742d5c0cc5e2e114 Mon Sep 17 00:00:00 2001 From: Koopzington Date: Tue, 17 Sep 2024 08:03:33 +0200 Subject: [PATCH] Add autofix support for ValidLogicalOperatorsSniff --- .../Operators/ValidLogicalOperatorsSniff.php | 54 +++++++++++++++++- .../ValidLogicalOperatorsUnitTest.inc | 29 ++++++++++ .../ValidLogicalOperatorsUnitTest.inc.fixed | 57 +++++++++++++++++++ .../ValidLogicalOperatorsUnitTest.php | 26 +++++++++ 4 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc.fixed diff --git a/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php b/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php index 720e4724ad..64434d2702 100644 --- a/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php +++ b/src/Standards/Squiz/Sniffs/Operators/ValidLogicalOperatorsSniff.php @@ -59,7 +59,59 @@ public function process(File $phpcsFile, $stackPtr) $operator, $replacements[$operator], ]; - $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data); + + // Based on https://www.php.net/manual/en/language.operators.precedence.php + // It contains the tokens that can result in different code behaviour when replacing "AND / OR" with "&& / ||". + // So we need to check for them to decide whether it's a fixable or non-fixable error. + $blockList = [ + T_EQUAL, + T_PLUS_EQUAL, + T_MINUS_EQUAL, + T_MUL_EQUAL, + T_POW_EQUAL, + T_DIV_EQUAL, + T_CONCAT_EQUAL, + T_MOD_EQUAL, + T_AND_EQUAL, + T_OR_EQUAL, + T_XOR_EQUAL, + T_SL_EQUAL, + T_SR_EQUAL, + T_COALESCE, + T_COALESCE_EQUAL, + T_INLINE_THEN, + T_INLINE_ELSE, + T_YIELD, + T_YIELD_FROM, + T_PRINT, + ]; + + // Extend blocklist depending on which operator is being processed. + if ($tokens[$stackPtr]['code'] === T_LOGICAL_OR) { + $blockList[] = T_LOGICAL_XOR; + } else if ($tokens[$stackPtr]['code'] === T_LOGICAL_AND) { + $blockList[] = T_BOOLEAN_OR; + } + + $start = $phpcsFile->findStartOfStatement($stackPtr); + $end = $phpcsFile->findEndOfStatement($stackPtr); + + for ($index = $start; $index <= $end; ++$index) { + // Skip checking contents of grouped statements. + if ($tokens[$index]['code'] === T_OPEN_PARENTHESIS) { + $index = ($phpcsFile->findEndOfStatement($index + 1) + 1); + } + + if (in_array($tokens[$index]['code'], $blockList, true) === true) { + $phpcsFile->addError($error, $stackPtr, 'NotAllowed', $data); + return; + } + } + + $fix = $phpcsFile->addFixableError($error, $stackPtr, 'NotAllowed', $data); + if ($fix === true) { + $phpcsFile->fixer->replaceToken($stackPtr, $replacements[$operator]); + } }//end process() diff --git a/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc b/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc index 328ccc5d46..30191542e2 100644 --- a/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc +++ b/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc @@ -25,4 +25,33 @@ if ($a xor $b) { if ($a XOR $b) { } + +$c = $a and $b; +$c += $a and $b; +$c -= $a and $b; +$c *= $a and $b; +$c **= $a and $b; +$c /= $a and $b; +$c .= $a and $b; +$c %= $a and $b; +$c &= $a and $b; +$c |= $a and $b; +$c ^= $a and $b; +$c ?? $a and $b; +$c ??= $a and $b; +$c <<= $a and $b; +$c >>= $a and $b; + +$c = ($a and $b); +$c = ($a and $c ?? ($c or $d)); +$c = ($a and ($b ?? $c)); +$foo = ($a and ($b ?? $c) ?? $d); +$foo = ($a and ($b ?? $c) or $d); +$foo = ($a and ($b ?? $c) or $d ?? $e); + +$foo = ($a and $b || $c); +$foo = ($a or $b xor $c); +$foo = ($a and $b or $c); +print $a and $b; +yield $a and $b; ?> diff --git a/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc.fixed b/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc.fixed new file mode 100644 index 0000000000..1f2d457808 --- /dev/null +++ b/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.inc.fixed @@ -0,0 +1,57 @@ +>= $a and $b; + +$c = ($a && $b); +$c = ($a and $c ?? ($c || $d)); +$c = ($a && ($b ?? $c)); +$foo = ($a and ($b ?? $c) ?? $d); +$foo = ($a && ($b ?? $c) || $d); +$foo = ($a and ($b ?? $c) or $d ?? $e); + +$foo = ($a and $b || $c); +$foo = ($a or $b xor $c); +$foo = ($a && $b || $c); +print $a and $b; +yield $a and $b; +?> diff --git a/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php b/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php index d7ce889e3c..30e0b90f36 100644 --- a/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php +++ b/src/Standards/Squiz/Tests/Operators/ValidLogicalOperatorsUnitTest.php @@ -34,6 +34,32 @@ public function getErrorList() 5 => 1, 11 => 1, 17 => 2, + 29 => 1, + 30 => 1, + 31 => 1, + 32 => 1, + 33 => 1, + 34 => 1, + 35 => 1, + 36 => 1, + 37 => 1, + 38 => 1, + 39 => 1, + 40 => 1, + 41 => 1, + 42 => 1, + 43 => 1, + 45 => 1, + 46 => 2, + 47 => 1, + 48 => 1, + 49 => 2, + 50 => 2, + 52 => 1, + 53 => 1, + 54 => 2, + 55 => 1, + 56 => 1, ]; }//end getErrorList()