From 841156e7113716f676f8384500f483f0e69a77f2 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Sat, 27 Sep 2025 22:18:52 +0200 Subject: [PATCH] Rely on RuleLevelHelper in InvalidKeyInArrayItemRule --- .../Arrays/InvalidKeyInArrayItemRule.php | 41 +++++++++++-------- .../Arrays/InvalidKeyInArrayItemRuleTest.php | 34 ++++++++++++++- .../Arrays/data/invalid-key-array-item.php | 7 ++++ 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/src/Rules/Arrays/InvalidKeyInArrayItemRule.php b/src/Rules/Arrays/InvalidKeyInArrayItemRule.php index 993a6dde61..a4c76cfc8a 100644 --- a/src/Rules/Arrays/InvalidKeyInArrayItemRule.php +++ b/src/Rules/Arrays/InvalidKeyInArrayItemRule.php @@ -4,11 +4,12 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; -use PHPStan\DependencyInjection\AutowiredParameter; use PHPStan\DependencyInjection\RegisteredRule; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\Type\MixedType; +use PHPStan\Rules\RuleLevelHelper; +use PHPStan\Type\ErrorType; +use PHPStan\Type\Type; use PHPStan\Type\VerbosityLevel; use function sprintf; @@ -20,8 +21,7 @@ final class InvalidKeyInArrayItemRule implements Rule { public function __construct( - #[AutowiredParameter] - private bool $reportMaybes, + private RuleLevelHelper $ruleLevelHelper, ) { } @@ -37,23 +37,28 @@ public function processNode(Node $node, Scope $scope): array return []; } - $dimensionType = $scope->getType($node->key); + $dimensionType = $this->ruleLevelHelper->findTypeToCheck( + $scope, + $node->key, + '', + static fn (Type $dimType): bool => AllowedArrayKeysTypes::getType()->isSuperTypeOf($dimType)->yes(), + )->getType(); + if ($dimensionType instanceof ErrorType) { + return []; + } + $isSuperType = AllowedArrayKeysTypes::getType()->isSuperTypeOf($dimensionType); - if ($isSuperType->no()) { - return [ - RuleErrorBuilder::message( - sprintf('Invalid array key type %s.', $dimensionType->describe(VerbosityLevel::typeOnly())), - )->identifier('array.invalidKey')->build(), - ]; - } elseif ($this->reportMaybes && $isSuperType->maybe() && !$dimensionType instanceof MixedType) { - return [ - RuleErrorBuilder::message( - sprintf('Possibly invalid array key type %s.', $dimensionType->describe(VerbosityLevel::typeOnly())), - )->identifier('array.invalidKey')->build(), - ]; + if ($isSuperType->yes()) { + return []; } - return []; + return [ + RuleErrorBuilder::message(sprintf( + '%s array key type %s.', + $isSuperType->no() ? 'Invalid' : 'Possibly invalid', + $dimensionType->describe(VerbosityLevel::typeOnly()), + ))->identifier('array.invalidKey')->build(), + ]; } } diff --git a/tests/PHPStan/Rules/Arrays/InvalidKeyInArrayItemRuleTest.php b/tests/PHPStan/Rules/Arrays/InvalidKeyInArrayItemRuleTest.php index ab486eeacf..17664a61f8 100644 --- a/tests/PHPStan/Rules/Arrays/InvalidKeyInArrayItemRuleTest.php +++ b/tests/PHPStan/Rules/Arrays/InvalidKeyInArrayItemRuleTest.php @@ -3,6 +3,7 @@ namespace PHPStan\Rules\Arrays; use PHPStan\Rules\Rule; +use PHPStan\Rules\RuleLevelHelper; use PHPStan\Testing\RuleTestCase; use PHPUnit\Framework\Attributes\RequiresPhp; @@ -12,9 +13,15 @@ class InvalidKeyInArrayItemRuleTest extends RuleTestCase { + private bool $checkExplicitMixed = false; + + private bool $checkImplicitMixed = false; + protected function getRule(): Rule { - return new InvalidKeyInArrayItemRule(true); + $ruleLevelHelper = new RuleLevelHelper(self::createReflectionProvider(), true, false, true, $this->checkExplicitMixed, $this->checkImplicitMixed, false, true); + + return new InvalidKeyInArrayItemRule($ruleLevelHelper); } public function testInvalidKey(): void @@ -35,6 +42,31 @@ public function testInvalidKey(): void ]); } + public function testInvalidMixedKey(): void + { + $this->checkExplicitMixed = true; + $this->checkImplicitMixed = true; + + $this->analyse([__DIR__ . '/data/invalid-key-array-item.php'], [ + [ + 'Invalid array key type DateTimeImmutable.', + 13, + ], + [ + 'Invalid array key type array.', + 14, + ], + [ + 'Possibly invalid array key type stdClass|string.', + 15, + ], + [ + 'Possibly invalid array key type mixed.', + 22, + ], + ]); + } + public function testInvalidKeyInList(): void { $this->analyse([__DIR__ . '/data/invalid-key-list.php'], [ diff --git a/tests/PHPStan/Rules/Arrays/data/invalid-key-array-item.php b/tests/PHPStan/Rules/Arrays/data/invalid-key-array-item.php index cde86133df..0343a0b1ad 100644 --- a/tests/PHPStan/Rules/Arrays/data/invalid-key-array-item.php +++ b/tests/PHPStan/Rules/Arrays/data/invalid-key-array-item.php @@ -14,3 +14,10 @@ [] => 'bbb', $stringOrObject => 'aaa', ]; + +/** @var mixed $mixed */ +$mixed = doFoo(); + +$b = [ + $mixed => 'foo', +];