mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-17 17:47:13 +00:00
Merge remote-tracking branch 'upstream/master' into fix_for_phpstorm_stubs
* upstream/master: Bump mockery Fix FQSEN resolving on see,covers,uses Improve test coverage
This commit is contained in:
@@ -30,7 +30,7 @@ psalm:
|
||||
.PHONY: test
|
||||
test:
|
||||
docker run -it --rm -v${CURDIR}:/github/workspace phpdoc/phpunit-ga
|
||||
docker run -it --rm -v${CURDIR}:/data -w /data php:7.2 -f ./tests/coverage-checker.php 89
|
||||
docker run -it --rm -v${CURDIR}:/data -w /data php:7.2 -f ./tests/coverage-checker.php 90
|
||||
|
||||
.PHONY: pre-commit-test
|
||||
pre-commit-test: test phpcs phpstan psalm
|
||||
|
||||
Generated
-14
@@ -160,20 +160,6 @@
|
||||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-06-06T08:46:27+00:00"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -20,6 +20,8 @@ use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_key_exists;
|
||||
use function explode;
|
||||
|
||||
/**
|
||||
* Reflection class for a @covers tag in a Docblock.
|
||||
@@ -54,11 +56,24 @@ final class Covers extends BaseTag implements Factory\StaticMethod
|
||||
$parts = Utils::pregSplit('/\s+/Su', $body, 2);
|
||||
|
||||
return new static(
|
||||
$resolver->resolve($parts[0], $context),
|
||||
self::resolveFqsen($parts[0], $resolver, $context),
|
||||
$descriptionFactory->create($parts[1] ?? '', $context)
|
||||
);
|
||||
}
|
||||
|
||||
private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context) : Fqsen
|
||||
{
|
||||
Assert::notNull($fqsenResolver);
|
||||
$fqsenParts = explode('::', $parts);
|
||||
$resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
|
||||
|
||||
if (!array_key_exists(1, $fqsenParts)) {
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
return new Fqsen($resolved . '::' . $fqsenParts[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the structural element this tag refers to.
|
||||
*/
|
||||
|
||||
@@ -48,7 +48,7 @@ final class Example implements Tag, Factory\StaticMethod
|
||||
public function __construct(string $filePath, bool $isURI, int $startingLine, int $lineCount, ?string $content)
|
||||
{
|
||||
Assert::notEmpty($filePath);
|
||||
Assert::greaterThanEq($startingLine, 0);
|
||||
Assert::greaterThanEq($startingLine, 1);
|
||||
Assert::greaterThanEq($lineCount, 0);
|
||||
|
||||
$this->filePath = $filePath;
|
||||
@@ -63,7 +63,7 @@ final class Example implements Tag, Factory\StaticMethod
|
||||
|
||||
public function getContent() : string
|
||||
{
|
||||
if ($this->content === null) {
|
||||
if ($this->content === null || $this->content === '') {
|
||||
$filePath = '"' . $this->filePath . '"';
|
||||
if ($this->isURI) {
|
||||
$filePath = $this->isUriRelative($this->filePath)
|
||||
@@ -107,7 +107,7 @@ final class Example implements Tag, Factory\StaticMethod
|
||||
// Starting line / Number of lines / Description
|
||||
if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) {
|
||||
$startingLine = (int) $contentMatches[1];
|
||||
if (isset($contentMatches[2]) && $contentMatches[2] !== '') {
|
||||
if (isset($contentMatches[2])) {
|
||||
$lineCount = (int) $contentMatches[2];
|
||||
}
|
||||
|
||||
|
||||
@@ -18,10 +18,13 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url;
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_key_exists;
|
||||
use function explode;
|
||||
use function preg_match;
|
||||
|
||||
/**
|
||||
@@ -50,7 +53,6 @@ final class See extends BaseTag implements Factory\StaticMethod
|
||||
?DescriptionFactory $descriptionFactory = null,
|
||||
?TypeContext $context = null
|
||||
) : self {
|
||||
Assert::notNull($typeResolver);
|
||||
Assert::notNull($descriptionFactory);
|
||||
|
||||
$parts = Utils::pregSplit('/\s+/Su', $body, 2);
|
||||
@@ -61,7 +63,20 @@ final class See extends BaseTag implements Factory\StaticMethod
|
||||
return new static(new Url($parts[0]), $description);
|
||||
}
|
||||
|
||||
return new static(new FqsenRef($typeResolver->resolve($parts[0], $context)), $description);
|
||||
return new static(new FqsenRef(self::resolveFqsen($parts[0], $typeResolver, $context)), $description);
|
||||
}
|
||||
|
||||
private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context) : Fqsen
|
||||
{
|
||||
Assert::notNull($fqsenResolver);
|
||||
$fqsenParts = explode('::', $parts);
|
||||
$resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
|
||||
|
||||
if (!array_key_exists(1, $fqsenParts)) {
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
return new Fqsen($resolved . '::' . $fqsenParts[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,8 @@ use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use phpDocumentor\Reflection\Utils;
|
||||
use Webmozart\Assert\Assert;
|
||||
use function array_key_exists;
|
||||
use function explode;
|
||||
|
||||
/**
|
||||
* Reflection class for a {@}uses tag in a Docblock.
|
||||
@@ -53,11 +55,24 @@ final class Uses extends BaseTag implements Factory\StaticMethod
|
||||
$parts = Utils::pregSplit('/\s+/Su', $body, 2);
|
||||
|
||||
return new static(
|
||||
$resolver->resolve($parts[0], $context),
|
||||
self::resolveFqsen($parts[0], $resolver, $context),
|
||||
$descriptionFactory->create($parts[1] ?? '', $context)
|
||||
);
|
||||
}
|
||||
|
||||
private static function resolveFqsen(string $parts, ?FqsenResolver $fqsenResolver, ?TypeContext $context) : Fqsen
|
||||
{
|
||||
Assert::notNull($fqsenResolver);
|
||||
$fqsenParts = explode('::', $parts);
|
||||
$resolved = $fqsenResolver->resolve($fqsenParts[0], $context);
|
||||
|
||||
if (!array_key_exists(1, $fqsenParts)) {
|
||||
return $resolved;
|
||||
}
|
||||
|
||||
return new Fqsen($resolved . '::' . $fqsenParts[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the structural element this tag refers to.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpDocumentor\Reflection;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\See;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DocblockSeeTagResolvingTest extends TestCase
|
||||
{
|
||||
public function testResolvesSeeFQSENOfInlineTags()
|
||||
{
|
||||
$context = new Context('\Project\Sub\Level', ['Issue2425B' => '\Project\Other\Level\Issue2425B', 'Aliased' => 'Project\Other\Level\Issue2425C']);
|
||||
$docblockString = <<<DOCBLOCK
|
||||
/**
|
||||
* Class summary.
|
||||
*
|
||||
* A description containing an inline {@see Issue2425B::bar()} tag
|
||||
* to a class inside of the project referenced via a use statement.
|
||||
*
|
||||
* And here is another inline {@see Aliased::bar()} tag to a class
|
||||
* aliased via a use statement.
|
||||
*/
|
||||
DOCBLOCK;
|
||||
|
||||
|
||||
|
||||
$factory = DocBlockFactory::createInstance();
|
||||
$docblock = $factory->create($docblockString, $context);
|
||||
|
||||
/** @var See $see1 */
|
||||
$see1 = $docblock->getDescription()->getTags()[0];
|
||||
|
||||
$this->assertSame('\Project\Other\Level\Issue2425B::bar()', (string)$see1->getReference());
|
||||
}
|
||||
}
|
||||
@@ -150,14 +150,40 @@ class AuthorTest extends TestCase
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Author::<public>
|
||||
*
|
||||
* @covers ::create
|
||||
* @dataProvider authorTagProvider
|
||||
*/
|
||||
public function testFactoryMethod() : void
|
||||
public function testFactoryMethod(string $input, string $output, string $name, string $email) : void
|
||||
{
|
||||
$fixture = Author::create('Mike van Riel <[email protected]>');
|
||||
$fixture = Author::create($input);
|
||||
|
||||
$this->assertSame('Mike van Riel <[email protected]>', (string) $fixture);
|
||||
$this->assertSame('Mike van Riel', $fixture->getAuthorName());
|
||||
$this->assertSame('[email protected]', $fixture->getEmail());
|
||||
$this->assertSame($output, (string) $fixture);
|
||||
$this->assertSame($name, $fixture->getAuthorName());
|
||||
$this->assertSame($email, $fixture->getEmail());
|
||||
}
|
||||
|
||||
/** @return mixed[][] */
|
||||
public function authorTagProvider() : array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'Mike van Riel <[email protected]>',
|
||||
'Mike van Riel <[email protected]>',
|
||||
'Mike van Riel',
|
||||
'[email protected]',
|
||||
],
|
||||
[
|
||||
'Mike van Riel < [email protected] >',
|
||||
'Mike van Riel <[email protected]>',
|
||||
'Mike van Riel',
|
||||
'[email protected]',
|
||||
],
|
||||
[
|
||||
'Mike van Riel',
|
||||
'Mike van Riel',
|
||||
'Mike van Riel',
|
||||
'',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,23 +4,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace DocBlock\Tags;
|
||||
|
||||
use Mockery as m;
|
||||
use InvalidArgumentException;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Example;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \phpDocumentor\Reflection\DocBlock\Tags\Example
|
||||
* @covers ::<private>
|
||||
*/
|
||||
class ExampleTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Call Mockery::close after each test.
|
||||
*/
|
||||
public function tearDown() : void
|
||||
{
|
||||
m::close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
|
||||
*
|
||||
@@ -103,19 +96,147 @@ class ExampleTest extends TestCase
|
||||
/**
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
|
||||
*
|
||||
* @dataProvider tagContentProvider
|
||||
* @covers ::create
|
||||
* @covers ::__construct
|
||||
* @covers ::getFilePath
|
||||
* @covers ::getStartingLine
|
||||
* @covers ::getLineCount
|
||||
* @covers ::getDescription
|
||||
* @covers ::getContent
|
||||
*/
|
||||
public function testFullExample() : void
|
||||
public function testFactoryMethod(
|
||||
string $input,
|
||||
string $filePath,
|
||||
int $startLine,
|
||||
int $lineCount,
|
||||
?string $description,
|
||||
string $content
|
||||
) : void {
|
||||
$tag = Example::create($input);
|
||||
$this->assertSame($filePath, $tag->getFilePath());
|
||||
$this->assertSame($startLine, $tag->getStartingLine());
|
||||
$this->assertSame($lineCount, $tag->getLineCount());
|
||||
$this->assertSame($description, $tag->getDescription());
|
||||
$this->assertSame($content, $tag->getContent());
|
||||
}
|
||||
|
||||
/** @return mixed[][] */
|
||||
public function tagContentProvider() : array
|
||||
{
|
||||
$tag = Example::create('"example1.php" 10 5 test text');
|
||||
$this->assertEquals('example1.php', $tag->getFilePath());
|
||||
$this->assertEquals(10, $tag->getStartingLine());
|
||||
$this->assertEquals(5, $tag->getLineCount());
|
||||
$this->assertEquals('test text', $tag->getDescription());
|
||||
return [
|
||||
[
|
||||
'"example1.php" 10 5 test text ',
|
||||
'example1.php',
|
||||
10,
|
||||
5,
|
||||
'test text',
|
||||
'test text',
|
||||
],
|
||||
[
|
||||
'example1.php 10 5 test text',
|
||||
'example1.php',
|
||||
10,
|
||||
5,
|
||||
'test text',
|
||||
'test text',
|
||||
],
|
||||
[
|
||||
'example1.php 1 10 test text',
|
||||
'example1.php',
|
||||
1,
|
||||
10,
|
||||
'test text',
|
||||
'test text',
|
||||
],
|
||||
[
|
||||
'example1.php',
|
||||
'example1.php',
|
||||
1,
|
||||
0,
|
||||
null,
|
||||
'example1.php',
|
||||
],
|
||||
[
|
||||
'file://example1.php ',
|
||||
'file://example1.php',
|
||||
1,
|
||||
0,
|
||||
'',
|
||||
'file://example1.php',
|
||||
],
|
||||
[
|
||||
'/example1.php',
|
||||
'/example1.php',
|
||||
1,
|
||||
0,
|
||||
null,
|
||||
'/example1.php',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider invalidExampleProvider
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testValidatesArguments(
|
||||
string $filePath,
|
||||
bool $isUrl,
|
||||
int $startLine,
|
||||
int $lineCount,
|
||||
string $description
|
||||
) : void {
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
|
||||
new Example(
|
||||
$filePath,
|
||||
$isUrl,
|
||||
$startLine,
|
||||
$lineCount,
|
||||
$description
|
||||
);
|
||||
}
|
||||
|
||||
/** @return mixed[][] */
|
||||
public function invalidExampleProvider() : array
|
||||
{
|
||||
return [
|
||||
'invalid start' => [
|
||||
'/some/path',
|
||||
false,
|
||||
-1,
|
||||
0,
|
||||
'text',
|
||||
],
|
||||
'invalid start 2' => [
|
||||
'/some/path',
|
||||
false,
|
||||
-10,
|
||||
0,
|
||||
'text',
|
||||
],
|
||||
'invalid length' => [
|
||||
'/some/path',
|
||||
false,
|
||||
1,
|
||||
-1,
|
||||
'text',
|
||||
],
|
||||
'invalid length 2' => [
|
||||
'/some/path',
|
||||
false,
|
||||
1,
|
||||
-10,
|
||||
'text',
|
||||
],
|
||||
'empty filepath' => [
|
||||
'',
|
||||
false,
|
||||
1,
|
||||
0,
|
||||
'text',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,6 +188,38 @@ class SeeTest extends TestCase
|
||||
$this->assertSame($description, $fixture->getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\See::<public>
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory
|
||||
* @uses \phpDocumentor\Reflection\FqsenResolver
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Description
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen
|
||||
* @uses \phpDocumentor\Reflection\Fqsen
|
||||
* @uses \phpDocumentor\Reflection\Types\Context
|
||||
*
|
||||
* @covers ::create
|
||||
*/
|
||||
public function testFactoryMethodWithNonClassFQSEN() : void
|
||||
{
|
||||
$descriptionFactory = m::mock(DescriptionFactory::class);
|
||||
$resolver = m::mock(FqsenResolver::class);
|
||||
$context = new Context('');
|
||||
|
||||
$fqsen = new Fqsen('\DateTime');
|
||||
$description = new Description('My Description');
|
||||
|
||||
$descriptionFactory
|
||||
->shouldReceive('create')->with('My Description', $context)->andReturn($description);
|
||||
$resolver->shouldReceive('resolve')->with('DateTime', $context)->andReturn($fqsen);
|
||||
|
||||
$fixture = See::create('DateTime::createFromFormat() My Description', $resolver, $descriptionFactory, $context);
|
||||
|
||||
$this->assertSame('\DateTime::createFromFormat() My Description', (string) $fixture);
|
||||
$this->assertInstanceOf(FqsenRef::class, $fixture->getReference());
|
||||
$this->assertSame('\DateTime::createFromFormat()', (string) $fixture->getReference());
|
||||
$this->assertSame($description, $fixture->getDescription());
|
||||
}
|
||||
|
||||
/**
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\See::<public>
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory
|
||||
|
||||
Reference in New Issue
Block a user