From d642eaefda75130fc70daba58db2d6c2d0bdacb3 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Mon, 25 Jan 2016 21:45:52 +0100 Subject: [PATCH] Use last version of reflection dockblock, avoid extra dependancy if library needed --- composer.json | 4 +- .../Extractor/PhpDocExtractor.php | 148 +++++++----------- .../Component/PropertyInfo/composer.json | 6 +- 3 files changed, 62 insertions(+), 96 deletions(-) diff --git a/composer.json b/composer.json index 3a54375327e6..e3fa133f4bf5 100644 --- a/composer.json +++ b/composer.json @@ -86,10 +86,10 @@ "egulias/email-validator": "~1.2", "symfony/polyfill-apcu": "~1.1", "symfony/security-acl": "~2.8|~3.0", - "phpdocumentor/reflection": "^1.0.7" + "phpdocumentor/reflection-docblock": "^3.0" }, "conflict": { - "phpdocumentor/reflection": "<1.0.7" + "phpdocumentor/reflection-docblock": "<3.0" }, "autoload": { "psr-4": { diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index b1f323c0bd6e..201fbde60037 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -11,9 +11,11 @@ namespace Symfony\Component\PropertyInfo\Extractor; -use phpDocumentor\Reflection\ClassReflector; use phpDocumentor\Reflection\DocBlock; -use phpDocumentor\Reflection\FileReflector; +use phpDocumentor\Reflection\DocBlockFactory; +use phpDocumentor\Reflection\Types\Compound; +use phpDocumentor\Reflection\Types\ContextFactory; +use phpDocumentor\Reflection\Types\Null_; use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; use Symfony\Component\PropertyInfo\Type; @@ -30,35 +32,48 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property const MUTATOR = 2; /** - * @var FileReflector[] + * @var DocBlock[] */ - private $fileReflectors = array(); + private $docBlocks = array(); /** - * @var DocBlock[] + * @var DocBlockFactory */ - private $docBlocks = array(); + private $docBlockFactory; + + /** + * @var ContextFactory + */ + private $contextFactory; + + public function __construct() + { + $this->docBlockFactory = DocBlockFactory::createInstance(); + $this->contextFactory = new ContextFactory(); + } /** * {@inheritdoc} */ public function getShortDescription($class, $property, array $context = array()) { + /** @var $docBlock DocBlock */ list($docBlock) = $this->getDocBlock($class, $property); if (!$docBlock) { return; } - $shortDescription = $docBlock->getShortDescription(); - if ($shortDescription) { + $shortDescription = $docBlock->getSummary(); + + if (!empty($shortDescription)) { return $shortDescription; } foreach ($docBlock->getTagsByName('var') as $var) { - $parsedDescription = $var->getParsedDescription(); + $varDescription = $var->getDescription()->render(); - if (isset($parsedDescription[0]) && '' !== $parsedDescription[0]) { - return $parsedDescription[0]; + if (!empty($varDescription)) { + return $varDescription; } } } @@ -68,12 +83,13 @@ public function getShortDescription($class, $property, array $context = array()) */ public function getLongDescription($class, $property, array $context = array()) { + /** @var $docBlock DocBlock */ list($docBlock) = $this->getDocBlock($class, $property); if (!$docBlock) { return; } - $contents = $docBlock->getLongDescription()->getContents(); + $contents = $docBlock->getDescription()->render(); return '' === $contents ? null : $contents; } @@ -83,6 +99,7 @@ public function getLongDescription($class, $property, array $context = array()) */ public function getTypes($class, $property, array $context = array()) { + /** @var $docBlock DocBlock */ list($docBlock, $source, $prefix) = $this->getDocBlock($class, $property); if (!$docBlock) { return; @@ -103,8 +120,31 @@ public function getTypes($class, $property, array $context = array()) } $types = array(); + /** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */ foreach ($docBlock->getTagsByName($tag) as $tag) { - $varTypes = $tag->getTypes(); + $varType = $tag->getType(); + $nullable = false; + + if (!$varType instanceof Compound) { + if ($varType instanceof Null_) { + $nullable = true; + } + + $type = $this->createType((string) $varType, $nullable); + + if (null !== $type) { + $types[] = $type; + } + + continue; + } + + $typeIndex = 0; + $varTypes = array(); + while ($varType->has($typeIndex)) { + $varTypes[] = (string) $varType->get($typeIndex); + ++$typeIndex; + } // If null is present, all types are nullable $nullKey = array_search(Type::BUILTIN_TYPE_NULL, $varTypes); @@ -134,29 +174,6 @@ public function getTypes($class, $property, array $context = array()) return array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $types[0])); } - /** - * Gets the FileReflector associated with the class. - * - * @param \ReflectionClass $reflectionClass - * - * @return FileReflector|null - */ - private function getFileReflector(\ReflectionClass $reflectionClass) - { - if (!($fileName = $reflectionClass->getFileName()) || 'hh' === pathinfo($fileName, PATHINFO_EXTENSION)) { - return; - } - - if (isset($this->fileReflectors[$fileName])) { - return $this->fileReflectors[$fileName]; - } - - $this->fileReflectors[$fileName] = new FileReflector($fileName); - $this->fileReflectors[$fileName]->process(); - - return $this->fileReflectors[$fileName]; - } - /** * Gets the DocBlock for this property. * @@ -212,27 +229,7 @@ private function getDocBlockFromProperty($class, $property) return; } - $reflectionCLass = $reflectionProperty->getDeclaringClass(); - - $fileReflector = $this->getFileReflector($reflectionCLass); - if (!$fileReflector) { - return; - } - - foreach ($fileReflector->getClasses() as $classReflector) { - $className = $this->getClassName($classReflector); - - if ($className === $reflectionCLass->name) { - foreach ($classReflector->getProperties() as $propertyReflector) { - // strip the $ prefix - $propertyName = substr($propertyReflector->getName(), 1); - - if ($propertyName === $property) { - return $propertyReflector->getDocBlock(); - } - } - } - } + return $this->docBlockFactory->create($reflectionProperty, $this->contextFactory->createFromReflector($reflectionProperty)); } /** @@ -242,11 +239,12 @@ private function getDocBlockFromProperty($class, $property) * @param string $ucFirstProperty * @param int $type * - * @return DocBlock|null + * @return array */ private function getDocBlockFromMethod($class, $ucFirstProperty, $type) { $prefixes = $type === self::ACCESSOR ? ReflectionExtractor::$accessorPrefixes : ReflectionExtractor::$mutatorPrefixes; + $prefix = null; foreach ($prefixes as $prefix) { $methodName = $prefix.$ucFirstProperty; @@ -269,39 +267,7 @@ private function getDocBlockFromMethod($class, $ucFirstProperty, $type) return; } - $reflectionClass = $reflectionMethod->getDeclaringClass(); - $fileReflector = $this->getFileReflector($reflectionClass); - - if (!$fileReflector) { - return; - } - - foreach ($fileReflector->getClasses() as $classReflector) { - $className = $this->getClassName($classReflector); - - if ($className === $reflectionClass->name) { - if ($methodReflector = $classReflector->getMethod($methodName)) { - return array($methodReflector->getDocBlock(), $prefix); - } - } - } - } - - /** - * Gets the normalized class name (without trailing backslash). - * - * @param ClassReflector $classReflector - * - * @return string - */ - private function getClassName(ClassReflector $classReflector) - { - $className = $classReflector->getName(); - if ('\\' === $className[0]) { - return substr($className, 1); - } - - return $className; + return array($this->docBlockFactory->create($reflectionMethod, $this->contextFactory->createFromReflector($reflectionMethod)), $prefix); } /** diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index b484a6fe3c62..dfc345fc5341 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -28,16 +28,16 @@ "require-dev": { "symfony/serializer": "~2.8|~3.0", "symfony/cache": "~3.1", - "phpdocumentor/reflection": "^1.0.7", + "phpdocumentor/reflection-docblock": "^3.0", "doctrine/annotations": "~1.0" }, "conflict": { - "phpdocumentor/reflection": "<1.0.7" + "phpdocumentor/reflection-docblock": "<3.0" }, "suggest": { "psr/cache-implementation": "To cache results", "symfony/doctrine-bridge": "To use Doctrine metadata", - "phpdocumentor/reflection": "To use the PHPDoc", + "phpdocumentor/reflection-docblock": "To use the PHPDoc", "symfony/serializer": "To use Serializer metadata" }, "autoload": {