Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 02fd76b

Browse files
Introduce reportCastedArrayKey parameter
1 parent 71f7b78 commit 02fd76b

File tree

9 files changed

+98
-10
lines changed

9 files changed

+98
-10
lines changed

‎conf/config.neon‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ parameters:
7676
reportStaticMethodSignatures: false
7777
reportWrongPhpDocTypeInVarTag: false
7878
reportAnyTypeWideningInVarTag: false
79+
reportArrayKeyCast: false
7980
reportPossiblyNonexistentGeneralArrayOffset: false
8081
reportPossiblyNonexistentConstantArrayOffset: false
8182
checkMissingOverrideMethodAttribute: false

‎conf/parametersSchema.neon‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ parametersSchema:
8585
reportStaticMethodSignatures: bool()
8686
reportWrongPhpDocTypeInVarTag: bool()
8787
reportAnyTypeWideningInVarTag: bool()
88+
reportArrayKeyCast: bool()
8889
reportPossiblyNonexistentGeneralArrayOffset: bool()
8990
reportPossiblyNonexistentConstantArrayOffset: bool()
9091
checkMissingOverrideMethodAttribute: bool()

‎src/Rules/Arrays/AllowedArrayKeysTypes.php‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,23 @@
2222
final class AllowedArrayKeysTypes
2323
{
2424

25-
public static function getType(?PhpVersion $phpVersion = null): Type
25+
public static function getType(?PhpVersion $phpVersion = null, bool$strict = false): Type
2626
{
2727
$types = [
2828
new IntegerType(),
2929
new StringType(),
3030
new BooleanType(),
3131
];
3232

33-
if ($phpVersion === null || !$phpVersion->deprecatesImplicitlyFloatConversionToInt()) {
34-
$types[] = new FloatType();
35-
}
36-
if ($phpVersion === null || !$phpVersion->deprecatesNullArrayOffset()) {
37-
$types[] = new NullType();
33+
if (!$strict) {
34+
$types[] = new BooleanType();
35+
36+
if ($phpVersion === null || !$phpVersion->deprecatesImplicitlyFloatConversionToInt()) {
37+
$types[] = new FloatType();
38+
}
39+
if ($phpVersion === null || !$phpVersion->deprecatesNullArrayOffset()) {
40+
$types[] = new NullType();
41+
}
3842
}
3943

4044
return new UnionType($types);

‎src/Rules/Arrays/InvalidKeyInArrayDimFetchRule.php‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public function __construct(
2727
private PhpVersion $phpVersion,
2828
#[AutowiredParameter]
2929
private bool $reportMaybes,
30+
#[AutowiredParameter]
31+
private bool $reportArrayKeyCast,
3032
)
3133
{
3234
}
@@ -59,17 +61,18 @@ public function processNode(Node $node, Scope $scope): array
5961
}
6062

6163
$phpVersion = $this->phpVersion;
64+
$reportArrayKeyCast = $this->reportArrayKeyCast;
6265
$dimensionType = $this->ruleLevelHelper->findTypeToCheck(
6366
$scope,
6467
$node->dim,
6568
'',
66-
static fn (Type $dimType): bool => AllowedArrayKeysTypes::getType($phpVersion)->isSuperTypeOf($dimType)->yes(),
69+
static fn (Type $dimType): bool => AllowedArrayKeysTypes::getType($phpVersion, $reportArrayKeyCast)->isSuperTypeOf($dimType)->yes(),
6770
)->getType();
6871
if ($dimensionType instanceof ErrorType) {
6972
return [];
7073
}
7174

72-
$isSuperType = AllowedArrayKeysTypes::getType($phpVersion)->isSuperTypeOf($dimensionType);
75+
$isSuperType = AllowedArrayKeysTypes::getType($phpVersion, $reportArrayKeyCast)->isSuperTypeOf($dimensionType);
7376
if ($isSuperType->yes() || ($isSuperType->maybe() && !$this->reportMaybes)) {
7477
return [];
7578
}

‎src/Rules/Arrays/InvalidKeyInArrayItemRule.php‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PhpParser\Node;
66
use PHPStan\Analyser\Scope;
7+
use PHPStan\DependencyInjection\AutowiredParameter;
78
use PHPStan\DependencyInjection\RegisteredRule;
89
use PHPStan\Php\PhpVersion;
910
use PHPStan\Rules\Rule;
@@ -24,6 +25,8 @@ final class InvalidKeyInArrayItemRule implements Rule
2425
public function __construct(
2526
private RuleLevelHelper $ruleLevelHelper,
2627
private PhpVersion $phpVersion,
28+
#[AutowiredParameter]
29+
private bool $reportArrayKeyCast,
2730
)
2831
{
2932
}
@@ -40,17 +43,18 @@ public function processNode(Node $node, Scope $scope): array
4043
}
4144

4245
$phpVersion = $this->phpVersion;
46+
$reportArrayKeyCast = $this->reportArrayKeyCast;
4347
$dimensionType = $this->ruleLevelHelper->findTypeToCheck(
4448
$scope,
4549
$node->key,
4650
'',
47-
static fn (Type $dimType): bool => AllowedArrayKeysTypes::getType($phpVersion)->isSuperTypeOf($dimType)->yes(),
51+
static fn (Type $dimType): bool => AllowedArrayKeysTypes::getType($phpVersion, $reportArrayKeyCast)->isSuperTypeOf($dimType)->yes(),
4852
)->getType();
4953
if ($dimensionType instanceof ErrorType) {
5054
return [];
5155
}
5256

53-
$isSuperType = AllowedArrayKeysTypes::getType($phpVersion)->isSuperTypeOf($dimensionType);
57+
$isSuperType = AllowedArrayKeysTypes::getType($phpVersion, $reportArrayKeyCast)->isSuperTypeOf($dimensionType);
5458
if ($isSuperType->yes()) {
5559
return [];
5660
}

‎tests/PHPStan/Rules/Arrays/InvalidKeyInArrayDimFetchRuleTest.php‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
class InvalidKeyInArrayDimFetchRuleTest extends RuleTestCase
1616
{
1717

18+
private bool $reportCastedArrayKey = false;
19+
1820
protected function getRule(): Rule
1921
{
2022
$ruleLevelHelper = new RuleLevelHelper(self::createReflectionProvider(), true, false, true, true, true, false, true);
2123
return new InvalidKeyInArrayDimFetchRule(
2224
$ruleLevelHelper,
2325
self::getContainer()->getByType(PhpVersion::class),
2426
true,
27+
$this->reportCastedArrayKey,
2528
);
2629
}
2730

@@ -163,4 +166,20 @@ public function testBug12981(): void
163166
]);
164167
}
165168

169+
public function testUnsetFalseKey(): void
170+
{
171+
$this->reportCastedArrayKey = true;
172+
173+
$this->analyse([__DIR__ . '/data/unset-false-key.php'], [
174+
[
175+
'Invalid array key type false.',
176+
6,
177+
],
178+
[
179+
'Invalid array key type false.',
180+
13,
181+
],
182+
]);
183+
}
184+
166185
}

‎tests/PHPStan/Rules/Arrays/InvalidKeyInArrayItemRuleTest.php‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
class InvalidKeyInArrayItemRuleTest extends RuleTestCase
1616
{
1717

18+
private bool $reportCastedArrayKey = false;
19+
1820
private bool $checkExplicitMixed = false;
1921

2022
private bool $checkImplicitMixed = false;
@@ -26,6 +28,7 @@ protected function getRule(): Rule
2628
return new InvalidKeyInArrayItemRule(
2729
$ruleLevelHelper,
2830
self::getContainer()->getByType(PhpVersion::class),
31+
$this->reportCastedArrayKey,
2932
);
3033
}
3134

@@ -102,6 +105,42 @@ public function testInvalidMixedKey(): void
102105
$this->analyse([__DIR__ . '/data/invalid-key-array-item.php'], $errors);
103106
}
104107

108+
public function testInvalidKeyReportingCastedArrayKey(): void
109+
{
110+
$this->reportCastedArrayKey = true;
111+
112+
$this->analyse([__DIR__ . '/data/invalid-key-array-item.php'], [
113+
[
114+
'Invalid array key type DateTimeImmutable.',
115+
12,
116+
],
117+
[
118+
'Invalid array key type array.',
119+
13,
120+
],
121+
[
122+
'Possibly invalid array key type stdClass|string.',
123+
14,
124+
],
125+
[
126+
'Possibly invalid array key type mixed.',
127+
21,
128+
],
129+
[
130+
'Invalid array key type float.',
131+
26,
132+
],
133+
[
134+
'Invalid array key type null.',
135+
27,
136+
],
137+
[
138+
'Invalid array key type bool.',
139+
27,
140+
],
141+
]);
142+
}
143+
105144
public function testInvalidKeyInList(): void
106145
{
107146
$this->analyse([__DIR__ . '/data/invalid-key-list.php'], [

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@
2525
$c = [
2626
1.0 => 'aaa',
2727
null => 'aaa',
28+
false => 'aaa',
2829
];
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace UnsetFalseKey;
4+
5+
/** @var array<int, int> $data */
6+
unset($data[false]);
7+
8+
function test_remove_element(): void {
9+
$modified = [1, 4, 6, 8];
10+
11+
// this would happen in the SUT
12+
unset($modified[array_search(4, $modified, true)]);
13+
unset($modified[array_search(5, $modified, true)]); // bug is here - will unset key `0` by accident
14+
15+
assert([1, 6, 8] === $modified); // actually is [6, 8]
16+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /