Skip to content

Commit c6fad64

Browse files
committed
TemplateTypeCheck tries to resolve template type names such as self because they're not usable
1 parent eb39381 commit c6fad64

File tree

8 files changed

+63
-1
lines changed

8 files changed

+63
-1
lines changed

src/Rules/Generics/ClassTemplateTypeRule.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ public function processNode(Node $node, Scope $scope): array
4141
}
4242

4343
return $this->templateTypeCheck->check(
44+
$scope,
4445
$node,
4546
TemplateTypeScope::createWithClass($className),
4647
$classReflection->getTemplateTags(),

src/Rules/Generics/FunctionTemplateTypeRule.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public function processNode(Node $node, Scope $scope): array
5252
$escapedFunctionName = SprintfHelper::escapeFormatString($functionName);
5353

5454
return $this->templateTypeCheck->check(
55+
$scope,
5556
$node,
5657
TemplateTypeScope::createWithFunction($functionName),
5758
$resolvedPhpDoc->getTemplateTags(),

src/Rules/Generics/InterfaceTemplateTypeRule.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function processNode(Node $node, Scope $scope): array
3838
$escapadInterfaceName = SprintfHelper::escapeFormatString($interfaceName);
3939

4040
return $this->templateTypeCheck->check(
41+
$scope,
4142
$node,
4243
TemplateTypeScope::createWithClass($interfaceName),
4344
$classReflection->getTemplateTags(),

src/Rules/Generics/MethodTemplateTypeRule.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ public function processNode(Node $node, Scope $scope): array
5858
$escapedClassName = SprintfHelper::escapeFormatString($className);
5959
$escapedMethodName = SprintfHelper::escapeFormatString($methodName);
6060
$messages = $this->templateTypeCheck->check(
61+
$scope,
6162
$node,
6263
TemplateTypeScope::createWithMethod($className, $methodName),
6364
$methodTemplateTags,

src/Rules/Generics/TemplateTypeCheck.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace PHPStan\Rules\Generics;
44

55
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
67
use PHPStan\Internal\SprintfHelper;
78
use PHPStan\PhpDoc\Tag\TemplateTag;
89
use PHPStan\Reflection\ReflectionProvider;
@@ -53,6 +54,7 @@ public function __construct(
5354
* @return RuleError[]
5455
*/
5556
public function check(
57+
Scope $scope,
5658
Node $node,
5759
TemplateTypeScope $templateTypeScope,
5860
array $templateTags,
@@ -64,7 +66,7 @@ public function check(
6466
{
6567
$messages = [];
6668
foreach ($templateTags as $templateTag) {
67-
$templateTagName = $templateTag->getName();
69+
$templateTagName = $scope->resolveName(new Node\Name($templateTag->getName()));
6870
if ($this->reflectionProvider->hasClass($templateTagName)) {
6971
$messages[] = RuleErrorBuilder::message(sprintf(
7072
$sameTemplateTypeNameAsClassMessage,

src/Rules/Generics/TraitTemplateTypeRule.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ public function processNode(Node $node, Scope $scope): array
5252
$escapedTraitName = SprintfHelper::escapeFormatString($traitName);
5353

5454
return $this->templateTypeCheck->check(
55+
$scope,
5556
$node,
5657
TemplateTypeScope::createWithClass($traitName),
5758
$resolvedPhpDoc->getTemplateTags(),

tests/PHPStan/Rules/Generics/ClassTemplateTypeRuleTest.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use PHPStan\Rules\ClassCaseSensitivityCheck;
66
use PHPStan\Rules\Rule;
77
use PHPStan\Testing\RuleTestCase;
8+
use const PHP_VERSION_ID;
89

910
/**
1011
* @extends RuleTestCase<ClassTemplateTypeRule>
@@ -119,4 +120,17 @@ public function testInInterface(): void
119120
$this->analyse([__DIR__ . '/data/interface-template.php'], []);
120121
}
121122

123+
public function testBug10049(): void
124+
{
125+
if (PHP_VERSION_ID < 80100) {
126+
$this->markTestSkipped('Test requires PHP 8.1.');
127+
}
128+
$this->analyse([__DIR__ . '/data/bug-10049.php'], [
129+
[
130+
'PHPDoc tag @template for class Bug10049\SimpleEntity cannot have existing class Bug10049\SimpleEntity as its name.',
131+
8,
132+
],
133+
]);
134+
}
135+
122136
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php // lint >= 8.1
2+
3+
namespace Bug10049;
4+
5+
/**
6+
* @template SELF of SimpleEntity
7+
*/
8+
abstract class SimpleEntity
9+
{
10+
/**
11+
* @param SimpleTable<SELF> $table
12+
*/
13+
public function __construct(protected readonly SimpleTable $table)
14+
{
15+
}
16+
}
17+
18+
/**
19+
* @template-covariant E of SimpleEntity
20+
*/
21+
class SimpleTable
22+
{
23+
/**
24+
* @template ENTITY of SimpleEntity
25+
*
26+
* @param class-string<ENTITY> $className
27+
*
28+
* @return SimpleTable<ENTITY>
29+
*/
30+
public static function table(string $className, string $name): SimpleTable
31+
{
32+
return new SimpleTable($className, $name);
33+
}
34+
35+
/**
36+
* @param class-string<E> $className
37+
*/
38+
private function __construct(readonly string $className, readonly string $table)
39+
{
40+
}
41+
}

0 commit comments

Comments
 (0)