Skip to content

Commit e707967

Browse files
minor symfony#37346 Added Unit tests for php 8 union types (derrabus)
This PR was merged into the 3.4 branch. Discussion ---------- Added Unit tests for php 8 union types | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | N/A | License | MIT | Doc PR | N/A The missing test cases for symfony#37340. Commits ------- 2ca8ecd Added Unit tests for php 8 union types.
2 parents 8bbbdbe + 2ca8ecd commit e707967

File tree

6 files changed

+147
-2
lines changed

6 files changed

+147
-2
lines changed

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

+68
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,25 @@ public function testTypeNotGuessableNoServicesFound()
254254
$pass->process($container);
255255
}
256256

257+
/**
258+
* @requires PHP 8
259+
*/
260+
public function testTypeNotGuessableUnionType()
261+
{
262+
$this->expectException('Symfony\Component\DependencyInjection\Exception\AutowiringFailedException');
263+
$this->expectExceptionMessage('Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\UnionClasses::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionA|Symfony\Component\DependencyInjection\Tests\Compiler\CollisionB" but this class was not found.');
264+
$container = new ContainerBuilder();
265+
266+
$container->register(CollisionA::class);
267+
$container->register(CollisionB::class);
268+
269+
$aDefinition = $container->register('a', UnionClasses::class);
270+
$aDefinition->setAutowired(true);
271+
272+
$pass = new AutowirePass();
273+
$pass->process($container);
274+
}
275+
257276
public function testTypeNotGuessableWithTypeSet()
258277
{
259278
$container = new ContainerBuilder();
@@ -350,6 +369,40 @@ public function testOptionalParameter()
350369
$this->assertEquals(Foo::class, $definition->getArgument(2));
351370
}
352371

372+
/**
373+
* @requires PHP 8
374+
*/
375+
public function testParameterWithNullUnionIsSkipped()
376+
{
377+
$container = new ContainerBuilder();
378+
379+
$optDefinition = $container->register('opt', UnionNull::class);
380+
$optDefinition->setAutowired(true);
381+
382+
(new AutowirePass())->process($container);
383+
384+
$definition = $container->getDefinition('opt');
385+
$this->assertNull($definition->getArgument(0));
386+
}
387+
388+
/**
389+
* @requires PHP 8
390+
*/
391+
public function testParameterWithNullUnionIsAutowired()
392+
{
393+
$container = new ContainerBuilder();
394+
395+
$container->register(CollisionInterface::class, CollisionA::class);
396+
397+
$optDefinition = $container->register('opt', UnionNull::class);
398+
$optDefinition->setAutowired(true);
399+
400+
(new AutowirePass())->process($container);
401+
402+
$definition = $container->getDefinition('opt');
403+
$this->assertEquals(CollisionInterface::class, $definition->getArgument(0));
404+
}
405+
353406
public function testDontTriggerAutowiring()
354407
{
355408
$container = new ContainerBuilder();
@@ -459,6 +512,21 @@ public function testScalarArgsCannotBeAutowired()
459512
(new AutowirePass())->process($container);
460513
}
461514

515+
/**
516+
* @requires PHP 8
517+
*/
518+
public function testUnionScalarArgsCannotBeAutowired()
519+
{
520+
$this->expectException('Symfony\Component\DependencyInjection\Exception\AutowiringFailedException');
521+
$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.');
522+
$container = new ContainerBuilder();
523+
524+
$container->register('union_scalars', UnionScalars::class)
525+
->setAutowired(true);
526+
527+
(new AutowirePass())->process($container);
528+
}
529+
462530
public function testNoTypeArgsCannotBeAutowired()
463531
{
464532
$this->expectException('Symfony\Component\DependencyInjection\Exception\AutowiringFailedException');

src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
44

5+
if (PHP_VERSION_ID >= 80000) {
6+
require __DIR__.'/uniontype_classes.php';
7+
}
8+
59
class Foo
610
{
711
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
4+
5+
class UnionScalars
6+
{
7+
public function __construct(int|float $timeout)
8+
{
9+
}
10+
}
11+
12+
class UnionClasses
13+
{
14+
public function __construct(CollisionA|CollisionB $collision)
15+
{
16+
}
17+
}
18+
19+
class UnionNull
20+
{
21+
public function __construct(CollisionInterface|null $c)
22+
{
23+
}
24+
}

src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php

+5-2
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,15 @@ private function extractFromReflectionType(\ReflectionType $reflectionType, \Ref
243243

244244
foreach ($reflectionType instanceof \ReflectionUnionType ? $reflectionType->getTypes() : [$reflectionType] as $type) {
245245
$phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : (string) $type;
246+
if ('null' === $phpTypeOrClass) {
247+
continue;
248+
}
246249

247250
if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) {
248251
$types[] = new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true);
249-
} elseif ('void' === $phpTypeOrClass || 'null' === $phpTypeOrClass) {
252+
} elseif ('void' === $phpTypeOrClass) {
250253
$types[] = new Type(Type::BUILTIN_TYPE_NULL, $nullable);
251-
} elseif ($reflectionType->isBuiltin()) {
254+
} elseif ($type->isBuiltin()) {
252255
$types[] = new Type($phpTypeOrClass, $nullable);
253256
} else {
254257
$types[] = new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, $this->resolveTypeName($phpTypeOrClass, $reflectionMethod));

src/Symfony/Component/PropertyInfo/Tests/Extractor/ReflectionExtractorTest.php

+20
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,26 @@ public function php71TypesProvider()
204204
];
205205
}
206206

207+
/**
208+
* @dataProvider php80TypesProvider
209+
* @requires PHP 8
210+
*/
211+
public function testExtractPhp80Type($property, array $type = null)
212+
{
213+
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Php80Dummy', $property, []));
214+
}
215+
216+
public function php80TypesProvider()
217+
{
218+
return [
219+
['foo', [new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)]],
220+
['bar', [new Type(Type::BUILTIN_TYPE_INT, true)]],
221+
['timeout', [new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_FLOAT)]],
222+
['optional', [new Type(Type::BUILTIN_TYPE_INT, true), new Type(Type::BUILTIN_TYPE_FLOAT, true)]],
223+
['string', [new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Stringable'), new Type(Type::BUILTIN_TYPE_STRING)]],
224+
];
225+
}
226+
207227
/**
208228
* @dataProvider getReadableProperties
209229
*/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace Symfony\Component\PropertyInfo\Tests\Fixtures;
4+
5+
class Php80Dummy
6+
{
7+
public function getFoo(): array|null
8+
{
9+
}
10+
11+
public function setBar(int|null $bar)
12+
{
13+
}
14+
15+
public function setTimeout(int|float $timeout)
16+
{
17+
}
18+
19+
public function getOptional(): int|float|null
20+
{
21+
}
22+
23+
public function setString(string|\Stringable $string)
24+
{
25+
}
26+
}

0 commit comments

Comments
 (0)