diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index 4837d2200c852..d4060f4fa45e3 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -14,6 +14,7 @@ use phpDocumentor\Reflection\DocBlock; use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\DocBlockFactoryInterface; +use phpDocumentor\Reflection\Types\Context; use phpDocumentor\Reflection\Types\ContextFactory; use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; @@ -38,6 +39,11 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property */ private $docBlocks = []; + /** + * @var Context[] + */ + private $contexts = []; + private $docBlockFactory; private $contextFactory; private $phpDocTypeHelper; @@ -191,7 +197,7 @@ private function getDocBlockFromProperty(string $class, string $property): ?DocB } try { - return $this->docBlockFactory->create($reflectionProperty, $this->contextFactory->createFromReflector($reflectionProperty->getDeclaringClass())); + return $this->docBlockFactory->create($reflectionProperty, $this->createFromReflector($reflectionProperty->getDeclaringClass())); } catch (\InvalidArgumentException $e) { return null; } @@ -227,9 +233,25 @@ private function getDocBlockFromMethod(string $class, string $ucFirstProperty, i } try { - return [$this->docBlockFactory->create($reflectionMethod, $this->contextFactory->createFromReflector($reflectionMethod)), $prefix]; + return [$this->docBlockFactory->create($reflectionMethod, $this->createFromReflector($reflectionMethod->getDeclaringClass())), $prefix]; } catch (\InvalidArgumentException $e) { return null; } } + + /** + * Prevents a lot of redundant calls to ContextFactory::createForNamespace(). + */ + private function createFromReflector(\ReflectionClass $reflector): Context + { + $cacheKey = $reflector->getNamespaceName().':'.$reflector->getFileName(); + + if (isset($this->contexts[$cacheKey])) { + return $this->contexts[$cacheKey]; + } + + $this->contexts[$cacheKey] = $this->contextFactory->createFromReflector($reflector); + + return $this->contexts[$cacheKey]; + } }