Skip to content

Commit 53c0d90

Browse files
Rename and use RuleLevelHelper
1 parent 154bb87 commit 53c0d90

File tree

7 files changed

+183
-17
lines changed

7 files changed

+183
-17
lines changed

conf/config.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ parameters:
6565
reportStaticMethodSignatures: false
6666
reportWrongPhpDocTypeInVarTag: false
6767
reportAnyTypeWideningInVarTag: false
68-
reportCastedArrayKey: false
68+
reportArrayKeyCast: false
6969
reportPossiblyNonexistentGeneralArrayOffset: false
7070
reportPossiblyNonexistentConstantArrayOffset: false
7171
checkMissingOverrideMethodAttribute: false

conf/parametersSchema.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ parametersSchema:
7575
reportStaticMethodSignatures: bool()
7676
reportWrongPhpDocTypeInVarTag: bool()
7777
reportAnyTypeWideningInVarTag: bool()
78-
reportCastedArrayKey: bool()
78+
reportArrayKeyCast: bool()
7979
reportPossiblyNonexistentGeneralArrayOffset: bool()
8080
reportPossiblyNonexistentConstantArrayOffset: bool()
8181
checkMissingOverrideMethodAttribute: bool()

src/Rules/Arrays/InvalidKeyInArrayDimFetchRule.php

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public function __construct(
2727
#[AutowiredParameter]
2828
private bool $reportMaybes,
2929
#[AutowiredParameter]
30-
private bool $reportCastedArrayKey,
30+
private bool $reportArrayKeyCast,
3131
)
3232
{
3333
}
@@ -43,24 +43,28 @@ public function processNode(Node $node, Scope $scope): array
4343
return [];
4444
}
4545

46-
$dimensionType = $scope->getType($node->dim);
47-
if ($dimensionType instanceof MixedType) {
48-
return [];
49-
}
50-
51-
$reportCastedArrayKey = $this->reportCastedArrayKey;
5246
$varType = $this->ruleLevelHelper->findTypeToCheck(
5347
$scope,
5448
$node->var,
5549
'',
56-
static fn (Type $varType): bool => $varType->isArray()->no() || AllowedArrayKeysTypes::getType($reportCastedArrayKey)->isSuperTypeOf($dimensionType)->yes(),
50+
static fn (Type $varType): bool => $varType->isArray()->no(),
5751
)->getType();
58-
5952
if ($varType instanceof ErrorType || $varType->isArray()->no()) {
6053
return [];
6154
}
6255

63-
$isSuperType = AllowedArrayKeysTypes::getType($this->reportCastedArrayKey)->isSuperTypeOf($dimensionType);
56+
$reportArrayKeyCast = $this->reportArrayKeyCast;
57+
$dimensionType = $this->ruleLevelHelper->findTypeToCheck(
58+
$scope,
59+
$node->dim,
60+
'',
61+
static fn (Type $dimType): bool => AllowedArrayKeysTypes::getType($reportArrayKeyCast)->isSuperTypeOf($dimType)->yes(),
62+
)->getType();
63+
if ($dimensionType instanceof MixedType) {
64+
return [];
65+
}
66+
67+
$isSuperType = AllowedArrayKeysTypes::getType($this->reportArrayKeyCast)->isSuperTypeOf($dimensionType);
6468
if ($isSuperType->yes() || ($isSuperType->maybe() && !$this->reportMaybes)) {
6569
return [];
6670
}

src/Rules/Arrays/InvalidKeyInArrayItemRule.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
use PHPStan\DependencyInjection\RegisteredRule;
99
use PHPStan\Rules\Rule;
1010
use PHPStan\Rules\RuleErrorBuilder;
11+
use PHPStan\Rules\RuleLevelHelper;
1112
use PHPStan\Type\MixedType;
13+
use PHPStan\Type\Type;
1214
use PHPStan\Type\VerbosityLevel;
1315
use function sprintf;
1416

@@ -20,10 +22,11 @@ final class InvalidKeyInArrayItemRule implements Rule
2022
{
2123

2224
public function __construct(
25+
private RuleLevelHelper $ruleLevelHelper,
2326
#[AutowiredParameter]
2427
private bool $reportMaybes,
2528
#[AutowiredParameter]
26-
private bool $reportCastedArrayKey,
29+
private bool $reportArrayKeyCast,
2730
)
2831
{
2932
}
@@ -39,8 +42,16 @@ public function processNode(Node $node, Scope $scope): array
3942
return [];
4043
}
4144

42-
$dimensionType = $scope->getType($node->key);
43-
$isSuperType = AllowedArrayKeysTypes::getType($this->reportCastedArrayKey)->isSuperTypeOf($dimensionType);
45+
$reportArrayKeyCast = $this->reportArrayKeyCast;
46+
$dimensionType = $this->ruleLevelHelper->findTypeToCheck(
47+
$scope,
48+
$node->key,
49+
'',
50+
static fn (Type $dimType): bool => AllowedArrayKeysTypes::getType($reportArrayKeyCast)->isSuperTypeOf($dimType)->yes(),
51+
)->getType();
52+
53+
54+
$isSuperType = AllowedArrayKeysTypes::getType($reportArrayKeyCast)->isSuperTypeOf($dimensionType);
4455
if ($isSuperType->no()) {
4556
return [
4657
RuleErrorBuilder::message(

tests/PHPStan/Rules/Arrays/InvalidKeyInArrayDimFetchRuleTest.php

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,12 @@ class InvalidKeyInArrayDimFetchRuleTest extends RuleTestCase
1414
{
1515

1616
private bool $reportCastedArrayKey = false;
17+
private bool $checkUnionType = true;
18+
private bool $checkNullable = true;
1719

1820
protected function getRule(): Rule
1921
{
20-
$ruleLevelHelper = new RuleLevelHelper(self::createReflectionProvider(), true, false, true, false, false, false, true);
22+
$ruleLevelHelper = new RuleLevelHelper(self::createReflectionProvider(), $this->checkNullable, false, $this->checkUnionType, false, false, false, true);
2123
return new InvalidKeyInArrayDimFetchRule($ruleLevelHelper, true, $this->reportCastedArrayKey);
2224
}
2325

@@ -63,6 +65,46 @@ public function testInvalidKey(): void
6365
]);
6466
}
6567

68+
public function testInvalidKeyOnLevel6(): void
69+
{
70+
$this->checkNullable = false;
71+
$this->checkUnionType = false;
72+
$this->analyse([__DIR__ . '/data/invalid-key-array-dim-fetch.php'], [
73+
[
74+
'Invalid array key type DateTimeImmutable.',
75+
7,
76+
],
77+
[
78+
'Invalid array key type array.',
79+
8,
80+
],
81+
[
82+
'Invalid array key type DateTimeImmutable.',
83+
31,
84+
],
85+
[
86+
'Invalid array key type DateTimeImmutable.',
87+
45,
88+
],
89+
[
90+
'Invalid array key type DateTimeImmutable.',
91+
46,
92+
],
93+
[
94+
'Invalid array key type DateTimeImmutable.',
95+
47,
96+
],
97+
[
98+
'Invalid array key type stdClass.',
99+
47,
100+
],
101+
[
102+
'Invalid array key type DateTimeImmutable.',
103+
48,
104+
],
105+
]);
106+
}
107+
66108
public function testInvalidKeyReportingCastedArrayKey(): void
67109
{
68110
$this->reportCastedArrayKey = true;
@@ -126,6 +168,63 @@ public function testInvalidKeyReportingCastedArrayKey(): void
126168
]);
127169
}
128170

171+
public function testInvalidKeyReportingCastedArrayKeyOnLevel6(): void
172+
{
173+
$this->checkNullable = false;
174+
$this->checkUnionType = false;
175+
$this->reportCastedArrayKey = true;
176+
$this->analyse([__DIR__ . '/data/invalid-key-array-dim-fetch.php'], [
177+
[
178+
'Invalid array key type null.',
179+
6,
180+
],
181+
[
182+
'Invalid array key type DateTimeImmutable.',
183+
7,
184+
],
185+
[
186+
'Invalid array key type array.',
187+
8,
188+
],
189+
[
190+
'Invalid array key type float.',
191+
10,
192+
],
193+
[
194+
'Invalid array key type true.',
195+
12,
196+
],
197+
[
198+
'Invalid array key type false.',
199+
13,
200+
],
201+
[
202+
'Invalid array key type DateTimeImmutable.',
203+
31,
204+
],
205+
[
206+
'Invalid array key type DateTimeImmutable.',
207+
45,
208+
],
209+
[
210+
'Invalid array key type DateTimeImmutable.',
211+
46,
212+
],
213+
[
214+
'Invalid array key type DateTimeImmutable.',
215+
47,
216+
],
217+
[
218+
'Invalid array key type stdClass.',
219+
47,
220+
],
221+
[
222+
'Invalid array key type DateTimeImmutable.',
223+
48,
224+
],
225+
]);
226+
}
227+
129228
#[RequiresPhp('>= 8.1')]
130229
public function testBug6315(): void
131230
{

tests/PHPStan/Rules/Arrays/InvalidKeyInArrayItemRuleTest.php

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

55
use PHPStan\Rules\Rule;
6+
use PHPStan\Rules\RuleLevelHelper;
67
use PHPStan\Testing\RuleTestCase;
78
use PHPUnit\Framework\Attributes\RequiresPhp;
89

@@ -13,10 +14,13 @@ class InvalidKeyInArrayItemRuleTest extends RuleTestCase
1314
{
1415

1516
private bool $reportCastedArrayKey = false;
17+
private bool $checkUnionType = true;
18+
private bool $checkNullable = true;
1619

1720
protected function getRule(): Rule
1821
{
19-
return new InvalidKeyInArrayItemRule(true, $this->reportCastedArrayKey);
22+
$ruleLevelHelper = new RuleLevelHelper(self::createReflectionProvider(), $this->checkNullable, false, $this->checkUnionType, false, false, false, true);
23+
return new InvalidKeyInArrayItemRule($ruleLevelHelper, true, $this->reportCastedArrayKey);
2024
}
2125

2226
public function testInvalidKey(): void
@@ -37,6 +41,22 @@ public function testInvalidKey(): void
3741
]);
3842
}
3943

44+
public function testInvalidKeyOnLevel6(): void
45+
{
46+
$this->checkNullable = false;
47+
$this->checkUnionType = false;
48+
$this->analyse([__DIR__ . '/data/invalid-key-array-item.php'], [
49+
[
50+
'Invalid array key type DateTimeImmutable.',
51+
13,
52+
],
53+
[
54+
'Invalid array key type array.',
55+
14,
56+
],
57+
]);
58+
}
59+
4060
public function testInvalidKeyReportingCastedArrayKey(): void
4161
{
4262
$this->reportCastedArrayKey = true;
@@ -57,6 +77,31 @@ public function testInvalidKeyReportingCastedArrayKey(): void
5777
'Possibly invalid array key type stdClass|string.',
5878
15,
5979
],
80+
[
81+
'Possibly invalid array key type string|null.',
82+
22,
83+
],
84+
]);
85+
}
86+
87+
public function testInvalidKeyReportingCastedArrayKeyOnLevel6(): void
88+
{
89+
$this->checkNullable = false;
90+
$this->checkUnionType = false;
91+
$this->reportCastedArrayKey = true;
92+
$this->analyse([__DIR__ . '/data/invalid-key-array-item.php'], [
93+
[
94+
'Invalid array key type null.',
95+
12,
96+
],
97+
[
98+
'Invalid array key type DateTimeImmutable.',
99+
13,
100+
],
101+
[
102+
'Invalid array key type array.',
103+
14,
104+
],
60105
]);
61106
}
62107

tests/PHPStan/Rules/Arrays/data/invalid-key-array-item.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,10 @@
1414
[] => 'bbb',
1515
$stringOrObject => 'aaa',
1616
];
17+
18+
/** @var string|null $stringOrNull */
19+
$stringOrNull = doFoo();
20+
21+
$b = [
22+
$stringOrNull => 'aaa',
23+
];

0 commit comments

Comments
 (0)