@@ -62,14 +62,19 @@ public function process(File $phpcsFile, $stackPtr) {
62
62
$ this ->loadStatements ($ phpcsFile );
63
63
$ this ->findSentinel ($ phpcsFile );
64
64
65
- if ($ tokens [$ stackPtr ]['code ' ] === T_CLASS ) {
65
+ if ($ tokens [$ stackPtr ]['code ' ] === T_CLASS || $ tokens [ $ stackPtr ][ ' code ' ] === T_INTERFACE || $ tokens [ $ stackPtr ][ ' code ' ] === T_TRAIT ) {
66
66
$ this ->checkUseForClass ($ phpcsFile , $ stackPtr );
67
67
} elseif ($ tokens [$ stackPtr ]['code ' ] === T_NEW ) {
68
68
$ this ->checkUseForNew ($ phpcsFile , $ stackPtr );
69
69
} elseif ($ tokens [$ stackPtr ]['code ' ] === T_DOUBLE_COLON ) {
70
70
$ this ->checkUseForStatic ($ phpcsFile , $ stackPtr );
71
+ } elseif ($ tokens [$ stackPtr ]['code ' ] === T_INSTANCEOF ) {
72
+ $ this ->checkUseForInstanceOf ($ phpcsFile , $ stackPtr );
73
+ } elseif ($ tokens [$ stackPtr ]['code ' ] === T_CATCH || $ tokens [$ stackPtr ]['code ' ] === T_CALLABLE ) {
74
+ $ this ->checkUseForCatchOrCallable ($ phpcsFile , $ stackPtr );
71
75
} else {
72
76
$ this ->checkUseForSignature ($ phpcsFile , $ stackPtr );
77
+ $ this ->checkUseForReturnTypeHint ($ phpcsFile , $ stackPtr );
73
78
}
74
79
$ this ->insertUseWhenSentinel ($ phpcsFile , $ stackPtr );
75
80
}
@@ -575,6 +580,218 @@ protected function checkUseForStatic(File $phpcsFile, $stackPtr) {
575
580
$ phpcsFile ->fixer ->endChangeset ();
576
581
}
577
582
583
+ /**
584
+ * @param \PHP_CodeSniffer\Files\File $phpcsFile
585
+ * @param int $stackPtr
586
+ *
587
+ * @return void
588
+ */
589
+ protected function checkUseForInstanceOf (File $ phpcsFile , $ stackPtr ) {
590
+ $ tokens = $ phpcsFile ->getTokens ();
591
+
592
+ $ classNameIndex = $ phpcsFile ->findNext (Tokens::$ emptyTokens , $ stackPtr + 1 , null , true );
593
+
594
+ $ lastIndex = null ;
595
+ $ i = $ classNameIndex ;
596
+ $ extractedUseStatement = '' ;
597
+ $ lastSeparatorIndex = null ;
598
+ while (true ) {
599
+ if (!$ this ->isGivenKind ([T_NS_SEPARATOR , T_STRING ], $ tokens [$ i ])) {
600
+ break ;
601
+ }
602
+ $ lastIndex = $ i ;
603
+ $ extractedUseStatement .= $ tokens [$ i ]['content ' ];
604
+
605
+ if ($ this ->isGivenKind ([T_NS_SEPARATOR ], $ tokens [$ i ])) {
606
+ $ lastSeparatorIndex = $ i ;
607
+ }
608
+ ++$ i ;
609
+ }
610
+
611
+ if ($ lastIndex === null || $ lastSeparatorIndex === null ) {
612
+ return ;
613
+ }
614
+
615
+ $ extractedUseStatement = ltrim ($ extractedUseStatement , '\\' );
616
+
617
+ $ className = '' ;
618
+ for ($ i = $ lastSeparatorIndex + 1 ; $ i <= $ lastIndex ; ++$ i ) {
619
+ $ className .= $ tokens [$ i ]['content ' ];
620
+ }
621
+
622
+ $ error = 'Use statement ' . $ extractedUseStatement . ' for class ' . $ className . ' should be in use block. ' ;
623
+ $ fix = $ phpcsFile ->addFixableError ($ error , $ stackPtr , 'InstanceOf ' );
624
+ if (!$ fix ) {
625
+ return ;
626
+ }
627
+
628
+ $ phpcsFile ->fixer ->beginChangeset ();
629
+
630
+ $ addedUseStatement = $ this ->addUseStatement ($ className , $ extractedUseStatement );
631
+ $ firstSeparatorIndex = $ classNameIndex ;
632
+
633
+ for ($ k = $ lastSeparatorIndex ; $ k > $ firstSeparatorIndex ; --$ k ) {
634
+ $ phpcsFile ->fixer ->replaceToken ($ k , '' );
635
+ }
636
+ $ phpcsFile ->fixer ->replaceToken ($ firstSeparatorIndex , '' );
637
+
638
+ if ($ addedUseStatement ['alias ' ] !== null ) {
639
+ $ phpcsFile ->fixer ->replaceToken ($ lastIndex , $ addedUseStatement ['alias ' ]);
640
+ for ($ k = $ lastSeparatorIndex + 1 ; $ k < $ lastIndex ; ++$ k ) {
641
+ $ phpcsFile ->fixer ->replaceToken ($ k , '' );
642
+ }
643
+ }
644
+
645
+ $ phpcsFile ->fixer ->endChangeset ();
646
+ }
647
+
648
+ /**
649
+ * @param \PHP_CodeSniffer\Files\File $phpcsFile
650
+ * @param int $stackPtr
651
+ *
652
+ * @return void
653
+ */
654
+ public function checkUseForCatchOrCallable (File $ phpcsFile , $ stackPtr ) {
655
+ $ tokens = $ phpcsFile ->getTokens ();
656
+
657
+ $ openParenthesisIndex = $ phpcsFile ->findNext (T_OPEN_PARENTHESIS , $ stackPtr + 1 );
658
+ $ closeParenthesisIndex = $ tokens [$ openParenthesisIndex ]['parenthesis_closer ' ];
659
+ $ classNameIndex = $ phpcsFile ->findNext (Tokens::$ emptyTokens , $ openParenthesisIndex + 1 , null , true );
660
+
661
+ $ lastIndex = null ;
662
+ $ i = $ classNameIndex ;
663
+ $ extractedUseStatement = '' ;
664
+ $ lastSeparatorIndex = null ;
665
+ while ($ i < $ closeParenthesisIndex ) {
666
+ if (!$ this ->isGivenKind ([T_NS_SEPARATOR , T_STRING ], $ tokens [$ i ])) {
667
+ break ;
668
+ }
669
+ $ lastIndex = $ i ;
670
+ $ extractedUseStatement .= $ tokens [$ i ]['content ' ];
671
+
672
+ if ($ this ->isGivenKind ([T_NS_SEPARATOR ], $ tokens [$ i ])) {
673
+ $ lastSeparatorIndex = $ i ;
674
+ }
675
+ ++$ i ;
676
+ }
677
+
678
+ if ($ lastIndex === null || $ lastSeparatorIndex === null ) {
679
+ return ;
680
+ }
681
+
682
+ $ extractedUseStatement = ltrim ($ extractedUseStatement , '\\' );
683
+
684
+ $ className = '' ;
685
+ for ($ k = $ lastSeparatorIndex + 1 ; $ k <= $ lastIndex ; ++$ k ) {
686
+ $ className .= $ tokens [$ k ]['content ' ];
687
+ }
688
+
689
+ $ error = 'Use statement ' . $ extractedUseStatement . ' for class ' . $ className . ' should be in use block. ' ;
690
+ $ fix = $ phpcsFile ->addFixableError ($ error , $ stackPtr , 'Catch ' );
691
+ if (!$ fix ) {
692
+ return ;
693
+ }
694
+
695
+ $ startIndex = $ openParenthesisIndex ;
696
+
697
+ $ phpcsFile ->fixer ->beginChangeset ();
698
+
699
+ $ firstSeparatorIndex = $ phpcsFile ->findNext (Tokens::$ emptyTokens , $ startIndex + 1 , null , true );
700
+
701
+ $ addedUseStatement = $ this ->addUseStatement ($ className , $ extractedUseStatement );
702
+
703
+ for ($ k = $ lastSeparatorIndex ; $ k > $ firstSeparatorIndex ; --$ k ) {
704
+ $ phpcsFile ->fixer ->replaceToken ($ k , '' );
705
+ }
706
+ $ phpcsFile ->fixer ->replaceToken ($ firstSeparatorIndex , '' );
707
+
708
+ if ($ addedUseStatement ['alias ' ] !== null ) {
709
+ $ phpcsFile ->fixer ->replaceToken ($ firstSeparatorIndex + 1 , $ addedUseStatement ['alias ' ]);
710
+ for ($ i = $ firstSeparatorIndex + 2 ; $ i <= $ lastIndex ; ++$ i ) {
711
+ $ phpcsFile ->fixer ->replaceToken ($ i , '' );
712
+ }
713
+ }
714
+
715
+ $ phpcsFile ->fixer ->endChangeset ();
716
+ }
717
+
718
+ /**
719
+ * @param \PHP_CodeSniffer\Files\File $phpcsFile
720
+ * @param int $stackPtr
721
+ *
722
+ * @return void
723
+ */
724
+ protected function checkUseForReturnTypeHint (File $ phpcsFile , $ stackPtr ) {
725
+ $ tokens = $ phpcsFile ->getTokens ();
726
+
727
+ $ openParenthesisIndex = $ phpcsFile ->findNext (T_OPEN_PARENTHESIS , $ stackPtr + 1 );
728
+ $ closeParenthesisIndex = $ tokens [$ openParenthesisIndex ]['parenthesis_closer ' ];
729
+
730
+ $ colonIndex = $ phpcsFile ->findNext (Tokens::$ emptyTokens , $ closeParenthesisIndex + 1 , null , true );
731
+ if (!$ colonIndex ) {
732
+ return ;
733
+ }
734
+
735
+ $ startIndex = $ phpcsFile ->findNext (Tokens::$ emptyTokens , $ colonIndex + 1 , $ colonIndex + 3 , true );
736
+ if (!$ startIndex ) {
737
+ return ;
738
+ }
739
+
740
+ if ($ tokens [$ startIndex ]['type ' ] === 'T_NULLABLE ' ) {
741
+ $ startIndex = $ phpcsFile ->findNext (Tokens::$ emptyTokens , $ startIndex + 1 , $ startIndex + 3 , true );
742
+ }
743
+
744
+ $ lastIndex = null ;
745
+ $ j = $ startIndex ;
746
+ $ extractedUseStatement = '' ;
747
+ $ lastSeparatorIndex = null ;
748
+ while (true ) {
749
+ if (!$ this ->isGivenKind ([T_NS_SEPARATOR , T_STRING , T_RETURN_TYPE ], $ tokens [$ j ])) {
750
+ break ;
751
+ }
752
+
753
+ $ lastIndex = $ j ;
754
+ $ extractedUseStatement .= $ tokens [$ j ]['content ' ];
755
+ if ($ this ->isGivenKind ([T_NS_SEPARATOR ], $ tokens [$ j ])) {
756
+ $ lastSeparatorIndex = $ j ;
757
+ }
758
+ ++$ j ;
759
+ }
760
+
761
+ if ($ lastIndex === null || $ lastSeparatorIndex === null ) {
762
+ return ;
763
+ }
764
+
765
+ $ extractedUseStatement = ltrim ($ extractedUseStatement , '\\' );
766
+ $ className = '' ;
767
+ for ($ k = $ lastSeparatorIndex + 1 ; $ k <= $ lastIndex ; ++$ k ) {
768
+ $ className .= $ tokens [$ k ]['content ' ];
769
+ }
770
+
771
+ $ error = 'Use statement ' . $ extractedUseStatement . ' for class ' . $ className . ' should be in use block. ' ;
772
+ $ fix = $ phpcsFile ->addFixableError ($ error , $ colonIndex , 'ReturnSignature ' );
773
+ if (!$ fix ) {
774
+ return ;
775
+ }
776
+
777
+ $ phpcsFile ->fixer ->beginChangeset ();
778
+
779
+ $ firstSeparatorIndex = $ phpcsFile ->findNext (Tokens::$ emptyTokens , $ startIndex , null , true );
780
+
781
+ $ addedUseStatement = $ this ->addUseStatement ($ className , $ extractedUseStatement );
782
+
783
+ for ($ k = $ lastSeparatorIndex ; $ k > $ firstSeparatorIndex ; --$ k ) {
784
+ $ phpcsFile ->fixer ->replaceToken ($ k , '' );
785
+ }
786
+ $ phpcsFile ->fixer ->replaceToken ($ firstSeparatorIndex , '' );
787
+
788
+ if ($ addedUseStatement ['alias ' ] !== null ) {
789
+ $ phpcsFile ->fixer ->replaceToken ($ lastIndex , $ addedUseStatement ['alias ' ]);
790
+ }
791
+
792
+ $ phpcsFile ->fixer ->endChangeset ();
793
+ }
794
+
578
795
/**
579
796
* @param \PHP_CodeSniffer\Files\File $phpcsFile
580
797
* @param int $stackPtr
0 commit comments