Skip to content

Commit 80f4734

Browse files
committed
ScopeGetTypeInGeneratorNamespaceRule
1 parent d07c200 commit 80f4734

File tree

4 files changed

+163
-0
lines changed

4 files changed

+163
-0
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Build;
4+
5+
use PhpParser\Node;
6+
use PhpParser\Node\Expr\MethodCall;
7+
use PHPStan\Analyser\Scope;
8+
use PHPStan\Rules\Rule;
9+
use PHPStan\Rules\RuleErrorBuilder;
10+
use PHPStan\Type\ObjectType;
11+
use PHPUnit\Framework\TestCase;
12+
use function sprintf;
13+
use function str_starts_with;
14+
15+
/**
16+
* @implements Rule<MethodCall>
17+
*/
18+
final class ScopeGetTypeInGeneratorNamespaceRule implements Rule
19+
{
20+
21+
public function getNodeType(): string
22+
{
23+
return MethodCall::class;
24+
}
25+
26+
public function processNode(Node $node, Scope $scope): array
27+
{
28+
$namespace = $scope->getNamespace();
29+
if ($namespace === null) {
30+
return [];
31+
}
32+
33+
$invalidNamespace = 'PHPStan\\Analyser\\Generator';
34+
if (!str_starts_with($namespace . '\\', $invalidNamespace . '\\')) {
35+
return [];
36+
}
37+
38+
if (!$node->name instanceof Node\Identifier) {
39+
return [];
40+
}
41+
42+
if ($node->name->toLowerString() !== 'gettype') {
43+
return [];
44+
}
45+
46+
$scopeType = new ObjectType(Scope::class);
47+
$calledOnType = $scope->getType($node->var);
48+
if (!$scopeType->isSuperTypeOf($calledOnType)->yes()) {
49+
return [];
50+
}
51+
52+
if ($scope->isInClass()) {
53+
$inClass = $scope->getClassReflection();
54+
if ($inClass->is(TestCase::class)) {
55+
return [];
56+
}
57+
}
58+
59+
return [
60+
RuleErrorBuilder::message(sprintf(
61+
'Scope::getType() cannot be called in %s namespace.',
62+
$invalidNamespace,
63+
))
64+
->identifier('phpstan.scopeGetType')
65+
->tip('Use new ExprAnalysisRequest instead.')
66+
->build(),
67+
];
68+
}
69+
70+
}

build/phpstan.neon

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ rules:
140140
- PHPStan\Build\SkipTestsWithRequiresPhpAttributeRule
141141
- PHPStan\Build\MemoizationPropertyRule
142142
- PHPStan\Build\OrChainIdenticalComparisonToInArrayRule
143+
- PHPStan\Build\ScopeGetTypeInGeneratorNamespaceRule
143144

144145
services:
145146
-
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Build;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
/**
9+
* @extends RuleTestCase<ScopeGetTypeInGeneratorNamespaceRule>
10+
*/
11+
class ScopeGetTypeInGeneratorNamespaceRuleTest extends RuleTestCase
12+
{
13+
14+
protected function getRule(): Rule
15+
{
16+
return new ScopeGetTypeInGeneratorNamespaceRule();
17+
}
18+
19+
public function testRule(): void
20+
{
21+
$this->analyse([__DIR__ . '/data/scope-get-type-generator-ns.php'], [
22+
[
23+
'Scope::getType() cannot be called in PHPStan\Analyser\Generator namespace.',
24+
27,
25+
'Use new ExprAnalysisRequest instead.',
26+
],
27+
[
28+
'Scope::getType() cannot be called in PHPStan\Analyser\Generator namespace.',
29+
43,
30+
'Use new ExprAnalysisRequest instead.',
31+
],
32+
[
33+
'Scope::getType() cannot be called in PHPStan\Analyser\Generator namespace.',
34+
48,
35+
'Use new ExprAnalysisRequest instead.',
36+
],
37+
]);
38+
}
39+
40+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace ScopeGetTypeGeneratorNs {
4+
5+
use PHPStan\Analyser\Scope;
6+
7+
class Foo
8+
{
9+
10+
public function doFoo(Scope $scope): void
11+
{
12+
$scope->getType();
13+
}
14+
15+
}
16+
}
17+
18+
namespace PHPStan\Analyser\Generator {
19+
20+
use PHPStan\Analyser\Scope;
21+
22+
class Foo
23+
{
24+
25+
public function doFoo(Scope $scope): void
26+
{
27+
$scope->getType();
28+
}
29+
30+
}
31+
}
32+
33+
namespace PHPStan\Analyser\Generator\ExprHandler {
34+
35+
use PHPStan\Analyser\Generator\GeneratorScope;
36+
use PHPStan\Analyser\Scope;
37+
38+
class Foo
39+
{
40+
41+
public function doFoo(Scope $scope): void
42+
{
43+
$scope->getType();
44+
}
45+
46+
public function doBar(GeneratorScope $scope): void
47+
{
48+
$scope->getType();
49+
}
50+
51+
}
52+
}

0 commit comments

Comments
 (0)