Skip to content

Commit 0110a47

Browse files
Fix support for PHP8 union types
1 parent 943c630 commit 0110a47

File tree

16 files changed

+123
-63
lines changed

16 files changed

+123
-63
lines changed

src/Symfony/Component/Config/Resource/ReflectionClassResource.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ private function generateSignature(\ReflectionClass $class): iterable
167167
if (!$parametersWithUndefinedConstants) {
168168
yield preg_replace('/^ @@.*/m', '', $m);
169169
} else {
170+
$t = $m->getReturnType();
170171
$stack = [
171172
$m->getDocComment(),
172173
$m->getName(),
@@ -177,15 +178,16 @@ private function generateSignature(\ReflectionClass $class): iterable
177178
$m->isPrivate(),
178179
$m->isProtected(),
179180
$m->returnsReference(),
180-
$m->hasReturnType() ? $m->getReturnType()->getName() : '',
181+
$t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t,
181182
];
182183

183184
foreach ($m->getParameters() as $p) {
184185
if (!isset($parametersWithUndefinedConstants[$p->name])) {
185186
$stack[] = (string) $p;
186187
} else {
188+
$t = $p->getType();
187189
$stack[] = $p->isOptional();
188-
$stack[] = $p->hasType() ? $p->getType()->getName() : '';
190+
$stack[] = $t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t;
189191
$stack[] = $p->isPassedByReference();
190192
$stack[] = $p->isVariadic();
191193
$stack[] = $p->getName();

src/Symfony/Component/DependencyInjection/Compiler/CheckTypeDeclarationsPass.php

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,25 @@ private function checkTypeDeclarations(Definition $checkedDefinition, \Reflectio
153153
/**
154154
* @throws InvalidParameterTypeException When a parameter is not compatible with the declared type
155155
*/
156-
private function checkType(Definition $checkedDefinition, $value, \ReflectionParameter $parameter, ?string $envPlaceholderUniquePrefix): void
156+
private function checkType(Definition $checkedDefinition, $value, \ReflectionParameter $parameter, ?string $envPlaceholderUniquePrefix, string $type = null): void
157157
{
158-
$type = $parameter->getType()->getName();
158+
if (null === $type) {
159+
$type = $parameter->getType();
160+
161+
if ($type instanceof \ReflectionUnionType) {
162+
foreach ($type->getTypes() as $type) {
163+
try {
164+
$this->checkType($checkedDefinition, $value, $parameter, $envPlaceholderUniquePrefix, $type);
165+
return;
166+
} catch (InvalidParameterTypeException $e) {
167+
}
168+
}
169+
170+
throw new InvalidParameterTypeException($this->currentId, $e->getCode(), $parameter);
171+
}
172+
173+
$type = $type->getName();
174+
}
159175

160176
if ($value instanceof Reference) {
161177
if (!$this->container->has($value = (string) $value)) {
@@ -266,7 +282,7 @@ private function checkType(Definition $checkedDefinition, $value, \ReflectionPar
266282
return;
267283
}
268284

269-
$checkFunction = sprintf('is_%s', $parameter->getType()->getName());
285+
$checkFunction = sprintf('is_%s', $type);
270286

271287
if (!$parameter->getType()->isBuiltin() || !$checkFunction($value)) {
272288
throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? $class : \gettype($value), $parameter);

src/Symfony/Component/DependencyInjection/Dumper/Preloader.php

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public static function preload(array $classes)
4848
}
4949
}
5050

51-
private static function doPreload(string $class, array &$preloaded)
51+
private static function doPreload(string $class, array &$preloaded): void
5252
{
5353
if (isset($preloaded[$class]) || \in_array($class, ['self', 'static', 'parent'], true)) {
5454
return;
@@ -68,9 +68,7 @@ private static function doPreload(string $class, array &$preloaded)
6868

6969
if (\PHP_VERSION_ID >= 70400) {
7070
foreach ($r->getProperties(\ReflectionProperty::IS_PUBLIC) as $p) {
71-
if (($t = $p->getType()) && !$t->isBuiltin()) {
72-
self::doPreload($t->getName(), $preloaded);
73-
}
71+
self::preloadType($p->getType(), $preloaded);
7472
}
7573
}
7674

@@ -84,17 +82,26 @@ private static function doPreload(string $class, array &$preloaded)
8482
}
8583
}
8684

87-
if (($t = $p->getType()) && !$t->isBuiltin()) {
88-
self::doPreload($t->getName(), $preloaded);
89-
}
85+
self::preloadType($p->getType(), $preloaded);
9086
}
9187

92-
if (($t = $m->getReturnType()) && !$t->isBuiltin()) {
93-
self::doPreload($t->getName(), $preloaded);
94-
}
88+
self::preloadType($p->getReturnType(), $preloaded);
9589
}
9690
} catch (\ReflectionException $e) {
9791
// ignore missing classes
9892
}
9993
}
94+
95+
private static function preloadType(?\ReflectionType $t, array &$preloaded): void
96+
{
97+
if (!$t || $t->isBuiltin()) {
98+
return;
99+
}
100+
101+
foreach ($t instanceof \ReflectionUnionType ? $t->getTypes() : [$t] as $t) {
102+
if (!$t->isBuiltin()) {
103+
self::doPreload($t instanceof \ReflectionNamedType ? $t->getName() : $t, $preloaded);
104+
}
105+
}
106+
}
100107
}

src/Symfony/Component/DependencyInjection/Exception/InvalidParameterTypeException.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ class InvalidParameterTypeException extends InvalidArgumentException
2121
{
2222
public function __construct(string $serviceId, string $type, \ReflectionParameter $parameter)
2323
{
24-
parent::__construct(sprintf('Invalid definition for service "%s": argument %d of "%s::%s" accepts "%s", "%s" passed.', $serviceId, 1 + $parameter->getPosition(), $parameter->getDeclaringClass()->getName(), $parameter->getDeclaringFunction()->getName(), $parameter->getType()->getName(), $type));
24+
$acceptedType = $parameter->getType();
25+
$acceptedType = $acceptedType instanceof \ReflectionNamedType ? $acceptedType->getName() : (string) $acceptedType;
26+
27+
parent::__construct(sprintf('Invalid definition for service "%s": argument %d of "%s::%s" accepts "%s", "%s" passed.', $serviceId, 1 + $parameter->getPosition(), $parameter->getDeclaringClass()->getName(), $parameter->getDeclaringFunction()->getName(), $acceptedType, $type), $type);
2528
}
2629
}

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

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,26 +31,36 @@ public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionPa
3131
if (!$type) {
3232
return null;
3333
}
34-
if (!\is_string($type)) {
35-
$name = $type->getName();
34+
35+
$types = [];
36+
37+
foreach ($type instanceof \ReflectionUnionType ? $type->getTypes() : [$type] as $type) {
38+
$name = $type instanceof \ReflectionNamedType ? $type->getName() : (string) $type;
3639

3740
if ($type->isBuiltin()) {
38-
return $noBuiltin ? null : $name;
41+
if (!$noBuiltin) {
42+
$types[] = $name;
43+
}
44+
continue;
3945
}
40-
}
41-
$lcName = strtolower($name);
42-
$prefix = $noBuiltin ? '' : '\\';
4346

44-
if ('self' !== $lcName && 'parent' !== $lcName) {
45-
return $prefix.$name;
46-
}
47-
if (!$r instanceof \ReflectionMethod) {
48-
return null;
49-
}
50-
if ('self' === $lcName) {
51-
return $prefix.$r->getDeclaringClass()->name;
47+
$lcName = strtolower($name);
48+
$prefix = $noBuiltin ? '' : '\\';
49+
50+
if ('self' !== $lcName && 'parent' !== $lcName) {
51+
$types[] = '' !== $prefix ? $prefix.$name : $name;
52+
continue;
53+
}
54+
if (!$r instanceof \ReflectionMethod) {
55+
continue;
56+
}
57+
if ('self' === $lcName) {
58+
$types[] = $prefix.$r->getDeclaringClass()->name;
59+
} else {
60+
$types[] = ($parent = $r->getDeclaringClass()->getParentClass()) ? $prefix.$parent->name : null;
61+
}
5262
}
5363

54-
return ($parent = $r->getDeclaringClass()->getParentClass()) ? $prefix.$parent->name : null;
64+
return $types ? implode('|', $types) : null;
5565
}
5666
}

src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ private function getEventFromTypeDeclaration(ContainerBuilder $container, string
138138
|| !($r = $container->getReflectionClass($class, false))
139139
|| !$r->hasMethod($method)
140140
|| 1 > ($m = $r->getMethod($method))->getNumberOfParameters()
141-
|| !($type = $m->getParameters()[0]->getType())
141+
|| !($type = $m->getParameters()[0]->getType()) instanceof \ReflectionNamedType
142142
|| $type->isBuiltin()
143143
|| Event::class === ($name = $type->getName())
144144
|| LegacyEvent::class === $name

src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public function createArgumentMetadata($controller): array
4545
*/
4646
private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function): ?string
4747
{
48-
if (!$type = $parameter->getType()) {
48+
if (!($type = $parameter->getType()) instanceof \ReflectionNamedType) {
4949
return null;
5050
}
5151
$name = $type->getName();

src/Symfony/Component/HttpKernel/EventListener/ErrorListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public function onControllerArguments(ControllerArgumentsEvent $event)
9999
$r = new \ReflectionFunction(\Closure::fromCallable($event->getController()));
100100
$r = $r->getParameters()[$k] ?? null;
101101

102-
if ($r && (!$r->hasType() || \in_array($r->getType()->getName(), [FlattenException::class, LegacyFlattenException::class], true))) {
102+
if ($r && (!($r = $r->getType()) instanceof \ReflectionNamedType || \in_array($r->getName(), [FlattenException::class, LegacyFlattenException::class], true))) {
103103
$arguments = $event->getArguments();
104104
$arguments[$k] = FlattenException::createFromThrowable($e);
105105
$event->setArguments($arguments);

src/Symfony/Component/Messenger/DependencyInjection/MessengerPass.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,24 @@ private function guessHandledClasses(\ReflectionClass $handlerClass, string $ser
228228
throw new RuntimeException(sprintf('Invalid handler service "%s": argument "$%s" of method "%s::__invoke()" must have a type-hint corresponding to the message class it handles.', $serviceId, $parameters[0]->getName(), $handlerClass->getName()));
229229
}
230230

231+
if ($type instanceof \ReflectionUnionType) {
232+
$types = [];
233+
foreach ($type->getTypes() as $type) {
234+
if (!$type->isBuiltin()) {
235+
$types[] = (string) $type;
236+
}
237+
}
238+
239+
if ($types) {
240+
return $types;
241+
}
242+
}
243+
231244
if ($type->isBuiltin()) {
232245
throw new RuntimeException(sprintf('Invalid handler service "%s": type-hint of argument "$%s" in method "%s::__invoke()" must be a class , "%s" given.', $serviceId, $parameters[0]->getName(), $handlerClass->getName(), $type instanceof \ReflectionNamedType ? $type->getName() : (string) $type));
233246
}
234247

235-
return [$parameters[0]->getType()->getName()];
248+
return [$type->getName()];
236249
}
237250

238251
private function registerReceivers(ContainerBuilder $container, array $busIds)

src/Symfony/Component/OptionsResolver/OptionsResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ public function setDefault($option, $value)
201201
return $this;
202202
}
203203

204-
if (isset($params[0]) && null !== ($type = $params[0]->getType()) && self::class === $type->getName() && (!isset($params[1]) || (null !== ($type = $params[1]->getType()) && Options::class === $type->getName()))) {
204+
if (isset($params[0]) && null !== ($type = $params[0]->getType()) && self::class === $type->getName() && (!isset($params[1]) || (($type = $params[1]->getType()) instanceof \ReflectionNamedType && Options::class === $type->getName()))) {
205205
// Store closure for later evaluation
206206
$this->nested[$option][] = $value;
207207
$this->defaults[$option] = [];
@@ -1220,7 +1220,7 @@ private function formatOptions(array $options): string
12201220

12211221
private function getParameterClassName(\ReflectionParameter $parameter): ?string
12221222
{
1223-
if (!($type = $parameter->getType()) || $type->isBuiltin()) {
1223+
if (!($type = $parameter->getType()) instanceof \ReflectionNamedType || $type->isBuiltin()) {
12241224
return null;
12251225
}
12261226

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy