8000 Remove non-autoloadable classes from preload · symfony/symfony@8c47b47 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8c47b47

Browse files
committed
Remove non-autoloadable classes from preload
1 parent e9a7026 commit 8c47b47

File tree

4 files changed

+53
-20
lines changed

4 files changed

+53
-20
lines changed

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

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ class PhpDumper extends Dumper
9090
private $serviceLocatorTag;
9191
private $exportedVariables = [];
9292
private $baseClass;
93+
private $preloadableCache = [];
9394

9495
/**
9596
* @var ProxyDumper
@@ -335,7 +336,7 @@ class %s extends {$options['class']}
335336
if (!$class || str_contains($class, '$') || \in_array($class, ['int', 'float', 'string', 'bool', 'resource', 'object', 'array', 'null', 'callable', 'iterable', 'mixed', 'void'], true)) {
336337
continue;
337338
}
338-
if (!(class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false)) || (new \ReflectionClass($class))->isUserDefined()) {
339+
if ($this->isPreloadable($class)) {
339340
$code[$options['class'].'.preload.php'] .= sprintf("\$classes[] = '%s';\n", $class);
340341
}
341342
}
@@ -398,6 +399,57 @@ class %s extends {$options['class']}
398399
return $code;
399400
}
400401

402+
private function isPreloadable(string $class): ?bool
403+
{
404+
if (array_key_exists($class, $this->preloadableCache)) {
405+
return $this->preloadableCache[$class];
406+
}
407+
$this->preloadableCache[$class] = true; // prevent recursion
408+
409+
if (!class_exists($class) && !interface_exists($class, false) && !trait_exists($class, false)) {
410+
return $this->preloadableCache[$class] = false;
411+
}
412+
$reflection = new \ReflectionClass($class);
413+
if (!$reflection->isUserDefined()) {
414+
return $this->preloadableCache[$class] = null;
415+
}
416+
417+
// Since PHP 8.1, typehinted properties does not have to be auto-loadable.
418+
// Before PHP 8.0, user can not define typehinted properties
419+
if (\PHP_VERSION_ID >= 80100 || \PHP_VERSION_ID < 80000) {
420+
return $this->preloadableCache[$class] = true;
421+
}
422+
423+
foreach ($reflection->getProperties() as $property) {
424+
if (null === $type = $property->getType()) {
425+
continue;
426+
}
427+
$typesToCheck = [$type];
428+
while (!empty($typesToCheck)) {
429+
$typeToCheck = array_shift($typesToCheck);
430+
if ($typeToCheck instanceof \ReflectionUnionType || $typeToCheck instanceof \ReflectionIntersectionType) {
431+
foreach ($typeToCheck->getTypes() as $t) {
432+
$typesToCheck[] = $t;
433+
}
434+
435+
continue;
436+
}
437+
if (!$typeToCheck instanceof \ReflectionNamedType) {
438+
continue;
439+
}
440+
$typeName = $typeToCheck->getName();
441+
if (!$typeName || str_contains($typeName, '$') || \in_array($typeName, ['int', 'false', 'float', 'string', 'bool', 'resource', 'object', 'array', 'null', 'callable', 'iterable', 'mixed', 'void'], true)) {
442+
continue;
443+
}
444+
if (false === $this->isPreloadable($typeName)) {
445+
return $this->preloadableCache[$class] = false;
446+
}
447+
}
448+
}
449+
450+
return $this->preloadableCache[$class] = true;
451+
}
452+
401453
/**
402454
* Retrieves the currently set proxy dumper or instantiates one.
403455
*/

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10_as_files.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ require __DIR__.'/Container%s/ProjectServiceContainer.php';
137137
require __DIR__.'/Container%s/getClosureService.php';
138138

139139
$classes = [];
140-
$classes[] = 'FooClass';
141140
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
142141

143142
Preloader::preload($classes);

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -935,17 +935,8 @@ require __DIR__.'/Container%s/getBAR2Service.php';
935935

936936
$classes = [];
937937
$classes[] = 'Bar\FooClass';
938-
$classes[] = 'Baz';
939-
$classes[] = 'ConfClass';
940-
$classes[] = 'Bar';
941938
$classes[] = 'BazClass';
942-
$classes[] = 'Foo';
943939
$classes[] = 'LazyContext';
944-
$classes[] = 'FooBarBaz';
945-
$classes[] = 'FactoryClass';
946-
$classes[] = 'Some\Sidekick1';
947-
$classes[] = 'Some\Sidekick2';
948-
$classes[] = 'Request';
949940
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
950941

951942
Preloader::preload($classes);

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_inlined_factories.txt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -566,17 +566,8 @@ require __DIR__.'/Container%s/ProjectServiceContainer.php';
566566

567567
$classes = [];
568568
$classes[] = 'Bar\FooClass';
569-
$classes[] = 'Baz';
570-
$classes[] = 'ConfClass';
571-
$classes[] = 'Bar';
572569
$classes[] = 'BazClass';
573-
$classes[] = 'Foo';
574570
$classes[] = 'LazyContext';
575-
$classes[] = 'FooBarBaz';
576-
$classes[] = 'FactoryClass';
577-
$classes[] = 'Some\Sidekick1';
578-
$classes[] = 'Some\Sidekick2';
579-
$classes[] = 'Request';
580571
$classes[] = 'Symfony\Component\DependencyInjection\ContainerInterface';
581572

582573
Preloader::preload($classes);

0 commit comments

Comments
 (0)
0