66use PHP_CodeSniffer \Sniffs \Sniff ;
77use SlevomatCodingStandard \Helpers \TokenHelper ;
88use const T_AND_EQUAL ;
9- use const T_CLOSE_CURLY_BRACKET ;
109use const T_CONCAT_EQUAL ;
1110use const T_DIV_EQUAL ;
1211use const T_DOC_COMMENT_CLOSE_TAG ;
2524use const T_VARIABLE ;
2625use const T_WHITESPACE ;
2726use const T_XOR_EQUAL ;
28- use function array_key_exists ;
2927use function array_reverse ;
3028use function count ;
3129use function in_array ;
@@ -91,66 +89,11 @@ public function process(File $phpcsFile, $returnPointer): void
9189 return ;
9290 }
9391
94- for ($ i = $ variablePointer + 1 ; $ i < count ($ tokens ); $ i ++) {
95- if (
96- in_array ($ tokens [$ i ]['code ' ], TokenHelper::$ functionTokenCodes , true )
97- && $ this ->isInSameScope ($ phpcsFile , $ variablePointer , $ i )
98- ) {
99- $ i = $ tokens [$ i ]['scope_closer ' ];
100- continue ;
101- }
102-
103- if ($ tokens [$ i ]['code ' ] !== T_VARIABLE ) {
104- continue ;
105- }
106-
107- if ($ tokens [$ i ]['content ' ] !== $ variableName ) {
108- continue ;
109- }
110-
111- if ($ this ->isInSameScope ($ phpcsFile , $ variablePointer , $ i )) {
112- return ;
113- }
114- }
115-
116- $ errorParameters = [
117- sprintf ('Useless variable %s. ' , $ variableName ),
118- $ previousVariablePointer ,
119- self ::CODE_USELESS_VARIABLE ,
120- ];
121-
122- $ pointerAfterReturnSemicolon = TokenHelper::findNextEffective ($ phpcsFile , $ returnSemicolonPointer + 1 );
123-
124- if (
125- $ tokens [$ pointerAfterReturnSemicolon ]['code ' ] !== T_CLOSE_CURLY_BRACKET
126- || !array_key_exists ('scope_condition ' , $ tokens [$ pointerAfterReturnSemicolon ])
127- || !in_array ($ tokens [$ tokens [$ pointerAfterReturnSemicolon ]['scope_condition ' ]]['code ' ], TokenHelper::$ functionTokenCodes , true )
128- ) {
129- $ phpcsFile ->addError (...$ errorParameters );
130- return ;
131- }
132-
133- $ previousVariableSemicolonPointer = null ;
134- for ($ i = $ previousVariablePointer + 1 ; $ i < $ returnPointer - 1 ; $ i ++) {
135- if ($ tokens [$ i ]['code ' ] !== T_SEMICOLON ) {
136- continue ;
137- }
138-
139- if (!$ this ->isInSameScope ($ phpcsFile , $ previousVariablePointer , $ i )) {
140- continue ;
141- }
142-
143- $ previousVariableSemicolonPointer = $ i ;
144- break ;
145- }
146- $ pointerAfterPreviousVariableSemicolon = TokenHelper::findNextEffective ($ phpcsFile , $ previousVariableSemicolonPointer + 1 );
147-
148- if ($ returnPointer !== $ pointerAfterPreviousVariableSemicolon ) {
149- $ phpcsFile ->addError (...$ errorParameters );
92+ if (!$ this ->areBothPointersNearby ($ phpcsFile , $ previousVariablePointer , $ returnPointer )) {
15093 return ;
15194 }
15295
153- $ fix = $ phpcsFile ->addFixableError (... $ errorParameters );
96+ $ fix = $ phpcsFile ->addFixableError (sprintf ( ' Useless variable %s. ' , $ variableName ), $ previousVariablePointer , self :: CODE_USELESS_VARIABLE );
15497
15598 if (!$ fix ) {
15699 return ;
@@ -174,6 +117,8 @@ public function process(File $phpcsFile, $returnPointer): void
174117 T_CONCAT_EQUAL => '. ' ,
175118 ];
176119
120+ $ previousVariableSemicolonPointer = $ this ->findSemicolon ($ phpcsFile , $ previousVariablePointer );
121+
177122 $ phpcsFile ->fixer ->beginChangeset ();
178123
179124 if ($ tokens [$ assigmentPointer ]['code ' ] === T_EQUAL ) {
@@ -198,15 +143,17 @@ private function isInSameScope(File $phpcsFile, int $firstPointer, int $secondPo
198143 $ tokens = $ phpcsFile ->getTokens ();
199144
200145 $ getScopeLevel = function (int $ pointer ) use ($ tokens ): int {
146+ $ level = $ tokens [$ pointer ]['level ' ];
201147 foreach (array_reverse ($ tokens [$ pointer ]['conditions ' ], true ) as $ conditionPointer => $ conditionTokenCode ) {
202148 if (!in_array ($ conditionTokenCode , TokenHelper::$ functionTokenCodes , true )) {
203149 continue ;
204150 }
205151
206- return $ tokens [$ conditionPointer ]['level ' ];
152+ $ level = $ tokens [$ conditionPointer ]['level ' ];
153+ break ;
207154 }
208155
209- return $ tokens [ $ pointer ][ ' level ' ] ;
156+ return $ level ;
210157 };
211158
212159 return $ getScopeLevel ($ firstPointer ) === $ getScopeLevel ($ secondPointer );
@@ -292,10 +239,38 @@ private function hasAnotherAssigmentBefore(File $phpcsFile, int $variablePointer
292239 return false ;
293240 }
294241
295- $ previousVariableSemicolonPointer = TokenHelper::findNext ($ phpcsFile , T_SEMICOLON , $ previousVariablePointer + 1 );
296- $ pointerAfterPreviousVariableSemicolon = TokenHelper::findNextEffective ($ phpcsFile , $ previousVariableSemicolonPointer + 1 );
242+ return $ this ->areBothPointersNearby ($ phpcsFile , $ previousVariablePointer , $ variablePointer );
243+ }
244+
245+ private function areBothPointersNearby (File $ phpcsFile , int $ firstPointer , int $ secondPointer ): bool
246+ {
247+ $ firstVariableSemicolonPointer = $ this ->findSemicolon ($ phpcsFile , $ firstPointer );
248+ $ pointerAfterFirstVariableSemicolon = TokenHelper::findNextEffective ($ phpcsFile , $ firstVariableSemicolonPointer + 1 );
249+
250+ return $ pointerAfterFirstVariableSemicolon === $ secondPointer ;
251+ }
252+
253+ private function findSemicolon (File $ phpcsFile , int $ pointer ): int
254+ {
255+ $ tokens = $ phpcsFile ->getTokens ();
256+
257+ $ semicolonPointer = null ;
258+ for ($ i = $ pointer + 1 ; $ i < count ($ tokens ) - 1 ; $ i ++) {
259+ if ($ tokens [$ i ]['code ' ] !== T_SEMICOLON ) {
260+ continue ;
261+ }
262+
263+ if (!$ this ->isInSameScope ($ phpcsFile , $ pointer , $ i )) {
264+ continue ;
265+ }
266+
267+ $ semicolonPointer = $ i ;
268+ break ;
269+ }
297270
298- return $ pointerAfterPreviousVariableSemicolon === $ variablePointer ;
271+ /** @var int $semicolonPointer */
272+ $ semicolonPointer = $ semicolonPointer ;
273+ return $ semicolonPointer ;
299274 }
300275
301276}
0 commit comments