@@ -1217,6 +1217,28 @@ function return types. We want to keep the parenthesis map clean,
1217
1217
continue ;
1218
1218
}
1219
1219
1220
+ /*
1221
+ Backfill the T_FN token for PHP versions < 7.4.
1222
+ */
1223
+
1224
+ if ($ tokenIsArray === true
1225
+ && $ token [0 ] === T_STRING
1226
+ && strtolower ($ token [1 ]) === 'fn '
1227
+ ) {
1228
+ $ finalTokens [$ newStackPtr ] = [
1229
+ 'content ' => $ token [1 ],
1230
+ 'code ' => T_FN ,
1231
+ 'type ' => 'T_FN ' ,
1232
+ ];
1233
+
1234
+ if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
1235
+ echo "\t\t* token $ stackPtr changed from T_STRING to T_FN " .PHP_EOL ;
1236
+ }
1237
+
1238
+ $ newStackPtr ++;
1239
+ continue ;
1240
+ }
1241
+
1220
1242
/*
1221
1243
PHP doesn't assign a token to goto labels, so we have to.
1222
1244
These are just string tokens with a single colon after them. Double
@@ -1606,9 +1628,7 @@ protected function processAdditional()
1606
1628
}//end if
1607
1629
1608
1630
continue ;
1609
- } else if ($ this ->tokens [$ i ]['code ' ] === T_STRING
1610
- && strtolower ($ this ->tokens [$ i ]['content ' ]) === 'fn '
1611
- ) {
1631
+ } else if ($ this ->tokens [$ i ]['code ' ] === T_FN ) {
1612
1632
// Possible arrow function.
1613
1633
for ($ x = ($ i + 1 ); $ i < $ numTokens ; $ x ++) {
1614
1634
if (isset (Util \Tokens::$ emptyTokens [$ this ->tokens [$ x ]['code ' ]]) === false ) {
@@ -1618,22 +1638,84 @@ protected function processAdditional()
1618
1638
}
1619
1639
1620
1640
if ($ this ->tokens [$ x ]['code ' ] === T_OPEN_PARENTHESIS ) {
1621
- if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
1622
- $ line = $ this ->tokens [$ i ]['line ' ];
1623
- echo "\t* token $ i on line $ line changed from T_STRING to T_FN " .PHP_EOL ;
1641
+ $ ignore = Util \Tokens::$ emptyTokens ;
1642
+ $ ignore += [
1643
+ T_STRING => T_STRING ,
1644
+ T_COLON => T_COLON ,
1645
+ ];
1646
+
1647
+ $ closer = $ this ->tokens [$ x ]['parenthesis_closer ' ];
1648
+ for ($ arrow = ($ closer + 1 ); $ arrow < $ numTokens ; $ arrow ++) {
1649
+ if (isset ($ ignore [$ this ->tokens [$ arrow ]['code ' ]]) === false ) {
1650
+ break ;
1651
+ }
1624
1652
}
1625
1653
1626
- $ this ->tokens [$ i ]['code ' ] = T_FN ;
1627
- $ this ->tokens [$ i ]['type ' ] = 'T_FN ' ;
1628
- $ this ->tokens [$ i ]['parenthesis_owner ' ] = $ i ;
1629
- $ this ->tokens [$ i ]['parenthesis_opener ' ] = $ x ;
1630
- $ this ->tokens [$ i ]['parenthesis_closer ' ] = $ this ->tokens [$ x ]['parenthesis_closer ' ];
1654
+ if ($ this ->tokens [$ arrow ]['code ' ] === T_DOUBLE_ARROW ) {
1655
+ $ endTokens = [
1656
+ T_COLON => true ,
1657
+ T_COMMA => true ,
1658
+ T_DOUBLE_ARROW => true ,
1659
+ T_SEMICOLON => true ,
1660
+ T_CLOSE_PARENTHESIS => true ,
1661
+ T_CLOSE_SQUARE_BRACKET => true ,
1662
+ T_CLOSE_CURLY_BRACKET => true ,
1663
+ T_CLOSE_SHORT_ARRAY => true ,
1664
+ T_OPEN_TAG => true ,
1665
+ T_CLOSE_TAG => true ,
1666
+ ];
1631
1667
1632
- $ opener = $ this ->tokens [$ i ]['parenthesis_opener ' ];
1633
- $ closer = $ this ->tokens [$ i ]['parenthesis_closer ' ];
1634
- $ this ->tokens [$ opener ]['parenthesis_owner ' ] = $ i ;
1635
- $ this ->tokens [$ closer ]['parenthesis_owner ' ] = $ i ;
1636
- }
1668
+ for ($ scopeCloser = ($ arrow + 1 ); $ scopeCloser < $ numTokens ; $ scopeCloser ++) {
1669
+ if (isset ($ endTokens [$ this ->tokens [$ scopeCloser ]['code ' ]]) === true ) {
1670
+ break ;
1671
+ }
1672
+
1673
+ if (isset ($ this ->tokens [$ scopeCloser ]['scope_closer ' ]) === true ) {
1674
+ // We minus 1 here in case the closer can be shared with us.
1675
+ $ scopeCloser = ($ this ->tokens [$ scopeCloser ]['scope_closer ' ] - 1 );
1676
+ continue ;
1677
+ }
1678
+
1679
+ if (isset ($ this ->tokens [$ scopeCloser ]['parenthesis_closer ' ]) === true ) {
1680
+ $ scopeCloser = $ this ->tokens [$ scopeCloser ]['parenthesis_closer ' ];
1681
+ continue ;
1682
+ }
1683
+
1684
+ if (isset ($ this ->tokens [$ scopeCloser ]['bracket_closer ' ]) === true ) {
1685
+ $ scopeCloser = $ this ->tokens [$ scopeCloser ]['bracket_closer ' ];
1686
+ continue ;
1687
+ }
1688
+ }//end for
1689
+
1690
+ if ($ scopeCloser !== $ numTokens ) {
1691
+ if (PHP_CODESNIFFER_VERBOSITY > 1 ) {
1692
+ $ line = $ this ->tokens [$ i ]['line ' ];
1693
+ echo "\t* token $ i on line $ line changed from T_STRING to T_FN " .PHP_EOL ;
1694
+ }
1695
+
1696
+ $ this ->tokens [$ i ]['code ' ] = T_FN ;
1697
+ $ this ->tokens [$ i ]['type ' ] = 'T_FN ' ;
1698
+ $ this ->tokens [$ i ]['scope_condition ' ] = $ i ;
1699
+ $ this ->tokens [$ i ]['scope_opener ' ] = $ arrow ;
1700
+ $ this ->tokens [$ i ]['scope_closer ' ] = $ scopeCloser ;
1701
+ $ this ->tokens [$ i ]['parenthesis_owner ' ] = $ i ;
1702
+ $ this ->tokens [$ i ]['parenthesis_opener ' ] = $ x ;
1703
+ $ this ->tokens [$ i ]['parenthesis_closer ' ] = $ this ->tokens [$ x ]['parenthesis_closer ' ];
1704
+
1705
+ $ this ->tokens [$ arrow ]['scope_condition ' ] = $ i ;
1706
+ $ this ->tokens [$ arrow ]['scope_opener ' ] = $ arrow ;
1707
+ $ this ->tokens [$ arrow ]['scope_closer ' ] = $ scopeCloser ;
1708
+ $ this ->tokens [$ scopeCloser ]['scope_condition ' ] = $ i ;
1709
+ $ this ->tokens [$ scopeCloser ]['scope_opener ' ] = $ arrow ;
1710
+ $ this ->tokens [$ scopeCloser ]['scope_closer ' ] = $ scopeCloser ;
1711
+
1712
+ $ opener = $ this ->tokens [$ i ]['parenthesis_opener ' ];
1713
+ $ closer = $ this ->tokens [$ i ]['parenthesis_closer ' ];
1714
+ $ this ->tokens [$ opener ]['parenthesis_owner ' ] = $ i ;
1715
+ $ this ->tokens [$ closer ]['parenthesis_owner ' ] = $ i ;
1716
+ }//end if
1717
+ }//end if
1718
+ }//end if
1637
1719
} else if ($ this ->tokens [$ i ]['code ' ] === T_OPEN_SQUARE_BRACKET ) {
1638
1720
if (isset ($ this ->tokens [$ i ]['bracket_closer ' ]) === false ) {
1639
1721
continue ;
0 commit comments