Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitaba31f9

Browse files
[DependencyInjection] autowire union and intersection types
1 parentab7f816 commitaba31f9

File tree

4 files changed

+102
-6
lines changed

4 files changed

+102
-6
lines changed

‎src/Symfony/Component/DependencyInjection/CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Add`service_closure()` to the PHP-DSL
88
* Add support for autoconfigurable attributes on methods, properties and parameters
99
* Make auto-aliases private by default
10+
* Add support for autowiring union and intersection types
1011

1112
5.3
1213
---

‎src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php‎

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class AutowirePass extends AbstractRecursivePass
4545
private$decoratedMethodIndex;
4646
private$decoratedMethodArgumentIndex;
4747
private$typesClone;
48+
private$combinedAliases;
4849

4950
publicfunction__construct(bool$throwOnAutowireException =true)
5051
{
@@ -60,6 +61,8 @@ public function __construct(bool $throwOnAutowireException = true)
6061
*/
6162
publicfunctionprocess(ContainerBuilder$container)
6263
{
64+
$this->populateCombinedAliases($container);
65+
6366
try {
6467
$this->typesClone =clone$this;
6568
parent::process($container);
@@ -72,6 +75,7 @@ public function process(ContainerBuilder $container)
7275
$this->decoratedMethodIndex =null;
7376
$this->decoratedMethodArgumentIndex =null;
7477
$this->typesClone =null;
78+
$this->combinedAliases = [];
7579
}
7680
}
7781

@@ -223,8 +227,6 @@ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot,
223227
/**
224228
* Autowires the constructor or a method.
225229
*
226-
* @return array
227-
*
228230
* @throws AutowiringFailedException
229231
*/
230232
privatefunctionautowireMethod(\ReflectionFunctionAbstract$reflectionMethod,array$arguments,bool$checkAttributes,int$methodIndex):array
@@ -363,8 +365,12 @@ private function getAutowiredReference(TypedReference $reference): ?TypedReferen
363365
returnnewTypedReference($alias,$type,$reference->getInvalidBehavior());
364366
}
365367

368+
if (null !== ($alias =$this->combinedAliases[$alias] ??null) && !$this->container->findDefinition($alias)->isAbstract()) {
369+
returnnewTypedReference($alias,$type,$reference->getInvalidBehavior());
370+
}
371+
366372
if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) {
367-
foreach ($this->container->getAliases()as$id =>$alias) {
373+
foreach ($this->container->getAliases()+$this->combinedAliasesas$id =>$alias) {
368374
if ($name === (string)$alias &&str_starts_with($id,$type.' $')) {
369375
returnnewTypedReference($name,$type,$reference->getInvalidBehavior());
370376
}
@@ -376,6 +382,10 @@ private function getAutowiredReference(TypedReference $reference): ?TypedReferen
376382
returnnewTypedReference($type,$type,$reference->getInvalidBehavior());
377383
}
378384

385+
if (null !== ($alias =$this->combinedAliases[$type] ??null) && !$this->container->findDefinition($alias)->isAbstract()) {
386+
returnnewTypedReference($alias,$type,$reference->getInvalidBehavior());
387+
}
388+
379389
returnnull;
380390
}
381391

@@ -565,4 +575,45 @@ private function populateAutowiringAlias(string $id): void
565575
$this->autowiringAliases[$type][$name] =$name;
566576
}
567577
}
578+
579+
privatefunctionpopulateCombinedAliases(ContainerBuilder$container):void
580+
{
581+
$this->combinedAliases = [];
582+
$reverseAliases = [];
583+
584+
foreach ($container->getAliases()as$id =>$alias) {
585+
if (!preg_match('/(?(DEFINE)(?<V>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+))^((?&V)(?:\\\\(?&V))*+)(?: \$((?&V)))?$/',$id,$m)) {
586+
continue;
587+
}
588+
589+
$type =$m[2];
590+
$name =$m[3] ??'';
591+
$reverseAliases[(string)$alias][$name][] =$type;
592+
}
593+
594+
foreach ($reverseAliasesas$alias =>$names) {
595+
foreach ($namesas$name =>$types) {
596+
if (2 >$count =\count($types)) {
597+
continue;
598+
}
599+
sort($types);
600+
$i =1 <<$count;
601+
602+
// compute the powerset of the list of types
603+
while ($i--) {
604+
$set = [];
605+
for ($j =0;$j <$count; ++$j) {
606+
if ($i & (1 <<$j)) {
607+
$set[] =$types[$j];
608+
}
609+
}
610+
611+
if (2 <=\count($set)) {
612+
$this->combinedAliases[implode('&',$set).('' ===$name ?'' :' $'.$name)] =$alias;
613+
$this->combinedAliases[implode('|',$set).('' ===$name ?'' :' $'.$name)] =$alias;
614+
}
615+
}
616+
}
617+
}
618+
}
568619
}

‎src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionPa
7070
}
7171
}
7272

73+
sort($types);
74+
7375
return$types ?implode($glue,$types) :null;
7476
}
7577
}

‎src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php‎

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -258,13 +258,31 @@ public function testTypeNotGuessableUnionType()
258258
$pass->process($container);
259259
}
260260

261+
/**
262+
* @requires PHP 8
263+
*/
264+
publicfunctiontestGuessableUnionType()
265+
{
266+
$container =newContainerBuilder();
267+
268+
$container->register('b', \stcClass::class);
269+
$container->setAlias(CollisionA::class.' $collision','b');
270+
$container->setAlias(CollisionB::class.' $collision','b');
271+
272+
$aDefinition =$container->register('a', UnionClasses::class);
273+
$aDefinition->setAutowired(true);
274+
275+
$pass =newAutowirePass();
276+
$pass->process($container);
277+
278+
$this->assertSame('b', (string)$aDefinition->getArgument(0));
279+
}
280+
261281
/**
262282
* @requires PHP 8.1
263283
*/
264284
publicfunctiontestTypeNotGuessableIntersectionType()
265285
{
266-
$this->expectException(AutowiringFailedException::class);
267-
$this->expectExceptionMessage('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\IntersectionClasses::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface&Symfony\Component\DependencyInjection\Tests\Compiler\AnotherInterface" but this class was not found.');
268286
$container =newContainerBuilder();
269287

270288
$container->register(CollisionInterface::class);
@@ -273,8 +291,32 @@ public function testTypeNotGuessableIntersectionType()
273291
$aDefinition =$container->register('a', IntersectionClasses::class);
274292
$aDefinition->setAutowired(true);
275293

294+
$pass =newAutowirePass();
295+
296+
$this->expectException(AutowiringFailedException::class);
297+
$this->expectExceptionMessage('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\IntersectionClasses::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\AnotherInterface&Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but this class was not found.');
298+
$pass->process($container);
299+
}
300+
301+
/**
302+
* @requires PHP 8.1
303+
*/
304+
publicfunctiontestGuessableIntersectionType()
305+
{
306+
$container =newContainerBuilder();
307+
308+
$container->register('b', \stcClass::class);
309+
$container->setAlias(CollisionInterface::class,'b');
310+
$container->setAlias(AnotherInterface::class,'b');
311+
$container->setAlias(DummyInterface::class,'b');
312+
313+
$aDefinition =$container->register('a', IntersectionClasses::class);
314+
$aDefinition->setAutowired(true);
315+
276316
$pass =newAutowirePass();
277317
$pass->process($container);
318+
319+
$this->assertSame('b', (string)$aDefinition->getArgument(0));
278320
}
279321

280322
publicfunctiontestTypeNotGuessableWithTypeSet()
@@ -516,7 +558,7 @@ public function testScalarArgsCannotBeAutowired()
516558
publicfunctiontestUnionScalarArgsCannotBeAutowired()
517559
{
518560
$this->expectException(AutowiringFailedException::class);
519-
$this->expectExceptionMessage('Cannot autowire service "union_scalars": argument "$timeout" of method "Symfony\Component\DependencyInjection\Tests\Compiler\UnionScalars::__construct()" is type-hinted "int|float", you should configure its value explicitly.');
561+
$this->expectExceptionMessage('Cannot autowire service "union_scalars": argument "$timeout" of method "Symfony\Component\DependencyInjection\Tests\Compiler\UnionScalars::__construct()" is type-hinted "float|int", you should configure its value explicitly.');
520562
$container =newContainerBuilder();
521563

522564
$container->register('union_scalars', UnionScalars::class)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp