Skip to content

Commit

Permalink
TemplateTypeCheck - look for nested unsupported types
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Feb 25, 2021
1 parent ea7e0ac commit 756af18
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 14 deletions.
27 changes: 16 additions & 11 deletions src/Rules/Generics/TemplateTypeCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeTraverser;
use PHPStan\Type\UnionType;
use PHPStan\Type\VerbosityLevel;
use function array_key_exists;
Expand Down Expand Up @@ -101,18 +103,21 @@ public function check(
$messages = array_merge($messages, $this->classCaseSensitivityCheck->checkClassNames($classNameNodePairs));
}

$bound = $templateTag->getBound();
$boundClass = get_class($bound);
if (
$boundClass === MixedType::class
|| $boundClass === ObjectWithoutClassType::class
|| $bound instanceof ObjectType
|| $bound instanceof UnionType
) {
continue;
}
TypeTraverser::map($templateTag->getBound(), static function (Type $type, callable $traverse) use (&$messages, $notSupportedBoundMessage, $templateTagName): Type {
$boundClass = get_class($type);
if (
$boundClass === MixedType::class
|| $boundClass === ObjectWithoutClassType::class
|| $boundClass === ObjectType::class
|| $type instanceof UnionType
) {
return $traverse($type);
}

$messages[] = RuleErrorBuilder::message(sprintf($notSupportedBoundMessage, $templateTagName, $type->describe(VerbosityLevel::typeOnly())))->build();

$messages[] = RuleErrorBuilder::message(sprintf($notSupportedBoundMessage, $templateTagName, $boundType->describe(VerbosityLevel::typeOnly())))->build();
return $type;
});
}

return $messages;
Expand Down
5 changes: 2 additions & 3 deletions src/Type/Generic/TemplateTypeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ public static function create(TemplateTypeScope $scope, string $name, ?Type $bou
return new TemplateMixedType($scope, $strategy, $variance, $name);
}

if ($bound instanceof ObjectType) {
$boundClass = get_class($bound);
if ($boundClass === ObjectType::class) {
return new TemplateObjectType($scope, $strategy, $variance, $name, $bound->getClassName());
}

$boundClass = get_class($bound);
if ($boundClass === ObjectWithoutClassType::class) {
return new TemplateObjectWithoutClassType($scope, $strategy, $variance, $name);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public function testRule(): void
'PHPDoc tag @template for interface InterfaceTemplateType\Lorem cannot have existing type alias TypeAlias as its name.',
32,
],
[
'PHPDoc tag @template T for interface InterfaceTemplateType\UnionBound with bound type InterfaceTemplateType\NormalT<stdClass> is not supported.',
44,
],
]);
}

Expand Down
12 changes: 12 additions & 0 deletions tests/PHPStan/Rules/Generics/data/interface-template.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,15 @@ interface Lorem
{

}

/** @template T */
interface NormalT
{

}

/** @template T of NormalT<\stdClass>|\stdClass */
interface UnionBound
{

}

0 comments on commit 756af18

Please sign in to comment.