@@ -173,6 +173,8 @@ protected function fixStatement(File $phpcsFile, array $statement, int $stackPtr
173173
174174 if ($ addedUseStatement ['alias ' ] !== null ) {
175175 $ phpcsFile ->fixer ->replaceToken ($ statement ['end ' ], $ addedUseStatement ['alias ' ]);
176+ } else {
177+ $ phpcsFile ->fixer ->replaceToken ($ statement ['end ' ], $ addedUseStatement ['shortName ' ]);
176178 }
177179
178180 $ phpcsFile ->fixer ->endChangeset ();
@@ -194,6 +196,42 @@ protected function checkUseForNew(File $phpcsFile, int $stackPtr): void
194196 return ;
195197 }
196198
199+ // PHP 8+: Check if it's a single T_NAME_FULLY_QUALIFIED token
200+ if (defined ('T_NAME_FULLY_QUALIFIED ' ) && $ this ->isGivenKind (T_NAME_FULLY_QUALIFIED , $ tokens [$ nextIndex ])) {
201+ $ extractedUseStatement = ltrim ($ tokens [$ nextIndex ]['content ' ], '\\' );
202+ if (!str_contains ($ extractedUseStatement , '\\' )) {
203+ return ;
204+ }
205+
206+ $ lastSeparatorPos = strrpos ($ extractedUseStatement , '\\' );
207+ $ className = substr ($ extractedUseStatement , $ lastSeparatorPos + 1 );
208+
209+ $ error = 'Use statement ' . $ extractedUseStatement . ' for class ' . $ className . ' should be in use block. ' ;
210+ $ fix = $ phpcsFile ->addFixableError ($ error , $ stackPtr , 'New ' );
211+ if (!$ fix ) {
212+ return ;
213+ }
214+
215+ $ phpcsFile ->fixer ->beginChangeset ();
216+
217+ $ addedUseStatement = $ this ->addUseStatement ($ phpcsFile , $ className , $ extractedUseStatement );
218+
219+ if ($ addedUseStatement ['alias ' ] !== null ) {
220+ $ phpcsFile ->fixer ->replaceToken ($ nextIndex , $ addedUseStatement ['alias ' ]);
221+ } else {
222+ $ phpcsFile ->fixer ->replaceToken ($ nextIndex , $ addedUseStatement ['shortName ' ]);
223+ }
224+
225+ if ($ nextIndex === $ stackPtr + 1 ) {
226+ $ phpcsFile ->fixer ->replaceToken ($ stackPtr , $ tokens [$ stackPtr ]['content ' ] . ' ' );
227+ }
228+
229+ $ phpcsFile ->fixer ->endChangeset ();
230+
231+ return ;
232+ }
233+
234+ // PHP < 8: Multi-token format (T_NS_SEPARATOR + T_STRING)
197235 $ lastIndex = null ;
198236 $ i = $ nextIndex ;
199237 $ extractedUseStatement = '' ;
@@ -241,6 +279,11 @@ protected function checkUseForNew(File $phpcsFile, int $stackPtr): void
241279 for ($ i = $ lastSeparatorIndex + 2 ; $ i <= $ lastIndex ; ++$ i ) {
242280 $ phpcsFile ->fixer ->replaceToken ($ i , '' );
243281 }
282+ } else {
283+ $ phpcsFile ->fixer ->replaceToken ($ lastSeparatorIndex + 1 , $ addedUseStatement ['shortName ' ]);
284+ for ($ i = $ lastSeparatorIndex + 2 ; $ i <= $ lastIndex ; ++$ i ) {
285+ $ phpcsFile ->fixer ->replaceToken ($ i , '' );
286+ }
244287 }
245288
246289 if ($ nextIndex === $ stackPtr + 1 ) {
@@ -266,6 +309,38 @@ protected function checkUseForStatic(File $phpcsFile, int $stackPtr): void
266309 return ;
267310 }
268311
312+ // PHP 8+: Check if it's a single T_NAME_FULLY_QUALIFIED token
313+ if (defined ('T_NAME_FULLY_QUALIFIED ' ) && $ this ->isGivenKind (T_NAME_FULLY_QUALIFIED , $ tokens [$ prevIndex ])) {
314+ $ extractedUseStatement = ltrim ($ tokens [$ prevIndex ]['content ' ], '\\' );
315+ if (!str_contains ($ extractedUseStatement , '\\' )) {
316+ return ;
317+ }
318+
319+ $ lastSeparatorPos = strrpos ($ extractedUseStatement , '\\' );
320+ $ className = substr ($ extractedUseStatement , $ lastSeparatorPos + 1 );
321+
322+ $ error = 'Use statement ' . $ extractedUseStatement . ' for class ' . $ className . ' should be in use block. ' ;
323+ $ fix = $ phpcsFile ->addFixableError ($ error , $ stackPtr , 'Static ' );
324+ if (!$ fix ) {
325+ return ;
326+ }
327+
328+ $ phpcsFile ->fixer ->beginChangeset ();
329+
330+ $ addedUseStatement = $ this ->addUseStatement ($ phpcsFile , $ className , $ extractedUseStatement );
331+
332+ if ($ addedUseStatement ['alias ' ] !== null ) {
333+ $ phpcsFile ->fixer ->replaceToken ($ prevIndex , $ addedUseStatement ['alias ' ]);
334+ } else {
335+ $ phpcsFile ->fixer ->replaceToken ($ prevIndex , $ addedUseStatement ['shortName ' ]);
336+ }
337+
338+ $ phpcsFile ->fixer ->endChangeset ();
339+
340+ return ;
341+ }
342+
343+ // PHP < 8: Multi-token format (T_NS_SEPARATOR + T_STRING)
269344 $ lastIndex = null ;
270345 $ i = $ prevIndex ;
271346 $ extractedUseStatement = '' ;
@@ -310,7 +385,12 @@ protected function checkUseForStatic(File $phpcsFile, int $stackPtr): void
310385
311386 if ($ addedUseStatement ['alias ' ] !== null ) {
312387 $ phpcsFile ->fixer ->replaceToken ($ firstSeparatorIndex + 1 , $ addedUseStatement ['alias ' ]);
313- for ($ i = $ firstSeparatorIndex + 2 ; $ i <= $ lastIndex ; ++$ i ) {
388+ for ($ i = $ firstSeparatorIndex + 2 ; $ i <= $ prevIndex ; ++$ i ) {
389+ $ phpcsFile ->fixer ->replaceToken ($ i , '' );
390+ }
391+ } else {
392+ $ phpcsFile ->fixer ->replaceToken ($ firstSeparatorIndex + 1 , $ addedUseStatement ['shortName ' ]);
393+ for ($ i = $ firstSeparatorIndex + 2 ; $ i <= $ prevIndex ; ++$ i ) {
314394 $ phpcsFile ->fixer ->replaceToken ($ i , '' );
315395 }
316396 }
@@ -334,6 +414,38 @@ protected function checkUseForInstanceOf(File $phpcsFile, int $stackPtr): void
334414 return ;
335415 }
336416
417+ // PHP 8+: Check if it's a single T_NAME_FULLY_QUALIFIED token
418+ if (defined ('T_NAME_FULLY_QUALIFIED ' ) && $ this ->isGivenKind (T_NAME_FULLY_QUALIFIED , $ tokens [$ classNameIndex ])) {
419+ $ extractedUseStatement = ltrim ($ tokens [$ classNameIndex ]['content ' ], '\\' );
420+ if (!str_contains ($ extractedUseStatement , '\\' )) {
421+ return ;
422+ }
423+
424+ $ lastSeparatorPos = strrpos ($ extractedUseStatement , '\\' );
425+ $ className = substr ($ extractedUseStatement , $ lastSeparatorPos + 1 );
426+
427+ $ error = 'Use statement ' . $ extractedUseStatement . ' for class ' . $ className . ' should be in use block. ' ;
428+ $ fix = $ phpcsFile ->addFixableError ($ error , $ stackPtr , 'InstanceOf ' );
429+ if (!$ fix ) {
430+ return ;
431+ }
432+
433+ $ phpcsFile ->fixer ->beginChangeset ();
434+
435+ $ addedUseStatement = $ this ->addUseStatement ($ phpcsFile , $ className , $ extractedUseStatement );
436+
437+ if ($ addedUseStatement ['alias ' ] !== null ) {
438+ $ phpcsFile ->fixer ->replaceToken ($ classNameIndex , $ addedUseStatement ['alias ' ]);
439+ } else {
440+ $ phpcsFile ->fixer ->replaceToken ($ classNameIndex , $ addedUseStatement ['shortName ' ]);
441+ }
442+
443+ $ phpcsFile ->fixer ->endChangeset ();
444+
445+ return ;
446+ }
447+
448+ // PHP < 8: Multi-token format (T_NS_SEPARATOR + T_STRING)
337449 $ lastIndex = null ;
338450 $ i = $ classNameIndex ;
339451 $ extractedUseStatement = '' ;
@@ -383,6 +495,11 @@ protected function checkUseForInstanceOf(File $phpcsFile, int $stackPtr): void
383495 for ($ k = $ lastSeparatorIndex + 1 ; $ k < $ lastIndex ; ++$ k ) {
384496 $ phpcsFile ->fixer ->replaceToken ($ k , '' );
385497 }
498+ } else {
499+ $ phpcsFile ->fixer ->replaceToken ($ lastIndex , $ addedUseStatement ['shortName ' ]);
500+ for ($ k = $ lastSeparatorIndex + 1 ; $ k < $ lastIndex ; ++$ k ) {
501+ $ phpcsFile ->fixer ->replaceToken ($ k , '' );
502+ }
386503 }
387504
388505 $ phpcsFile ->fixer ->endChangeset ();
@@ -406,6 +523,38 @@ public function checkUseForCatchOrCallable(File $phpcsFile, int $stackPtr): void
406523 return ;
407524 }
408525
526+ // PHP 8+: Check if it's a single T_NAME_FULLY_QUALIFIED token
527+ if (defined ('T_NAME_FULLY_QUALIFIED ' ) && $ this ->isGivenKind (T_NAME_FULLY_QUALIFIED , $ tokens [$ classNameIndex ])) {
528+ $ extractedUseStatement = ltrim ($ tokens [$ classNameIndex ]['content ' ], '\\' );
529+ if (!str_contains ($ extractedUseStatement , '\\' )) {
530+ return ;
531+ }
532+
533+ $ lastSeparatorPos = strrpos ($ extractedUseStatement , '\\' );
534+ $ className = substr ($ extractedUseStatement , $ lastSeparatorPos + 1 );
535+
536+ $ error = 'Use statement ' . $ extractedUseStatement . ' for class ' . $ className . ' should be in use block. ' ;
537+ $ fix = $ phpcsFile ->addFixableError ($ error , $ stackPtr , 'Catch ' );
538+ if (!$ fix ) {
539+ return ;
540+ }
541+
542+ $ phpcsFile ->fixer ->beginChangeset ();
543+
544+ $ addedUseStatement = $ this ->addUseStatement ($ phpcsFile , $ className , $ extractedUseStatement );
545+
546+ if ($ addedUseStatement ['alias ' ] !== null ) {
547+ $ phpcsFile ->fixer ->replaceToken ($ classNameIndex , $ addedUseStatement ['alias ' ]);
548+ } else {
549+ $ phpcsFile ->fixer ->replaceToken ($ classNameIndex , $ addedUseStatement ['shortName ' ]);
550+ }
551+
552+ $ phpcsFile ->fixer ->endChangeset ();
553+
554+ return ;
555+ }
556+
557+ // PHP < 8: Multi-token format (T_NS_SEPARATOR + T_STRING)
409558 $ lastIndex = null ;
410559 $ i = $ classNameIndex ;
411560 $ extractedUseStatement = '' ;
@@ -462,6 +611,11 @@ public function checkUseForCatchOrCallable(File $phpcsFile, int $stackPtr): void
462611 for ($ i = $ firstSeparatorIndex + 2 ; $ i <= $ lastIndex ; ++$ i ) {
463612 $ phpcsFile ->fixer ->replaceToken ($ i , '' );
464613 }
614+ } else {
615+ $ phpcsFile ->fixer ->replaceToken ($ firstSeparatorIndex + 1 , $ addedUseStatement ['shortName ' ]);
616+ for ($ i = $ firstSeparatorIndex + 2 ; $ i <= $ lastIndex ; ++$ i ) {
617+ $ phpcsFile ->fixer ->replaceToken ($ i , '' );
618+ }
465619 }
466620
467621 $ phpcsFile ->fixer ->endChangeset ();
@@ -486,6 +640,38 @@ protected function checkUseForSignature(File $phpcsFile, int $stackPtr): void
486640 $ startIndex = $ i ;
487641 }
488642
643+ // PHP 8+: Check if it's a single T_NAME_FULLY_QUALIFIED token
644+ if (defined ('T_NAME_FULLY_QUALIFIED ' ) && $ this ->isGivenKind (T_NAME_FULLY_QUALIFIED , $ tokens [$ i ])) {
645+ $ extractedUseStatement = ltrim ($ tokens [$ i ]['content ' ], '\\' );
646+ if (!str_contains ($ extractedUseStatement , '\\' )) {
647+ continue ;
648+ }
649+
650+ $ lastSeparatorPos = strrpos ($ extractedUseStatement , '\\' );
651+ $ className = substr ($ extractedUseStatement , $ lastSeparatorPos + 1 );
652+
653+ $ error = 'Use statement ' . $ extractedUseStatement . ' for class ' . $ className . ' should be in use block. ' ;
654+ $ fix = $ phpcsFile ->addFixableError ($ error , $ stackPtr , 'Signature ' );
655+ if (!$ fix ) {
656+ continue ;
657+ }
658+
659+ $ phpcsFile ->fixer ->beginChangeset ();
660+
661+ $ addedUseStatement = $ this ->addUseStatement ($ phpcsFile , $ className , $ extractedUseStatement );
662+
663+ if ($ addedUseStatement ['alias ' ] !== null ) {
664+ $ phpcsFile ->fixer ->replaceToken ($ i , $ addedUseStatement ['alias ' ]);
665+ } else {
666+ $ phpcsFile ->fixer ->replaceToken ($ i , $ addedUseStatement ['shortName ' ]);
667+ }
668+
669+ $ phpcsFile ->fixer ->endChangeset ();
670+
671+ continue ;
672+ }
673+
674+ // PHP < 8: Multi-token format (T_NS_SEPARATOR + T_STRING)
489675 $ lastIndex = null ;
490676 $ j = $ i ;
491677 $ extractedUseStatement = '' ;
@@ -532,6 +718,8 @@ protected function checkUseForSignature(File $phpcsFile, int $stackPtr): void
532718
533719 if ($ addedUseStatement ['alias ' ] !== null ) {
534720 $ phpcsFile ->fixer ->replaceToken ($ lastIndex , $ addedUseStatement ['alias ' ]);
721+ } else {
722+ $ phpcsFile ->fixer ->replaceToken ($ lastIndex , $ addedUseStatement ['shortName ' ]);
535723 }
536724
537725 $ phpcsFile ->fixer ->endChangeset ();
@@ -569,6 +757,38 @@ protected function checkUseForReturnTypeHint(File $phpcsFile, int $stackPtr): vo
569757 return ;
570758 }
571759
760+ // PHP 8+: Check if it's a single T_NAME_FULLY_QUALIFIED token
761+ if (defined ('T_NAME_FULLY_QUALIFIED ' ) && $ this ->isGivenKind (T_NAME_FULLY_QUALIFIED , $ tokens [$ startIndex ])) {
762+ $ extractedUseStatement = ltrim ($ tokens [$ startIndex ]['content ' ], '\\' );
763+ if (!str_contains ($ extractedUseStatement , '\\' )) {
764+ return ;
765+ }
766+
767+ $ lastSeparatorPos = strrpos ($ extractedUseStatement , '\\' );
768+ $ className = substr ($ extractedUseStatement , $ lastSeparatorPos + 1 );
769+
770+ $ error = 'Use statement ' . $ extractedUseStatement . ' for class ' . $ className . ' should be in use block. ' ;
771+ $ fix = $ phpcsFile ->addFixableError ($ error , $ colonIndex , 'ReturnSignature ' );
772+ if (!$ fix ) {
773+ return ;
774+ }
775+
776+ $ phpcsFile ->fixer ->beginChangeset ();
777+
778+ $ addedUseStatement = $ this ->addUseStatement ($ phpcsFile , $ className , $ extractedUseStatement );
779+
780+ if ($ addedUseStatement ['alias ' ] !== null ) {
781+ $ phpcsFile ->fixer ->replaceToken ($ startIndex , $ addedUseStatement ['alias ' ]);
782+ } else {
783+ $ phpcsFile ->fixer ->replaceToken ($ startIndex , $ addedUseStatement ['shortName ' ]);
784+ }
785+
786+ $ phpcsFile ->fixer ->endChangeset ();
787+
788+ return ;
789+ }
790+
791+ // PHP < 8: Multi-token format (T_NS_SEPARATOR + T_STRING)
572792 $ lastIndex = null ;
573793 $ j = $ startIndex ;
574794 $ extractedUseStatement = '' ;
@@ -619,6 +839,8 @@ protected function checkUseForReturnTypeHint(File $phpcsFile, int $stackPtr): vo
619839
620840 if ($ addedUseStatement ['alias ' ] !== null ) {
621841 $ phpcsFile ->fixer ->replaceToken ($ lastIndex , $ addedUseStatement ['alias ' ]);
842+ } else {
843+ $ phpcsFile ->fixer ->replaceToken ($ lastIndex , $ addedUseStatement ['shortName ' ]);
622844 }
623845
624846 $ phpcsFile ->fixer ->endChangeset ();
@@ -643,7 +865,7 @@ protected function checkPropertyForInstanceOf(File $phpcsFile, int $stackPtr): v
643865 $ className = '' ;
644866 if ($ tokens [$ startIndex ]['code ' ] === T_NAME_FULLY_QUALIFIED ) {
645867 $ extractedUseStatement = ltrim ($ tokens [$ startIndex ]['content ' ], '\\' );
646- if (strpos ($ extractedUseStatement , '\\' ) === false ) {
868+ if (! str_contains ($ extractedUseStatement , '\\' )) {
647869 return ; // Not a namespaced class
648870 }
649871 $ lastSeparatorPos = strrpos ($ extractedUseStatement , '\\' );
@@ -1029,6 +1251,19 @@ protected function parse(File $phpcsFile, int $startIndex, int $endIndex): array
10291251 break ;
10301252 }
10311253
1254+ // PHP 8+: Check for T_NAME_FULLY_QUALIFIED token
1255+ if (defined ('T_NAME_FULLY_QUALIFIED ' ) && $ tokens [$ i ]['code ' ] === T_NAME_FULLY_QUALIFIED ) {
1256+ $ implements [] = [
1257+ 'start ' => $ i ,
1258+ 'end ' => $ i ,
1259+ 'content ' => $ tokens [$ i ]['content ' ],
1260+ ];
1261+ $ i ++;
1262+
1263+ continue ;
1264+ }
1265+
1266+ // PHP < 8: Multi-token format (T_NS_SEPARATOR + T_STRING)
10321267 while ($ tokens [$ i ]['code ' ] !== T_NS_SEPARATOR && $ tokens [$ i ]['code ' ] !== T_STRING && $ i < $ endIndex ) {
10331268 $ i ++;
10341269 if (empty ($ tokens [$ i ])) {
0 commit comments