From 3175c81f26fd5bcb4a161b24e774921870ed2533 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Sat, 24 Aug 2024 12:33:05 +0200 Subject: [PATCH] Bleeding edge - add missing MissingTypehintCheck calls --- conf/config.level2.neon | 1 + src/Rules/Classes/MixinRule.php | 25 +++++++++++++++++++ tests/PHPStan/Rules/Classes/MixinRuleTest.php | 10 ++++++++ tests/PHPStan/Rules/Classes/data/mixin.php | 16 ++++++++++++ 4 files changed, 52 insertions(+) diff --git a/conf/config.level2.neon b/conf/config.level2.neon index 347bdb2629..72ff318df0 100644 --- a/conf/config.level2.neon +++ b/conf/config.level2.neon @@ -71,6 +71,7 @@ services: class: PHPStan\Rules\Classes\MixinRule arguments: checkClassCaseSensitivity: %checkClassCaseSensitivity% + absentTypeChecks: %featureToggles.absentTypeChecks% tags: - phpstan.rules.rule diff --git a/src/Rules/Classes/MixinRule.php b/src/Rules/Classes/MixinRule.php index 07e39383c7..56f19a7203 100644 --- a/src/Rules/Classes/MixinRule.php +++ b/src/Rules/Classes/MixinRule.php @@ -31,6 +31,7 @@ public function __construct( private MissingTypehintCheck $missingTypehintCheck, private UnresolvableTypeHelper $unresolvableTypeHelper, private bool $checkClassCaseSensitivity, + private bool $absentTypeChecks, ) { } @@ -83,6 +84,30 @@ public function processNode(Node $node, Scope $scope): array ->build(); } + if ($this->absentTypeChecks) { + foreach ($this->missingTypehintCheck->getIterableTypesWithMissingValueTypehint($type) as $iterableType) { + $iterableTypeDescription = $iterableType->describe(VerbosityLevel::typeOnly()); + $errors[] = RuleErrorBuilder::message(sprintf( + '%s %s has PHPDoc tag @mixin with no value type specified in iterable type %s.', + $classReflection->getClassTypeDescription(), + $classReflection->getDisplayName(), + $iterableTypeDescription, + )) + ->tip(MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP) + ->identifier('missingType.iterableValue') + ->build(); + } + + foreach ($this->missingTypehintCheck->getCallablesWithMissingSignature($type) as $callableType) { + $errors[] = RuleErrorBuilder::message(sprintf( + '%s %s has PHPDoc tag @mixin with no signature specified for %s.', + $classReflection->getClassTypeDescription(), + $classReflection->getDisplayName(), + $callableType->describe(VerbosityLevel::typeOnly()), + ))->identifier('missingType.callable')->build(); + } + } + foreach ($type->getReferencedClasses() as $class) { if (!$this->reflectionProvider->hasClass($class)) { $errors[] = RuleErrorBuilder::message(sprintf('PHPDoc tag @mixin contains unknown class %s.', $class)) diff --git a/tests/PHPStan/Rules/Classes/MixinRuleTest.php b/tests/PHPStan/Rules/Classes/MixinRuleTest.php index a396245146..1d93a8a299 100644 --- a/tests/PHPStan/Rules/Classes/MixinRuleTest.php +++ b/tests/PHPStan/Rules/Classes/MixinRuleTest.php @@ -32,6 +32,7 @@ protected function getRule(): Rule new MissingTypehintCheck(true, true, true, true, []), new UnresolvableTypeHelper(), true, + true, ); } @@ -97,6 +98,15 @@ public function testRule(): void 116, 'You can safely remove the call-site variance annotation.', ], + [ + 'Class MixinRule\NoIterableValue has PHPDoc tag @mixin with no value type specified in iterable type array.', + 124, + MissingTypehintCheck::MISSING_ITERABLE_VALUE_TYPE_TIP, + ], + [ + 'Class MixinRule\NoCallableSignature has PHPDoc tag @mixin with no signature specified for callable.', + 132, + ], ]); } diff --git a/tests/PHPStan/Rules/Classes/data/mixin.php b/tests/PHPStan/Rules/Classes/data/mixin.php index d5a3fafd67..b6ab1b092b 100644 --- a/tests/PHPStan/Rules/Classes/data/mixin.php +++ b/tests/PHPStan/Rules/Classes/data/mixin.php @@ -117,3 +117,19 @@ class Elit2 { } + +/** + * @mixin Dolor + */ +class NoIterableValue +{ + +} + +/** + * @mixin Dolor + */ +class NoCallableSignature +{ + +}