@@ -406,69 +406,42 @@ private function analyzeReferences()
406
406
$ this ->singleUsePrivateIds [$ id ] = $ id ;
407
407
}
408
408
409
- $ newNodes = [];
410
- if (!$ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ newNodes )) {
411
- foreach ($ newNodes as $ newNodeId => $ _ ) {
412
- $ checkedNodes [$ newNodeId ] = [];
413
- }
414
- continue ;
415
- }
416
-
417
- $ nodesToFlatten = $ newNodes ;
418
- do {
419
- $ changedNodes = [];
420
- foreach ($ nodesToFlatten as $ newNodeId => $ _ ) {
421
- $ deps = &$ checkedNodes [$ newNodeId ];
422
- foreach ($ deps as $ id => [$ path , $ depsByConstructor ]) {
423
- foreach ($ checkedNodes [$ id ] as $ depsId => [$ subPath , $ subDepsByConstructor ]) {
424
- if (!isset ($ deps [$ depsId ]) || ($ depsByConstructor && $ subDepsByConstructor && !$ deps [$ depsId ][1 ])) {
425
- array_unshift ($ subPath , $ id );
426
- $ deps [$ depsId ] = [$ subPath , $ depsByConstructor && $ subDepsByConstructor ];
427
- $ changedNodes += $ newNodes [$ newNodeId ] ?? [];
428
- }
429
- }
430
- }
431
- }
432
- } while ($ nodesToFlatten = $ changedNodes );
433
-
434
- foreach ($ newNodes as $ newNodeId => $ _ ) {
435
- if (null !== $ n = $ checkedNodes [$ newNodeId ][$ newNodeId ] ?? null ) {
436
- $ this ->addCircularReferences ($ newNodeId , $ n [0 ], $ n [1 ]);
437
- }
438
- }
409
+ $ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes );
439
410
}
440
411
441
412
$ this ->container ->getCompiler ()->getServiceReferenceGraph ()->clear ();
442
413
$ this ->singleUsePrivateIds = array_diff_key ($ this ->singleUsePrivateIds , $ this ->circularReferences );
443
414
}
444
415
445
- private function collectCircularReferences (string $ sourceId , array $ edges , array &$ checkedNodes , array & $ newNodes , array $ path = [] ): bool
416
+ private function collectCircularReferences (string $ sourceId , array $ edges , array &$ checkedNodes , array $ path = [], bool $ byConstructor = true ): void
446
417
{
447
- $ path [$ sourceId ] = true ;
448
- $ checkedNodes [$ sourceId ] = [];
449
- $ newNodes [$ sourceId ] = [];
450
- $ circular = false ;
418
+ $ path [$ sourceId ] = $ byConstructor ;
419
+ $ checkedNodes [$ sourceId ] = true ;
451
420
foreach ($ edges as $ edge ) {
452
421
$ node = $ edge ->getDestNode ();
453
422
$ id = $ node ->getId ();
454
- if (!$ node ->getValue () instanceof Definition || $ sourceId === $ id || $ edge ->isWeak ()) {
423
+
424
+ if (!($ definition = $ node ->getValue ()) instanceof Definition || $ sourceId === $ id || ($ edge ->isLazy () && ($ this ->proxyDumper ?? $ this ->getProxyDumper ())->isProxyCandidate ($ definition )) || $ edge ->isWeak ()) {
455
425
continue ;
456
426
}
457
427
458
428
if (isset ($ path [$ id ])) {
459
- $ circular = true ;
429
+ $ loop = null ;
430
+ $ loopByConstructor = $ edge ->isReferencedByConstructor ();
431
+ foreach ($ path as $ k => $ pathByConstructor ) {
432
+ if (null !== $ loop ) {
433
+ $ loop [] = $ k ;
434
+ $ loopByConstructor = $ loopByConstructor && $ pathByConstructor ;
435
+ } elseif ($ k === $ id ) {
436
+ $ loop = [];
437
+ }
438
+ }
439
+ $ this ->addCircularReferences ($ id , $ loop , $ loopByConstructor );
460
440
} elseif (!isset ($ checkedNodes [$ id ])) {
461
- $ circular = $ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ newNodes , $ path ) || $ circular ;
462
- }
463
-
464
- $ checkedNodes [$ sourceId ][$ id ] = [[], $ edge ->isReferencedByConstructor ()];
465
- if (isset ($ newNodes [$ id ])) {
466
- $ newNodes [$ id ][$ sourceId ] = true ;
441
+ $ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ path , $ edge ->isReferencedByConstructor ());
467
442
}
468
443
}
469
444
unset($ path [$ sourceId ]);
470
-
471
- return $ circular ;
472
445
}
473
446
474
447
private function addCircularReferences (string $ sourceId , array $ currentPath , bool $ byConstructor )
0 commit comments