@@ -76,7 +76,8 @@ final class BCFile
76
76
*
77
77
* Changelog for the PHPCS native function:
78
78
* - Introduced in PHPCS 0.0.5.
79
- * - The upstream method has received no significant updates since PHPCS 3.13.0.
79
+ * - PHPCS 4.0: The method no longer accepts `T_CLOSURE` and `T_ANON_CLASS` tokens.
80
+ * - PHPCS 4.0: The method will now always return a string.
80
81
*
81
82
* @see \PHP_CodeSniffer\Files\File::getDeclarationName() Original source.
82
83
* @see \PHPCSUtils\Utils\ObjectDeclarations::getName() PHPCSUtils native improved version.
@@ -88,17 +89,53 @@ final class BCFile
88
89
* which declared the class, interface,
89
90
* trait, enum or function.
90
91
*
91
- * @return string|null The name of the class, interface, trait, enum, or function;
92
- * or `NULL` if the function or class is anonymous or
93
- * in case of a parse error/live coding.
92
+ * @return string The name of the class, interface, trait, or function or an empty string
93
+ * if the name could not be determined (live coding).
94
94
*
95
95
* @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified token is not of type
96
- * `T_FUNCTION`, `T_CLASS`, `T_ANON_CLASS`,
97
- * `T_CLOSURE`, `T_TRAIT`, `T_ENUM` or `T_INTERFACE`.
96
+ * `T_FUNCTION`, `T_CLASS`, `T_TRAIT`, `T_ENUM`, or `T_INTERFACE`.
98
97
*/
99
98
public static function getDeclarationName (File $ phpcsFile , $ stackPtr )
100
99
{
101
- return $ phpcsFile ->getDeclarationName ($ stackPtr );
100
+ $ tokens = $ phpcsFile ->getTokens ();
101
+
102
+ $ tokenCode = $ tokens [$ stackPtr ]['code ' ];
103
+
104
+ if ($ tokenCode !== T_FUNCTION
105
+ && $ tokenCode !== T_CLASS
106
+ && $ tokenCode !== T_INTERFACE
107
+ && $ tokenCode !== T_TRAIT
108
+ && $ tokenCode !== T_ENUM
109
+ ) {
110
+ throw new RuntimeException ('Token type " ' . $ tokens [$ stackPtr ]['type ' ] . '" is not T_FUNCTION, T_CLASS, T_INTERFACE, T_TRAIT or T_ENUM ' );
111
+ }
112
+
113
+ if ($ tokenCode === T_FUNCTION
114
+ && strtolower ($ tokens [$ stackPtr ]['content ' ]) !== 'function '
115
+ ) {
116
+ // This is a function declared without the "function" keyword.
117
+ // So this token is the function name.
118
+ return $ tokens [$ stackPtr ]['content ' ];
119
+ }
120
+
121
+ $ stopPoint = $ phpcsFile ->numTokens ;
122
+ if (isset ($ tokens [$ stackPtr ]['parenthesis_opener ' ]) === true ) {
123
+ // For functions, stop searching at the parenthesis opener.
124
+ $ stopPoint = $ tokens [$ stackPtr ]['parenthesis_opener ' ];
125
+ } elseif (isset ($ tokens [$ stackPtr ]['scope_opener ' ]) === true ) {
126
+ // For OO tokens, stop searching at the open curly.
127
+ $ stopPoint = $ tokens [$ stackPtr ]['scope_opener ' ];
128
+ }
129
+
130
+ $ content = '' ;
131
+ for ($ i = $ stackPtr ; $ i < $ stopPoint ; $ i ++) {
132
+ if ($ tokens [$ i ]['code ' ] === T_STRING ) {
133
+ $ content = $ tokens [$ i ]['content ' ];
134
+ break ;
135
+ }
136
+ }
137
+
138
+ return $ content ;
102
139
}
103
140
104
141
/**
@@ -512,7 +549,8 @@ public static function getMethodProperties(File $phpcsFile, $stackPtr)
512
549
*
513
550
* Changelog for the PHPCS native function:
514
551
* - Introduced in PHPCS 0.0.5.
515
- * - The upstream method has received no significant updates since PHPCS 3.13.0.
552
+ * - PHPCS 4.0: properties in interfaces (PHP 8.4+) are accepted.
553
+ * - PHPCS 4.0: will no longer throw a parse error warning.
516
554
*
517
555
* @see \PHP_CodeSniffer\Files\File::getMemberProperties() Original source.
518
556
* @see \PHPCSUtils\Utils\Variables::getMemberProperties() PHPCSUtils native improved version.
@@ -531,7 +569,137 @@ public static function getMethodProperties(File $phpcsFile, $stackPtr)
531
569
*/
532
570
public static function getMemberProperties (File $ phpcsFile , $ stackPtr )
533
571
{
534
- return $ phpcsFile ->getMemberProperties ($ stackPtr );
572
+ $ tokens = $ phpcsFile ->getTokens ();
573
+
574
+ if ($ tokens [$ stackPtr ]['code ' ] !== T_VARIABLE ) {
575
+ throw new RuntimeException ('$stackPtr must be of type T_VARIABLE ' );
576
+ }
577
+
578
+ $ conditions = $ tokens [$ stackPtr ]['conditions ' ];
579
+ $ conditions = array_keys ($ conditions );
580
+ $ ptr = array_pop ($ conditions );
581
+ if (isset ($ tokens [$ ptr ]) === false
582
+ || isset (Tokens::$ ooScopeTokens [$ tokens [$ ptr ]['code ' ]]) === false
583
+ || $ tokens [$ ptr ]['code ' ] === T_ENUM
584
+ ) {
585
+ throw new RuntimeException ('$stackPtr is not a class member var ' );
586
+ }
587
+
588
+ // Make sure it's not a method parameter.
589
+ if (empty ($ tokens [$ stackPtr ]['nested_parenthesis ' ]) === false ) {
590
+ $ parenthesis = array_keys ($ tokens [$ stackPtr ]['nested_parenthesis ' ]);
591
+ $ deepestOpen = array_pop ($ parenthesis );
592
+ if ($ deepestOpen > $ ptr
593
+ && isset ($ tokens [$ deepestOpen ]['parenthesis_owner ' ]) === true
594
+ && $ tokens [$ tokens [$ deepestOpen ]['parenthesis_owner ' ]]['code ' ] === T_FUNCTION
595
+ ) {
596
+ throw new RuntimeException ('$stackPtr is not a class member var ' );
597
+ }
598
+ }
599
+
600
+ $ valid = [
601
+ T_PUBLIC => T_PUBLIC ,
602
+ T_PRIVATE => T_PRIVATE ,
603
+ T_PROTECTED => T_PROTECTED ,
604
+ T_STATIC => T_STATIC ,
605
+ T_VAR => T_VAR ,
606
+ T_READONLY => T_READONLY ,
607
+ T_FINAL => T_FINAL ,
608
+ ];
609
+
610
+ $ valid += Tokens::$ emptyTokens ;
611
+
612
+ $ scope = 'public ' ;
613
+ $ scopeSpecified = false ;
614
+ $ isStatic = false ;
615
+ $ isReadonly = false ;
616
+ $ isFinal = false ;
617
+
618
+ $ startOfStatement = $ phpcsFile ->findPrevious (
619
+ [
620
+ T_SEMICOLON ,
621
+ T_OPEN_CURLY_BRACKET ,
622
+ T_CLOSE_CURLY_BRACKET ,
623
+ T_ATTRIBUTE_END ,
624
+ ],
625
+ ($ stackPtr - 1 )
626
+ );
627
+
628
+ for ($ i = ($ startOfStatement + 1 ); $ i < $ stackPtr ; $ i ++) {
629
+ if (isset ($ valid [$ tokens [$ i ]['code ' ]]) === false ) {
630
+ break ;
631
+ }
632
+
633
+ switch ($ tokens [$ i ]['code ' ]) {
634
+ case T_PUBLIC :
635
+ $ scope = 'public ' ;
636
+ $ scopeSpecified = true ;
637
+ break ;
638
+ case T_PRIVATE :
639
+ $ scope = 'private ' ;
640
+ $ scopeSpecified = true ;
641
+ break ;
642
+ case T_PROTECTED :
643
+ $ scope = 'protected ' ;
644
+ $ scopeSpecified = true ;
645
+ break ;
646
+ case T_STATIC :
647
+ $ isStatic = true ;
648
+ break ;
649
+ case T_READONLY :
650
+ $ isReadonly = true ;
651
+ break ;
652
+ case T_FINAL :
653
+ $ isFinal = true ;
654
+ break ;
655
+ }
656
+ }
657
+
658
+ $ type = '' ;
659
+ $ typeToken = false ;
660
+ $ typeEndToken = false ;
661
+ $ nullableType = false ;
662
+
663
+ if ($ i < $ stackPtr ) {
664
+ // We've found a type.
665
+ $ valid = Collections::propertyTypeTokens ();
666
+
667
+ for ($ i ; $ i < $ stackPtr ; $ i ++) {
668
+ if ($ tokens [$ i ]['code ' ] === T_VARIABLE ) {
669
+ // Hit another variable in a group definition.
670
+ break ;
671
+ }
672
+
673
+ if ($ tokens [$ i ]['code ' ] === T_NULLABLE ) {
674
+ $ nullableType = true ;
675
+ }
676
+
677
+ if (isset ($ valid [$ tokens [$ i ]['code ' ]]) === true ) {
678
+ $ typeEndToken = $ i ;
679
+ if ($ typeToken === false ) {
680
+ $ typeToken = $ i ;
681
+ }
682
+
683
+ $ type .= $ tokens [$ i ]['content ' ];
684
+ }
685
+ }
686
+
687
+ if ($ type !== '' && $ nullableType === true ) {
688
+ $ type = '? ' . $ type ;
689
+ }
690
+ }
691
+
692
+ return [
693
+ 'scope ' => $ scope ,
694
+ 'scope_specified ' => $ scopeSpecified ,
695
+ 'is_static ' => $ isStatic ,
696
+ 'is_readonly ' => $ isReadonly ,
697
+ 'is_final ' => $ isFinal ,
698
+ 'type ' => $ type ,
699
+ 'type_token ' => $ typeToken ,
700
+ 'type_end_token ' => $ typeEndToken ,
701
+ 'nullable_type ' => $ nullableType ,
702
+ ];
535
703
}
536
704
537
705
/**
@@ -737,7 +905,7 @@ public static function getCondition(File $phpcsFile, $stackPtr, $type, $first =
737
905
*
738
906
* Changelog for the PHPCS native function:
739
907
* - Introduced in PHPCS 1.2.0.
740
- * - The upstream method has received no significant updates since PHPCS 3.13.0 .
908
+ * - PHPCS 4.0.0: Handling of the namespace relative parent class using the namespace keyword as operator .
741
909
*
742
910
* @see \PHP_CodeSniffer\Files\File::findExtendedClassName() Original source.
743
911
* @see \PHPCSUtils\Utils\ObjectDeclarations::findExtendedClassName() PHPCSUtils native improved version.
@@ -752,7 +920,42 @@ public static function getCondition(File $phpcsFile, $stackPtr, $type, $first =
752
920
*/
753
921
public static function findExtendedClassName (File $ phpcsFile , $ stackPtr )
754
922
{
755
- return $ phpcsFile ->findExtendedClassName ($ stackPtr );
923
+ $ tokens = $ phpcsFile ->getTokens ();
924
+
925
+ // Check for the existence of the token.
926
+ if (isset ($ tokens [$ stackPtr ]) === false ) {
927
+ return false ;
928
+ }
929
+
930
+ if ($ tokens [$ stackPtr ]['code ' ] !== T_CLASS
931
+ && $ tokens [$ stackPtr ]['code ' ] !== T_ANON_CLASS
932
+ && $ tokens [$ stackPtr ]['code ' ] !== T_INTERFACE
933
+ ) {
934
+ return false ;
935
+ }
936
+
937
+ if (isset ($ tokens [$ stackPtr ]['scope_opener ' ]) === false ) {
938
+ return false ;
939
+ }
940
+
941
+ $ classOpenerIndex = $ tokens [$ stackPtr ]['scope_opener ' ];
942
+ $ extendsIndex = $ phpcsFile ->findNext (T_EXTENDS , $ stackPtr , $ classOpenerIndex );
943
+ if ($ extendsIndex === false ) {
944
+ return false ;
945
+ }
946
+
947
+ $ find = Collections::namespacedNameTokens ();
948
+ $ find [] = T_WHITESPACE ;
949
+
950
+ $ end = $ phpcsFile ->findNext ($ find , ($ extendsIndex + 1 ), ($ classOpenerIndex + 1 ), true );
951
+ $ name = $ phpcsFile ->getTokensAsString (($ extendsIndex + 1 ), ($ end - $ extendsIndex - 1 ));
952
+ $ name = trim ($ name );
953
+
954
+ if ($ name === '' ) {
955
+ return false ;
956
+ }
957
+
958
+ return $ name ;
756
959
}
757
960
758
961
/**
@@ -762,7 +965,7 @@ public static function findExtendedClassName(File $phpcsFile, $stackPtr)
762
965
*
763
966
* Changelog for the PHPCS native function:
764
967
* - Introduced in PHPCS 2.7.0.
765
- * - The upstream method has received no significant updates since PHPCS 3.13.0 .
968
+ * - PHPCS 4.0.0: Handling of the namespace relative parent class using the namespace keyword as operator .
766
969
*
767
970
* @see \PHP_CodeSniffer\Files\File::findImplementedInterfaceNames() Original source.
768
971
* @see \PHPCSUtils\Utils\ObjectDeclarations::findImplementedInterfaceNames() PHPCSUtils native improved version.
@@ -777,6 +980,44 @@ public static function findExtendedClassName(File $phpcsFile, $stackPtr)
777
980
*/
778
981
public static function findImplementedInterfaceNames (File $ phpcsFile , $ stackPtr )
779
982
{
780
- return $ phpcsFile ->findImplementedInterfaceNames ($ stackPtr );
983
+ $ tokens = $ phpcsFile ->getTokens ();
984
+
985
+ // Check for the existence of the token.
986
+ if (isset ($ tokens [$ stackPtr ]) === false ) {
987
+ return false ;
988
+ }
989
+
990
+ if ($ tokens [$ stackPtr ]['code ' ] !== T_CLASS
991
+ && $ tokens [$ stackPtr ]['code ' ] !== T_ANON_CLASS
992
+ && $ tokens [$ stackPtr ]['code ' ] !== T_ENUM
993
+ ) {
994
+ return false ;
995
+ }
996
+
997
+ if (isset ($ tokens [$ stackPtr ]['scope_closer ' ]) === false ) {
998
+ return false ;
999
+ }
1000
+
1001
+ $ classOpenerIndex = $ tokens [$ stackPtr ]['scope_opener ' ];
1002
+ $ implementsIndex = $ phpcsFile ->findNext (T_IMPLEMENTS , $ stackPtr , $ classOpenerIndex );
1003
+ if ($ implementsIndex === false ) {
1004
+ return false ;
1005
+ }
1006
+
1007
+ $ find = Collections::namespacedNameTokens ();
1008
+ $ find [] = T_WHITESPACE ;
1009
+ $ find [] = T_COMMA ;
1010
+
1011
+ $ end = $ phpcsFile ->findNext ($ find , ($ implementsIndex + 1 ), ($ classOpenerIndex + 1 ), true );
1012
+ $ name = $ phpcsFile ->getTokensAsString (($ implementsIndex + 1 ), ($ end - $ implementsIndex - 1 ));
1013
+ $ name = trim ($ name );
1014
+
1015
+ if ($ name === '' ) {
1016
+ return false ;
1017
+ } else {
1018
+ $ names = explode (', ' , $ name );
1019
+ $ names = array_map ('trim ' , $ names );
1020
+ return $ names ;
1021
+ }
781
1022
}
782
1023
}
0 commit comments