@@ -187,6 +187,7 @@ public function dump(array $options = [])
187187 }
188188$ this ->container ->getCompiler ()->getServiceReferenceGraph ()->clear ();
189189$ checkedNodes = [];
190+ $ this ->singleUsePrivateIds =array_diff_key ($ this ->singleUsePrivateIds ,$ this ->circularReferences );
190191
191192$ this ->docStar =$ options ['debug ' ] ?'* ' :'' ;
192193
@@ -339,10 +340,10 @@ private function getProxyDumper(): ProxyDumper
339340return $ this ->proxyDumper ;
340341 }
341342
342- private function analyzeCircularReferences ($ sourceId ,array $ edges , &$ checkedNodes , &$ currentPath = [])
343+ private function analyzeCircularReferences ($ sourceId ,array $ edges , &$ checkedNodes , &$ currentPath = [], $ byConstructor = true )
343344 {
344345$ checkedNodes [$ sourceId ] =true ;
345- $ currentPath [$ sourceId ] =$ sourceId ;
346+ $ currentPath [$ sourceId ] =$ byConstructor ;
346347
347348foreach ($ edgesas $ edge ) {
348349$ node =$ edge ->getDestNode ();
@@ -351,44 +352,52 @@ private function analyzeCircularReferences($sourceId, array $edges, &$checkedNod
351352if (!$ node ->getValue ()instanceof Definition ||$ sourceId ===$ id ||$ edge ->isLazy () ||$ edge ->isWeak ()) {
352353// no-op
353354 }elseif (isset ($ currentPath [$ id ])) {
354- $ currentId =$ id ;
355- foreach (array_reverse ($ currentPath )as $ parentId ) {
356- $ this ->circularReferences [$ parentId ][$ currentId ] =$ currentId ;
357- if ($ parentId ===$ id ) {
358- break ;
359- }
360- $ currentId =$ parentId ;
361- }
355+ $ this ->addCircularReferences ($ id ,$ currentPath ,$ edge ->isReferencedByConstructor ());
362356 }elseif (!isset ($ checkedNodes [$ id ])) {
363- $ this ->analyzeCircularReferences ($ id ,$ node ->getOutEdges (),$ checkedNodes ,$ currentPath );
357+ $ this ->analyzeCircularReferences ($ id ,$ node ->getOutEdges (),$ checkedNodes ,$ currentPath, $ edge -> isReferencedByConstructor () );
364358 }elseif (isset ($ this ->circularReferences [$ id ])) {
365- $ this ->connectCircularReferences ($ id ,$ currentPath );
359+ $ this ->connectCircularReferences ($ id ,$ currentPath, $ edge -> isReferencedByConstructor () );
366360 }
367361 }
368362 unset($ currentPath [$ sourceId ]);
369363 }
370364
371- private function connectCircularReferences ($ sourceId , &$ currentPath , &$ subPath = [])
365+ private function connectCircularReferences ($ sourceId , &$ currentPath ,$ byConstructor , &$ subPath = [])
372366 {
373- $ subPath [$ sourceId ] =$ sourceId ;
374- $ currentPath [$ sourceId ] =$ sourceId ;
367+ $ currentPath [$ sourceId ] =$ subPath [$ sourceId ] =$ byConstructor ;
375368
376- foreach ($ this ->circularReferences [$ sourceId ]as $ id ) {
369+ foreach ($ this ->circularReferences [$ sourceId ]as $ id => $ byConstructor ) {
377370if (isset ($ currentPath [$ id ])) {
378- $ currentId =$ id ;
379- foreach (array_reverse ($ currentPath )as $ parentId ) {
380- $ this ->circularReferences [$ parentId ][$ currentId ] =$ currentId ;
381- if ($ parentId ===$ id ) {
382- break ;
383- }
384- $ currentId =$ parentId ;
385- }
371+ $ this ->addCircularReferences ($ id ,$ currentPath ,$ byConstructor );
386372 }elseif (!isset ($ subPath [$ id ]) &&isset ($ this ->circularReferences [$ id ])) {
387- $ this ->connectCircularReferences ($ id ,$ currentPath ,$ subPath );
373+ $ this ->connectCircularReferences ($ id ,$ currentPath ,$ byConstructor , $ subPath );
388374 }
389375 }
390- unset($ currentPath [$ sourceId ]);
391- unset($ subPath [$ sourceId ]);
376+ unset($ currentPath [$ sourceId ],$ subPath [$ sourceId ]);
377+ }
378+
379+ private function addCircularReferences ($ id ,$ currentPath ,$ byConstructor )
380+ {
381+ $ currentPath [$ id ] =$ byConstructor ;
382+ $ circularRefs = [];
383+
384+ foreach (array_reverse ($ currentPath )as $ parentId =>$ v ) {
385+ $ byConstructor =$ byConstructor &&$ v ;
386+ $ circularRefs [] =$ parentId ;
387+
388+ if ($ parentId ===$ id ) {
389+ break ;
390+ }
391+ }
392+
393+ $ currentId =$ id ;
394+ foreach ($ circularRefsas $ parentId ) {
395+ if (empty ($ this ->circularReferences [$ parentId ][$ currentId ])) {
396+ $ this ->circularReferences [$ parentId ][$ currentId ] =$ byConstructor ;
397+ }
398+
399+ $ currentId =$ parentId ;
400+ }
392401 }
393402
394403private function collectLineage ($ class ,array &$ lineage )
@@ -679,7 +688,6 @@ private function addService(string $id, Definition $definition): array
679688$ autowired =$ definition ->isAutowired () ?' autowired ' :'' ;
680689
681690if ($ definition ->isLazy ()) {
682- unset($ this ->circularReferences [$ id ]);
683691$ lazyInitialization ='$lazyLoad = true ' ;
684692 }else {
685693$ lazyInitialization ='' ;
@@ -755,12 +763,12 @@ private function addInlineVariables(string $id, Definition $definition, array $a
755763
756764private function addInlineReference (string $ id ,Definition $ definition ,string $ targetId ,bool $ forConstructor ):string
757765 {
758- list ($ callCount ,$ behavior ) =$ this ->serviceCalls [$ targetId ];
759-
760766while ($ this ->container ->hasAlias ($ targetId )) {
761767$ targetId = (string )$ this ->container ->getAlias ($ targetId );
762768 }
763769
770+ list ($ callCount ,$ behavior ) =$ this ->serviceCalls [$ targetId ];
771+
764772if ($ id ===$ targetId ) {
765773return $ this ->addInlineService ($ id ,$ definition ,$ definition );
766774 }
@@ -769,9 +777,13 @@ private function addInlineReference(string $id, Definition $definition, string $
769777return '' ;
770778 }
771779
772- $ hasSelfRef =isset ($ this ->circularReferences [$ id ][$ targetId ]);
773- $ forConstructor =$ forConstructor && !isset ($ this ->definitionVariables [$ definition ]);
774- $ code =$ hasSelfRef && !$ forConstructor ?$ this ->addInlineService ($ id ,$ definition ,$ definition ) :'' ;
780+ $ hasSelfRef =isset ($ this ->circularReferences [$ id ][$ targetId ]) && !isset ($ this ->definitionVariables [$ definition ]);
781+
782+ if ($ hasSelfRef && !$ forConstructor && !$ forConstructor = !$ this ->circularReferences [$ id ][$ targetId ]) {
783+ $ code =$ this ->addInlineService ($ id ,$ definition ,$ definition );
784+ }else {
785+ $ code ='' ;
786+ }
775787
776788if (isset ($ this ->referenceVariables [$ targetId ]) || (2 >$ callCount && (!$ hasSelfRef || !$ forConstructor ))) {
777789return $ code ;
@@ -804,15 +816,23 @@ private function addInlineReference(string $id, Definition $definition, string $
804816
805817private function addInlineService (string $ id ,Definition $ definition ,Definition $ inlineDef =null ,bool $ forConstructor =true ):string
806818 {
807- $ isSimpleInstance =$ isRootInstance =null ===$ inlineDef ;
819+ $ code ='' ;
820+
821+ if ($ isSimpleInstance =$ isRootInstance =null ===$ inlineDef ) {
822+ foreach ($ this ->serviceCalls as $ targetId =>list ($ callCount ,$ behavior ,$ byConstructor )) {
823+ if ($ byConstructor &&isset ($ this ->circularReferences [$ id ][$ targetId ]) && !$ this ->circularReferences [$ id ][$ targetId ]) {
824+ $ code .=$ this ->addInlineReference ($ id ,$ definition ,$ targetId ,$ forConstructor );
825+ }
826+ }
827+ }
808828
809829if (isset ($ this ->definitionVariables [$ inlineDef =$ inlineDef ?:$ definition ])) {
810- return '' ;
830+ return $ code ;
811831 }
812832
813833$ arguments = [$ inlineDef ->getArguments (),$ inlineDef ->getFactory ()];
814834
815- $ code =$ this ->addInlineVariables ($ id ,$ definition ,$ arguments ,$ forConstructor );
835+ $ code. =$ this ->addInlineVariables ($ id ,$ definition ,$ arguments ,$ forConstructor );
816836
817837if ($ arguments =array_filter ([$ inlineDef ->getProperties (),$ inlineDef ->getMethodCalls (),$ inlineDef ->getConfigurator ()])) {
818838$ isSimpleInstance =false ;
@@ -1473,20 +1493,24 @@ private function getServiceConditionals($value): string
14731493return implode (' && ' ,$ conditions );
14741494 }
14751495
1476- private function getDefinitionsFromArguments (array $ arguments ,\SplObjectStorage $ definitions =null ,array &$ calls = []):\SplObjectStorage
1496+ private function getDefinitionsFromArguments (array $ arguments ,\SplObjectStorage $ definitions =null ,array &$ calls = [], bool $ byConstructor = null ):\SplObjectStorage
14771497 {
14781498if (null ===$ definitions ) {
14791499$ definitions =new \SplObjectStorage ();
14801500 }
14811501
14821502foreach ($ argumentsas $ argument ) {
14831503if (\is_array ($ argument )) {
1484- $ this ->getDefinitionsFromArguments ($ argument ,$ definitions ,$ calls );
1504+ $ this ->getDefinitionsFromArguments ($ argument ,$ definitions ,$ calls, $ byConstructor );
14851505 }elseif ($ argumentinstanceof Reference) {
14861506$ id = (string )$ argument ;
14871507
1508+ while ($ this ->container ->hasAlias ($ id )) {
1509+ $ id = (string )$ this ->container ->getAlias ($ id );
1510+ }
1511+
14881512if (!isset ($ calls [$ id ])) {
1489- $ calls [$ id ] = [0 ,$ argument ->getInvalidBehavior ()];
1513+ $ calls [$ id ] = [0 ,$ argument ->getInvalidBehavior (), $ byConstructor ];
14901514 }else {
14911515$ calls [$ id ][1 ] =min ($ calls [$ id ][1 ],$ argument ->getInvalidBehavior ());
14921516 }
@@ -1498,8 +1522,10 @@ private function getDefinitionsFromArguments(array $arguments, \SplObjectStorage
14981522$ definitions [$ argument ] =1 +$ definitions [$ argument ];
14991523 }else {
15001524$ definitions [$ argument ] =1 ;
1501- $ arguments = [$ argument ->getArguments (),$ argument ->getFactory (),$ argument ->getProperties (),$ argument ->getMethodCalls (),$ argument ->getConfigurator ()];
1502- $ this ->getDefinitionsFromArguments ($ arguments ,$ definitions ,$ calls );
1525+ $ arguments = [$ argument ->getArguments (),$ argument ->getFactory ()];
1526+ $ this ->getDefinitionsFromArguments ($ arguments ,$ definitions ,$ calls ,null ===$ byConstructor ||$ byConstructor );
1527+ $ arguments = [$ argument ->getProperties (),$ argument ->getMethodCalls (),$ argument ->getConfigurator ()];
1528+ $ this ->getDefinitionsFromArguments ($ arguments ,$ definitions ,$ calls ,null !==$ byConstructor &&$ byConstructor );
15031529 }
15041530 }
15051531
@@ -1620,6 +1646,11 @@ private function dumpValue($value, bool $interpolate = true): string
16201646return '$ ' .$ value ;
16211647 }elseif ($ valueinstanceof Reference) {
16221648$ id = (string )$ value ;
1649+
1650+ while ($ this ->container ->hasAlias ($ id )) {
1651+ $ id = (string )$ this ->container ->getAlias ($ id );
1652+ }
1653+
16231654if (null !==$ this ->referenceVariables &&isset ($ this ->referenceVariables [$ id ])) {
16241655return $ this ->dumpValue ($ this ->referenceVariables [$ id ],$ interpolate );
16251656 }