Skip to content

Commit

Permalink
TemplateTypeCheck tries to resolve template type names such as self
Browse files Browse the repository at this point in the history
… because they're not usable
  • Loading branch information
ondrejmirtes committed Oct 30, 2023
1 parent eb39381 commit c6fad64
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/Rules/Generics/ClassTemplateTypeRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public function processNode(Node $node, Scope $scope): array
}

return $this->templateTypeCheck->check(
$scope,
$node,
TemplateTypeScope::createWithClass($className),
$classReflection->getTemplateTags(),
Expand Down
1 change: 1 addition & 0 deletions src/Rules/Generics/FunctionTemplateTypeRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public function processNode(Node $node, Scope $scope): array
$escapedFunctionName = SprintfHelper::escapeFormatString($functionName);

return $this->templateTypeCheck->check(
$scope,
$node,
TemplateTypeScope::createWithFunction($functionName),
$resolvedPhpDoc->getTemplateTags(),
Expand Down
1 change: 1 addition & 0 deletions src/Rules/Generics/InterfaceTemplateTypeRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function processNode(Node $node, Scope $scope): array
$escapadInterfaceName = SprintfHelper::escapeFormatString($interfaceName);

return $this->templateTypeCheck->check(
$scope,
$node,
TemplateTypeScope::createWithClass($interfaceName),
$classReflection->getTemplateTags(),
Expand Down
1 change: 1 addition & 0 deletions src/Rules/Generics/MethodTemplateTypeRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public function processNode(Node $node, Scope $scope): array
$escapedClassName = SprintfHelper::escapeFormatString($className);
$escapedMethodName = SprintfHelper::escapeFormatString($methodName);
$messages = $this->templateTypeCheck->check(
$scope,
$node,
TemplateTypeScope::createWithMethod($className, $methodName),
$methodTemplateTags,
Expand Down
4 changes: 3 additions & 1 deletion src/Rules/Generics/TemplateTypeCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace PHPStan\Rules\Generics;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Internal\SprintfHelper;
use PHPStan\PhpDoc\Tag\TemplateTag;
use PHPStan\Reflection\ReflectionProvider;
Expand Down Expand Up @@ -53,6 +54,7 @@ public function __construct(
* @return RuleError[]
*/
public function check(
Scope $scope,
Node $node,
TemplateTypeScope $templateTypeScope,
array $templateTags,
Expand All @@ -64,7 +66,7 @@ public function check(
{
$messages = [];
foreach ($templateTags as $templateTag) {
$templateTagName = $templateTag->getName();
$templateTagName = $scope->resolveName(new Node\Name($templateTag->getName()));
if ($this->reflectionProvider->hasClass($templateTagName)) {
$messages[] = RuleErrorBuilder::message(sprintf(
$sameTemplateTypeNameAsClassMessage,
Expand Down
1 change: 1 addition & 0 deletions src/Rules/Generics/TraitTemplateTypeRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public function processNode(Node $node, Scope $scope): array
$escapedTraitName = SprintfHelper::escapeFormatString($traitName);

return $this->templateTypeCheck->check(
$scope,
$node,
TemplateTypeScope::createWithClass($traitName),
$resolvedPhpDoc->getTemplateTags(),
Expand Down
14 changes: 14 additions & 0 deletions tests/PHPStan/Rules/Generics/ClassTemplateTypeRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PHPStan\Rules\ClassCaseSensitivityCheck;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use const PHP_VERSION_ID;

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

public function testBug10049(): void
{
if (PHP_VERSION_ID < 80100) {
$this->markTestSkipped('Test requires PHP 8.1.');
}
$this->analyse([__DIR__ . '/data/bug-10049.php'], [
[
'PHPDoc tag @template for class Bug10049\SimpleEntity cannot have existing class Bug10049\SimpleEntity as its name.',
8,
],
]);
}

}
41 changes: 41 additions & 0 deletions tests/PHPStan/Rules/Generics/data/bug-10049.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php // lint >= 8.1

namespace Bug10049;

/**
* @template SELF of SimpleEntity
*/
abstract class SimpleEntity
{
/**
* @param SimpleTable<SELF> $table
*/
public function __construct(protected readonly SimpleTable $table)
{
}
}

/**
* @template-covariant E of SimpleEntity
*/
class SimpleTable
{
/**
* @template ENTITY of SimpleEntity
*
* @param class-string<ENTITY> $className
*
* @return SimpleTable<ENTITY>
*/
public static function table(string $className, string $name): SimpleTable
{
return new SimpleTable($className, $name);
}

/**
* @param class-string<E> $className
*/
private function __construct(readonly string $className, readonly string $table)
{
}
}

0 comments on commit c6fad64

Please sign in to comment.