Skip to content

Commit

Permalink
feature #17531 [PropertyInfo] Use last version of reflection docblock…
Browse files Browse the repository at this point in the history
… (joelwurtz)

This PR was merged into the 3.1-dev branch.

Discussion
----------

[PropertyInfo] Use last version of reflection docblock

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

This PR improve the PhpDocExtractor to use https://github.com/phpDocumentor/ReflectionDocBlock 3.0 dev branch instead of https://github.com/phpDocumentor/ReflectionDocBlock 1.0.7 which is not maintained since 2014

I don't know if it's a BC break since it's only a suggested dependency.

This is somehow mandatory (we can maybe use a more stable, but also not maintained version of this repository) for #17516 as it does not have a dependency on php-parser 0.9.4 which is very old and not really suitable for the new component.

Commits
-------

d642eae Use last version of reflection dockblock, avoid extra dependancy if library needed
  • Loading branch information
fabpot committed Feb 26, 2016
2 parents aa770e1 + d642eae commit c2d1c02
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 96 deletions.
4 changes: 2 additions & 2 deletions composer.json
Expand Up @@ -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": {
Expand Down
148 changes: 57 additions & 91 deletions src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php
Expand Up @@ -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;
Expand All @@ -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;
}
}
}
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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.
*
Expand Down Expand Up @@ -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));
}

/**
Expand All @@ -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;
Expand All @@ -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);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/Symfony/Component/PropertyInfo/composer.json
Expand Up @@ -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": {
Expand Down

0 comments on commit c2d1c02

Please sign in to comment.