Skip to content

Commit 7dc98b6

Browse files
committed
Playground rule - StaticVarWithoutTypeRule
1 parent 33a45f4 commit 7dc98b6

File tree

4 files changed

+154
-0
lines changed

4 files changed

+154
-0
lines changed

issue-bot/playground.neon

+8
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,11 @@ rules:
33
- PHPStan\Rules\Playground\MethodNeverRule
44
- PHPStan\Rules\Playground\NotAnalysedTraitRule
55
- PHPStan\Rules\Playground\NoPhpCodeRule
6+
7+
conditionalTags:
8+
PHPStan\Rules\Playground\StaticVarWithoutTypeRule:
9+
phpstan.rules.rule: %checkImplicitMixed%
10+
11+
services:
12+
-
13+
class: PHPStan\Rules\Playground\StaticVarWithoutTypeRule
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Playground;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\Rules\Rule;
8+
use PHPStan\Rules\RuleErrorBuilder;
9+
use PHPStan\ShouldNotHappenException;
10+
use PHPStan\Type\FileTypeMapper;
11+
use function count;
12+
use function is_string;
13+
14+
/**
15+
* @implements Rule<Node\Stmt\Static_>
16+
*/
17+
final class StaticVarWithoutTypeRule implements Rule
18+
{
19+
20+
public function __construct(
21+
private FileTypeMapper $fileTypeMapper,
22+
)
23+
{
24+
}
25+
26+
public function getNodeType(): string
27+
{
28+
return Node\Stmt\Static_::class;
29+
}
30+
31+
public function processNode(Node $node, Scope $scope): array
32+
{
33+
$docComment = $node->getDocComment();
34+
$ruleError = RuleErrorBuilder::message('Static variable needs to be typed with PHPDoc @var tag.')
35+
->identifier('phpstanPlayground.staticWithoutType')
36+
->build();
37+
if ($docComment === null) {
38+
return [$ruleError];
39+
}
40+
$variableNames = [];
41+
foreach ($node->vars as $var) {
42+
if (!is_string($var->var->name)) {
43+
throw new ShouldNotHappenException();
44+
}
45+
46+
$variableNames[] = $var->var->name;
47+
}
48+
49+
$function = $scope->getFunction();
50+
$resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc(
51+
$scope->getFile(),
52+
$scope->isInClass() ? $scope->getClassReflection()->getName() : null,
53+
$scope->isInTrait() ? $scope->getTraitReflection()->getName() : null,
54+
$function !== null ? $function->getName() : null,
55+
$docComment->getText(),
56+
);
57+
$varTags = [];
58+
foreach ($resolvedPhpDoc->getVarTags() as $key => $varTag) {
59+
$varTags[$key] = $varTag;
60+
}
61+
62+
if (count($varTags) === 0) {
63+
return [$ruleError];
64+
}
65+
66+
if (count($variableNames) === 1 && count($varTags) === 1 && isset($varTags[0])) {
67+
return [];
68+
}
69+
70+
foreach ($variableNames as $variableName) {
71+
if (isset($varTags[$variableName])) {
72+
continue;
73+
}
74+
75+
return [$ruleError];
76+
}
77+
78+
return [];
79+
}
80+
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Playground;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
use PHPStan\Type\FileTypeMapper;
8+
9+
/**
10+
* @extends RuleTestCase<StaticVarWithoutTypeRule>
11+
*/
12+
class StaticVarWithoutTypeRuleTest extends RuleTestCase
13+
{
14+
15+
protected function getRule(): Rule
16+
{
17+
return new StaticVarWithoutTypeRule(self::getContainer()->getByType(FileTypeMapper::class));
18+
}
19+
20+
public function testRule(): void
21+
{
22+
$this->analyse([__DIR__ . '/data/static-var-without-type.php'], [
23+
[
24+
'Static variable needs to be typed with PHPDoc @var tag.',
25+
23,
26+
],
27+
[
28+
'Static variable needs to be typed with PHPDoc @var tag.',
29+
28,
30+
],
31+
]);
32+
}
33+
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace StaticVarWithoutType;
4+
5+
class Foo
6+
{
7+
8+
public function doFoo(): void
9+
{
10+
/** @var int */
11+
static $i = 0;
12+
}
13+
14+
public function doBar(): void
15+
{
16+
/** @var int $i */
17+
static $i = 0;
18+
}
19+
20+
public function doBaz(): void
21+
{
22+
/** @var int $j */
23+
static $i = 0;
24+
}
25+
26+
public function doLorem(): void
27+
{
28+
static $i = 0;
29+
}
30+
31+
}

0 commit comments

Comments
 (0)