@@ -76,7 +76,8 @@ final class BCFile
7676 *
7777 * Changelog for the PHPCS native function:
7878 * - 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.
8081 *
8182 * @see \PHP_CodeSniffer\Files\File::getDeclarationName() Original source.
8283 * @see \PHPCSUtils\Utils\ObjectDeclarations::getName() PHPCSUtils native improved version.
@@ -88,17 +89,53 @@ final class BCFile
8889 * which declared the class, interface,
8990 * trait, enum or function.
9091 *
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).
9494 *
9595 * @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`.
9897 */
9998 public static function getDeclarationName (File $ phpcsFile , $ stackPtr )
10099 {
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 ;
102139 }
103140
104141 /**
@@ -512,7 +549,8 @@ public static function getMethodProperties(File $phpcsFile, $stackPtr)
512549 *
513550 * Changelog for the PHPCS native function:
514551 * - 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.
516554 *
517555 * @see \PHP_CodeSniffer\Files\File::getMemberProperties() Original source.
518556 * @see \PHPCSUtils\Utils\Variables::getMemberProperties() PHPCSUtils native improved version.
@@ -531,7 +569,137 @@ public static function getMethodProperties(File $phpcsFile, $stackPtr)
531569 */
532570 public static function getMemberProperties (File $ phpcsFile , $ stackPtr )
533571 {
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+ ];
535703 }
536704
537705 /**
@@ -737,7 +905,7 @@ public static function getCondition(File $phpcsFile, $stackPtr, $type, $first =
737905 *
738906 * Changelog for the PHPCS native function:
739907 * - 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 .
741909 *
742910 * @see \PHP_CodeSniffer\Files\File::findExtendedClassName() Original source.
743911 * @see \PHPCSUtils\Utils\ObjectDeclarations::findExtendedClassName() PHPCSUtils native improved version.
@@ -752,7 +920,42 @@ public static function getCondition(File $phpcsFile, $stackPtr, $type, $first =
752920 */
753921 public static function findExtendedClassName (File $ phpcsFile , $ stackPtr )
754922 {
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 ;
756959 }
757960
758961 /**
@@ -762,7 +965,7 @@ public static function findExtendedClassName(File $phpcsFile, $stackPtr)
762965 *
763966 * Changelog for the PHPCS native function:
764967 * - 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 .
766969 *
767970 * @see \PHP_CodeSniffer\Files\File::findImplementedInterfaceNames() Original source.
768971 * @see \PHPCSUtils\Utils\ObjectDeclarations::findImplementedInterfaceNames() PHPCSUtils native improved version.
@@ -777,6 +980,44 @@ public static function findExtendedClassName(File $phpcsFile, $stackPtr)
777980 */
778981 public static function findImplementedInterfaceNames (File $ phpcsFile , $ stackPtr )
779982 {
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+ }
7811022 }
7821023}
0 commit comments