@@ -694,6 +694,25 @@ protected function tokenize($string)
694694 break ;
695695 }
696696 }
697+
698+ // Fully Qualified `\exit`/`\die` should be preserved.
699+ if ($ token [0 ] === T_EXIT
700+ && $ finalTokens [$ lastNotEmptyToken ]['code ' ] === T_NS_SEPARATOR
701+ ) {
702+ for ($ i = ($ lastNotEmptyToken - 1 ); $ i >= 0 ; $ i --) {
703+ if (isset (Tokens::$ emptyTokens [$ finalTokens [$ i ]['code ' ]]) === true ) {
704+ continue ;
705+ }
706+
707+ if ($ finalTokens [$ i ]['code ' ] !== T_STRING
708+ && $ finalTokens [$ i ]['code ' ] !== T_NAMESPACE
709+ ) {
710+ $ preserveKeyword = true ;
711+ }
712+
713+ break ;
714+ }
715+ }
697716 }//end if
698717
699718 // Types in typed constants should not be touched, but the constant name should be.
@@ -1355,6 +1374,38 @@ protected function tokenize($string)
13551374 $ name = substr ($ name , 10 );
13561375 }
13571376
1377+ // Special case keywords which can be used in fully qualified form.
1378+ if ($ token [0 ] === T_NAME_FULLY_QUALIFIED ) {
1379+ $ specialCasedType = null ;
1380+ $ nameLc = strtolower ($ name );
1381+ if ($ nameLc === 'exit ' || $ nameLc === 'die ' ) {
1382+ $ specialCasedType = 'T_EXIT ' ;
1383+ } else if ($ nameLc === 'true ' ) {
1384+ $ specialCasedType = 'T_TRUE ' ;
1385+ } else if ($ nameLc === 'false ' ) {
1386+ $ specialCasedType = 'T_FALSE ' ;
1387+ } else if ($ nameLc === 'null ' ) {
1388+ $ specialCasedType = 'T_NULL ' ;
1389+ }
1390+
1391+ if ($ specialCasedType !== null ) {
1392+ $ newToken = [];
1393+ $ newToken ['code ' ] = constant ($ specialCasedType );
1394+ $ newToken ['type ' ] = $ specialCasedType ;
1395+ $ newToken ['content ' ] = $ name ;
1396+ $ finalTokens [$ newStackPtr ] = $ newToken ;
1397+ ++$ newStackPtr ;
1398+
1399+ if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
1400+ $ type = Tokens::tokenName ($ token [0 ]);
1401+ $ content = Common::prepareForOutput ($ token [1 ]);
1402+ echo "\t\t* token $ stackPtr split into individual tokens T_NS_SEPARATOR + $ specialCasedType " .PHP_EOL ;
1403+ }
1404+
1405+ continue ;
1406+ }
1407+ }//end if
1408+
13581409 $ parts = explode ('\\' , $ name );
13591410 $ partCount = count ($ parts );
13601411 $ lastPart = ($ partCount - 1 );
@@ -2523,16 +2574,37 @@ function return types. We want to keep the parenthesis map clean,
25232574 } else if (isset ($ this ->tstringContexts [$ finalTokens [$ lastNotEmptyToken ]['code ' ]]) === true
25242575 && $ finalTokens [$ lastNotEmptyToken ]['code ' ] !== T_CONST
25252576 ) {
2526- $ preserveTstring = true ;
2577+ $ preserveTstring = true ;
2578+ $ tokenContentLower = strtolower ($ token [1 ]);
25272579
25282580 // Special case for syntax like: return new self/new parent
25292581 // where self/parent should not be a string.
2530- $ tokenContentLower = strtolower ($ token [1 ]);
25312582 if ($ finalTokens [$ lastNotEmptyToken ]['code ' ] === T_NEW
25322583 && ($ tokenContentLower === 'self ' || $ tokenContentLower === 'parent ' )
25332584 ) {
25342585 $ preserveTstring = false ;
25352586 }
2587+
2588+ // Special case for fully qualified \true, \false and \null
2589+ // where true/false/null should not be a string.
2590+ // Note: if this is the _start_ of a longer namespaced name, this will undone again later.
2591+ if ($ finalTokens [$ lastNotEmptyToken ]['code ' ] === T_NS_SEPARATOR
2592+ && ($ tokenContentLower === 'true ' || $ tokenContentLower === 'false ' || $ tokenContentLower === 'null ' )
2593+ ) {
2594+ for ($ i = ($ lastNotEmptyToken - 1 ); $ i >= 0 ; $ i --) {
2595+ if (isset (Tokens::$ emptyTokens [$ finalTokens [$ i ]['code ' ]]) === true ) {
2596+ continue ;
2597+ }
2598+
2599+ if ($ finalTokens [$ i ]['code ' ] !== T_STRING
2600+ && $ finalTokens [$ i ]['code ' ] !== T_NAMESPACE
2601+ ) {
2602+ $ preserveTstring = false ;
2603+ }
2604+
2605+ break ;
2606+ }
2607+ }
25362608 } else if ($ finalTokens [$ lastNotEmptyToken ]['content ' ] === '& ' ) {
25372609 // Function names for functions declared to return by reference.
25382610 for ($ i = ($ lastNotEmptyToken - 1 ); $ i >= 0 ; $ i --) {
@@ -3629,6 +3701,7 @@ protected function processAdditional()
36293701 } else if ($ this ->tokens [$ i ]['code ' ] === T_TRUE
36303702 || $ this ->tokens [$ i ]['code ' ] === T_FALSE
36313703 || $ this ->tokens [$ i ]['code ' ] === T_NULL
3704+ || $ this ->tokens [$ i ]['code ' ] === T_EXIT
36323705 ) {
36333706 for ($ x = ($ i + 1 ); $ x < $ numTokens ; $ x ++) {
36343707 if (isset (Tokens::$ emptyTokens [$ this ->tokens [$ x ]['code ' ]]) === false ) {
0 commit comments