Skip to content

Commit 2baea4f

Browse files
authored
Fix issues reported by PHPStan (#41)
* Fix issues reported by PHPStan * Relax phpstan/phpstan-symfony version constraint
1 parent f990774 commit 2baea4f

7 files changed

Lines changed: 65 additions & 37 deletions

File tree

composer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@
3131
},
3232
"require-dev": {
3333
"friendsofphp/php-cs-fixer": "3.4.0 || ^3.12",
34+
"phpstan/extension-installer": "^1.4",
3435
"phpstan/phpstan": "^1.0 || ^2.0",
36+
"phpstan/phpstan-symfony": "^1.0 || ^2.0",
3537
"phpunit/phpunit": "^9.4"
3638
},
3739
"scripts": {
@@ -41,6 +43,9 @@
4143
"phpstan": "phpstan analyse"
4244
},
4345
"config": {
46+
"allow-plugins": {
47+
"phpstan/extension-installer": true
48+
},
4449
"sort-packages": true
4550
}
4651
}

phpstan.neon

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ parameters:
22
level: max
33
paths:
44
- src
5+
symfony:
6+
consoleApplicationLoader: test/console-loader.php

src/GenerateStubsCommand.php

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,7 @@
2222
class GenerateStubsCommand extends Command
2323
{
2424
/**
25-
* @var (string|int)[][]
26-
* @psalm-var array<int,array{0: string, 1: string, 2: int}>
25+
* @var array<int, array{0: string, 1: int}>
2726
*/
2827
private const SYMBOL_OPTIONS = [
2928
['functions', StubsGenerator::FUNCTIONS],
@@ -37,13 +36,11 @@ class GenerateStubsCommand extends Command
3736
];
3837

3938
/**
40-
* @psalm-suppress PropertyNotSetInConstructor
4139
* @var Filesystem
4240
*/
4341
private $filesystem;
4442

4543
/**
46-
* @psalm-suppress PropertyNotSetInConstructor
4744
* @var string|null
4845
*/
4946
private $outFile;

src/NodeVisitor.php

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
namespace StubsGenerator;
33

44
use PhpParser\Node;
5+
use PhpParser\Node\Arg;
56
use PhpParser\Node\Expr\ArrayDimFetch;
67
use PhpParser\Node\Expr\Assign;
78
use PhpParser\Node\Expr\ConstFetch;
@@ -25,6 +26,10 @@
2526
use PhpParser\NodeTraverser;
2627
use PhpParser\NodeVisitorAbstract;
2728

29+
use function count;
30+
use function defined;
31+
use function is_string;
32+
2833
/**
2934
* On node traversal, this visitor converts any AST to one just containing stub
3035
* definitions, removing anything uninteresting.
@@ -53,22 +58,21 @@ class NodeVisitor extends NodeVisitorAbstract
5358
private $includeInaccessibleClassNodes;
5459

5560
/**
56-
* @psalm-suppress PropertyNotSetInConstructor
57-
* @var Node[]
61+
* @var array<Node>
5862
*/
5963
protected $stack;
6064

61-
/** @var Namespace_[] */
65+
/** @var array<Namespace_> */
6266
private $namespaces = [];
6367
/** @var Namespace_ */
6468
private $globalNamespace;
65-
/** @var Node[] */
69+
/** @var array<Node> */
6670
private $globalExpressions = [];
67-
/** @var ClassLikeWithDependencies[] */
71+
/** @var array<string, ClassLikeWithDependencies> */
6872
private $classLikes = [];
69-
/** @var true[] */
73+
/** @var array<string, true> */
7074
private $resolvedClassLikes = [];
71-
/** @var Namespace_[] */
75+
/** @var array<Namespace_> */
7276
private $classLikeNamespaces = [];
7377
/** @var Namespace_|null */
7478
private $currentClassLikeNamespace = null;
@@ -79,8 +83,7 @@ class NodeVisitor extends NodeVisitorAbstract
7983
private $isInIf = false;
8084

8185
/**
82-
* @var int[][]
83-
* @psalm-var array<string, array<string, int>>
86+
* @var array<string, array<string, int>>
8487
*/
8588
private $counts = [
8689
'functions' => [],
@@ -93,6 +96,8 @@ class NodeVisitor extends NodeVisitorAbstract
9396

9497
/**
9598
* @param int $symbols Set of symbol types to include stubs for.
99+
* @param array<mixed> $config
100+
* @return void
96101
*/
97102
public function init(int $symbols = StubsGenerator::DEFAULT, array $config = [])
98103
{
@@ -113,6 +118,7 @@ public function init(int $symbols = StubsGenerator::DEFAULT, array $config = [])
113118
public function beforeTraverse(array $nodes)
114119
{
115120
$this->stack = [];
121+
return null;
116122
}
117123

118124
public function enterNode(Node $node)
@@ -121,7 +127,7 @@ public function enterNode(Node $node)
121127

122128
if ($node instanceof Namespace_) {
123129
// We always need to parse the children of namespaces.
124-
return;
130+
return null;
125131
}
126132

127133
if (($this->needsClasses && $node instanceof Class_)
@@ -180,14 +186,15 @@ public function enterNode(Node $node)
180186
// We'll examine the first level inside of an if statement to
181187
// look for function/class/etc. declarations.
182188
$this->isInIf = true;
183-
return; // Traverse children.
189+
return null; // Traverse children.
184190
}
185191
}
186192

187193
if (!$this->isInDeclaration) {
188194
// Don't bother parsing descendents of uninteresting nodes.
189195
return NodeTraverser::DONT_TRAVERSE_CHILDREN;
190196
}
197+
return null;
191198
}
192199

193200
public function leaveNode(Node $node, bool $preserveStack = false)
@@ -231,12 +238,12 @@ public function leaveNode(Node $node, bool $preserveStack = false)
231238

232239
if ($node instanceof Namespace_) {
233240
$this->namespaces[] = $node;
234-
return;
241+
return null;
235242
}
236243

237244
if ($node instanceof Name) {
238245
// Can't delete namespace names!
239-
return;
246+
return null;
240247
}
241248

242249
if ($parent && !($parent instanceof Namespace_)) {
@@ -250,7 +257,7 @@ public function leaveNode(Node $node, bool $preserveStack = false)
250257
}
251258
}
252259

253-
return;
260+
return null;
254261
}
255262

256263
$namespaceName = ($parent && $parent->name) ? $parent->name->toString() : '';
@@ -265,7 +272,7 @@ public function leaveNode(Node $node, bool $preserveStack = false)
265272
} elseif ($parent) {
266273
// If we're here, `$parent` is a namespace. Let's just keep the
267274
// `$node` around in `$parent->stmts`.
268-
return; // Don't remove.
275+
return null; // Don't remove.
269276
} elseif ($node instanceof Stmt) {
270277
// Anything other than a namespace which doesn't have a parent
271278
// node must belong in the global namespace. We can still remove
@@ -290,12 +297,13 @@ public function afterTraverse(array $nodes)
290297
$this->namespaces = array_filter($this->namespaces, function (Namespace_ $ns): bool {
291298
return (bool) $ns->stmts;
292299
});
300+
return null;
293301
}
294302

295303
/**
296304
* Returns the stored set of stub nodes which are built up during traversal.
297305
*
298-
* @return Node[]
306+
* @return array<Node>
299307
*/
300308
public function getStubStmts(): array
301309
{
@@ -325,7 +333,7 @@ public function getStubStmts(): array
325333
*
326334
* These counts are built up during traversal.
327335
*
328-
* @psalm-return array<string, array<string, int>>
336+
* @return array<string, array<string, int>>
329337
*/
330338
public function getCounts(): array
331339
{
@@ -394,7 +402,9 @@ function (\PhpParser\Node\Const_ $const) {
394402
$node instanceof Expression &&
395403
$node->expr instanceof FuncCall &&
396404
$node->expr->name instanceof Name &&
397-
$node->expr->name->getFirst() === 'define'
405+
$node->expr->name->getFirst() === 'define' &&
406+
$node->expr->args[0] instanceof Arg &&
407+
$node->expr->args[0]->value instanceof String_
398408
) {
399409
$fullyQualifiedName = $node->expr->args[0]->value->value;
400410

src/Result.php

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,23 @@
1010
/**
1111
* Contains the results of stub generation, including the stubs themselves as
1212
* well as some metadata.
13+
*
14+
* @implements IteratorAggregate<int, \PhpParser\Node>
1315
*/
1416
class Result implements IteratorAggregate
1517
{
1618
/** @var NodeVisitor */
1719
private $visitor;
1820

1921
/**
20-
* @var \Exception[]
21-
* @psalm-var array<string, \Exception>
22+
* @var array<string, \Exception>
2223
*/
2324
private $unparsed;
2425

2526
/**
2627
* @param NodeVisitor $visitor The visitor which was used to generate stubs.
27-
* @param \Exception[] $unparsed A map of file path => reason for any
28-
* unparsed files.
29-
* @psalm-param $unparsed array<string, \Exception>
28+
* @param array<string, \Exception> $unparsed A map of file path => reason
29+
* for any unparsed files.
3030
*/
3131
public function __construct(NodeVisitor $visitor, array $unparsed)
3232
{
@@ -43,7 +43,7 @@ public function getIterator(): Traversable
4343
* Returns the list of stub statements, which can be pretty-printed or
4444
* operated on further.
4545
*
46-
* @return \PhpParser\Node[]
46+
* @return array<\PhpParser\Node>
4747
*/
4848
public function getStubStmts(): array
4949
{
@@ -54,12 +54,7 @@ public function getStubStmts(): array
5454
* Returns a map of symbol type to count of unique symbols of that type
5555
* which are included in the stubs.
5656
*
57-
* Psalm doesn't seem to parse this correctly.
58-
* @psalm-suppress InvalidReturnType
59-
* @psalm-suppress InvalidReturnStatement
60-
*
61-
* @return int[]
62-
* @psalm-return array<string, int>
57+
* @return array<string, int>
6358
*/
6459
public function getStats(): array
6560
{
@@ -70,8 +65,7 @@ public function getStats(): array
7065
* Returns a list which includes any symbols for which more than one
7166
* declaration was found during stub generation.
7267
*
73-
* @return (string|int)[][]
74-
* @psalm-return array<array{ type: string, name: string, count: int }>
68+
* @return array<array{type: string, name: string, count: int}>
7569
*/
7670
public function getDuplicates(): array
7771
{

src/StubsGenerator.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,12 @@ class StubsGenerator
8989

9090
/** @var int */
9191
private $symbols;
92-
/** @var array */
92+
/** @var array<mixed> */
9393
private $config;
9494

9595
/**
9696
* @param int $symbols Bitmask of symbol types to include in the stubs.
97+
* @param array<mixed> $config
9798
*/
9899
public function __construct(int $symbols = self::DEFAULT, array $config = [])
99100
{

test/console-loader.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
foreach ([__DIR__ . '/../../../autoload.php', __DIR__ . '/../vendor/autoload.php'] as $file) {
4+
if (file_exists($file)) {
5+
require $file;
6+
break;
7+
}
8+
}
9+
10+
use StubsGenerator\GenerateStubsCommand;
11+
use Symfony\Component\Console\Application;
12+
13+
$command = new GenerateStubsCommand();
14+
$application = new Application();
15+
$application->add($command);
16+
$application->setDefaultCommand($command->getName(), true);
17+
18+
// Return the application for PHPStan (don't run it)
19+
return $application;

0 commit comments

Comments
 (0)