@@ -444,22 +444,30 @@ public static function generate(int $layer, string $inputSchema, string $outputF
444444
445445 $ locations ['account.uploadTheme ' ][] = new Noop ('A freshly uploaded theme file will obtain a context only once it is created via account.createTheme ' );
446446
447- $ recurse = static function (Closure $ onStackEnd , string $ type , array &$ stack , array &$ stackTypes ) use ($ TL , &$ recurse ): void {
448- if ($ type === 'Update ' || $ type === 'Updates ' ) {
449- $ onStackEnd ($ stack );
450- return ;
451- }
452- if ($ type === 'PeerStories ' ) {
453- $ onStackEnd ($ stack );
447+ $ constructorList = $ TL ->tl ->getConstructors ()->by_id ;
448+ $ mergedConstructorMethods = [
449+ ...$ constructorList ,
450+ ...$ TL ->tl ->getMethods ()->by_id ,
451+ ];
452+ $ recurse = static function (Closure $ onStackEnd , string $ type , array &$ stack , array &$ stackTypes , bool $ incoming ) use ($ TL , &$ recurse , $ mergedConstructorMethods , $ constructorList ): void {
453+ if ($ incoming ) {
454+ if ($ type === 'Update ' || $ type === 'Updates ' ) {
455+ $ onStackEnd ($ stack );
456+ return ;
457+ }
458+ if ($ type === 'PeerStories ' ) {
459+ $ onStackEnd ($ stack );
460+ }
454461 }
455462
456463 $ pos = \count ($ stack );
457- foreach ([... $ TL -> tl -> getConstructors ()-> by_id , ... $ TL -> tl -> getMethods ()-> by_id ] as $ constructor ) {
464+ foreach ($ incoming ? $ constructorList : $ mergedConstructorMethods as $ constructor ) {
458465 $ predicate = $ constructor ['predicate ' ] ?? $ constructor ['method ' ];
459466 if ($ predicate === 'updateShortMessage ' || $ predicate === 'updateShortChatMessage ' || $ predicate === 'updateShortSentMessage ' ) {
460467 // Assume these are converted to message constructors by the client.
461468 continue ;
462469 }
470+ $ isMethod = isset ($ constructor ['method ' ]);
463471 $ t = $ constructor ['type ' ];
464472 $ stackTypes [$ t ] ??= 0 ;
465473 if ($ stackTypes [$ t ] > 1 ) {
@@ -482,20 +490,29 @@ public static function generate(int $layer, string $inputSchema, string $outputF
482490 $ oldFlag = $ stack [$ pos ][2 ] ?? 0 ;
483491 $ stack [$ pos ][2 ] = $ oldFlag | Path::FLAG_UNPACK_ARRAY ;
484492 }
485- $ recurse ($ onStackEnd , $ t , $ stack , $ stackTypes );
493+ if ($ isMethod ) {
494+ if (!$ incoming ) {
495+ $ onStackEnd ($ stack );
496+ }
497+ } else {
498+ $ recurse ($ onStackEnd , $ t , $ stack , $ stackTypes , $ incoming );
499+ }
486500 unset($ stack [$ pos ]);
487501
488502 }
489503 }
490504 $ stackTypes [$ t ]--;
491505 }
492- foreach ($ TL ->getMethodsOfType ($ type , true ) as $ method => $ data ) {
493- $ stack [$ pos ] = [$ method , '' ];
494- $ onStackEnd ($ stack );
495- }
496- foreach ($ TL ->getMethodsOfType ("Vector< $ type> " , true ) as $ method => $ data ) {
497- $ stack [$ pos ] = [$ method , '' , Path::FLAG_UNPACK_ARRAY ];
498- $ onStackEnd ($ stack );
506+
507+ if ($ incoming ) {
508+ foreach ($ TL ->getMethodsOfType ($ type , true ) as $ method => $ data ) {
509+ $ stack [$ pos ] = [$ method , '' ];
510+ $ onStackEnd ($ stack );
511+ }
512+ foreach ($ TL ->getMethodsOfType ("Vector< $ type> " , true ) as $ method => $ data ) {
513+ $ stack [$ pos ] = [$ method , '' , Path::FLAG_UNPACK_ARRAY ];
514+ $ onStackEnd ($ stack );
515+ }
499516 }
500517 unset($ stack [$ pos ]);
501518 };
@@ -566,14 +583,46 @@ public static function generate(int $layer, string $inputSchema, string $outputF
566583 }
567584 }
568585
569- $ traversalPairs = [];
586+ $ outgoingTraversalPairsByCons = [];
587+ foreach ($ outgoingCons as $ constructor => $ contents ) {
588+ if ($ contents === false ) {
589+ continue ;
590+ }
591+ $ type = $ TL ->tl ->getConstructors ()->findByPredicate ($ constructor )['type ' ];
592+ $ stack = [[$ constructor , 'file_reference ' ]];
593+ $ stackTypes = [$ type => 1 ];
594+
595+ $ outgoingTraversalPairs = [];
596+ $ recurse (
597+ static function (array $ stack ) use (&$ outgoingTraversalPairs ): void {
598+ foreach ($ stack as $ pair ) {
599+ $ encoded = json_encode ($ pair );
600+ if (!isset ($ outgoingTraversalPairs [$ encoded ])) {
601+ $ outgoingTraversalPairs [$ encoded ] = $ pair ;
602+ }
603+ }
604+ },
605+ $ type ,
606+ $ stack ,
607+ $ stackTypes ,
608+ false ,
609+ );
610+ ksort ($ outgoingTraversalPairs );
611+ $ outgoingTraversalPairs = array_values ($ outgoingTraversalPairs );
612+ $ outgoingTraversalPairsByCons [$ constructor ] = $ outgoingTraversalPairs ;
613+ }
614+ unset($ outgoingTraversalPairs );
615+
616+ $ incomingTraversalPairsByCons = [];
570617 $ tmp = new Ast (blacklistedPredicates: $ blacklistedPredicates , allowUnpacking: true , outputSchema: $ pre );
571618 foreach ($ incomingCons as $ constructor => $ _ ) {
572619 $ type = ucfirst ($ constructor );
573620 $ stack = [[$ constructor , 'file_reference ' ]];
574621 $ stackTypes = [$ type => 1 ];
622+
623+ $ incomingTraversalPairs = [];
575624 $ recurse (
576- static function (array $ stack ) use ($ locations , $ TL , $ tmp , &$ traversalPairs , &$ validated , $ storyMethods , $ starMethods , $ stickerMethods ): void {
625+ static function (array $ stack ) use ($ locations , $ TL , $ tmp , &$ incomingTraversalPairs , &$ validated , $ storyMethods , $ starMethods , $ stickerMethods ): void {
577626 $ slice = [];
578627 $ hadAny = false ;
579628 $ hadAnyNotNoop = false ;
@@ -583,6 +632,11 @@ static function (array $stack) use ($locations, $TL, $tmp, &$traversalPairs, &$v
583632 $ top = end ($ stack )[0 ];
584633 for ($ x = \count ($ stack )-1 ; $ x >= 0 ; $ x --) {
585634 $ pair = $ stack [$ x ];
635+ $ encoded = json_encode ($ pair );
636+ if (!isset ($ tmpPairs [$ encoded ])) {
637+ $ tmpPairs [$ encoded ] = $ pair ;
638+ }
639+
586640 foreach ($ locations [$ pair [0 ]] ?? [] as $ op ) {
587641 $ normalized = $ op ->normalize ($ slice , $ pair [0 ], false );
588642 if ($ normalized === null ) {
@@ -591,7 +645,6 @@ static function (array $stack) use ($locations, $TL, $tmp, &$traversalPairs, &$v
591645 if (!$ normalized instanceof Noop) {
592646 $ hadAnyNotNoop = true ;
593647 }
594- $ tmpPairs [json_encode ($ pair )] = $ pair ;
595648 $ hadAny = true ;
596649 $ normalized ->build (new TLContext ($ TL , $ tmp , $ top , $ TL ->isConstructor ($ top )));
597650 $ validated [$ pair [0 ]][spl_object_id ($ op )] = $ op ;
@@ -606,7 +659,7 @@ static function (array $stack) use ($locations, $TL, $tmp, &$traversalPairs, &$v
606659 $ slice [] = $ pair ;
607660 }
608661 if ($ hadAnyNotNoop ) {
609- $ traversalPairs += $ tmpPairs ;
662+ $ incomingTraversalPairs += $ tmpPairs ;
610663 }
611664 if (!$ hadAny ) {
612665 throw new AssertionError ("Uncovered path: " . json_encode ($ stack ));
@@ -653,9 +706,14 @@ static function (array $stack) use ($locations, $TL, $tmp, &$traversalPairs, &$v
653706 $ type ,
654707 $ stack ,
655708 $ stackTypes ,
709+ true ,
656710 );
711+
712+ ksort ($ incomingTraversalPairs );
713+ $ incomingTraversalPairs = array_values ($ incomingTraversalPairs );
714+ $ incomingTraversalPairsByCons [$ constructor ] = $ incomingTraversalPairs ;
657715 }
658- //var_dump(array_values($traversalPairs) );
716+ unset( $ incomingTraversalPairs );
659717
660718 $ diff = [];
661719 foreach ($ locations as $ constructor => $ ops ) {
@@ -680,7 +738,15 @@ static function (array $stack) use ($locations, $TL, $tmp, &$traversalPairs, &$v
680738 }
681739 }
682740
683- $ output ->finalize ($ layer , array_filter ($ outgoingCons ), $ incomingCons , $ outputFile , $ outputFileJson );
741+ $ output ->finalize (
742+ $ layer ,
743+ array_filter ($ outgoingCons ),
744+ $ incomingCons ,
745+ $ incomingTraversalPairsByCons ,
746+ $ outgoingTraversalPairsByCons ,
747+ $ outputFile ,
748+ $ outputFileJson
749+ );
684750
685751 echo ("OK $ layer! \n" .PHP_EOL );
686752 }
0 commit comments