Skip to content

Commit 19a1f3a

Browse files
committed
Phpstan to max level
1 parent aee9840 commit 19a1f3a

21 files changed

+156
-102
lines changed

phpstan.neon

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1+
includes:
2+
- /composer/vendor/phpstan/phpstan-mockery/extension.neon
3+
- /composer/vendor/phpstan/phpstan-webmozart-assert/extension.neon
4+
15
parameters:
26
ignoreErrors:
37
# false positive
4-
- '#Call to an undefined method object::getDocComment\(\)#'
8+
- '#Method phpDocumentor\Reflection\DocBlock\Tags\Method::filterArguments() should return array<array> but returns array<array|string>#'
9+
- "~Parameter #1 $function of function call_user_func_array expects callable(): mixed, array(string, 'create') given.~"
510
- '#Cannot call method render\(\) on phpDocumentor\\Reflection\\DocBlock\\Description\|string#'
6-
- '#Calling method create\(\) on possibly null value of type phpDocumentor\\Reflection\\DocBlock\\DescriptionFactory\|null#'
7-
- '#Calling method resolve\(\) on possibly null value of type phpDocumentor\\Reflection\\(TypeResolver|FqsenResolver)\|null#'
8-
9-
# nested parents
10-
- '#Calling method render\(\) on possibly null value of type phpDocumentor\\Reflection\\DocBlock\\Description\|string\|null#'

src/DocBlock/DescriptionFactory.php

Lines changed: 25 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace phpDocumentor\Reflection\DocBlock;
1515

1616
use phpDocumentor\Reflection\Types\Context as TypeContext;
17+
use Webmozart\Assert\Assert;
1718
use const PREG_SPLIT_DELIM_CAPTURE;
1819
use function count;
1920
use function explode;
@@ -62,9 +63,28 @@ public function __construct(TagFactory $tagFactory)
6263
*/
6364
public function create(string $contents, ?TypeContext $context = null) : Description
6465
{
65-
[$text, $tags] = $this->parse($this->lex($contents), $context);
66+
$tokens = $this->lex($contents);
67+
$count = count($tokens);
68+
$tagCount = 0;
69+
$tags = [];
70+
71+
for ($i = 1; $i < $count; $i += 2) {
72+
$tag = $this->tagFactory->create($tokens[$i], $context);
73+
if ($tag !== null) {
74+
$tags[] = $tag;
75+
}
76+
$tokens[$i] = '%' . ++$tagCount . '$s';
77+
}
78+
79+
//In order to allow "literal" inline tags, the otherwise invalid
80+
//sequence "{@}" is changed to "@", and "{}" is changed to "}".
81+
//"%" is escaped to "%%" because of vsprintf.
82+
//See unit tests for examples.
83+
for ($i = 0; $i < $count; $i += 2) {
84+
$tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]);
85+
}
6686

67-
return new Description($text, $tags);
87+
return new Description(implode('', $tokens), $tags);
6888
}
6989

7090
/**
@@ -81,7 +101,7 @@ private function lex(string $contents) : array
81101
return [$contents];
82102
}
83103

84-
return preg_split(
104+
$parts = preg_split(
85105
'/\{
86106
# "{@}" is not a valid inline tag. This ensures that we do not treat it as one, but treat it literally.
87107
(?!@\})
@@ -110,35 +130,8 @@ private function lex(string $contents) : array
110130
0,
111131
PREG_SPLIT_DELIM_CAPTURE
112132
);
113-
}
114-
115-
/**
116-
* Parses the stream of tokens in to a new set of tokens containing Tags.
117-
*
118-
* @param string[] $tokens
119-
*
120-
* @return string[]|Tag[]
121-
*/
122-
private function parse(array $tokens, ?TypeContext $context = null) : array
123-
{
124-
$count = count($tokens);
125-
$tagCount = 0;
126-
$tags = [];
127-
128-
for ($i = 1; $i < $count; $i += 2) {
129-
$tags[] = $this->tagFactory->create($tokens[$i], $context);
130-
$tokens[$i] = '%' . ++$tagCount . '$s';
131-
}
132-
133-
//In order to allow "literal" inline tags, the otherwise invalid
134-
//sequence "{@}" is changed to "@", and "{}" is changed to "}".
135-
//"%" is escaped to "%%" because of vsprintf.
136-
//See unit tests for examples.
137-
for ($i = 0; $i < $count; $i += 2) {
138-
$tokens[$i] = str_replace(['{@}', '{}', '%'], ['@', '}', '%%'], $tokens[$i]);
139-
}
140-
141-
return [implode('', $tokens), $tags];
133+
Assert::isArray($parts);
134+
return $parts;
142135
}
143136

144137
/**

src/DocBlock/ExampleFinder.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,10 @@ public function getExampleDirectories() : array
9696
* 2. Checks the source folder for the given filename
9797
* 3. Checks the 'examples' folder in the current working directory for examples
9898
* 4. Checks the path relative to the current working directory for the given filename
99+
*
100+
* @return string[] all lines of the example file
99101
*/
100-
private function getExampleFileContents(string $filename) : ?string
102+
private function getExampleFileContents(string $filename) : ?array
101103
{
102104
$normalizedPath = null;
103105

@@ -119,7 +121,8 @@ private function getExampleFileContents(string $filename) : ?string
119121
}
120122
}
121123

122-
return $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : null;
124+
$lines = $normalizedPath && is_readable($normalizedPath) ? file($normalizedPath) : false;
125+
return $lines !== false ? $lines : null;
123126
}
124127

125128
/**

src/DocBlock/StandardTagFactory.php

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@
2828
use function get_class;
2929
use function preg_match;
3030
use function strpos;
31+
use phpDocumentor\Reflection\DocBlock\Tags\Author;
32+
use phpDocumentor\Reflection\DocBlock\Tags\Covers;
33+
use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
34+
use phpDocumentor\Reflection\DocBlock\Tags\Link;
35+
use phpDocumentor\Reflection\DocBlock\Tags\Method;
36+
use phpDocumentor\Reflection\DocBlock\Tags\Param;
37+
use phpDocumentor\Reflection\DocBlock\Tags\PropertyRead;
38+
use phpDocumentor\Reflection\DocBlock\Tags\Property;
39+
use phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite;
40+
use phpDocumentor\Reflection\DocBlock\Tags\Return_;
41+
use phpDocumentor\Reflection\DocBlock\Tags\See;
42+
use phpDocumentor\Reflection\DocBlock\Tags\Since;
43+
use phpDocumentor\Reflection\DocBlock\Tags\Source;
44+
use phpDocumentor\Reflection\DocBlock\Tags\Throws;
45+
use phpDocumentor\Reflection\DocBlock\Tags\Uses;
46+
use phpDocumentor\Reflection\DocBlock\Tags\Var_;
47+
use phpDocumentor\Reflection\DocBlock\Tags\Version;
3148

3249
/**
3350
* Creates a Tag object given the contents of a tag.
@@ -56,25 +73,25 @@ final class StandardTagFactory implements TagFactory
5673
* FQCN to a class that handles it as an array value.
5774
*/
5875
private $tagHandlerMappings = [
59-
'author' => '\phpDocumentor\Reflection\DocBlock\Tags\Author',
60-
'covers' => '\phpDocumentor\Reflection\DocBlock\Tags\Covers',
61-
'deprecated' => '\phpDocumentor\Reflection\DocBlock\Tags\Deprecated',
76+
'author' => Author::class,
77+
'covers' => Covers::class,
78+
'deprecated' => Deprecated::class,
6279
// 'example' => '\phpDocumentor\Reflection\DocBlock\Tags\Example',
63-
'link' => '\phpDocumentor\Reflection\DocBlock\Tags\Link',
64-
'method' => '\phpDocumentor\Reflection\DocBlock\Tags\Method',
65-
'param' => '\phpDocumentor\Reflection\DocBlock\Tags\Param',
66-
'property-read' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyRead',
67-
'property' => '\phpDocumentor\Reflection\DocBlock\Tags\Property',
68-
'property-write' => '\phpDocumentor\Reflection\DocBlock\Tags\PropertyWrite',
69-
'return' => '\phpDocumentor\Reflection\DocBlock\Tags\Return_',
70-
'see' => '\phpDocumentor\Reflection\DocBlock\Tags\See',
71-
'since' => '\phpDocumentor\Reflection\DocBlock\Tags\Since',
72-
'source' => '\phpDocumentor\Reflection\DocBlock\Tags\Source',
73-
'throw' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws',
74-
'throws' => '\phpDocumentor\Reflection\DocBlock\Tags\Throws',
75-
'uses' => '\phpDocumentor\Reflection\DocBlock\Tags\Uses',
76-
'var' => '\phpDocumentor\Reflection\DocBlock\Tags\Var_',
77-
'version' => '\phpDocumentor\Reflection\DocBlock\Tags\Version',
80+
'link' => Link::class,
81+
'method' => Method::class,
82+
'param' => Param::class,
83+
'property-read' => PropertyRead::class,
84+
'property' => Property::class,
85+
'property-write' => PropertyWrite::class,
86+
'return' => Return_::class,
87+
'see' => See::class,
88+
'since' => Since::class,
89+
'source' => Source::class,
90+
'throw' => Throws::class,
91+
'throws' => Throws::class,
92+
'uses' => Uses::class,
93+
'var' => Var_::class,
94+
'version' => Version::class,
7895
];
7996

8097
/**
@@ -149,7 +166,7 @@ public function addParameter(string $name, $value) : void
149166
/**
150167
* {@inheritDoc}
151168
*/
152-
public function addService($service, $alias = null) : void
169+
public function addService(object $service, $alias = null) : void
153170
{
154171
$this->serviceLocator[$alias ?: get_class($service)] = $service;
155172
}
@@ -215,6 +232,8 @@ private function createTag(string $body, string $name, TypeContext $context) : ?
215232

216233
/**
217234
* Determines the Fully Qualified Class Name of the Factory or Tag (containing a Factory Method `create`).
235+
*
236+
* @return
218237
*/
219238
private function findHandlerClassName(string $tagName, TypeContext $context) : string
220239
{
@@ -245,7 +264,7 @@ private function getArgumentsForParametersFromWiring(array $parameters, array $l
245264
{
246265
$arguments = [];
247266
foreach ($parameters as $parameter) {
248-
$typeHint = $parameter->getClass() ? $parameter->getClass()->getName() : null;
267+
$typeHint = $parameter->getClass() !== null ? $parameter->getClass()->getName() : null;
249268
if (isset($locator[$typeHint])) {
250269
$arguments[] = $locator[$typeHint];
251270
continue;

src/DocBlock/Tags/Covers.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,11 @@ public static function create(
5151
?TypeContext $context = null
5252
) : self {
5353
Assert::notEmpty($body);
54+
Assert::notNull($descriptionFactory);
55+
Assert::notNull($resolver);
5456

5557
$parts = preg_split('/\s+/Su', $body, 2);
58+
Assert::isArray($parts);
5659

5760
return new static(
5861
$resolver->resolve($parts[0], $context),

src/DocBlock/Tags/Deprecated.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ final class Deprecated extends BaseTag implements Factory\StaticMethod
4343
[^\s\:]+\:\s*\$[^\$]+\$
4444
)';
4545

46-
/** @var string The version vector. */
46+
/** @var string|null The version vector. */
4747
private $version = '';
4848

4949
public function __construct(?string $version = null, ?Description $description = null)
@@ -74,6 +74,7 @@ public static function create(
7474
);
7575
}
7676

77+
Assert::notNull($descriptionFactory);
7778
return new static(
7879
$matches[1],
7980
$descriptionFactory->create($matches[2] ?? '', $context)

src/DocBlock/Tags/Generic.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public static function create(
5454
Assert::stringNotEmpty($name);
5555
Assert::notNull($descriptionFactory);
5656

57-
$description = $descriptionFactory && $body !== '' ? $descriptionFactory->create($body, $context) : null;
57+
$description = $body !== '' ? $descriptionFactory->create($body, $context) : null;
5858

5959
return new static($name, $description);
6060
}

src/DocBlock/Tags/Link.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public static function create(
5050
Assert::notNull($descriptionFactory);
5151

5252
$parts = preg_split('/\s+/Su', $body, 2);
53+
Assert::isArray($parts);
5354
$description = isset($parts[1]) ? $descriptionFactory->create($parts[1], $context) : null;
5455

5556
return new static($parts[0], $description);

src/DocBlock/Tags/Method.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ final class Method extends BaseTag implements Factory\StaticMethod
4444
/** @var string */
4545
private $methodName = '';
4646

47-
/** @var string[] */
47+
/** @var string[][] */
4848
private $arguments = [];
4949

5050
/** @var bool */
@@ -87,7 +87,8 @@ public static function create(
8787
?TypeContext $context = null
8888
) : ?self {
8989
Assert::stringNotEmpty($body);
90-
Assert::allNotNull([$typeResolver, $descriptionFactory]);
90+
Assert::notNull($typeResolver);
91+
Assert::notNull($descriptionFactory);
9192

9293
// 1. none or more whitespace
9394
// 2. optionally the keyword "static" followed by whitespace
@@ -184,7 +185,7 @@ public function getMethodName() : string
184185
}
185186

186187
/**
187-
* @return string[]
188+
* @return string[][]
188189
*/
189190
public function getArguments() : array
190191
{
@@ -221,7 +222,7 @@ public function __toString() : string
221222
}
222223

223224
/**
224-
* @param mixed[][] $arguments
225+
* @param array<string|mixed[]> $arguments
225226
*
226227
* @return mixed[][]
227228
*/

src/DocBlock/Tags/Param.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,32 +66,34 @@ public static function create(
6666
?TypeContext $context = null
6767
) : self {
6868
Assert::stringNotEmpty($body);
69-
Assert::allNotNull([$typeResolver, $descriptionFactory]);
69+
Assert::notNull($typeResolver);
70+
Assert::notNull($descriptionFactory);
7071

7172
$parts = preg_split('/(\s+)/Su', $body, 3, PREG_SPLIT_DELIM_CAPTURE);
73+
Assert::isArray($parts);
7274
$type = null;
7375
$variableName = '';
7476
$isVariadic = false;
7577

7678
// if the first item that is encountered is not a variable; it is a type
77-
if (isset($parts[0]) && (strlen($parts[0]) > 0) && ($parts[0][0] !== '$')) {
79+
if (isset($parts[0]) && ($parts[0] !== '') && ($parts[0][0] !== '$')) {
7880
$type = $typeResolver->resolve(array_shift($parts), $context);
7981
array_shift($parts);
8082
}
8183

8284
// if the next item starts with a $ or ...$ it must be the variable name
83-
if (isset($parts[0]) && (strlen($parts[0]) > 0) &&
85+
if (isset($parts[0]) && ($parts[0] !== '') &&
8486
(strpos($parts[0], '$') === 0 || strpos($parts[0], '...$') === 0)
8587
) {
8688
$variableName = array_shift($parts);
8789
array_shift($parts);
8890

89-
if (substr($variableName, 0, 3) === '...') {
91+
if ($variableName !== null && strpos($variableName, '...') === 0) {
9092
$isVariadic = true;
9193
$variableName = substr($variableName, 3);
9294
}
9395

94-
if (substr($variableName, 0, 1) === '$') {
96+
if ($variableName !== null && strpos($variableName, '$') === 0) {
9597
$variableName = substr($variableName, 1);
9698
}
9799
}

0 commit comments

Comments
 (0)