Skip to content

Commit 15a5616

Browse files
committed
DuplicateKeysInLiteralArraysRule: Fixed union type handling
1 parent 2fb3dbe commit 15a5616

File tree

3 files changed

+40
-3
lines changed

3 files changed

+40
-3
lines changed

src/Rules/Arrays/DuplicateKeysInLiteralArraysRule.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PHPStan\Rules\Rule;
1010
use PHPStan\Rules\RuleErrorBuilder;
1111
use PHPStan\Type\Constant\ConstantIntegerType;
12+
use PHPStan\Type\TypeCombinator;
1213
use function array_keys;
1314
use function count;
1415
use function implode;
@@ -49,6 +50,7 @@ public function processNode(Node $node, Scope $scope): array
4950
* - False means a non-scalar value was encountered and we cannot be sure of the next keys.
5051
*/
5152
$autoGeneratedIndex = null;
53+
$overallKeyType = null;
5254
foreach ($node->getItemNodes() as $itemNode) {
5355
$item = $itemNode->getArrayItem();
5456
if ($item === null) {
@@ -75,6 +77,8 @@ public function processNode(Node $node, Scope $scope): array
7577
$autoGeneratedIndex = $autoGeneratedIndex === null
7678
? $arrayKeyValues[0]
7779
: max($autoGeneratedIndex, $arrayKeyValues[0]);
80+
} elseif (count($arrayKeyValues) > 1) {
81+
$autoGeneratedIndex = false;
7882
}
7983
}
8084

@@ -84,6 +88,14 @@ public function processNode(Node $node, Scope $scope): array
8488
continue;
8589
}
8690

91+
if ($overallKeyType === null) {
92+
$duplicate = false;
93+
$overallKeyType = $keyType;
94+
} else {
95+
$duplicate = $overallKeyType->isSuperTypeOf($keyType)->yes();
96+
$overallKeyType = TypeCombinator::union($overallKeyType, $keyType);
97+
}
98+
8799
foreach ($keyValues as $value) {
88100
$printedValue = $key !== null
89101
? $this->exprPrinter->printExpr($key)
@@ -94,9 +106,7 @@ public function processNode(Node $node, Scope $scope): array
94106
$valueLines[$value] = $item->getStartLine();
95107
}
96108

97-
$previousCount = count($values);
98-
$values[$value] = $printedValue;
99-
if ($previousCount !== count($values)) {
109+
if (!$duplicate) {
100110
continue;
101111
}
102112

tests/PHPStan/Rules/Arrays/DuplicateKeysInLiteralArraysRuleTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ public function testDuplicateKeys(): void
7373
'Array has 2 duplicate keys with value \'key\' (\'key\', $key2).',
7474
105,
7575
],
76+
[
77+
"Array has 2 duplicate keys with value 'bar' (\$key, 'bar').",
78+
128,
79+
],
7680
]);
7781
}
7882

tests/PHPStan/Rules/Arrays/data/duplicate-keys.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,27 @@ public function doUnionKeys(string $key): void
107107
];
108108
}
109109

110+
/**
111+
* @param 'foo'|'bar' $key
112+
*/
113+
public function maybeDuplicate(string $key): void
114+
{
115+
$a = [
116+
'foo' => 'foo',
117+
$key => 'foo|bar',
118+
];
119+
}
120+
121+
/**
122+
* @param 'foo'|'bar' $key
123+
*/
124+
public function sureDuplicate(string $key): void
125+
{
126+
$a = [
127+
'foo' => 'foo',
128+
$key => 'foo|bar',
129+
'bar' => 'bar',
130+
];
131+
}
132+
110133
}

0 commit comments

Comments
 (0)