Skip to content

Commit

Permalink
bug #36975 [PropertyInfo] Make PhpDocExtractor compatible with phpDoc…
Browse files Browse the repository at this point in the history
…umentor v5 (DerManoMann)

This PR was merged into the 4.4 branch.

Discussion
----------

[PropertyInfo] Make PhpDocExtractor compatible with phpDocumentor v5

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #36049
| License       | MIT
| Doc PR        | N/A

Version 5 of phpDocumentor introduced some changes to the `getTagsByName()` method that break the `PhpDocExtractor`.

More specific, it now returns an instance of `InvalidTag` instead of `null` when parsing an invalid tag.

Commits
-------

b1f8e5a Make PhpDocExtractor compatible with phpDocumentor v5
  • Loading branch information
fabpot committed Jun 15, 2020
2 parents 055dd28 + b1f8e5a commit bb8e66b
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 7 deletions.
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -121,7 +121,7 @@
"egulias/email-validator": "~1.2,>=1.2.8|~2.0",
"symfony/phpunit-bridge": "^5.0.8",
"symfony/security-acl": "~2.8|~3.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
"twig/cssinliner-extra": "^2.12",
"twig/inky-extra": "^2.12",
"twig/markdown-extra": "^2.12"
Expand Down
11 changes: 7 additions & 4 deletions src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php
Expand Up @@ -12,6 +12,7 @@
namespace Symfony\Component\PropertyInfo\Extractor;

use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\DocBlockFactoryInterface;
use phpDocumentor\Reflection\Types\Context;
Expand Down Expand Up @@ -88,10 +89,12 @@ public function getShortDescription($class, $property, array $context = []): ?st
}

foreach ($docBlock->getTagsByName('var') as $var) {
$varDescription = $var->getDescription()->render();
if ($var && !$var instanceof InvalidTag) {
$varDescription = $var->getDescription()->render();

if (!empty($varDescription)) {
return $varDescription;
if (!empty($varDescription)) {
return $varDescription;
}
}
}

Expand Down Expand Up @@ -142,7 +145,7 @@ public function getTypes($class, $property, array $context = []): ?array
$types = [];
/** @var DocBlock\Tags\Var_|DocBlock\Tags\Return_|DocBlock\Tags\Param $tag */
foreach ($docBlock->getTagsByName($tag) as $tag) {
if ($tag && null !== $tag->getType()) {
if ($tag && !$tag instanceof InvalidTag && null !== $tag->getType()) {
$types = array_merge($types, $this->phpDocTypeHelper->getTypes($tag->getType()));
}
}
Expand Down
Expand Up @@ -11,6 +11,8 @@

namespace Symfony\Component\PropertyInfo\Tests\Extractor;

use phpDocumentor\Reflection\DocBlock\StandardTagFactory;
use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
use phpDocumentor\Reflection\Types\Collection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
Expand Down Expand Up @@ -46,6 +48,26 @@ public function testParamTagTypeIsOmitted()
$this->assertNull($this->extractor->getTypes(OmittedParamTagTypeDocBlock::class, 'omittedType'));
}

public function invalidTypesProvider()
{
return [
'pub' => ['pub', null, null],
'stat' => ['stat', null, null],
'foo' => ['foo', $this->isPhpDocumentorV5() ? 'Foo.' : null, null],
'bar' => ['bar', $this->isPhpDocumentorV5() ? 'Bar.' : null, null],
];
}

/**
* @dataProvider invalidTypesProvider
*/
public function testInvalid($property, $shortDescription, $longDescription)
{
$this->assertNull($this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property));
$this->assertSame($shortDescription, $this->extractor->getShortDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property));
$this->assertSame($longDescription, $this->extractor->getLongDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\InvalidDummy', $property));
}

/**
* @dataProvider typesWithNoPrefixesProvider
*/
Expand Down Expand Up @@ -94,7 +116,7 @@ public function typesProvider()
['donotexist', null, null, null],
['staticGetter', null, null, null],
['staticSetter', null, null, null],
['emptyVar', null, null, null],
['emptyVar', null, $this->isPhpDocumentorV5() ? 'This should not be removed.' : null, null],
];
}

Expand Down Expand Up @@ -250,6 +272,16 @@ public function testDocBlockFallback($property, $types)
{
$this->assertEquals($types, $this->extractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\DockBlockFallback', $property));
}

protected function isPhpDocumentorV5()
{
if (class_exists(InvalidTag::class)) {
return true;
}

return (new \ReflectionMethod(StandardTagFactory::class, 'create'))
->hasReturnType();
}
}

class EmptyDocBlock
Expand Down
50 changes: 50 additions & 0 deletions src/Symfony/Component/PropertyInfo/Tests/Fixtures/InvalidDummy.php
@@ -0,0 +1,50 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\PropertyInfo\Tests\Fixtures;

/**
* @author Martin Rademacher <mano@radebatz.net>
*/
class InvalidDummy
{
/**
* @var
*/
public $pub;

/**
* @return
*/
public static function getStat()
{
return 'stat';
}

/**
* Foo.
*
* @param
*/
public function setFoo($foo)
{
}

/**
* Bar.
*
* @return
*/
public function getBar()
{
return 'bar';
}
}
2 changes: 1 addition & 1 deletion src/Symfony/Component/PropertyInfo/composer.json
Expand Up @@ -30,7 +30,7 @@
"symfony/serializer": "^3.4|^4.0|^5.0",
"symfony/cache": "^3.4|^4.0|^5.0",
"symfony/dependency-injection": "^3.4|^4.0|^5.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
"doctrine/annotations": "~1.7"
},
"conflict": {
Expand Down

0 comments on commit bb8e66b

Please sign in to comment.