@@ -426,69 +426,42 @@ private function analyzeReferences()
426
426
$ this ->singleUsePrivateIds [$ id ] = $ id ;
427
427
}
428
428
429
- $ newNodes = [];
430
- if (!$ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ newNodes )) {
431
- foreach ($ newNodes as $ newNodeId => $ _ ) {
432
- $ checkedNodes [$ newNodeId ] = [];
433
- }
434
- continue ;
435
- }
436
-
437
- $ nodesToFlatten = $ newNodes ;
438
- do {
439
- $ changedNodes = [];
440
- foreach ($ nodesToFlatten as $ newNodeId => $ _ ) {
441
- $ deps = &$ checkedNodes [$ newNodeId ];
442
- foreach ($ deps as $ id => [$ path , $ depsByConstructor ]) {
443
- foreach ($ checkedNodes [$ id ] as $ depsId => [$ subPath , $ subDepsByConstructor ]) {
444
- if (!isset ($ deps [$ depsId ]) || ($ depsByConstructor && $ subDepsByConstructor && !$ deps [$ depsId ][1 ])) {
445
- array_unshift ($ subPath , $ id );
446
- $ deps [$ depsId ] = [$ subPath , $ depsByConstructor && $ subDepsByConstructor ];
447
- $ changedNodes += $ newNodes [$ newNodeId ] ?? [];
448
- }
449
- }
450
- }
451
- }
452
- } while ($ nodesToFlatten = $ changedNodes );
453
-
454
- foreach ($ newNodes as $ newNodeId => $ _ ) {
455
- if (null !== $ n = $ checkedNodes [$ newNodeId ][$ newNodeId ] ?? null ) {
456
- $ this ->addCircularReferences ($ newNodeId , $ n [0 ], $ n [1 ]);
457
- }
458
- }
429
+ $ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes );
459
430
}
460
431
461
432
$ this ->container ->getCompiler ()->getServiceReferenceGraph ()->clear ();
462
433
$ this ->singleUsePrivateIds = array_diff_key ($ this ->singleUsePrivateIds , $ this ->circularReferences );
463
434
}
464
435
465
- private function collectCircularReferences (string $ sourceId , array $ edges , array &$ checkedNodes , array & $ newNodes , array $ path = [] ): bool
436
+ private function collectCircularReferences (string $ sourceId , array $ edges , array &$ checkedNodes , array $ path = [], bool $ byConstructor = true ): void
466
437
{
467
- $ path [$ sourceId ] = true ;
468
- $ checkedNodes [$ sourceId ] = [];
469
- $ newNodes [$ sourceId ] = [];
470
- $ circular = false ;
438
+ $ path [$ sourceId ] = $ byConstructor ;
439
+ $ checkedNodes [$ sourceId ] = true ;
471
440
foreach ($ edges as $ edge ) {
472
441
$ node = $ edge ->getDestNode ();
473
442
$ id = $ node ->getId ();
474
- if (!$ node ->getValue () instanceof Definition || $ sourceId === $ id || $ edge ->isWeak ()) {
443
+
444
+ if (!($ definition = $ node ->getValue ()) instanceof Definition || $ sourceId === $ id || ($ edge ->isLazy () && ($ this ->proxyDumper ?? $ this ->getProxyDumper ())->isProxyCandidate ($ definition )) || $ edge ->isWeak ()) {
475
445
continue ;
476
446
}
477
447
478
448
if (isset ($ path [$ id ])) {
479
- $ circular = true ;
449
+ $ loop = null ;
450
+ $ loopByConstructor = $ edge ->isReferencedByConstructor ();
451
+ foreach ($ path as $ k => $ pathByConstructor ) {
452
+ if (null !== $ loop ) {
453
+ $ loop [] = $ k ;
454
+ $ loopByConstructor = $ loopByConstructor && $ pathByConstructor ;
455
+ } elseif ($ k === $ id ) {
456
+ $ loop = [];
457
+ }
458
+ }
459
+ $ this ->addCircularReferences ($ id , $ loop , $ loopByConstructor );
480
460
} elseif (!isset ($ checkedNodes [$ id ])) {
481
- $ circular = $ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ newNodes , $ path ) || $ circular ;
482
- }
483
-
484
- $ checkedNodes [$ sourceId ][$ id ] = [[], $ edge ->isReferencedByConstructor ()];
485
- if (isset ($ newNodes [$ id ])) {
486
- $ newNodes [$ id ][$ sourceId ] = true ;
461
+ $ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ path , $ edge ->isReferencedByConstructor ());
487
462
}
488
463
}
489
464
unset($ path [$ sourceId ]);
490
-
491
- return $ circular ;
492
465
}
493
466
494
467
private function addCircularReferences (string $ sourceId , array $ currentPath , bool $ byConstructor )
0 commit comments