@@ -589,6 +589,64 @@ protected function tokenize($string)
589
589
echo PHP_EOL ;
590
590
}
591
591
592
+ /*
593
+ Tokenize context sensitive keyword as string when it should be string.
594
+ */
595
+
596
+ if ($ tokenIsArray === true
597
+ && isset (Util \Tokens::$ contextSensitiveKeywords [$ token [0 ]]) === true
598
+ && isset ($ this ->tstringContexts [$ finalTokens [$ lastNotEmptyToken ]['code ' ]]) === true
599
+ ) {
600
+ $ preserveKeyword = false ;
601
+
602
+ // `new class` should be preserved
603
+ if ($ token [0 ] === T_CLASS && $ finalTokens [$ lastNotEmptyToken ]['code ' ] === T_NEW ) {
604
+ $ preserveKeyword = true ;
605
+ }
606
+
607
+ // `new class extends` `new class implements` should be preserved
608
+ if (($ token [0 ] === T_EXTENDS || $ token [0 ] === T_IMPLEMENTS )
609
+ && $ finalTokens [$ lastNotEmptyToken ]['code ' ] === T_CLASS
610
+ ) {
611
+ $ preserveKeyword = true ;
612
+ }
613
+
614
+ // `namespace\` should be preserved
615
+ if ($ token [0 ] === T_NAMESPACE ) {
616
+ for ($ i = ($ stackPtr + 1 ); $ i < $ numTokens ; $ i ++) {
617
+ if (is_array ($ tokens [$ i ]) === false ) {
618
+ break ;
619
+ }
620
+
621
+ if (isset (Util \Tokens::$ emptyTokens [$ tokens [$ i ][0 ]]) === true ) {
622
+ continue ;
623
+ }
624
+
625
+ if ($ tokens [$ i ][0 ] === T_NS_SEPARATOR ) {
626
+ $ preserveKeyword = true ;
627
+ }
628
+
629
+ break ;
630
+ }
631
+ }
632
+
633
+ if ($ preserveKeyword === false ) {
634
+ if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
635
+ $ type = Util \Tokens::tokenName ($ token [0 ]);
636
+ echo "\t\t* token $ stackPtr changed from $ type to T_STRING " .PHP_EOL ;
637
+ }
638
+
639
+ $ finalTokens [$ newStackPtr ] = [
640
+ 'code ' => T_STRING ,
641
+ 'type ' => 'T_STRING ' ,
642
+ 'content ' => $ token [1 ],
643
+ ];
644
+
645
+ $ newStackPtr ++;
646
+ continue ;
647
+ }
648
+ }//end if
649
+
592
650
/*
593
651
Parse doc blocks into something that can be easily iterated over.
594
652
*/
@@ -1113,6 +1171,7 @@ protected function tokenize($string)
1113
1171
&& $ tokenIsArray === true
1114
1172
&& $ token [0 ] === T_STRING
1115
1173
&& strtolower ($ token [1 ]) === 'yield '
1174
+ && isset ($ this ->tstringContexts [$ finalTokens [$ lastNotEmptyToken ]['code ' ]]) === false
1116
1175
) {
1117
1176
if (isset ($ tokens [($ stackPtr + 1 )]) === true
1118
1177
&& isset ($ tokens [($ stackPtr + 2 )]) === true
@@ -1446,57 +1505,42 @@ protected function tokenize($string)
1446
1505
1447
1506
if ($ tokenIsArray === true
1448
1507
&& $ token [0 ] === T_DEFAULT
1508
+ && isset ($ this ->tstringContexts [$ finalTokens [$ lastNotEmptyToken ]['code ' ]]) === false
1449
1509
) {
1450
- if (isset ($ this ->tstringContexts [$ finalTokens [$ lastNotEmptyToken ]['code ' ]]) === false ) {
1451
- for ($ x = ($ stackPtr + 1 ); $ x < $ numTokens ; $ x ++) {
1452
- if ($ tokens [$ x ] === ', ' ) {
1453
- // Skip over potential trailing comma (supported in PHP).
1454
- continue ;
1455
- }
1456
-
1457
- if (is_array ($ tokens [$ x ]) === false
1458
- || isset (Util \Tokens::$ emptyTokens [$ tokens [$ x ][0 ]]) === false
1459
- ) {
1460
- // Non-empty, non-comma content.
1461
- break ;
1462
- }
1510
+ for ($ x = ($ stackPtr + 1 ); $ x < $ numTokens ; $ x ++) {
1511
+ if ($ tokens [$ x ] === ', ' ) {
1512
+ // Skip over potential trailing comma (supported in PHP).
1513
+ continue ;
1463
1514
}
1464
1515
1465
- if (isset ($ tokens [$ x ]) === true
1466
- && is_array ($ tokens [$ x ]) === true
1467
- && $ tokens [$ x ][0 ] === T_DOUBLE_ARROW
1516
+ if (is_array ($ tokens [$ x ]) === false
1517
+ || isset (Util \Tokens::$ emptyTokens [$ tokens [$ x ][0 ]]) === false
1468
1518
) {
1469
- // Modify the original token stack for the double arrow so that
1470
- // future checks can disregard the double arrow token more easily.
1471
- // For match expression "case" statements, this is handled
1472
- // in PHP::processAdditional().
1473
- $ tokens [$ x ][0 ] = T_MATCH_ARROW ;
1474
- if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
1475
- echo "\t\t* token $ x changed from T_DOUBLE_ARROW to T_MATCH_ARROW " .PHP_EOL ;
1476
- }
1477
-
1478
- $ newToken = [];
1479
- $ newToken ['code ' ] = T_MATCH_DEFAULT ;
1480
- $ newToken ['type ' ] = 'T_MATCH_DEFAULT ' ;
1481
- $ newToken ['content ' ] = $ token [1 ];
1519
+ // Non-empty, non-comma content.
1520
+ break ;
1521
+ }
1522
+ }
1482
1523
1483
- if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
1484
- echo "\t\t* token $ stackPtr changed from T_DEFAULT to T_MATCH_DEFAULT " .PHP_EOL ;
1485
- }
1524
+ if (isset ($ tokens [$ x ]) === true
1525
+ && is_array ($ tokens [$ x ]) === true
1526
+ && $ tokens [$ x ][0 ] === T_DOUBLE_ARROW
1527
+ ) {
1528
+ // Modify the original token stack for the double arrow so that
1529
+ // future checks can disregard the double arrow token more easily.
1530
+ // For match expression "case" statements, this is handled
1531
+ // in PHP::processAdditional().
1532
+ $ tokens [$ x ][0 ] = T_MATCH_ARROW ;
1533
+ if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
1534
+ echo "\t\t* token $ x changed from T_DOUBLE_ARROW to T_MATCH_ARROW " .PHP_EOL ;
1535
+ }
1486
1536
1487
- $ finalTokens [$ newStackPtr ] = $ newToken ;
1488
- $ newStackPtr ++;
1489
- continue ;
1490
- }//end if
1491
- } else {
1492
- // Definitely not the "default" keyword.
1493
1537
$ newToken = [];
1494
- $ newToken ['code ' ] = T_STRING ;
1495
- $ newToken ['type ' ] = 'T_STRING ' ;
1538
+ $ newToken ['code ' ] = T_MATCH_DEFAULT ;
1539
+ $ newToken ['type ' ] = 'T_MATCH_DEFAULT ' ;
1496
1540
$ newToken ['content ' ] = $ token [1 ];
1497
1541
1498
1542
if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
1499
- echo "\t\t* token $ stackPtr changed from T_DEFAULT to T_STRING " .PHP_EOL ;
1543
+ echo "\t\t* token $ stackPtr changed from T_DEFAULT to T_MATCH_DEFAULT " .PHP_EOL ;
1500
1544
}
1501
1545
1502
1546
$ finalTokens [$ newStackPtr ] = $ newToken ;
@@ -1693,52 +1737,16 @@ protected function tokenize($string)
1693
1737
}
1694
1738
1695
1739
/*
1696
- The string-like token after a function keyword should always be
1697
- tokenized as T_STRING even if it appears to be a different token,
1698
- such as when writing code like: function default(): foo
1699
- so go forward and change the token type before it is processed.
1700
-
1701
- Note: this should not be done for `function Level\Name` within a
1702
- group use statement for the PHP 8 identifier name tokens as it
1703
- would interfere with the re-tokenization of those.
1740
+ This is a special condition for T_ARRAY tokens used for
1741
+ function return types. We want to keep the parenthesis map clean,
1742
+ so let's tag these tokens as T_STRING.
1704
1743
*/
1705
1744
1706
1745
if ($ tokenIsArray === true
1707
1746
&& ($ token [0 ] === T_FUNCTION
1708
1747
|| $ token [0 ] === T_FN )
1709
1748
&& $ finalTokens [$ lastNotEmptyToken ]['code ' ] !== T_USE
1710
1749
) {
1711
- if ($ token [0 ] === T_FUNCTION ) {
1712
- for ($ x = ($ stackPtr + 1 ); $ x < $ numTokens ; $ x ++) {
1713
- if (is_array ($ tokens [$ x ]) === false
1714
- || (isset (Util \Tokens::$ emptyTokens [$ tokens [$ x ][0 ]]) === false
1715
- && $ tokens [$ x ][1 ] !== '& ' )
1716
- ) {
1717
- // Non-empty content.
1718
- break ;
1719
- }
1720
- }
1721
-
1722
- if ($ x < $ numTokens
1723
- && is_array ($ tokens [$ x ]) === true
1724
- && $ tokens [$ x ][0 ] !== T_STRING
1725
- && $ tokens [$ x ][0 ] !== T_NAME_QUALIFIED
1726
- ) {
1727
- if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
1728
- $ oldType = Util \Tokens::tokenName ($ tokens [$ x ][0 ]);
1729
- echo "\t\t* token $ x changed from $ oldType to T_STRING " .PHP_EOL ;
1730
- }
1731
-
1732
- $ tokens [$ x ][0 ] = T_STRING ;
1733
- }
1734
- }//end if
1735
-
1736
- /*
1737
- This is a special condition for T_ARRAY tokens used for
1738
- function return types. We want to keep the parenthesis map clean,
1739
- so let's tag these tokens as T_STRING.
1740
- */
1741
-
1742
1750
// Go looking for the colon to start the return type hint.
1743
1751
// Start by finding the closing parenthesis of the function.
1744
1752
$ parenthesisStack = [];
@@ -1926,31 +1934,31 @@ function return types. We want to keep the parenthesis map clean,
1926
1934
$ newStackPtr ++;
1927
1935
}
1928
1936
} else {
1929
- if ($ tokenIsArray === true && $ token [0 ] === T_STRING ) {
1930
- // Some T_STRING tokens should remain that way
1931
- // due to their context.
1932
- if (isset ($ this ->tstringContexts [$ finalTokens [$ lastNotEmptyToken ]['code ' ]]) === true ) {
1933
- // Special case for syntax like: return new self
1934
- // where self should not be a string.
1935
- if ($ finalTokens [$ lastNotEmptyToken ]['code ' ] === T_NEW
1936
- && strtolower ($ token [1 ]) === 'self '
1937
- ) {
1938
- $ finalTokens [$ newStackPtr ] = [
1939
- 'content ' => $ token [1 ],
1940
- 'code ' => T_SELF ,
1941
- 'type ' => 'T_SELF ' ,
1942
- ];
1943
- } else {
1944
- $ finalTokens [$ newStackPtr ] = [
1945
- 'content ' => $ token [1 ],
1946
- 'code ' => T_STRING ,
1947
- 'type ' => 'T_STRING ' ,
1948
- ];
1949
- }
1937
+ // Some T_STRING tokens should remain that way due to their context.
1938
+ if ($ tokenIsArray === true
1939
+ && $ token [0 ] === T_STRING
1940
+ && isset ($ this ->tstringContexts [$ finalTokens [$ lastNotEmptyToken ]['code ' ]]) === true
1941
+ ) {
1942
+ // Special case for syntax like: return new self
1943
+ // where self should not be a string.
1944
+ if ($ finalTokens [$ lastNotEmptyToken ]['code ' ] === T_NEW
1945
+ && strtolower ($ token [1 ]) === 'self '
1946
+ ) {
1947
+ $ finalTokens [$ newStackPtr ] = [
1948
+ 'content ' => $ token [1 ],
1949
+ 'code ' => T_SELF ,
1950
+ 'type ' => 'T_SELF ' ,
1951
+ ];
1952
+ } else {
1953
+ $ finalTokens [$ newStackPtr ] = [
1954
+ 'content ' => $ token [1 ],
1955
+ 'code ' => T_STRING ,
1956
+ 'type ' => 'T_STRING ' ,
1957
+ ];
1958
+ }
1950
1959
1951
- $ newStackPtr ++;
1952
- continue ;
1953
- }//end if
1960
+ $ newStackPtr ++;
1961
+ continue ;
1954
1962
}//end if
1955
1963
1956
1964
$ newToken = null ;
@@ -2114,16 +2122,6 @@ function return types. We want to keep the parenthesis map clean,
2114
2122
$ newToken ['type ' ] = 'T_FINALLY ' ;
2115
2123
}
2116
2124
2117
- // This is a special case for the PHP 5.5 classname::class syntax
2118
- // where "class" should be T_STRING instead of T_CLASS.
2119
- if (($ newToken ['code ' ] === T_CLASS
2120
- || $ newToken ['code ' ] === T_FUNCTION )
2121
- && $ finalTokens [$ lastNotEmptyToken ]['code ' ] === T_DOUBLE_COLON
2122
- ) {
2123
- $ newToken ['code ' ] = T_STRING ;
2124
- $ newToken ['type ' ] = 'T_STRING ' ;
2125
- }
2126
-
2127
2125
// This is a special case for PHP 5.6 use function and use const
2128
2126
// where "function" and "const" should be T_STRING instead of T_FUNCTION
2129
2127
// and T_CONST.
@@ -2819,34 +2817,11 @@ protected function processAdditional()
2819
2817
$ this ->tokens [$ i ]['code ' ] = T_STRING ;
2820
2818
$ this ->tokens [$ i ]['type ' ] = 'T_STRING ' ;
2821
2819
}
2822
- } else if ($ this ->tokens [$ i ]['code ' ] === T_CONST ) {
2823
- // Context sensitive keywords support.
2824
- for ($ x = ($ i + 1 ); $ i < $ numTokens ; $ x ++) {
2825
- if (isset (Util \Tokens::$ emptyTokens [$ this ->tokens [$ x ]['code ' ]]) === false ) {
2826
- // Non-whitespace content.
2827
- break ;
2828
- }
2829
- }
2830
-
2831
- if ($ this ->tokens [$ x ]['code ' ] !== T_STRING ) {
2832
- if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
2833
- $ line = $ this ->tokens [$ x ]['line ' ];
2834
- $ type = $ this ->tokens [$ x ]['type ' ];
2835
- echo "\t* token $ x on line $ line changed from $ type to T_STRING " .PHP_EOL ;
2836
- }
2837
-
2838
- $ this ->tokens [$ x ]['code ' ] = T_STRING ;
2839
- $ this ->tokens [$ x ]['type ' ] = 'T_STRING ' ;
2840
- }
2841
- } else if ($ this ->tokens [$ i ]['code ' ] === T_READONLY
2842
- || ($ this ->tokens [$ i ]['code ' ] === T_STRING
2843
- && strtolower ($ this ->tokens [$ i ]['content ' ]) === 'readonly ' )
2820
+ } else if ($ this ->tokens [$ i ]['code ' ] === T_STRING
2821
+ && strtolower ($ this ->tokens [$ i ]['content ' ]) === 'readonly '
2844
2822
) {
2845
2823
/*
2846
- Adds "readonly" keyword support:
2847
- PHP < 8.1: Converts T_STRING to T_READONLY
2848
- PHP >= 8.1: Converts some T_READONLY to T_STRING because token_get_all()
2849
- without the TOKEN_PARSE flag cannot distinguish between them in some situations.
2824
+ Adds "readonly" keyword support for PHP < 8.1.
2850
2825
*/
2851
2826
2852
2827
$ allowedAfter = [
@@ -2890,22 +2865,14 @@ protected function processAdditional()
2890
2865
}
2891
2866
}
2892
2867
2893
- if ($ this -> tokens [ $ i ][ ' code ' ] === T_STRING && $ shouldBeReadonly === true ) {
2868
+ if ($ shouldBeReadonly === true ) {
2894
2869
if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
2895
2870
$ line = $ this ->tokens [$ i ]['line ' ];
2896
2871
echo "\t* token $ i on line $ line changed from T_STRING to T_READONLY " .PHP_EOL ;
2897
2872
}
2898
2873
2899
2874
$ this ->tokens [$ i ]['code ' ] = T_READONLY ;
2900
2875
$ this ->tokens [$ i ]['type ' ] = 'T_READONLY ' ;
2901
- } else if ($ this ->tokens [$ i ]['code ' ] === T_READONLY && $ shouldBeReadonly === false ) {
2902
- if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
2903
- $ line = $ this ->tokens [$ i ]['line ' ];
2904
- echo "\t* token $ i on line $ line changed from T_READONLY to T_STRING " .PHP_EOL ;
2905
- }
2906
-
2907
- $ this ->tokens [$ i ]['code ' ] = T_STRING ;
2908
- $ this ->tokens [$ i ]['type ' ] = 'T_STRING ' ;
2909
2876
}
2910
2877
2911
2878
continue ;
0 commit comments