|
6 | 6 | use PHP_CodeSniffer\Sniffs\Sniff; |
7 | 7 | use SlevomatCodingStandard\Helpers\TokenHelper; |
8 | 8 | use const T_AND_EQUAL; |
| 9 | +use const T_CLOSE_CURLY_BRACKET; |
9 | 10 | use const T_CONCAT_EQUAL; |
10 | 11 | use const T_DIV_EQUAL; |
11 | 12 | use const T_EQUAL; |
|
21 | 22 | use const T_SR_EQUAL; |
22 | 23 | use const T_VARIABLE; |
23 | 24 | use const T_XOR_EQUAL; |
| 25 | +use function array_key_exists; |
24 | 26 | use function array_reverse; |
25 | 27 | use function count; |
26 | 28 | use function in_array; |
@@ -56,8 +58,8 @@ public function process(File $phpcsFile, $returnPointer): void |
56 | 58 | return; |
57 | 59 | } |
58 | 60 |
|
59 | | - $pointerAfterVariable = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1); |
60 | | - if ($tokens[$pointerAfterVariable]['code'] !== T_SEMICOLON) { |
| 61 | + $returnSemicolonPointer = TokenHelper::findNextEffective($phpcsFile, $variablePointer + 1); |
| 62 | + if ($tokens[$returnSemicolonPointer]['code'] !== T_SEMICOLON) { |
61 | 63 | return; |
62 | 64 | } |
63 | 65 |
|
@@ -92,8 +94,9 @@ public function process(File $phpcsFile, $returnPointer): void |
92 | 94 | return; |
93 | 95 | } |
94 | 96 |
|
95 | | - $pointerAfterPreviousVariable = TokenHelper::findNextEffective($phpcsFile, $previousVariablePointer + 1); |
96 | | - if (!in_array($tokens[$pointerAfterPreviousVariable]['code'], [ |
| 97 | + /** @var int $assigmentPointer */ |
| 98 | + $assigmentPointer = TokenHelper::findNextEffective($phpcsFile, $previousVariablePointer + 1); |
| 99 | + if (!in_array($tokens[$assigmentPointer]['code'], [ |
97 | 100 | T_EQUAL, |
98 | 101 | T_PLUS_EQUAL, |
99 | 102 | T_MINUS_EQUAL, |
@@ -133,7 +136,81 @@ public function process(File $phpcsFile, $returnPointer): void |
133 | 136 | } |
134 | 137 | } |
135 | 138 |
|
136 | | - $phpcsFile->addError(sprintf('Useless variable %s.', $variableName), $previousVariablePointer, self::CODE_USELESS_VARIABLE); |
| 139 | + $errorParameters = [ |
| 140 | + sprintf('Useless variable %s.', $variableName), |
| 141 | + $previousVariablePointer, |
| 142 | + self::CODE_USELESS_VARIABLE, |
| 143 | + ]; |
| 144 | + |
| 145 | + $pointerAfterReturnSemicolon = TokenHelper::findNextEffective($phpcsFile, $returnSemicolonPointer + 1); |
| 146 | + |
| 147 | + if ( |
| 148 | + $tokens[$pointerAfterReturnSemicolon]['code'] !== T_CLOSE_CURLY_BRACKET |
| 149 | + || !array_key_exists('scope_condition', $tokens[$pointerAfterReturnSemicolon]) |
| 150 | + || !in_array($tokens[$tokens[$pointerAfterReturnSemicolon]['scope_condition']]['code'], TokenHelper::$functionTokenCodes, true) |
| 151 | + ) { |
| 152 | + $phpcsFile->addError(...$errorParameters); |
| 153 | + return; |
| 154 | + } |
| 155 | + |
| 156 | + $previousVariableSemicolonPointer = null; |
| 157 | + for ($i = $previousVariablePointer + 1; $i < $returnPointer - 1; $i++) { |
| 158 | + if ($tokens[$i]['code'] !== T_SEMICOLON) { |
| 159 | + continue; |
| 160 | + } |
| 161 | + |
| 162 | + if (!$this->isInSameScope($phpcsFile, $previousVariablePointer, $i)) { |
| 163 | + continue; |
| 164 | + } |
| 165 | + |
| 166 | + $previousVariableSemicolonPointer = $i; |
| 167 | + break; |
| 168 | + } |
| 169 | + $pointerAfterPreviousVariableSemicolon = TokenHelper::findNextEffective($phpcsFile, $previousVariableSemicolonPointer + 1); |
| 170 | + |
| 171 | + if ($returnPointer !== $pointerAfterPreviousVariableSemicolon) { |
| 172 | + $phpcsFile->addError(...$errorParameters); |
| 173 | + return; |
| 174 | + } |
| 175 | + |
| 176 | + $fix = $phpcsFile->addFixableError(...$errorParameters); |
| 177 | + |
| 178 | + if (!$fix) { |
| 179 | + return; |
| 180 | + } |
| 181 | + |
| 182 | + $assigmentFixerMapping = [ |
| 183 | + T_PLUS_EQUAL => '+', |
| 184 | + T_MINUS_EQUAL => '-', |
| 185 | + T_MUL_EQUAL => '*', |
| 186 | + T_DIV_EQUAL => '/', |
| 187 | + T_POW_EQUAL => '**', |
| 188 | + T_MOD_EQUAL => '%', |
| 189 | + T_AND_EQUAL => '&', |
| 190 | + T_OR_EQUAL => '|', |
| 191 | + T_XOR_EQUAL => '^', |
| 192 | + T_SL_EQUAL => '<<', |
| 193 | + T_SR_EQUAL => '>>', |
| 194 | + T_CONCAT_EQUAL => '.', |
| 195 | + ]; |
| 196 | + |
| 197 | + $phpcsFile->fixer->beginChangeset(); |
| 198 | + |
| 199 | + if ($tokens[$assigmentPointer]['code'] === T_EQUAL) { |
| 200 | + for ($i = $previousVariablePointer; $i < $assigmentPointer; $i++) { |
| 201 | + $phpcsFile->fixer->replaceToken($i, ''); |
| 202 | + } |
| 203 | + $phpcsFile->fixer->replaceToken($assigmentPointer, 'return'); |
| 204 | + } else { |
| 205 | + $phpcsFile->fixer->addContentBefore($previousVariablePointer, 'return '); |
| 206 | + $phpcsFile->fixer->replaceToken($assigmentPointer, $assigmentFixerMapping[$tokens[$assigmentPointer]['code']]); |
| 207 | + } |
| 208 | + |
| 209 | + for ($i = $previousVariableSemicolonPointer + 1; $i <= $returnSemicolonPointer; $i++) { |
| 210 | + $phpcsFile->fixer->replaceToken($i, ''); |
| 211 | + } |
| 212 | + |
| 213 | + $phpcsFile->fixer->endChangeset(); |
137 | 214 | } |
138 | 215 |
|
139 | 216 | private function isInSameScope(File $phpcsFile, int $firstPointer, int $secondPointer): bool |
|
0 commit comments