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:
Lars Moelleken
2020-09-03 00:41:27 +02:00
10 changed files with 290 additions and 42 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ psalm:
.PHONY: test .PHONY: test
test: test:
docker run -it --rm -v${CURDIR}:/github/workspace phpdoc/phpunit-ga 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 .PHONY: pre-commit-test
pre-commit-test: test phpcs phpstan psalm pre-commit-test: test phpcs phpstan psalm
Generated
-14
View File
@@ -160,20 +160,6 @@
"polyfill", "polyfill",
"portable" "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" "time": "2020-06-06T08:46:27+00:00"
}, },
{ {
+16 -1
View File
@@ -20,6 +20,8 @@ use phpDocumentor\Reflection\FqsenResolver;
use phpDocumentor\Reflection\Types\Context as TypeContext; use phpDocumentor\Reflection\Types\Context as TypeContext;
use phpDocumentor\Reflection\Utils; use phpDocumentor\Reflection\Utils;
use Webmozart\Assert\Assert; use Webmozart\Assert\Assert;
use function array_key_exists;
use function explode;
/** /**
* Reflection class for a @covers tag in a Docblock. * 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); $parts = Utils::pregSplit('/\s+/Su', $body, 2);
return new static( return new static(
$resolver->resolve($parts[0], $context), self::resolveFqsen($parts[0], $resolver, $context),
$descriptionFactory->create($parts[1] ?? '', $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. * Returns the structural element this tag refers to.
*/ */
+3 -3
View File
@@ -48,7 +48,7 @@ final class Example implements Tag, Factory\StaticMethod
public function __construct(string $filePath, bool $isURI, int $startingLine, int $lineCount, ?string $content) public function __construct(string $filePath, bool $isURI, int $startingLine, int $lineCount, ?string $content)
{ {
Assert::notEmpty($filePath); Assert::notEmpty($filePath);
Assert::greaterThanEq($startingLine, 0); Assert::greaterThanEq($startingLine, 1);
Assert::greaterThanEq($lineCount, 0); Assert::greaterThanEq($lineCount, 0);
$this->filePath = $filePath; $this->filePath = $filePath;
@@ -63,7 +63,7 @@ final class Example implements Tag, Factory\StaticMethod
public function getContent() : string public function getContent() : string
{ {
if ($this->content === null) { if ($this->content === null || $this->content === '') {
$filePath = '"' . $this->filePath . '"'; $filePath = '"' . $this->filePath . '"';
if ($this->isURI) { if ($this->isURI) {
$filePath = $this->isUriRelative($this->filePath) $filePath = $this->isUriRelative($this->filePath)
@@ -107,7 +107,7 @@ final class Example implements Tag, Factory\StaticMethod
// Starting line / Number of lines / Description // Starting line / Number of lines / Description
if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) { if (preg_match('/^([1-9]\d*)(?:\s+((?1))\s*)?(.*)$/sux', $matches[3], $contentMatches)) {
$startingLine = (int) $contentMatches[1]; $startingLine = (int) $contentMatches[1];
if (isset($contentMatches[2]) && $contentMatches[2] !== '') { if (isset($contentMatches[2])) {
$lineCount = (int) $contentMatches[2]; $lineCount = (int) $contentMatches[2];
} }
+17 -2
View File
@@ -18,10 +18,13 @@ use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef; use phpDocumentor\Reflection\DocBlock\Tags\Reference\Fqsen as FqsenRef;
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference; use phpDocumentor\Reflection\DocBlock\Tags\Reference\Reference;
use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url; use phpDocumentor\Reflection\DocBlock\Tags\Reference\Url;
use phpDocumentor\Reflection\Fqsen;
use phpDocumentor\Reflection\FqsenResolver; use phpDocumentor\Reflection\FqsenResolver;
use phpDocumentor\Reflection\Types\Context as TypeContext; use phpDocumentor\Reflection\Types\Context as TypeContext;
use phpDocumentor\Reflection\Utils; use phpDocumentor\Reflection\Utils;
use Webmozart\Assert\Assert; use Webmozart\Assert\Assert;
use function array_key_exists;
use function explode;
use function preg_match; use function preg_match;
/** /**
@@ -50,7 +53,6 @@ final class See extends BaseTag implements Factory\StaticMethod
?DescriptionFactory $descriptionFactory = null, ?DescriptionFactory $descriptionFactory = null,
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory); Assert::notNull($descriptionFactory);
$parts = Utils::pregSplit('/\s+/Su', $body, 2); $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 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]);
} }
/** /**
+16 -1
View File
@@ -20,6 +20,8 @@ use phpDocumentor\Reflection\FqsenResolver;
use phpDocumentor\Reflection\Types\Context as TypeContext; use phpDocumentor\Reflection\Types\Context as TypeContext;
use phpDocumentor\Reflection\Utils; use phpDocumentor\Reflection\Utils;
use Webmozart\Assert\Assert; use Webmozart\Assert\Assert;
use function array_key_exists;
use function explode;
/** /**
* Reflection class for a {@}uses tag in a Docblock. * 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); $parts = Utils::pregSplit('/\s+/Su', $body, 2);
return new static( return new static(
$resolver->resolve($parts[0], $context), self::resolveFqsen($parts[0], $resolver, $context),
$descriptionFactory->create($parts[1] ?? '', $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. * 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());
}
}
+31 -5
View File
@@ -150,14 +150,40 @@ class AuthorTest extends TestCase
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Author::<public> * @uses \phpDocumentor\Reflection\DocBlock\Tags\Author::<public>
* *
* @covers ::create * @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($output, (string) $fixture);
$this->assertSame('Mike van Riel', $fixture->getAuthorName()); $this->assertSame($name, $fixture->getAuthorName());
$this->assertSame('[email protected]', $fixture->getEmail()); $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',
'',
],
];
} }
/** /**
+136 -15
View File
@@ -4,23 +4,16 @@ declare(strict_types=1);
namespace DocBlock\Tags; namespace DocBlock\Tags;
use Mockery as m; use InvalidArgumentException;
use phpDocumentor\Reflection\DocBlock\Tags\Example; use phpDocumentor\Reflection\DocBlock\Tags\Example;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
/** /**
* @coversDefaultClass \phpDocumentor\Reflection\DocBlock\Tags\Example * @coversDefaultClass \phpDocumentor\Reflection\DocBlock\Tags\Example
* @covers ::<private>
*/ */
class ExampleTest extends TestCase class ExampleTest extends TestCase
{ {
/**
* Call Mockery::close after each test.
*/
public function tearDown() : void
{
m::close();
}
/** /**
* @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
* *
@@ -103,19 +96,147 @@ class ExampleTest extends TestCase
/** /**
* @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag * @uses \phpDocumentor\Reflection\DocBlock\Tags\BaseTag
* *
* @dataProvider tagContentProvider
* @covers ::create * @covers ::create
* @covers ::__construct * @covers ::__construct
* @covers ::getFilePath * @covers ::getFilePath
* @covers ::getStartingLine * @covers ::getStartingLine
* @covers ::getLineCount * @covers ::getLineCount
* @covers ::getDescription * @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'); return [
$this->assertEquals('example1.php', $tag->getFilePath()); [
$this->assertEquals(10, $tag->getStartingLine()); '"example1.php" 10 5 test text ',
$this->assertEquals(5, $tag->getLineCount()); 'example1.php',
$this->assertEquals('test text', $tag->getDescription()); 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',
],
];
} }
} }
+32
View File
@@ -188,6 +188,38 @@ class SeeTest extends TestCase
$this->assertSame($description, $fixture->getDescription()); $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\Tags\See::<public>
* @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory * @uses \phpDocumentor\Reflection\DocBlock\DescriptionFactory