mirror of
https://github.com/barryvdh/ReflectionDocBlock.git
synced 2026-08-17 17:47:13 +00:00
Merge pull request #431 from phpDocumentor/phpstan-improvements
More phpstan checks for better code
This commit is contained in:
+2
-1
@@ -29,7 +29,8 @@
|
||||
"phpstan/phpstan-mockery": "^1.1",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan-webmozart-assert": "^1.2",
|
||||
"psalm/phar": "^5.26"
|
||||
"psalm/phar": "^5.26",
|
||||
"shipmonk/dead-code-detector": "^0.5.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
|
||||
Generated
+70
-1
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "69aa0af5bad8d21df103f96a6e42e6dc",
|
||||
"content-hash": "2af32665428eb750a10f182d03577049",
|
||||
"packages": [
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
@@ -2391,6 +2391,75 @@
|
||||
],
|
||||
"time": "2020-09-28T06:39:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "shipmonk/dead-code-detector",
|
||||
"version": "0.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/shipmonk-rnd/dead-code-detector.git",
|
||||
"reference": "bcfa0a0ca5c2610422a141d6430727738dbcda36"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/shipmonk-rnd/dead-code-detector/zipball/bcfa0a0ca5c2610422a141d6430727738dbcda36",
|
||||
"reference": "bcfa0a0ca5c2610422a141d6430727738dbcda36",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"phpstan/phpstan": "^1.11.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/orm": "^2.19 || ^3.0",
|
||||
"editorconfig-checker/editorconfig-checker": "^10.3.0",
|
||||
"ergebnis/composer-normalize": "^2.28",
|
||||
"nette/application": "^3.1",
|
||||
"nette/component-model": "^3.0",
|
||||
"nette/utils": "^3.0 || ^4.0",
|
||||
"nikic/php-parser": "^4.19",
|
||||
"phpstan/phpstan-phpunit": "^1.1.1",
|
||||
"phpstan/phpstan-strict-rules": "^1.2.3",
|
||||
"phpstan/phpstan-symfony": "^1.4",
|
||||
"phpunit/phpunit": "^9.5.20",
|
||||
"shipmonk/composer-dependency-analyser": "^1.6",
|
||||
"shipmonk/name-collision-detector": "^2.0.0",
|
||||
"shipmonk/phpstan-rules": "^3.1",
|
||||
"slevomat/coding-standard": "^8.15.0",
|
||||
"symfony/contracts": "^2.5 || ^3.0",
|
||||
"symfony/event-dispatcher": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/http-kernel": "^5.4 || ^6.0 || ^7.0",
|
||||
"symfony/routing": "^5.4 || ^6.0 || ^7.0"
|
||||
},
|
||||
"type": "phpstan-extension",
|
||||
"extra": {
|
||||
"phpstan": {
|
||||
"includes": [
|
||||
"rules.neon"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ShipMonk\\PHPStan\\DeadCode\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Dead code detector to find unused PHP code via PHPStan extension.",
|
||||
"keywords": [
|
||||
"PHPStan",
|
||||
"dead code",
|
||||
"static analysis",
|
||||
"unused code"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/shipmonk-rnd/dead-code-detector/issues",
|
||||
"source": "https://github.com/shipmonk-rnd/dead-code-detector/tree/0.5.1"
|
||||
},
|
||||
"time": "2024-11-05T09:28:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
"version": "1.3.1",
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
parameters:
|
||||
ignoreErrors:
|
||||
-
|
||||
message: "#^Unused phpDocumentor\\\\Reflection\\\\DocBlock\\\\ExampleFinder\\:\\:getExampleDirectories$#"
|
||||
count: 1
|
||||
path: src/DocBlock/ExampleFinder.php
|
||||
|
||||
-
|
||||
message: "#^Unused phpDocumentor\\\\Reflection\\\\DocBlock\\\\ExampleFinder\\:\\:setExampleDirectories$#"
|
||||
count: 1
|
||||
path: src/DocBlock/ExampleFinder.php
|
||||
|
||||
-
|
||||
message: "#^Unused phpDocumentor\\\\Reflection\\\\DocBlock\\\\ExampleFinder\\:\\:setSourceDirectory$#"
|
||||
count: 1
|
||||
path: src/DocBlock/ExampleFinder.php
|
||||
|
||||
-
|
||||
message: "#^Unused phpDocumentor\\\\Reflection\\\\DocBlock\\\\Tags\\\\Factory\\\\MethodParameterFactory\\:\\:formatNull$#"
|
||||
count: 1
|
||||
path: src/DocBlock/Tags/Factory/MethodParameterFactory.php
|
||||
@@ -1,7 +1,17 @@
|
||||
includes:
|
||||
- phpstan-baseline.neon
|
||||
|
||||
parameters:
|
||||
level: max
|
||||
ignoreErrors:
|
||||
- '#Method phpDocumentor\\Reflection\\DocBlock\\StandardTagFactory::createTag\(\) should return phpDocumentor\\Reflection\\DocBlock\\Tag but returns mixed#'
|
||||
- '#Offset 2 on array\{string, 28, int\} on left side of \?\? always exists and is not nullable\.#'
|
||||
-
|
||||
path: src/DocBlockFactoryInterface.php
|
||||
identifier: shipmonk.deadMethod
|
||||
-
|
||||
path: src/DocBlock/TagFactory.php
|
||||
identifier: shipmonk.deadMethod
|
||||
paths:
|
||||
- src
|
||||
- tests/unit
|
||||
|
||||
+22
-37
@@ -1,39 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<phpunit
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/8.0/phpunit.xsd"
|
||||
colors="true"
|
||||
convertDeprecationsToExceptions="false"
|
||||
beStrictAboutOutputDuringTests="false"
|
||||
forceCoversAnnotation="true"
|
||||
verbose="true"
|
||||
bootstrap="vendor/autoload.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="unit">
|
||||
<directory>./tests/unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="integration">
|
||||
<directory>./tests/integration</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<filter>
|
||||
<whitelist>
|
||||
<directory suffix=".php">./src/</directory>
|
||||
</whitelist>
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-html"
|
||||
target="build/coverage"
|
||||
lowUpperBound="35"
|
||||
highLowerBound="70"/>
|
||||
<log type="coverage-clover" target="build/logs/clover.xml"/>
|
||||
</logging>
|
||||
<listeners>
|
||||
<listener
|
||||
class="Mockery\Adapter\Phpunit\TestListener"
|
||||
file="vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php"
|
||||
/>
|
||||
</listeners>
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd" colors="true" convertDeprecationsToExceptions="false" beStrictAboutOutputDuringTests="false" forceCoversAnnotation="true" verbose="true" bootstrap="vendor/autoload.php">
|
||||
<coverage>
|
||||
<include>
|
||||
<directory suffix=".php">./src/</directory>
|
||||
</include>
|
||||
<report>
|
||||
<clover outputFile="build/logs/clover.xml"/>
|
||||
<html outputDirectory="build/coverage" lowUpperBound="35" highLowerBound="70"/>
|
||||
</report>
|
||||
</coverage>
|
||||
<testsuites>
|
||||
<testsuite name="unit">
|
||||
<directory>./tests/unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="integration">
|
||||
<directory>./tests/integration</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
<logging/>
|
||||
<listeners>
|
||||
<listener class="Mockery\Adapter\Phpunit\TestListener" file="vendor/mockery/mockery/library/Mockery/Adapter/Phpunit/TestListener.php"/>
|
||||
</listeners>
|
||||
</phpunit>
|
||||
|
||||
@@ -22,14 +22,14 @@ use phpDocumentor\Reflection\DocBlock\Tags\Factory\ExtendsFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\Factory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\ImplementsFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\MethodFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\MixinFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\ParamFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\PropertyFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\PropertyReadFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\PropertyWriteFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\ReturnFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateExtendsFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateCovariantFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateImplementsFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\ThrowsFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\VarFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Generic;
|
||||
@@ -151,11 +151,11 @@ final class StandardTagFactory implements TagFactory
|
||||
new PropertyReadFactory($typeResolver, $descriptionFactory),
|
||||
new PropertyWriteFactory($typeResolver, $descriptionFactory),
|
||||
new MethodFactory($typeResolver, $descriptionFactory),
|
||||
new MixinFactory($typeResolver, $descriptionFactory),
|
||||
new ImplementsFactory($typeResolver, $descriptionFactory),
|
||||
new ExtendsFactory($typeResolver, $descriptionFactory),
|
||||
new TemplateFactory($typeResolver, $descriptionFactory),
|
||||
new TemplateImplementsFactory($typeResolver, $descriptionFactory),
|
||||
new TemplateExtendsFactory($typeResolver, $descriptionFactory),
|
||||
new TemplateCovariantFactory($typeResolver, $descriptionFactory),
|
||||
new ThrowsFactory($typeResolver, $descriptionFactory),
|
||||
);
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
|
||||
use phpDocumentor\Reflection\Types\Context as TypeContext;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use PHPStan\PhpDocParser\Parser\ConstExprParser;
|
||||
use PHPStan\PhpDocParser\Parser\ParserException;
|
||||
use PHPStan\PhpDocParser\Parser\PhpDocParser;
|
||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||
use PHPStan\PhpDocParser\Parser\TypeParser;
|
||||
@@ -59,13 +60,17 @@ class AbstractPHPStanFactory implements Factory
|
||||
|
||||
public function create(string $tagLine, ?TypeContext $context = null): Tag
|
||||
{
|
||||
$tokens = $this->tokenizeLine($tagLine . "\n");
|
||||
$ast = $this->parser->parseTag($tokens);
|
||||
if (property_exists($ast->value, 'description') === true) {
|
||||
$ast->value->setAttribute(
|
||||
'description',
|
||||
rtrim($ast->value->description . $tokens->joinUntil(Lexer::TOKEN_END), "\n")
|
||||
);
|
||||
try {
|
||||
$tokens = $this->tokenizeLine($tagLine . "\n");
|
||||
$ast = $this->parser->parseTag($tokens);
|
||||
if (property_exists($ast->value, 'description') === true) {
|
||||
$ast->value->setAttribute(
|
||||
'description',
|
||||
rtrim($ast->value->description . $tokens->joinUntil(Lexer::TOKEN_END), "\n")
|
||||
);
|
||||
}
|
||||
} catch (ParserException $e) {
|
||||
return InvalidTag::create($tagLine, '')->withError($e);
|
||||
}
|
||||
|
||||
if ($context === null) {
|
||||
@@ -80,6 +85,8 @@ class AbstractPHPStanFactory implements Factory
|
||||
}
|
||||
} catch (RuntimeException $e) {
|
||||
return InvalidTag::create((string) $ast->value, 'method')->withError($e);
|
||||
} catch (ParserException $e) {
|
||||
return InvalidTag::create((string) $ast->value, $ast->name)->withError($e);
|
||||
}
|
||||
|
||||
return InvalidTag::create(
|
||||
|
||||
@@ -34,7 +34,7 @@ final class MethodParameterFactory
|
||||
{
|
||||
$method = 'format' . ucfirst(gettype($defaultValue));
|
||||
if (method_exists($this, $method)) {
|
||||
return ' = ' . $this->{$method}($defaultValue);
|
||||
return $this->{$method}($defaultValue);
|
||||
}
|
||||
|
||||
return '';
|
||||
|
||||
+8
-7
@@ -6,11 +6,12 @@ namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\TemplateExtends;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\TemplateCovariant;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ExtendsTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
use function is_string;
|
||||
@@ -18,7 +19,7 @@ use function is_string;
|
||||
/**
|
||||
* @internal This class is not part of the BC promise of this library.
|
||||
*/
|
||||
final class TemplateExtendsFactory implements PHPStanFactory
|
||||
final class TemplateCovariantFactory implements PHPStanFactory
|
||||
{
|
||||
private DescriptionFactory $descriptionFactory;
|
||||
private TypeResolver $typeResolver;
|
||||
@@ -31,21 +32,21 @@ final class TemplateExtendsFactory implements PHPStanFactory
|
||||
|
||||
public function supports(PhpDocTagNode $node, Context $context): bool
|
||||
{
|
||||
return $node->value instanceof ExtendsTagValueNode && $node->name === '@template-extends';
|
||||
return $node->value instanceof TemplateTagValueNode && $node->name === '@template-covariant';
|
||||
}
|
||||
|
||||
public function create(PhpDocTagNode $node, Context $context): Tag
|
||||
{
|
||||
$tagValue = $node->value;
|
||||
Assert::isInstanceOf($tagValue, ExtendsTagValueNode::class);
|
||||
Assert::isInstanceOf($tagValue, TemplateTagValueNode::class);
|
||||
|
||||
$description = $tagValue->getAttribute('description');
|
||||
if (is_string($description) === false) {
|
||||
$description = $tagValue->description;
|
||||
}
|
||||
|
||||
return new TemplateExtends(
|
||||
$this->typeResolver->createType($tagValue->type, $context),
|
||||
return new TemplateCovariant(
|
||||
$this->typeResolver->createType(new IdentifierTypeNode($tagValue->name), $context),
|
||||
$this->descriptionFactory->create($description, $context)
|
||||
);
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\DescriptionFactory;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\TemplateImplements;
|
||||
use phpDocumentor\Reflection\TypeResolver;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\ImplementsTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
use function is_string;
|
||||
|
||||
/**
|
||||
* @internal This class is not part of the BC promise of this library.
|
||||
*/
|
||||
final class TemplateImplementsFactory implements PHPStanFactory
|
||||
{
|
||||
private DescriptionFactory $descriptionFactory;
|
||||
private TypeResolver $typeResolver;
|
||||
|
||||
public function __construct(TypeResolver $typeResolver, DescriptionFactory $descriptionFactory)
|
||||
{
|
||||
$this->descriptionFactory = $descriptionFactory;
|
||||
$this->typeResolver = $typeResolver;
|
||||
}
|
||||
|
||||
public function supports(PhpDocTagNode $node, Context $context): bool
|
||||
{
|
||||
return $node->value instanceof ImplementsTagValueNode && $node->name === '@template-implements';
|
||||
}
|
||||
|
||||
public function create(PhpDocTagNode $node, Context $context): Tag
|
||||
{
|
||||
$tagValue = $node->value;
|
||||
Assert::isInstanceOf($tagValue, ImplementsTagValueNode::class);
|
||||
|
||||
$description = $tagValue->getAttribute('description');
|
||||
if (is_string($description) === false) {
|
||||
$description = $tagValue->description;
|
||||
}
|
||||
|
||||
return new TemplateImplements(
|
||||
$this->typeResolver->createType($tagValue->type, $context),
|
||||
$this->descriptionFactory->create($description, $context)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ final class MethodParameter
|
||||
'$' . $this->getName() .
|
||||
(
|
||||
$this->defaultValue !== self::NO_DEFAULT_VALUE ?
|
||||
(new MethodParameterFactory())->format($this->defaultValue) :
|
||||
' = ' . (new MethodParameterFactory())->format($this->defaultValue) :
|
||||
''
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,17 +13,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\Exception\CannotCreateTag;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
|
||||
use function in_array;
|
||||
use function sprintf;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
use function trim;
|
||||
|
||||
abstract class TagWithType extends BaseTag
|
||||
{
|
||||
/** @var ?Type */
|
||||
@@ -42,43 +35,6 @@ abstract class TagWithType extends BaseTag
|
||||
throw new CannotCreateTag('Typed tag cannot be created');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
protected static function extractTypeFromBody(string $body): array
|
||||
{
|
||||
$type = '';
|
||||
$nestingLevel = 0;
|
||||
for ($i = 0, $iMax = strlen($body); $i < $iMax; $i++) {
|
||||
$character = $body[$i];
|
||||
|
||||
if ($nestingLevel === 0 && trim($character) === '') {
|
||||
break;
|
||||
}
|
||||
|
||||
$type .= $character;
|
||||
if (in_array($character, ['<', '(', '[', '{'])) {
|
||||
$nestingLevel++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (in_array($character, ['>', ')', ']', '}'])) {
|
||||
$nestingLevel--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ($nestingLevel < 0 || $nestingLevel > 0) {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('Could not find type in %s, please check for malformed notations', $body)
|
||||
);
|
||||
}
|
||||
|
||||
$description = trim(substr($body, strlen($type)));
|
||||
|
||||
return [$type, $description];
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
if ($this->description) {
|
||||
|
||||
@@ -13,9 +13,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags;
|
||||
|
||||
use Doctrine\Deprecations\Deprecation;
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\Exception\CannotCreateTag;
|
||||
use phpDocumentor\Reflection\Type;
|
||||
|
||||
/**
|
||||
@@ -51,14 +51,7 @@ final class Template extends BaseTag
|
||||
*/
|
||||
public static function create(string $body): ?Tag
|
||||
{
|
||||
Deprecation::trigger(
|
||||
'phpdocumentor/reflection-docblock',
|
||||
'https://github.com/phpDocumentor/ReflectionDocBlock/issues/361',
|
||||
'Create using static factory is deprecated, this method should not be called directly
|
||||
by library consumers',
|
||||
);
|
||||
|
||||
return null;
|
||||
throw new CannotCreateTag('Template tag cannot be created');
|
||||
}
|
||||
|
||||
public function getTemplateName(): string
|
||||
|
||||
@@ -10,7 +10,10 @@ use phpDocumentor\Reflection\FqsenResolver;
|
||||
|
||||
final class CustomParam implements Tag
|
||||
{
|
||||
/** @var string|null */
|
||||
public $myParam;
|
||||
|
||||
/** @var FqsenResolver|null */
|
||||
public $fqsenResolver;
|
||||
|
||||
public function getName() : string
|
||||
@@ -18,7 +21,7 @@ final class CustomParam implements Tag
|
||||
return 'spy';
|
||||
}
|
||||
|
||||
public static function create($body, FqsenResolver $fqsenResolver = null, ?string $myParam = null)
|
||||
public static function create(string $body, FqsenResolver $fqsenResolver = null, ?string $myParam = null)
|
||||
{
|
||||
$tag = new self();
|
||||
$tag->fqsenResolver = $fqsenResolver;
|
||||
|
||||
@@ -7,11 +7,10 @@ namespace phpDocumentor\Reflection\Assets;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Formatter;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Formatter\PassthroughFormatter;
|
||||
use phpDocumentor\Reflection\FqsenResolver;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod;
|
||||
|
||||
final class CustomServiceClass implements Tag
|
||||
{
|
||||
/** @var Formatter|null */
|
||||
public $formatter;
|
||||
|
||||
public function getName() : string
|
||||
@@ -19,7 +18,7 @@ final class CustomServiceClass implements Tag
|
||||
return 'spy';
|
||||
}
|
||||
|
||||
public static function create($body, PassthroughFormatter $formatter = null)
|
||||
public static function create(string $body, PassthroughFormatter $formatter = null)
|
||||
{
|
||||
$tag = new self();
|
||||
$tag->formatter = $formatter;
|
||||
|
||||
@@ -11,6 +11,7 @@ use phpDocumentor\Reflection\DocBlock\Tags\Factory\StaticMethod;
|
||||
|
||||
final class CustomServiceInterface implements Tag
|
||||
{
|
||||
/** @var Formatter|null */
|
||||
public $formatter;
|
||||
|
||||
public function getName() : string
|
||||
@@ -18,7 +19,7 @@ final class CustomServiceInterface implements Tag
|
||||
return 'spy';
|
||||
}
|
||||
|
||||
public static function create($body, Formatter $formatter = null)
|
||||
public static function create(string $body, Formatter $formatter = null)
|
||||
{
|
||||
$tag = new self();
|
||||
$tag->formatter = $formatter;
|
||||
|
||||
@@ -20,6 +20,7 @@ use phpDocumentor\Reflection\Types\Context;
|
||||
|
||||
class CustomTagFactory implements Factory
|
||||
{
|
||||
/** @var CustomServiceClass|null */
|
||||
public $class;
|
||||
|
||||
public function create(string $tagLine, ?Context $context = null, CustomServiceClass $class = null): Tag
|
||||
|
||||
@@ -13,7 +13,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock;
|
||||
|
||||
use Exception;
|
||||
use Mockery as m;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Link as LinkTag;
|
||||
@@ -216,7 +215,7 @@ DESCRIPTION;
|
||||
$tagFactory->shouldReceive('create')
|
||||
->once()
|
||||
->with('@see $name', $context)
|
||||
->andReturn(InvalidTag::create('$name', 'see', new Exception()));
|
||||
->andReturn(InvalidTag::create('$name', 'see'));
|
||||
|
||||
$factory = new DescriptionFactory($tagFactory);
|
||||
$description = $factory->create($contents, $context);
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace phpDocumentor\Reflection\DocBlock;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Mockery as m;
|
||||
use Name\Spaced\Tag;
|
||||
use phpDocumentor\Reflection\Assets\CustomParam;
|
||||
use phpDocumentor\Reflection\Assets\CustomServiceClass;
|
||||
use phpDocumentor\Reflection\Assets\CustomServiceInterface;
|
||||
@@ -134,10 +135,10 @@ class StandardTagFactoryTest extends TestCase
|
||||
public function testAnEmptyContextIsCreatedIfNoneIsProvided(): void
|
||||
{
|
||||
$fqsen = '\Tag';
|
||||
$resolver = m::mock(FqsenResolver::class)
|
||||
->shouldReceive('resolve')
|
||||
$resolver = m::mock(FqsenResolver::class);
|
||||
$resolver->allows('resolve')
|
||||
->with('Tag', m::type(Context::class))
|
||||
->andReturn(new Fqsen($fqsen))
|
||||
->andReturns(new Fqsen($fqsen))
|
||||
->getMock();
|
||||
$descriptionFactory = m::mock(DescriptionFactory::class);
|
||||
$descriptionFactory->shouldIgnoreMissing();
|
||||
@@ -246,18 +247,14 @@ class StandardTagFactoryTest extends TestCase
|
||||
'The tag "@my-täg " does not seem to be wellformed, please check it for errors'
|
||||
);
|
||||
|
||||
$typeResolver = new TypeResolver();
|
||||
$fqsenResolver = new FqsenResolver();
|
||||
$tagFactory = StandardTagFactory::createInstance($fqsenResolver);
|
||||
$descriptionFactory = new DescriptionFactory($tagFactory);
|
||||
$context = new Context('');
|
||||
|
||||
$tagFactory = StandardTagFactory::createInstance(
|
||||
$fqsenResolver,
|
||||
['my-täg' => Author::class]
|
||||
);
|
||||
|
||||
$tag = $tagFactory->create('@my-täg ', $context);
|
||||
$tagFactory->create('@my-täg ', $context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -291,6 +288,7 @@ class StandardTagFactoryTest extends TestCase
|
||||
$tagFactory->addParameter('myParam', 'myValue');
|
||||
$spy = $tagFactory->create('@spy');
|
||||
|
||||
self::assertInstanceOf(CustomParam::class, $spy);
|
||||
$this->assertSame($resolver, $spy->fqsenResolver);
|
||||
$this->assertSame('myValue', $spy->myParam);
|
||||
}
|
||||
@@ -311,6 +309,7 @@ class StandardTagFactoryTest extends TestCase
|
||||
|
||||
$spy = $tagFactory->create('@spy');
|
||||
|
||||
self::assertInstanceOf(CustomServiceClass::class, $spy);
|
||||
$this->assertSame($service, $spy->formatter);
|
||||
}
|
||||
|
||||
@@ -331,6 +330,7 @@ class StandardTagFactoryTest extends TestCase
|
||||
|
||||
$spy = $tagFactory->create('@spy');
|
||||
|
||||
self::assertInstanceOf(CustomServiceInterface::class, $spy);
|
||||
$this->assertSame($service, $spy->formatter);
|
||||
}
|
||||
|
||||
@@ -366,7 +366,10 @@ class StandardTagFactoryTest extends TestCase
|
||||
$resolver = m::mock(FqsenResolver::class);
|
||||
$tagFactory = StandardTagFactory::createInstance($resolver);
|
||||
// phpcs:ignore SlevomatCodingStandard.Namespaces.ReferenceUsedNamesOnly.ReferenceViaFullyQualifiedName
|
||||
$tagFactory->registerTagHandler(\Name\Spaced\Tag::class, Author::class);
|
||||
$tagFactory->registerTagHandler(
|
||||
Tag::class, // @phpstan-ignore class.notFound
|
||||
Author::class
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,6 +383,7 @@ class StandardTagFactoryTest extends TestCase
|
||||
$this->expectException('InvalidArgumentException');
|
||||
$resolver = m::mock(FqsenResolver::class);
|
||||
$tagFactory = StandardTagFactory::createInstance($resolver);
|
||||
//@phpstan-ignore argument.type
|
||||
$tagFactory->registerTagHandler('my-tag', '');
|
||||
}
|
||||
|
||||
@@ -394,6 +398,8 @@ class StandardTagFactoryTest extends TestCase
|
||||
$this->expectException('InvalidArgumentException');
|
||||
$resolver = m::mock(FqsenResolver::class);
|
||||
$tagFactory = StandardTagFactory::createInstance($resolver);
|
||||
|
||||
//@phpstan-ignore argument.type
|
||||
$tagFactory->registerTagHandler('my-tag', 'IDoNotExist');
|
||||
}
|
||||
|
||||
@@ -408,6 +414,8 @@ class StandardTagFactoryTest extends TestCase
|
||||
$this->expectException('InvalidArgumentException');
|
||||
$resolver = m::mock(FqsenResolver::class);
|
||||
$tagFactory = StandardTagFactory::createInstance($resolver);
|
||||
|
||||
//@phpstan-ignore argument.type
|
||||
$tagFactory->registerTagHandler('my-tag', 'stdClass');
|
||||
}
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ class AuthorTest extends TestCase
|
||||
|
||||
$fixture = new Author($expected, '[email protected]');
|
||||
|
||||
self::assertInstanceOf(Author::class, $fixture);
|
||||
$this->assertSame($expected, $fixture->getAuthorName());
|
||||
}
|
||||
|
||||
@@ -95,6 +96,7 @@ class AuthorTest extends TestCase
|
||||
|
||||
$fixture = new Author('Mike van Riel', $expected);
|
||||
|
||||
self::assertInstanceOf(Author::class, $fixture);
|
||||
$this->assertSame($expected, $fixture->getEmail());
|
||||
}
|
||||
|
||||
@@ -156,6 +158,7 @@ class AuthorTest extends TestCase
|
||||
{
|
||||
$fixture = Author::create($input);
|
||||
|
||||
self::assertInstanceOf(Author::class, $fixture);
|
||||
$this->assertSame($output, (string) $fixture);
|
||||
$this->assertSame($name, $fixture->getAuthorName());
|
||||
$this->assertSame($email, $fixture->getEmail());
|
||||
|
||||
@@ -23,6 +23,7 @@ class ExampleTest extends TestCase
|
||||
public function testExampleWithoutContent(): void
|
||||
{
|
||||
$tag = Example::create('"example1.php"');
|
||||
self::assertInstanceOf(Example::class, $tag);
|
||||
$this->assertEquals('"example1.php"', $tag->getContent());
|
||||
$this->assertEquals('', $tag->getDescription());
|
||||
$this->assertEquals('example', $tag->getName());
|
||||
@@ -39,6 +40,7 @@ class ExampleTest extends TestCase
|
||||
public function testWithDescription(): void
|
||||
{
|
||||
$tag = Example::create('"example1.php" some text');
|
||||
self::assertInstanceOf(Example::class, $tag);
|
||||
$this->assertEquals('example1.php', $tag->getFilePath());
|
||||
$this->assertEquals('some text', $tag->getDescription());
|
||||
}
|
||||
@@ -54,6 +56,7 @@ class ExampleTest extends TestCase
|
||||
public function testStartlineIsParsed(): void
|
||||
{
|
||||
$tag = Example::create('"example1.php" 10');
|
||||
self::assertInstanceOf(Example::class, $tag);
|
||||
$this->assertEquals('example1.php', $tag->getFilePath());
|
||||
$this->assertEquals(10, $tag->getStartingLine());
|
||||
}
|
||||
@@ -70,6 +73,7 @@ class ExampleTest extends TestCase
|
||||
public function testAllowOmittingLineCount(): void
|
||||
{
|
||||
$tag = Example::create('"example1.php" 10 some text');
|
||||
self::assertInstanceOf(Example::class, $tag);
|
||||
$this->assertEquals('example1.php', $tag->getFilePath());
|
||||
$this->assertEquals(10, $tag->getStartingLine());
|
||||
$this->assertEquals('some text', $tag->getDescription());
|
||||
@@ -87,6 +91,7 @@ class ExampleTest extends TestCase
|
||||
public function testLengthIsParsed(): void
|
||||
{
|
||||
$tag = Example::create('"example1.php" 10 5');
|
||||
self::assertInstanceOf(Example::class, $tag);
|
||||
$this->assertEquals('example1.php', $tag->getFilePath());
|
||||
$this->assertEquals(10, $tag->getStartingLine());
|
||||
$this->assertEquals(5, $tag->getLineCount());
|
||||
@@ -159,6 +164,7 @@ class ExampleTest extends TestCase
|
||||
string $content
|
||||
): void {
|
||||
$tag = Example::create($input);
|
||||
self::assertInstanceOf(Example::class, $tag);
|
||||
$this->assertSame($filePath, $tag->getFilePath());
|
||||
$this->assertSame($startLine, $tag->getStartingLine());
|
||||
$this->assertSame($lineCount, $tag->getLineCount());
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use Exception;
|
||||
use Mockery as m;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\InvalidTag;
|
||||
use PHPStan\PhpDocParser\Parser\ParserException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\Factory\AbstractPHPStanFactory
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Tags\InvalidTag
|
||||
*
|
||||
* @coversDefaultClass \phpDocumentor\Reflection\DocBlock\Tags\Factory\AbstractPHPStanFactory
|
||||
* @covers ::<private>
|
||||
*/
|
||||
class AbstractPHPStanFactoryTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Call Mockery::close after each test.
|
||||
*/
|
||||
public function tearDown(): void
|
||||
{
|
||||
m::close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
*/
|
||||
public function testCreateReturnsTagFromSupportingFactory(): void
|
||||
{
|
||||
$tag = m::mock(Tag::class);
|
||||
$factory = m::mock(PHPStanFactory::class);
|
||||
$factory->shouldReceive('supports')->andReturn(true);
|
||||
$factory->shouldReceive('create')->andReturn($tag);
|
||||
|
||||
$sut = new AbstractPHPStanFactory($factory);
|
||||
|
||||
$result = $sut->create('@param string $param');
|
||||
|
||||
self::assertSame($tag, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
*/
|
||||
public function testCreateReturnsInvalidTagWhenNoFactorySupports(): void
|
||||
{
|
||||
$factory = m::mock(PHPStanFactory::class);
|
||||
$factory->shouldReceive('supports')->andReturn(false);
|
||||
|
||||
$sut = new AbstractPHPStanFactory($factory);
|
||||
|
||||
$result = $sut->create('@unknown string $param');
|
||||
|
||||
self::assertInstanceOf(InvalidTag::class, $result);
|
||||
self::assertEquals('@unknown', $result->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
*/
|
||||
public function testCreateReturnsInvalidTagWithErrorOnFactoryRuntimeException(): void
|
||||
{
|
||||
$factory = m::mock(PHPStanFactory::class);
|
||||
$factory->shouldReceive('supports')->andReturn(true);
|
||||
$factory->shouldReceive('create')->andThrow(new RuntimeException('Factory error'));
|
||||
|
||||
$sut = new AbstractPHPStanFactory($factory);
|
||||
|
||||
$result = $sut->create('@param string $param');
|
||||
|
||||
self::assertInstanceOf(InvalidTag::class, $result);
|
||||
self::assertInstanceOf(Exception::class, $result->getException());
|
||||
self::assertEquals('Factory error', $result->getException()->getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
*/
|
||||
public function testCreateReturnsInvalidTagWithErrorOnFactoryParserException(): void
|
||||
{
|
||||
$exception = m::mock(ParserException::class);
|
||||
$exception->shouldReceive('getMessage')->andReturn('Parser error');
|
||||
|
||||
$factory = m::mock(PHPStanFactory::class);
|
||||
$factory->shouldReceive('supports')->andReturn(true);
|
||||
$factory->shouldReceive('create')->andThrow($exception);
|
||||
|
||||
$sut = new AbstractPHPStanFactory($factory);
|
||||
|
||||
$result = $sut->create('@param string $param');
|
||||
|
||||
self::assertInstanceOf(InvalidTag::class, $result);
|
||||
self::assertSame($exception, $result->getException());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Extends_;
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\PseudoTypes\Generic;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\Object_;
|
||||
|
||||
final class ExtendsFactoryTest extends TagFactoryTestCase
|
||||
{
|
||||
/**
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ExtendsFactory::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ExtendsFactory::create
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ExtendsFactory::supports
|
||||
*/
|
||||
public function testExtendsIsCreated(): void
|
||||
{
|
||||
$ast = $this->parseTag('@extends SomeClass<OtherType>');
|
||||
$factory = new ExtendsFactory($this->giveTypeResolver(), $this->givenDescriptionFactory());
|
||||
$context = new Context('global');
|
||||
|
||||
self::assertTrue($factory->supports($ast, $context));
|
||||
self::assertEquals(
|
||||
new Extends_(
|
||||
new Generic(new Fqsen('\\SomeClass'), [new Object_(new Fqsen('\\OtherType'))]),
|
||||
new Description('')
|
||||
),
|
||||
$factory->create($ast, $context)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Implements_;
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\PseudoTypes\Generic;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\Object_;
|
||||
|
||||
final class ImplementsFactoryTest extends TagFactoryTestCase
|
||||
{
|
||||
/**
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ImplementsFactory::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ImplementsFactory::create
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ImplementsFactory::supports
|
||||
*/
|
||||
public function testImplementsIsCreated(): void
|
||||
{
|
||||
$ast = $this->parseTag('@implements SomeClass<OtherType>');
|
||||
$factory = new ImplementsFactory($this->giveTypeResolver(), $this->givenDescriptionFactory());
|
||||
$context = new Context('global');
|
||||
|
||||
self::assertTrue($factory->supports($ast, $context));
|
||||
self::assertEquals(
|
||||
new Implements_(
|
||||
new Generic(new Fqsen('\\SomeClass'), [new Object_(new Fqsen('\\OtherType'))]),
|
||||
new Description('')
|
||||
),
|
||||
$factory->create($ast, $context)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Mixin;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\String_;
|
||||
|
||||
final class MixinFactoryTest extends TagFactoryTestCase
|
||||
{
|
||||
/**
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\MixinFactory::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\MixinFactory::create
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\MixinFactory::supports
|
||||
*/
|
||||
public function testMixinIsCreated(): void
|
||||
{
|
||||
$ast = $this->parseTag('@mixin string');
|
||||
$factory = new MixinFactory($this->giveTypeResolver(), $this->givenDescriptionFactory());
|
||||
$context = new Context('global');
|
||||
|
||||
self::assertTrue($factory->supports($ast, $context));
|
||||
self::assertEquals(
|
||||
new Mixin(
|
||||
new String_(),
|
||||
new Description('')
|
||||
),
|
||||
$factory->create($ast, $context)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ final class ParamFactoryTest extends TagFactoryTestCase
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<array-key, string|Param>
|
||||
* @return array<int, array<int, string|Param|InvalidTag>>
|
||||
*/
|
||||
public function paramInputProvider(): array
|
||||
{
|
||||
|
||||
@@ -27,23 +27,16 @@ use PHPStan\PhpDocParser\Parser\TypeParser;
|
||||
use PHPStan\PhpDocParser\ParserConfig;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use function class_exists;
|
||||
use function property_exists;
|
||||
|
||||
abstract class TagFactoryTestCase extends TestCase
|
||||
{
|
||||
public function parseTag(string $tag): PhpDocTagNode
|
||||
{
|
||||
if (class_exists(ParserConfig::class)) {
|
||||
$config = new ParserConfig([]);
|
||||
$lexer = new Lexer($config);
|
||||
$constParser = new ConstExprParser($config);
|
||||
$phpDocParser = new PhpDocParser($config, new TypeParser($config, $constParser), $constParser);
|
||||
} else {
|
||||
$lexer = new Lexer();
|
||||
$constParser = new ConstExprParser();
|
||||
$phpDocParser = new PhpDocParser(new TypeParser($constParser), $constParser);
|
||||
}
|
||||
$config = new ParserConfig(['indexes' => true, 'lines' => true]);
|
||||
$lexer = new Lexer($config);
|
||||
$constParser = new ConstExprParser($config);
|
||||
$phpDocParser = new PhpDocParser($config, new TypeParser($config, $constParser), $constParser);
|
||||
|
||||
$tagNode = $phpDocParser->parseTag(new TokenIterator($lexer->tokenize($tag)));
|
||||
if (property_exists($tagNode->value, 'description') === true) {
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\TemplateCovariant;
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\Object_;
|
||||
use phpDocumentor\Reflection\Types\String_;
|
||||
|
||||
final class TemplateCovariantFactoryTest extends TagFactoryTestCase
|
||||
{
|
||||
/**
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateCovariantFactory::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateCovariantFactory::create
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateCovariantFactory::supports
|
||||
* @dataProvider templateCovariantInputProvider
|
||||
*/
|
||||
public function testTemplateCovariantIsCreated(string $input, Tag $expected): void
|
||||
{
|
||||
$ast = $this->parseTag($input);
|
||||
$factory = new TemplateCovariantFactory($this->giveTypeResolver(), $this->givenDescriptionFactory());
|
||||
$context = new Context('global');
|
||||
|
||||
self::assertTrue($factory->supports($ast, $context));
|
||||
self::assertEquals(
|
||||
$expected,
|
||||
$factory->create($ast, $context)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, string|TemplateCovariant>>
|
||||
*/
|
||||
public function templateCovariantInputProvider(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'@template-covariant string',
|
||||
new TemplateCovariant(
|
||||
new String_(),
|
||||
new Description('')
|
||||
),
|
||||
],
|
||||
[
|
||||
'@template-covariant SomeClass Description',
|
||||
new TemplateCovariant(
|
||||
new Object_(new Fqsen('\SomeClass')),
|
||||
new Description('Description')
|
||||
),
|
||||
],
|
||||
[
|
||||
'@template-covariant SomeClass',
|
||||
new TemplateCovariant(
|
||||
new Object_(new Fqsen('\SomeClass')),
|
||||
new Description('')
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\Tag;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Template;
|
||||
use phpDocumentor\Reflection\Fqsen;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\Mixed_;
|
||||
use phpDocumentor\Reflection\Types\Object_;
|
||||
|
||||
final class TemplateFactoryTest extends TagFactoryTestCase
|
||||
{
|
||||
/**
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateFactory::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateFactory::create
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\TemplateFactory::supports
|
||||
* @dataProvider templateInputProvider
|
||||
*/
|
||||
public function testTemplateIsCreated(string $input, Tag $expected): void
|
||||
{
|
||||
$ast = $this->parseTag($input);
|
||||
$factory = new TemplateFactory($this->giveTypeResolver(), $this->givenDescriptionFactory());
|
||||
$context = new Context('global');
|
||||
|
||||
self::assertTrue($factory->supports($ast, $context));
|
||||
self::assertEquals(
|
||||
$expected,
|
||||
$factory->create($ast, $context)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, string|Template>>
|
||||
*/
|
||||
public function templateInputProvider(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'@template T',
|
||||
new Template(
|
||||
'T',
|
||||
new Mixed_(),
|
||||
new Mixed_(),
|
||||
new Description('')
|
||||
),
|
||||
],
|
||||
[
|
||||
'@template T of SomeClass Description',
|
||||
new Template(
|
||||
'T',
|
||||
new Object_(new Fqsen('\SomeClass')),
|
||||
new Mixed_(),
|
||||
new Description('Description')
|
||||
),
|
||||
],
|
||||
[
|
||||
'@template T of SomeClass = Default',
|
||||
new Template(
|
||||
'T',
|
||||
new Object_(new Fqsen('\SomeClass')),
|
||||
new Object_(new Fqsen('\Default')),
|
||||
new Description('')
|
||||
),
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* This file is part of phpDocumentor.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*
|
||||
* @link http://phpdoc.org
|
||||
*/
|
||||
|
||||
namespace phpDocumentor\Reflection\DocBlock\Tags\Factory;
|
||||
|
||||
use phpDocumentor\Reflection\DocBlock\Description;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Throws;
|
||||
use phpDocumentor\Reflection\Types\Context;
|
||||
use phpDocumentor\Reflection\Types\String_;
|
||||
|
||||
final class ThrowsFactoryTest extends TagFactoryTestCase
|
||||
{
|
||||
/**
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ThrowsFactory::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ThrowsFactory::create
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Factory\ThrowsFactory::supports
|
||||
*/
|
||||
public function testThrowsIsCreated(): void
|
||||
{
|
||||
$ast = $this->parseTag('@throws string');
|
||||
$factory = new ThrowsFactory($this->giveTypeResolver(), $this->givenDescriptionFactory());
|
||||
$context = new Context('global');
|
||||
|
||||
self::assertTrue($factory->supports($ast, $context));
|
||||
self::assertEquals(
|
||||
new Throws(
|
||||
new String_(),
|
||||
new Description('')
|
||||
),
|
||||
$factory->create($ast, $context)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ use PHPUnit\Framework\TestCase;
|
||||
use Throwable;
|
||||
|
||||
use function fopen;
|
||||
use function is_string;
|
||||
use function serialize;
|
||||
use function unserialize;
|
||||
|
||||
@@ -57,9 +58,12 @@ final class InvalidTagTest extends TestCase
|
||||
self::assertSame('name', $tag->getName());
|
||||
self::assertSame('@name Body', $tag->render());
|
||||
self::assertSame($parentException, $tag->getException());
|
||||
|
||||
self::assertSame($e, $tag->getException()->getPrevious());
|
||||
$trace = $tag->getException()->getPrevious()->getTrace();
|
||||
|
||||
if (isset($trace[0]['args'])) { // Not set by default on 7.4
|
||||
self::assertTrue(is_string($trace[0]['args'][0]));
|
||||
self::assertStringStartsWith('(Closure at', $trace[0]['args'][0]);
|
||||
self::assertStringContainsString(__FILE__, $trace[0]['args'][0]);
|
||||
}
|
||||
@@ -70,7 +74,7 @@ final class InvalidTagTest extends TestCase
|
||||
|
||||
private function throwExceptionFromClosureWithClosureArgument(): void
|
||||
{
|
||||
$function = static function (): void {
|
||||
$function = static function (?callable $foo = null): void {
|
||||
throw new InvalidArgumentException();
|
||||
};
|
||||
|
||||
@@ -87,9 +91,11 @@ final class InvalidTagTest extends TestCase
|
||||
self::assertSame('name', $tag->getName());
|
||||
self::assertSame('@name Body', $tag->render());
|
||||
self::assertSame($parentException, $tag->getException());
|
||||
self::assertSame($e, $tag->getException()->getPrevious());
|
||||
$trace = $tag->getException()->getPrevious()->getTrace();
|
||||
|
||||
if (isset($trace[0]['args'])) { // Not set by default on 7.4
|
||||
self::assertTrue(is_string($trace[0]['args'][0]));
|
||||
self::assertStringStartsWith(
|
||||
'resource(stream)',
|
||||
$trace[0]['args'][0]
|
||||
@@ -102,7 +108,7 @@ final class InvalidTagTest extends TestCase
|
||||
|
||||
private function throwExceptionWithResourceArgument(): void
|
||||
{
|
||||
$function = static function (): void {
|
||||
$function = static function ($file): void {
|
||||
throw new InvalidArgumentException();
|
||||
};
|
||||
|
||||
|
||||
@@ -81,6 +81,10 @@ class MethodParameterTest extends TestCase
|
||||
sprintf('%s $argument = %s', $type, $defaultValueStr),
|
||||
(string) $fixture
|
||||
);
|
||||
$this->assertSame(
|
||||
$defaultValueStr,
|
||||
$fixture->getDefaultValue()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -225,6 +225,19 @@ class MethodTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
* @covers ::getReturnType
|
||||
*/
|
||||
public function testReturnsReference(): void
|
||||
{
|
||||
$expected = new String_();
|
||||
|
||||
$fixture = new Method('myMethod', [], $expected);
|
||||
|
||||
$this->assertFalse($fixture->returnsReference());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::create
|
||||
*/
|
||||
|
||||
@@ -153,4 +153,19 @@ class ParamTest extends TestCase
|
||||
|
||||
$this->assertSame('string ...$myParameter Description', (string) $fixture);
|
||||
}
|
||||
|
||||
/**
|
||||
* @uses \phpDocumentor\Reflection\DocBlock\Description
|
||||
*
|
||||
* @covers ::__construct
|
||||
* @covers \phpDocumentor\Reflection\DocBlock\Tags\Param::isReference
|
||||
*/
|
||||
public function testIsReference(): void
|
||||
{
|
||||
$expected = new Description('Description');
|
||||
|
||||
$fixture = new Param('1.0', null, false, $expected);
|
||||
|
||||
$this->assertFalse($fixture->isReference());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,7 @@ class SinceTest extends TestCase
|
||||
|
||||
$fixture = Since::create('1.0 My Description', $descriptionFactory, $context);
|
||||
|
||||
self::assertInstanceOf(Since::class, $fixture);
|
||||
$this->assertSame('1.0 My Description', (string) $fixture);
|
||||
$this->assertSame($version, $fixture->getVersion());
|
||||
$this->assertSame($description, $fixture->getDescription());
|
||||
@@ -178,6 +179,7 @@ class SinceTest extends TestCase
|
||||
|
||||
$fixture = Since::create('', $descriptionFactory, new Context(''));
|
||||
|
||||
self::assertInstanceOf(Since::class, $fixture);
|
||||
$this->assertSame('', (string) $fixture);
|
||||
$this->assertSame(null, $fixture->getVersion());
|
||||
$this->assertSame(null, $fixture->getDescription());
|
||||
|
||||
@@ -227,6 +227,8 @@ class SourceTest extends TestCase
|
||||
public function testExceptionIsThrownIfLineCountIsNotIntegerOrNull(): void
|
||||
{
|
||||
$this->expectException('InvalidArgumentException');
|
||||
|
||||
//@phpstan-ignore argument.type
|
||||
new Source('1', []);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,6 +158,7 @@ class VersionTest extends TestCase
|
||||
|
||||
$fixture = Version::create('1.0 My Description', $descriptionFactory, $context);
|
||||
|
||||
self::assertInstanceOf(Version::class, $fixture);
|
||||
$this->assertSame('1.0 My Description', (string) $fixture);
|
||||
$this->assertSame($version, $fixture->getVersion());
|
||||
$this->assertSame($description, $fixture->getDescription());
|
||||
@@ -178,6 +179,7 @@ class VersionTest extends TestCase
|
||||
|
||||
$fixture = Version::create('', $descriptionFactory, new Context(''));
|
||||
|
||||
self::assertInstanceOf(Version::class, $fixture);
|
||||
$this->assertSame('', (string) $fixture);
|
||||
$this->assertSame(null, $fixture->getVersion());
|
||||
$this->assertSame(null, $fixture->getDescription());
|
||||
|
||||
@@ -200,7 +200,7 @@ DOCBLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @return array<int, array<int, string>>
|
||||
*/
|
||||
public function provideSummaryAndDescriptions(): array
|
||||
{
|
||||
|
||||
@@ -108,8 +108,9 @@ class DocBlockTest extends TestCase
|
||||
public function testDocBlockAllowsOnlyTags(): void
|
||||
{
|
||||
$this->expectException('InvalidArgumentException');
|
||||
$tags = [null];
|
||||
$fixture = new DocBlock('', null, $tags);
|
||||
$tags = [null];
|
||||
// @phpstan-ignore argument.type
|
||||
new DocBlock('', null, $tags);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -41,8 +41,12 @@ final class PregSplitTest extends TestCase
|
||||
public function testPregSplitThrowsOnError(): void
|
||||
{
|
||||
//We need to disable the error handler for phpunit... because we expect some errors here
|
||||
$this->errorHandler = set_error_handler(static function (): void {
|
||||
}, E_WARNING);
|
||||
$this->errorHandler = set_error_handler(
|
||||
static function (int $i, string $s, string $s2, int $x, ?array $trace = null): bool {
|
||||
return true;
|
||||
},
|
||||
E_WARNING
|
||||
);
|
||||
|
||||
$this->expectException(PcreException::class);
|
||||
Utils::pregSplit('~InvalidRegular)Expression~', 'some word');
|
||||
|
||||
Reference in New Issue
Block a user