Skip to content

Commit 8bda796

Browse files
committed
Change representation of ConstantArrayType with optional keys
1 parent 1cbbde0 commit 8bda796

20 files changed

Lines changed: 594 additions & 220 deletions

src/PhpDoc/TypeNodeResolver.php

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -449,47 +449,23 @@ function (CallableTypeParameterNode $parameterNode) use ($nameScope, &$isVariadi
449449

450450
private function resolveArrayShapeNode(ArrayShapeNode $typeNode, NameScope $nameScope): Type
451451
{
452-
$requiredItems = [];
453-
$optionalItems = [];
454-
foreach ($typeNode->items as $itemNode) {
455-
if ($itemNode->optional) {
456-
$optionalItems[] = $itemNode;
457-
continue;
458-
}
459-
460-
$requiredItems[] = $itemNode;
461-
}
462-
463452
$builder = ConstantArrayTypeBuilder::createEmpty();
464453

465-
$addToBuilder = function (ConstantArrayTypeBuilder $builder, array $items) use ($nameScope): void {
466-
foreach ($items as $itemNode) {
467-
$offsetType = null;
468-
if ($itemNode->keyName instanceof ConstExprIntegerNode) {
469-
$offsetType = new ConstantIntegerType((int) $itemNode->keyName->value);
470-
} elseif ($itemNode->keyName instanceof IdentifierTypeNode) {
471-
$offsetType = new ConstantStringType($itemNode->keyName->name);
472-
} elseif ($itemNode->keyName instanceof ConstExprStringNode) {
473-
$offsetType = new ConstantStringType($itemNode->keyName->value);
474-
} elseif ($itemNode->keyName !== null) {
475-
throw new \PHPStan\ShouldNotHappenException('Unsupported key node type: ' . get_class($itemNode->keyName));
476-
}
477-
$builder->setOffsetValueType($offsetType, $this->resolve($itemNode->valueType, $nameScope));
454+
foreach ($typeNode->items as $itemNode) {
455+
$offsetType = null;
456+
if ($itemNode->keyName instanceof ConstExprIntegerNode) {
457+
$offsetType = new ConstantIntegerType((int) $itemNode->keyName->value);
458+
} elseif ($itemNode->keyName instanceof IdentifierTypeNode) {
459+
$offsetType = new ConstantStringType($itemNode->keyName->name);
460+
} elseif ($itemNode->keyName instanceof ConstExprStringNode) {
461+
$offsetType = new ConstantStringType($itemNode->keyName->value);
462+
} elseif ($itemNode->keyName !== null) {
463+
throw new \PHPStan\ShouldNotHappenException('Unsupported key node type: ' . get_class($itemNode->keyName));
478464
}
479-
};
480-
481-
$arrays = [];
482-
$addToBuilder($builder, $requiredItems);
483-
$arrays[] = $builder->getArray();
484-
485-
if (count($optionalItems) === 0) {
486-
return $arrays[0];
465+
$builder->setOffsetValueType($offsetType, $this->resolve($itemNode->valueType, $nameScope), $itemNode->optional);
487466
}
488467

489-
$addToBuilder($builder, $optionalItems);
490-
$arrays[] = $builder->getArray();
491-
492-
return TypeCombinator::union(...$arrays);
468+
return $builder->getArray();
493469
}
494470

495471
private function resolveConstTypeNode(ConstTypeNode $typeNode, NameScope $nameScope): Type

src/Rules/Comparison/ImpossibleCheckTypeHelper.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,19 @@ public function findSpecifiedType(
9191
return null;
9292
}
9393

94-
if (!$haystackType instanceof ConstantArrayType || count($haystackType->getValueTypes()) > 1) {
94+
if (!$haystackType->isArray()->yes()) {
95+
return null;
96+
}
97+
98+
if (!$haystackType instanceof ConstantArrayType || count($haystackType->getValueTypes()) > 0) {
9599
$needleType = $scope->getType($node->args[0]->value);
96100

97101
$haystackArrayTypes = TypeUtils::getArrays($haystackType);
98102
if (count($haystackArrayTypes) === 1 && $haystackArrayTypes[0]->getIterableValueType() instanceof NeverType) {
99103
return null;
100104
}
101105

102-
$valueType = TypeCombinator::union(...$haystackArrayTypes)->getIterableValueType();
106+
$valueType = $haystackType->getIterableValueType();
103107
$isNeedleSupertype = $needleType->isSuperTypeOf($valueType);
104108

105109
if ($isNeedleSupertype->maybe() || $isNeedleSupertype->yes()) {

src/Type/Accessory/HasOffsetType.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ public function __construct(Type $offsetType)
3434
$this->offsetType = $offsetType;
3535
}
3636

37+
public function getOffsetType(): Type
38+
{
39+
return $this->offsetType;
40+
}
41+
3742
public function getReferencedClasses(): array
3843
{
3944
return [];

0 commit comments

Comments
 (0)