@@ -406,48 +406,22 @@ 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
- }
409
+ $ circular = $ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes );
410
+ foreach ($ circular as [$ loop , $ byConstructor ]) {
411
+ $ sourceId = array_shift ($ loop );
412
+ $ this ->addCircularReferences ($ sourceId , $ loop , $ byConstructor );
438
413
}
439
414
}
440
415
441
416
$ this ->container ->getCompiler ()->getServiceReferenceGraph ()->clear ();
442
417
$ this ->singleUsePrivateIds = array_diff_key ($ this ->singleUsePrivateIds , $ this ->circularReferences );
443
418
}
444
419
445
- private function collectCircularReferences (string $ sourceId , array $ edges , array &$ checkedNodes , array & $ newNodes , array $ path = [] ): bool
420
+ private function collectCircularReferences (string $ sourceId , array $ edges , array &$ checkedNodes , array $ path = [], bool $ byConstructor = true ): array
446
421
{
447
- $ path [$ sourceId ] = true ;
448
- $ checkedNodes [$ sourceId ] = [];
449
- $ newNodes [$ sourceId ] = [];
450
- $ circular = false ;
422
+ $ path [$ sourceId ] = $ byConstructor ;
423
+ $ checkedNodes [$ sourceId ] = true ;
424
+ $ circular = [];
451
425
foreach ($ edges as $ edge ) {
452
426
$ node = $ edge ->getDestNode ();
453
427
$ id = $ node ->getId ();
@@ -456,14 +430,19 @@ private function collectCircularReferences(string $sourceId, array $edges, array
456
430
}
457
431
458
432
if (isset ($ path [$ id ])) {
459
- $ circular = true ;
433
+ $ loop = null ;
434
+ $ loopByConstructor = $ edge ->isReferencedByConstructor ();
435
+ foreach ($ path as $ k => $ pathByConstructor ) {
436
+ if (null !== $ loop ) {
437
+ $ loop [] = $ k ;
438
+ $ loopByConstructor = $ loopByConstructor && $ pathByConstructor ;
439
+ } elseif ($ k === $ id ) {
440
+ $ loop = [$ k ];
441
+ }
442
+ }
443
+ $ circular [] = [$ loop , $ loopByConstructor ];
460
444
} 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 ;
445
+ $ circular = array_merge ($ circular , $ this ->collectCircularReferences ($ id , $ node ->getOutEdges (), $ checkedNodes , $ path , $ edge ->isReferencedByConstructor ()));
467
446
}
468
447
}
469
448
unset($ path [$ sourceId ]);
0 commit comments