@@ -6577,7 +6577,9 @@ public function format($source) {
65776577 $ this ->tkns = token_get_all ($ source );
65786578 $ this ->code = '' ;
65796579
6580- $ found = [];
6580+ $ curlyDepth = 0 ;
6581+ $ classCurlyDepthStack = [];
6582+ $ awaitingClassCurly = false ;
65816583 $ visibility = null ;
65826584 $ finalOrAbstract = null ;
65836585 $ static = null ;
@@ -6635,7 +6637,7 @@ public function format($source) {
66356637 $ this ->appendCode ($ text );
66366638 break ;
66376639 }
6638- $ found [] = T_CLASS ;
6640+ $ awaitingClassCurly = true ;
66396641 $ touchedClassInterfaceTrait = true ;
66406642 if ($ static !== null ) {
66416643 $ this ->appendCode ($ static . ' ' );
@@ -6648,59 +6650,82 @@ public function format($source) {
66486650 $ skipWhitespaces = false ;
66496651 }
66506652 $ this ->appendCode ($ text );
6651- $ this ->printUntilAny ([T_EXTENDS , T_IMPLEMENTS , ST_CURLY_OPEN ]);
6653+ while (list ($ index , $ token ) = $ this ->each ($ this ->tkns )) {
6654+ list ($ id , $ text ) = $ this ->getToken ($ token );
6655+ $ this ->ptr = $ index ;
6656+ if (ST_CURLY_OPEN === $ id ) {
6657+ ++$ curlyDepth ;
6658+ if ($ awaitingClassCurly ) {
6659+ $ classCurlyDepthStack [] = $ curlyDepth ;
6660+ $ awaitingClassCurly = false ;
6661+ }
6662+ $ this ->appendCode ($ text );
6663+ $ touchedClassInterfaceTrait = false ;
6664+ break ;
6665+ }
6666+ $ this ->appendCode ($ text );
6667+ }
66526668 break ;
66536669 case T_NAMESPACE :
6654- $ found [] = T_NAMESPACE ;
66556670 $ touchedClassInterfaceTrait = true ;
66566671 $ this ->appendCode ($ text );
66576672 break ;
66586673 case T_INTERFACE :
6659- // $found[] = T_INTERFACE ;
6674+ $ awaitingClassCurly = true ;
66606675 $ touchedClassInterfaceTrait = true ;
66616676 $ this ->appendCode ($ text );
66626677 break ;
66636678 case T_TRAIT :
6664- $ found [] = T_TRAIT ;
6679+ $ awaitingClassCurly = true ;
66656680 $ touchedClassInterfaceTrait = true ;
66666681 $ this ->appendCode ($ text );
66676682 break ;
66686683 case T_ENUM :
6669- $ found [] = T_ENUM ;
6684+ $ awaitingClassCurly = true ;
66706685 $ touchedClassInterfaceTrait = true ;
66716686 $ this ->appendCode ($ text );
66726687 break ;
66736688 case ST_CURLY_OPEN :
6674- case ST_PARENTHESES_OPEN :
6675- if ($ touchedClassInterfaceTrait ) {
6676- $ found [] = $ text ;
6689+ ++$ curlyDepth ;
6690+ if ($ awaitingClassCurly ) {
6691+ $ classCurlyDepthStack [] = $ curlyDepth ;
6692+ $ awaitingClassCurly = false ;
66776693 }
66786694 $ this ->appendCode ($ text );
66796695 $ touchedClassInterfaceTrait = false ;
66806696 break ;
66816697 case ST_CURLY_CLOSE :
6682- case ST_PARENTHESES_CLOSE :
6683- array_pop ($ found );
6684- if (1 === sizeof ($ found )) {
6685- array_pop ($ found );
6698+ if (!empty ($ classCurlyDepthStack ) && end ($ classCurlyDepthStack ) === $ curlyDepth ) {
6699+ array_pop ($ classCurlyDepthStack );
66866700 }
6687- if (count ($ found ) === 0 ) {
6688- $ touchedClassInterfaceTrait = false ;
6689- }
6701+ $ curlyDepth = max (0 , $ curlyDepth - 1 );
6702+ if (count ($ classCurlyDepthStack ) === 0 ) {
6703+ $ touchedClassInterfaceTrait = false ;
6704+ }
6705+ $ this ->appendCode ($ text );
6706+ break ;
6707+ case ST_PARENTHESES_OPEN :
6708+ case ST_PARENTHESES_CLOSE :
66906709 $ this ->appendCode ($ text );
6710+ $ touchedClassInterfaceTrait = false ;
66916711 break ;
66926712 case T_WHITESPACE :
66936713 if (!$ skipWhitespaces ) {
66946714 $ this ->appendCode ($ text );
66956715 }
66966716 break ;
66976717 case '? ' :
6698- $ tidx = $ this ->rightUsefulTokenIdx ();
6699- if (in_array ($ this ->tkns [$ tidx ][0 ], [T_STRING , T_ARRAY , T_NAME_RELATIVE , T_NAME_QUALIFIED , T_NAME_FULLY_QUALIFIED ]) && (! isset ($ this ->tkns [$ tidx + 1 ]) || $ this ->tkns [$ tidx + 1 ][0 ] !== '( ' )) {
6700- $ this ->tkns [$ tidx ][1 ] = $ text . $ this ->tkns [$ tidx ][1 ];
6701- } else {
6702- $ this ->appendCode ($ text );
6703- }
6718+ // Only merge ? with following type for nullable types (e.g., ?string)
6719+ // Skip this optimization inside function bodies (ternary operator)
6720+ $ insideFunctionBody = !empty ($ classCurlyDepthStack ) && $ curlyDepth > end ($ classCurlyDepthStack );
6721+ if (!$ insideFunctionBody ) {
6722+ $ tidx = $ this ->rightUsefulTokenIdx ();
6723+ if (in_array ($ this ->tkns [$ tidx ][0 ], [T_STRING , T_ARRAY , T_NAME_RELATIVE , T_NAME_QUALIFIED , T_NAME_FULLY_QUALIFIED ]) && (! isset ($ this ->tkns [$ tidx + 1 ]) || $ this ->tkns [$ tidx + 1 ][0 ] !== '( ' )) {
6724+ $ this ->tkns [$ tidx ][1 ] = $ text . $ this ->tkns [$ tidx ][1 ];
6725+ break ;
6726+ }
6727+ }
6728+ $ this ->appendCode ($ text );
67046729 break ;
67056730 case '| ' :
67066731 case T_NAME_RELATIVE :
@@ -6819,45 +6844,49 @@ public function format($source) {
68196844
68206845 case T_CONST :
68216846 case T_FUNCTION :
6822- if (count ($ found ) === 0 || (count ($ found ) === 1 && $ found [0 ] === T_NAMESPACE )) {
6823- $ this ->appendCode ($ text );
6824- break ;
6825- }
6826- $ hasFoundClassOrInterface = isset ($ found [0 ]) && (ST_CURLY_OPEN == $ found [0 ] || T_CLASS === $ found [0 ] || T_INTERFACE === $ found [0 ] || T_TRAIT === $ found [0 ] || T_ENUM === $ found [0 ] || T_NAMESPACE === $ found [0 ]) && ! $ this ->rightUsefulTokenIs ([ST_PARENTHESES_OPEN ]);
6847+ if (empty ($ classCurlyDepthStack )) {
6848+ // Global scope (incl. namespace blocks). Do not inject visibility.
6849+ // Preserve `static function () {}` for closures: if we captured a preceding static, flush it here.
6850+ if ($ id === T_FUNCTION && null !== $ static && $ this ->rightUsefulTokenIs ([ST_PARENTHESES_OPEN ])) {
6851+ $ this ->appendCode ($ static . $ this ->getSpace ());
6852+ $ static = null ;
6853+ $ skipWhitespaces = false ;
6854+ }
6855+ $ this ->appendCode ($ text );
6856+ break ;
6857+ }
6858+ $ classDepth = end ($ classCurlyDepthStack );
6859+ $ hasFoundClassOrInterface = (
6860+ $ curlyDepth === $ classDepth &&
6861+ ! $ this ->rightUsefulTokenIs ([ST_PARENTHESES_OPEN ])
6862+ );
6863+
6864+ // Inside class but not at top-level (e.g. closure inside method): do not inject visibility.
6865+ if (!$ hasFoundClassOrInterface ) {
6866+ if ($ id === T_FUNCTION && null !== $ static && $ this ->rightUsefulTokenIs ([ST_PARENTHESES_OPEN ])) {
6867+ $ this ->appendCode ($ static . $ this ->getSpace ());
6868+ }
6869+ $ this ->appendCode ($ text );
6870+ $ visibility = null ;
6871+ $ static = null ;
6872+ $ readonly = null ;
6873+ $ skipWhitespaces = false ;
6874+ break ;
6875+ }
6876+
6877+ if ($ id === T_FUNCTION && null === $ visibility ) {
6878+ $ visibility = 'public ' ;
6879+ }
68276880
68286881 if ($ hasFoundClassOrInterface && null !== $ finalOrAbstract ) {
68296882 $ this ->appendCode ($ finalOrAbstract . $ this ->getSpace ());
68306883 }
68316884 if ($ hasFoundClassOrInterface && null !== $ visibility ) {
68326885 $ this ->appendCode ($ visibility . $ this ->getSpace ());
6833- } elseif (
6834- $ hasFoundClassOrInterface &&
6835- !$ this ->leftTokenIs ([T_DOUBLE_ARROW , T_RETURN , ST_EQUAL , ST_COMMA , ST_PARENTHESES_OPEN ])
6836- ) {
6837- if (count ($ found ) - 2 >= 0 && $ found [count ($ found )-2 ] !== T_NAMESPACE ) {
6838- if ($ id === T_FUNCTION ) {
6839- $ visibility = 'public ' ;
6840- $ this ->appendCode ('public ' . $ this ->getSpace ());
6841- }
6842- }
68436886 }
6844- if ($ visibility === null && $ static !== null ) {
6845- if ($ id === T_FUNCTION ) {
6846- $ visibility = 'public ' ;
6847- $ this ->appendCode ('public ' . $ this ->getSpace ());
6848- }
6849- }
68506887 if ($ hasFoundClassOrInterface && null !== $ static ) {
68516888 $ this ->appendCode ($ static . $ this ->getSpace ());
68526889 }
6853- if ($ visibility === null && $ static === null ) {
6854- if (count ($ found ) === 1 || (count ($ found ) > 1 && $ found [count ($ found ) - 2 ] !== T_NAMESPACE )) {
6855- if ($ id === T_FUNCTION ) {
6856- $ visibility = 'public ' ;
6857- $ this ->appendCode ('public ' . $ this ->getSpace ());
6858- }
6859- }
6860- }
68616890 $ this ->appendCode ($ text );
68626891 $ visibility = null ;
68636892 $ static = null ;
@@ -6869,10 +6898,28 @@ public function format($source) {
68696898 break ;
68706899 }
68716900 $ finalOrAbstract = null ;
6872- if ($ id === T_FUNCTION ) {
6873- $ this ->printUntil (ST_CURLY_OPEN );
6874- $ this ->printCurlyBlock ();
6875- } else {
6901+ if ($ id === T_FUNCTION ) {
6902+ // Skip to the opening curly or semicolon (for abstract/interface methods)
6903+ // but do NOT consume the curly block - let the main loop handle it
6904+ // so that $curlyDepth stays synchronized for nested anonymous classes
6905+ $ parenCount = 0 ;
6906+ while (list ($ index , $ token ) = $ this ->each ($ this ->tkns )) {
6907+ list ($ subId , $ subText ) = $ this ->getToken ($ token );
6908+ $ this ->ptr = $ index ;
6909+ $ this ->appendCode ($ subText );
6910+ if (ST_PARENTHESES_OPEN === $ subId ) {
6911+ ++$ parenCount ;
6912+ } elseif (ST_PARENTHESES_CLOSE === $ subId ) {
6913+ $ parenCount = max (0 , $ parenCount - 1 );
6914+ } elseif (0 === $ parenCount && ST_SEMI_COLON === $ subId ) {
6915+ break ;
6916+ } elseif (0 === $ parenCount && ST_CURLY_OPEN === $ subId ) {
6917+ // Increment curlyDepth and continue - main loop will handle the rest
6918+ ++$ curlyDepth ;
6919+ break ;
6920+ }
6921+ }
6922+ } else {
68766923 $ this ->printUntil (ST_SEMI_COLON );
68776924 }
68786925 break ;
0 commit comments