Phpstan to max level

This commit is contained in:
Jaapio
2019-09-20 16:52:17 +02:00
parent aee984014b
commit 19a1f3a91f
21 changed files with 156 additions and 102 deletions
+6 -6
View File
@@ -1,10 +1,10 @@
includes:
- /composer/vendor/phpstan/phpstan-mockery/extension.neon
- /composer/vendor/phpstan/phpstan-webmozart-assert/extension.neon
parameters: parameters:
ignoreErrors: ignoreErrors:
# false positive # false positive
- '#Call to an undefined method object::getDocComment\(\)#' - '#Method phpDocumentor\Reflection\DocBlock\Tags\Method::filterArguments() should return array<array> but returns array<array|string>#'
- "~Parameter #1 $function of function call_user_func_array expects callable(): mixed, array(string, 'create') given.~"
- '#Cannot call method render\(\) on phpDocumentor\\Reflection\\DocBlock\\Description\|string#' - '#Cannot call method render\(\) on phpDocumentor\\Reflection\\DocBlock\\Description\|string#'
- '#Calling method create\(\) on possibly null value of type phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory\|null#'
- '#Calling method resolve\(\) on possibly null value of type phpDocumentor\\Reflection\\(TypeResolver|FqsenResolver)\|null#'
# nested parents
- '#Calling method render\(\) on possibly null value of type phpDocumentor\\Reflection\\DocBlock\\Description\|string\|null#'
+25 -32
View File
@@ -14,6 +14,7 @@ declare(strict_types=1);
namespace phpDocumentor\Reflection\DocBlock; namespace phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\Types\Context as TypeContext; use phpDocumentor\Reflection\Types\Context as TypeContext;
use Webmozart\Assert\Assert;
use const PREG_SPLIT_DELIM_CAPTURE; use const PREG_SPLIT_DELIM_CAPTURE;
use function count; use function count;
use function explode; use function explode;
@@ -62,9 +63,28 @@ class DescriptionFactory
*/ */
public function create(string $contents, ?TypeContext $context = null) : Description public function create(string $contents, ?TypeContext $context = null) : Description
{ {
[$text, $tags] = $this->parse($this->lex($contents), $context); $tokens = $this->lex($contents);
$count = count($tokens);
$tagCount = 0;
$tags = [];
return new Description($text, $tags); for ($i = 1; $i < $count; $i += 2) {
$tag = $this->tagFactory->create($tokens[$i], $context);
if ($tag !== null) {
$tags[] = $tag;
}
$tokens[$i] = '%' . ++$tagCount . '$s';
}
//In order to allow "literal" inline tags, the otherwise invalid
//sequence "{@}" is changed to "@", and "{}" is changed to "}".
//"%" is escaped to "%%" because of vsprintf.
//See unit tests for examples.
for ($i = 0; $i < $count; $i += 2) {
$tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]);
}
return new Description(implode('', $tokens), $tags);
} }
/** /**
@@ -81,7 +101,7 @@ class DescriptionFactory
return [$contents]; return [$contents];
} }
return preg_split( $parts = preg_split(
'/\{ '/\{
# "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally. # "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally.
(?!@\}) (?!@\})
@@ -110,35 +130,8 @@ class DescriptionFactory
0, 0,
PREG_SPLIT_DELIM_CAPTURE PREG_SPLIT_DELIM_CAPTURE
); );
} Assert::isArray($parts);
return $parts;
/**
* Parses the stream of tokens in to a new set of tokens containing Tags.
*
* @param string[] $tokens
*
* @return string[]|Tag[]
*/
private function parse(array $tokens, ?TypeContext $context = null) : array
{
$count = count($tokens);
$tagCount = 0;
$tags = [];
for ($i = 1; $i < $count; $i += 2) {
$tags[] = $this->tagFactory->create($tokens[$i], $context);
$tokens[$i] = '%' . ++$tagCount . '$s';
}
//In order to allow "literal" inline tags, the otherwise invalid
//sequence "{@}" is changed to "@", and "{}" is changed to "}".
//"%" is escaped to "%%" because of vsprintf.
//See unit tests for examples.
for ($i = 0; $i < $count; $i += 2) {
$tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]);
}
return [implode('', $tokens), $tags];
} }
/** /**
+5 -2
View File
@@ -96,8 +96,10 @@ class ExampleFinder
* 2. Checks the source folder for the given filename * 2. Checks the source folder for the given filename
* 3. Checks the 'examples' folder in the current working directory for examples * 3. Checks the 'examples' folder in the current working directory for examples
* 4. Checks the path relative to the current working directory for the given filename * 4. Checks the path relative to the current working directory for the given filename
*
* @return string[] all lines of the example file
*/ */
private function getExampleFileContents(string $filename) : ?string private function getExampleFileContents(string $filename) : ?array
{ {
$normalizedPath = null; $normalizedPath = null;
@@ -119,7 +121,8 @@ class ExampleFinder
} }
} }
return $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : null; $lines = $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : false;
return $lines !== false ? $lines : null;
} }
/** /**
+39 -20
View File
@@ -28,6 +28,23 @@ use function count;
use function get_class; use function get_class;
use function preg_match; use function preg_match;
use function strpos; use function strpos;
use phpDocumentor\Reflection\DocBlock\Tags\Author;
use phpDocumentor\Reflection\DocBlock\Tags\Covers;
use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
use phpDocumentor\Reflection\DocBlock\Tags\Link;
use phpDocumentor\Reflection\DocBlock\Tags\Method;
use phpDocumentor\Reflection\DocBlock\Tags\Param;
use phpDocumentor\Reflection\DocBlock\Tags\PropertyRead;
use phpDocumentor\Reflection\DocBlock\Tags\Property;
use phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite;
use phpDocumentor\Reflection\DocBlock\Tags\Return_;
use phpDocumentor\Reflection\DocBlock\Tags\See;
use phpDocumentor\Reflection\DocBlock\Tags\Since;
use phpDocumentor\Reflection\DocBlock\Tags\Source;
use phpDocumentor\Reflection\DocBlock\Tags\Throws;
use phpDocumentor\Reflection\DocBlock\Tags\Uses;
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
use phpDocumentor\Reflection\DocBlock\Tags\Version;
/** /**
* Creates a Tag object given the contents of a tag. * Creates a Tag object given the contents of a tag.
@@ -56,25 +73,25 @@ final class StandardTagFactory implements TagFactory
* FQCN to a class that handles it as an array value. * FQCN to a class that handles it as an array value.
*/ */
private $tagHandlerMappings = [ private $tagHandlerMappings = [
'author' => '\phpDocumentor\Reflection\DocBlock\Tags\Author', 'author' => Author::class,
'covers' => '\phpDocumentor\Reflection\DocBlock\Tags\Covers', 'covers' => Covers::class,
'deprecated' => '\phpDocumentor\Reflection\DocBlock\Tags\Deprecated', 'deprecated' => Deprecated::class,
// 'example' => '\phpDocumentor\Reflection\DocBlock\Tags\Example', // 'example' => '\phpDocumentor\Reflection\DocBlock\Tags\Example',
'link' => '\phpDocumentor\Reflection\DocBlock\Tags\Link', 'link' => Link::class,
'method' => '\phpDocumentor\Reflection\DocBlock\Tags\Method', 'method' => Method::class,
'param' => '\phpDocumentor\Reflection\DocBlock\Tags\Param', 'param' => Param::class,
'property-read' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead', 'property-read' => PropertyRead::class,
'property' => '\phpDocumentor\Reflection\DocBlock\Tags\Property', 'property' => Property::class,
'property-write' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite', 'property-write' => PropertyWrite::class,
'return' => '\phpDocumentor\Reflection\DocBlock\Tags\Return_', 'return' => Return_::class,
'see' => '\phpDocumentor\Reflection\DocBlock\Tags\See', 'see' => See::class,
'since' => '\phpDocumentor\Reflection\DocBlock\Tags\Since', 'since' => Since::class,
'source' => '\phpDocumentor\Reflection\DocBlock\Tags\Source', 'source' => Source::class,
'throw' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws', 'throw' => Throws::class,
'throws' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws', 'throws' => Throws::class,
'uses' => '\phpDocumentor\Reflection\DocBlock\Tags\Uses', 'uses' => Uses::class,
'var' => '\phpDocumentor\Reflection\DocBlock\Tags\Var_', 'var' => Var_::class,
'version' => '\phpDocumentor\Reflection\DocBlock\Tags\Version', 'version' => Version::class,
]; ];
/** /**
@@ -149,7 +166,7 @@ final class StandardTagFactory implements TagFactory
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */
public function addService($service, $alias = null) : void public function addService(object $service, $alias = null) : void
{ {
$this->serviceLocator[$alias ?: get_class($service)] = $service; $this->serviceLocator[$alias ?: get_class($service)] = $service;
} }
@@ -215,6 +232,8 @@ final class StandardTagFactory implements TagFactory
/** /**
* Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`). * Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`).
*
* @return
*/ */
private function findHandlerClassName(string $tagName, TypeContext $context) : string private function findHandlerClassName(string $tagName, TypeContext $context) : string
{ {
@@ -245,7 +264,7 @@ final class StandardTagFactory implements TagFactory
{ {
$arguments = []; $arguments = [];
foreach ($parameters as $parameter) { foreach ($parameters as $parameter) {
$typeHint = $parameter->getClass() ? $parameter->getClass()->getName() : null; $typeHint = $parameter->getClass() !== null ? $parameter->getClass()->getName() : null;
if (isset($locator[$typeHint])) { if (isset($locator[$typeHint])) {
$arguments[] = $locator[$typeHint]; $arguments[] = $locator[$typeHint];
continue; continue;
+3
View File
@@ -51,8 +51,11 @@ final class Covers extends BaseTag implements Factory\StaticMethod
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::notEmpty($body); Assert::notEmpty($body);
Assert::notNull($descriptionFactory);
Assert::notNull($resolver);
$parts = preg_split('/\s+/Su', $body, 2); $parts = preg_split('/\s+/Su', $body, 2);
Assert::isArray($parts);
return new static( return new static(
$resolver->resolve($parts[0], $context), $resolver->resolve($parts[0], $context),
+2 -1
View File
@@ -43,7 +43,7 @@ final class Deprecated extends BaseTag implements Factory\StaticMethod
[^\s\:]+\:\s*\$[^\$]+\$ [^\s\:]+\:\s*\$[^\$]+\$
)'; )';
/** @var string The version vector. */ /** @var string|null The version vector. */
private $version = ''; private $version = '';
public function __construct(?string $version = null, ?Description $description = null) public function __construct(?string $version = null, ?Description $description = null)
@@ -74,6 +74,7 @@ final class Deprecated extends BaseTag implements Factory\StaticMethod
); );
} }
Assert::notNull($descriptionFactory);
return new static( return new static(
$matches[1], $matches[1],
$descriptionFactory->create($matches[2] ?? '', $context) $descriptionFactory->create($matches[2] ?? '', $context)
+1 -1
View File
@@ -54,7 +54,7 @@ class Generic extends BaseTag implements Factory\StaticMethod
Assert::stringNotEmpty($name); Assert::stringNotEmpty($name);
Assert::notNull($descriptionFactory); Assert::notNull($descriptionFactory);
$description = $descriptionFactory && $body !== '' ? $descriptionFactory->create($body, $context) : null; $description = $body !== '' ? $descriptionFactory->create($body, $context) : null;
return new static($name, $description); return new static($name, $description);
} }
+1
View File
@@ -50,6 +50,7 @@ final class Link extends BaseTag implements Factory\StaticMethod
Assert::notNull($descriptionFactory); Assert::notNull($descriptionFactory);
$parts = preg_split('/\s+/Su', $body, 2); $parts = preg_split('/\s+/Su', $body, 2);
Assert::isArray($parts);
$description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
return new static($parts[0], $description); return new static($parts[0], $description);
+5 -4
View File
@@ -44,7 +44,7 @@ final class Method extends BaseTag implements Factory\StaticMethod
/** @var string */ /** @var string */
private $methodName = ''; private $methodName = '';
/** @var string[] */ /** @var string[][] */
private $arguments = []; private $arguments = [];
/** @var bool */ /** @var bool */
@@ -87,7 +87,8 @@ final class Method extends BaseTag implements Factory\StaticMethod
?TypeContext $context = null ?TypeContext $context = null
) : ?self { ) : ?self {
Assert::stringNotEmpty($body); Assert::stringNotEmpty($body);
Assert::allNotNull([$typeResolver, $descriptionFactory]); Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory);
// 1. none or more whitespace // 1. none or more whitespace
// 2. optionally the keyword "static" followed by whitespace // 2. optionally the keyword "static" followed by whitespace
@@ -184,7 +185,7 @@ final class Method extends BaseTag implements Factory\StaticMethod
} }
/** /**
* @return string[] * @return string[][]
*/ */
public function getArguments() : array public function getArguments() : array
{ {
@@ -221,7 +222,7 @@ final class Method extends BaseTag implements Factory\StaticMethod
} }
/** /**
* @param mixed[][] $arguments * @param array<string|mixed[]> $arguments
* *
* @return mixed[][] * @return mixed[][]
*/ */
+7 -5
View File
@@ -66,32 +66,34 @@ final class Param extends BaseTag implements Factory\StaticMethod
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::stringNotEmpty($body); Assert::stringNotEmpty($body);
Assert::allNotNull([$typeResolver, $descriptionFactory]); Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory);
$parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE);
Assert::isArray($parts);
$type = null; $type = null;
$variableName = ''; $variableName = '';
$isVariadic = false; $isVariadic = false;
// if the first item that is encountered is not a variable; it is a type // if the first item that is encountered is not a variable; it is a type
if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { if (isset($parts[0]) && ($parts[0] !== '') && ($parts[0][0] !== '$')) {
$type = $typeResolver->resolve(array_shift($parts), $context); $type = $typeResolver->resolve(array_shift($parts), $context);
array_shift($parts); array_shift($parts);
} }
// if the next item starts with a $ or ...$ it must be the variable name // if the next item starts with a $ or ...$ it must be the variable name
if (isset($parts[0]) && (strlen($parts[0]) > 0) && if (isset($parts[0]) && ($parts[0] !== '') &&
(strpos($parts[0], '$') === 0 || strpos($parts[0], '...$') === 0) (strpos($parts[0], '$') === 0 || strpos($parts[0], '...$') === 0)
) { ) {
$variableName = array_shift($parts); $variableName = array_shift($parts);
array_shift($parts); array_shift($parts);
if (substr($variableName, 0, 3) === '...') { if ($variableName !== null && strpos($variableName, '...') === 0) {
$isVariadic = true; $isVariadic = true;
$variableName = substr($variableName, 3); $variableName = substr($variableName, 3);
} }
if (substr($variableName, 0, 1) === '$') { if ($variableName !== null && strpos($variableName, '$') === 0) {
$variableName = substr($variableName, 1); $variableName = substr($variableName, 1);
} }
} }
+8 -6
View File
@@ -23,7 +23,7 @@ use const PREG_SPLIT_DELIM_CAPTURE;
use function array_shift; use function array_shift;
use function implode; use function implode;
use function preg_split; use function preg_split;
use function strlen; use function strpos;
use function substr; use function substr;
/** /**
@@ -57,24 +57,26 @@ class Property extends BaseTag implements Factory\StaticMethod
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::stringNotEmpty($body); Assert::stringNotEmpty($body);
Assert::allNotNull([$typeResolver, $descriptionFactory]); Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory);
$parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE);
Assert::isArray($parts);
$type = null; $type = null;
$variableName = ''; $variableName = '';
// if the first item that is encountered is not a variable; it is a type // if the first item that is encountered is not a variable; it is a type
if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { if (isset($parts[0]) && ($parts[0] !== '') && ($parts[0][0] !== '$')) {
$type = $typeResolver->resolve(array_shift($parts), $context); $type = $typeResolver->resolve(array_shift($parts), $context);
array_shift($parts); array_shift($parts);
} }
// if the next item starts with a $ or ...$ it must be the variable name // if the next item starts with a $ or ...$ it must be the variable name
if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { if (isset($parts[0]) && ($parts[0] !== '') && (strpos($parts[0], '$') === 0)) {
$variableName = array_shift($parts); $variableName = array_shift($parts);
array_shift($parts); array_shift($parts);
if (substr($variableName, 0, 1) === '$') { if ($variableName !== null && strpos($variableName, '$') === 0) {
$variableName = substr($variableName, 1); $variableName = substr($variableName, 1);
} }
} }
+6 -4
View File
@@ -57,24 +57,26 @@ class PropertyRead extends BaseTag implements Factory\StaticMethod
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::stringNotEmpty($body); Assert::stringNotEmpty($body);
Assert::allNotNull([$typeResolver, $descriptionFactory]); Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory);
$parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE);
Assert::isArray($parts);
$type = null; $type = null;
$variableName = ''; $variableName = '';
// if the first item that is encountered is not a variable; it is a type // if the first item that is encountered is not a variable; it is a type
if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { if (isset($parts[0]) && ($parts[0] !== '') && ($parts[0][0] !== '$')) {
$type = $typeResolver->resolve(array_shift($parts), $context); $type = $typeResolver->resolve(array_shift($parts), $context);
array_shift($parts); array_shift($parts);
} }
// if the next item starts with a $ or ...$ it must be the variable name // if the next item starts with a $ or ...$ it must be the variable name
if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { if (isset($parts[0]) && ($parts[0] !== '') && (strpos($parts[0], '$') === 0)) {
$variableName = array_shift($parts); $variableName = array_shift($parts);
array_shift($parts); array_shift($parts);
if (substr($variableName, 0, 1) === '$') { if ($variableName !== null && strpos($variableName, '$') === 0) {
$variableName = substr($variableName, 1); $variableName = substr($variableName, 1);
} }
} }
+6 -3
View File
@@ -24,6 +24,7 @@ use function array_shift;
use function implode; use function implode;
use function preg_split; use function preg_split;
use function strlen; use function strlen;
use function strpos;
use function substr; use function substr;
/** /**
@@ -57,14 +58,16 @@ class PropertyWrite extends BaseTag implements Factory\StaticMethod
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::stringNotEmpty($body); Assert::stringNotEmpty($body);
Assert::allNotNull([$typeResolver, $descriptionFactory]); Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory);
$parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE);
Assert::isArray($parts);
$type = null; $type = null;
$variableName = ''; $variableName = '';
// if the first item that is encountered is not a variable; it is a type // if the first item that is encountered is not a variable; it is a type
if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { if (isset($parts[0]) && ($parts[0] !== '') && ($parts[0][0] !== '$')) {
$type = $typeResolver->resolve(array_shift($parts), $context); $type = $typeResolver->resolve(array_shift($parts), $context);
array_shift($parts); array_shift($parts);
} }
@@ -74,7 +77,7 @@ class PropertyWrite extends BaseTag implements Factory\StaticMethod
$variableName = array_shift($parts); $variableName = array_shift($parts);
array_shift($parts); array_shift($parts);
if (substr($variableName, 0, 1) === '$') { if ($variableName !== null && strpos($variableName, '$') === 0) {
$variableName = substr($variableName, 1); $variableName = substr($variableName, 1);
} }
} }
+3 -1
View File
@@ -47,9 +47,11 @@ final class Return_ extends BaseTag implements Factory\StaticMethod
?DescriptionFactory $descriptionFactory = null, ?DescriptionFactory $descriptionFactory = null,
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::allNotNull([$typeResolver, $descriptionFactory]); Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory);
$parts = preg_split('/\s+/Su', $body, 2); $parts = preg_split('/\s+/Su', $body, 2);
Assert::isArray($parts);
$type = $typeResolver->resolve($parts[0] ?? '', $context); $type = $typeResolver->resolve($parts[0] ?? '', $context);
$description = $descriptionFactory->create($parts[1] ?? '', $context); $description = $descriptionFactory->create($parts[1] ?? '', $context);
+5 -3
View File
@@ -49,13 +49,15 @@ class See extends BaseTag implements Factory\StaticMethod
*/ */
public static function create( public static function create(
string $body, string $body,
?FqsenResolver $resolver = null, ?FqsenResolver $typeResolver = null,
?DescriptionFactory $descriptionFactory = null, ?DescriptionFactory $descriptionFactory = null,
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::allNotNull([$resolver, $descriptionFactory]); Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory);
$parts = preg_split('/\s+/Su', $body, 2); $parts = preg_split('/\s+/Su', $body, 2);
Assert::isArray($parts);
$description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null; $description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
// https://tools.ietf.org/html/rfc2396#section-3 // https://tools.ietf.org/html/rfc2396#section-3
@@ -63,7 +65,7 @@ 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($resolver->resolve($parts[0], $context)), $description); return new static(new FqsenRef($typeResolver->resolve($parts[0], $context)), $description);
} }
/** /**
+2 -1
View File
@@ -43,7 +43,7 @@ final class Since extends BaseTag implements Factory\StaticMethod
[^\s\:]+\:\s*\$[^\$]+\$ [^\s\:]+\:\s*\$[^\$]+\$
)'; )';
/** @var string The version vector. */ /** @var string|null The version vector. */
private $version = ''; private $version = '';
public function __construct(?string $version = null, ?Description $description = null) public function __construct(?string $version = null, ?Description $description = null)
@@ -68,6 +68,7 @@ final class Since extends BaseTag implements Factory\StaticMethod
return null; return null;
} }
Assert::notNull($descriptionFactory);
return new static( return new static(
$matches[1], $matches[1],
$descriptionFactory->create($matches[2] ?? '', $context) $descriptionFactory->create($matches[2] ?? '', $context)
+3 -1
View File
@@ -47,9 +47,11 @@ final class Throws extends BaseTag implements Factory\StaticMethod
?DescriptionFactory $descriptionFactory = null, ?DescriptionFactory $descriptionFactory = null,
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::allNotNull([$typeResolver, $descriptionFactory]); Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory);
$parts = preg_split('/\s+/Su', $body, 2); $parts = preg_split('/\s+/Su', $body, 2);
Assert::isArray($parts);
$type = $typeResolver->resolve($parts[0] ?? '', $context); $type = $typeResolver->resolve($parts[0] ?? '', $context);
$description = $descriptionFactory->create($parts[1] ?? '', $context); $description = $descriptionFactory->create($parts[1] ?? '', $context);
+4 -1
View File
@@ -50,9 +50,12 @@ final class Uses extends BaseTag implements Factory\StaticMethod
?DescriptionFactory $descriptionFactory = null, ?DescriptionFactory $descriptionFactory = null,
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::allNotNull([$resolver, $descriptionFactory]); Assert::notNull($resolver);
Assert::notNull($descriptionFactory);
$parts = preg_split('/\s+/Su', $body, 2); $parts = preg_split('/\s+/Su', $body, 2);
Assert::isArray($parts);
Assert::allString($parts);
return new static( return new static(
$resolver->resolve($parts[0], $context), $resolver->resolve($parts[0], $context),
+10 -5
View File
@@ -57,24 +57,29 @@ class Var_ extends BaseTag implements Factory\StaticMethod
?TypeContext $context = null ?TypeContext $context = null
) : self { ) : self {
Assert::stringNotEmpty($body); Assert::stringNotEmpty($body);
Assert::allNotNull([$typeResolver, $descriptionFactory]); Assert::notNull($typeResolver);
Assert::notNull($descriptionFactory);
$parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE); $parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE);
Assert::isArray($parts);
Assert::allString($parts);
$type = null; $type = null;
$variableName = ''; $variableName = '';
// if the first item that is encountered is not a variable; it is a type // if the first item that is encountered is not a variable; it is a type
if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) { if (isset($parts[0]) && ($parts[0] !== '') && ($parts[0][0] !== '$')) {
$type = $typeResolver->resolve(array_shift($parts), $context); if ($typeResolver !== null) {
$type = $typeResolver->resolve(array_shift($parts), $context);
}
array_shift($parts); array_shift($parts);
} }
// if the next item starts with a $ or ...$ it must be the variable name // if the next item starts with a $ or ...$ it must be the variable name
if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] === '$')) { if (isset($parts[0]) && ($parts[0] !== '') && (strpos($parts[0], '$') === 0)) {
$variableName = array_shift($parts); $variableName = array_shift($parts);
array_shift($parts); array_shift($parts);
if (substr($variableName, 0, 1) === '$') { if ($variableName !== null && strpos($variableName, '$') === 0) {
$variableName = substr($variableName, 1); $variableName = substr($variableName, 1);
} }
} }
+7 -2
View File
@@ -43,7 +43,7 @@ final class Version extends BaseTag implements Factory\StaticMethod
[^\s\:]+\:\s*\$[^\$]+\$ [^\s\:]+\:\s*\$[^\$]+\$
)'; )';
/** @var string The version vector. */ /** @var string|null The version vector. */
private $version = ''; private $version = '';
public function __construct(?string $version = null, ?Description $description = null) public function __construct(?string $version = null, ?Description $description = null)
@@ -68,9 +68,14 @@ final class Version extends BaseTag implements Factory\StaticMethod
return null; return null;
} }
$description = null;
if ($descriptionFactory !== null) {
$description = $descriptionFactory->create($matches[2] ?? '', $context);
}
return new static( return new static(
$matches[1], $matches[1],
$descriptionFactory->create($matches[2] ?? '', $context) $description
); );
} }
+8 -4
View File
@@ -230,7 +230,7 @@ final class DocBlockFactory implements DocBlockFactoryInterface
* @param string $tags Tag block to parse. * @param string $tags Tag block to parse.
* @param Types\Context $context Context of the parsed Tag * @param Types\Context $context Context of the parsed Tag
* *
* @return DocBlock\Tag[]|string[]|null[] * @return DocBlock\Tag[]
*/ */
private function parseTagBlock(string $tags, Types\Context $context) : array private function parseTagBlock(string $tags, Types\Context $context) : array
{ {
@@ -239,9 +239,13 @@ final class DocBlockFactory implements DocBlockFactoryInterface
return []; return [];
} }
$result = $this->splitTagBlockIntoTagLines($tags); $result = [];
foreach ($result as $key => $tagLine) { $lines = $this->splitTagBlockIntoTagLines($tags);
$result[$key] = $this->tagFactory->create(trim($tagLine), $context); foreach ($lines as $key => $tagLine) {
$tag = $this->tagFactory->create(trim($tagLine), $context);
if ($tag instanceof Tag) {
$result[$key] = $tag;
}
} }
return $result; return $result;